summaryrefslogtreecommitdiffstats
path: root/lib/libarchive
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2005-03-29 05:24:08 +0000
committerkientzle <kientzle@FreeBSD.org>2005-03-29 05:24:08 +0000
commit886428519a567eeec0864685070d25dd31f8d9ca (patch)
tree450d179d741cbc112ac8c499db6ba31828835b35 /lib/libarchive
parented1d4fbad5c27213cf394c7b62f627ffc170d661 (diff)
downloadFreeBSD-src-886428519a567eeec0864685070d25dd31f8d9ca.zip
FreeBSD-src-886428519a567eeec0864685070d25dd31f8d9ca.tar.gz
Clean up the support for extracting very long pathnames.
Diffstat (limited to 'lib/libarchive')
-rw-r--r--lib/libarchive/Makefile2
-rw-r--r--lib/libarchive/archive_read_extract.c30
2 files changed, 18 insertions, 14 deletions
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 8ea2237..e7bc573 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -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}
diff --git a/lib/libarchive/archive_read_extract.c b/lib/libarchive/archive_read_extract.c
index 041a19b..bb1327c 100644
--- a/lib/libarchive/archive_read_extract.c
+++ b/lib/libarchive/archive_read_extract.c
@@ -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);
}
OpenPOWER on IntegriCloud