Clean up the support for extracting very long pathnames.

This commit is contained in:
Tim Kientzle 2005-03-29 05:24:08 +00:00
parent a4e4c868b7
commit fa37cdf60b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=144267
2 changed files with 18 additions and 14 deletions

View file

@ -7,7 +7,7 @@
LIB= archive
VERSION= 1.02.013
VERSION= 1.02.016
ARCHIVE_API_FEATURE= 2
ARCHIVE_API_VERSION= 1
SHLIB_MAJOR= ${ARCHIVE_API_VERSION}

View file

@ -185,15 +185,16 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
/*
* If pathname is longer than PATH_MAX, record starting directory
* and move to a suitable intermediate dir.
* and chdir to a suitable intermediate dir.
*/
if (strlen(archive_entry_pathname(entry)) > PATH_MAX) {
char *intdir, *tail;
/*
* Yes, the copy here is necessary because we edit
* the pathname in-place to create intermediate dirnames.
*/
original_filename = strdup(archive_entry_pathname(entry));
char *intdir, *tail;
restore_pwd = open(".", O_RDONLY);
/*
@ -203,28 +204,28 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
intdir = tail = original_filename;
while (strlen(tail) > PATH_MAX) {
intdir = tail;
/* Locate a dir prefix shorter than PATH_MAX. */
tail = intdir + PATH_MAX - 8;
while (tail > intdir && *tail != '/')
tail--;
if (tail <= intdir) {
close(restore_pwd);
archive_set_error(a, EPERM,
"Path element too long");
return (ARCHIVE_WARN);
ret = ARCHIVE_WARN;
goto cleanup;
}
/* Create intdir and chdir to it. */
*tail = '\0'; /* Terminate dir portion */
if (create_dir(a, intdir, flags) != ARCHIVE_OK) {
fchdir(restore_pwd);
close(restore_pwd);
return (ARCHIVE_WARN);
}
if (chdir(intdir) != 0) {
ret = create_dir(a, intdir, flags);
if (ret == ARCHIVE_OK && chdir(intdir) != 0) {
archive_set_error(a, errno, "Couldn't chdir");
fchdir(restore_pwd);
close(restore_pwd);
return (ARCHIVE_WARN);
ret = ARCHIVE_WARN;
}
*tail = '/'; /* Restore the / we removed. */
if (ret != ARCHIVE_OK)
goto cleanup;
tail++;
}
archive_entry_set_pathname(entry, tail);
@ -266,9 +267,12 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
}
}
cleanup:
/* If we changed directory above, restore it here. */
if (restore_pwd >= 0 && original_filename != NULL) {
fchdir(restore_pwd);
close(restore_pwd);
archive_entry_copy_pathname(entry, original_filename);
free(original_filename);
}