summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2004-09-04 21:49:42 +0000
committerkientzle <kientzle@FreeBSD.org>2004-09-04 21:49:42 +0000
commit2a0558f74f8c424f58d3e404474e9e1361b7c9ea (patch)
tree90bfca819433b9d784bd966e8387dcda0b6dee2d /lib
parentbc3177594847c472e25979621a8b83457fbf3eb6 (diff)
downloadFreeBSD-src-2a0558f74f8c424f58d3e404474e9e1361b7c9ea.zip
FreeBSD-src-2a0558f74f8c424f58d3e404474e9e1361b7c9ea.tar.gz
Some old tar archives rely on "regular-file-plus-trailing-slash" to
denote a directory. Unfortunately, in the presence of GNU or POSIX extensions, this code was checking the truncated filename stored in the regular header rather than the full filename stored in the extended attribute. As a result, long filenames with '/' in just the right position would trigger this check and be erroneously marked as directories. Move the check so it only considers the full filename. Note: the check can't simply be disabled for archives that contain these extensions because there are some very broken archivers out there. Thanks to: Will Froning MFC after: 3 days
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/archive_read_support_format_tar.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c
index ecc42ad..e8a769c 100644
--- a/lib/libarchive/archive_read_support_format_tar.c
+++ b/lib/libarchive/archive_read_support_format_tar.c
@@ -351,12 +351,33 @@ archive_read_format_tar_read_header(struct archive *a,
{
struct stat st;
struct tar *tar;
+ const char *p;
+ int r;
+ size_t l;
memset(&st, 0, sizeof(st));
tar = *(a->pformat_data);
tar->entry_offset = 0;
- return (tar_read_header(a, tar, entry, &st));
+ r = tar_read_header(a, tar, entry, &st);
+
+ if (r == ARCHIVE_OK) {
+ /*
+ * "Regular" entry with trailing '/' is really
+ * directory: This is needed for certain old tar
+ * variants and even for some broken newer ones.
+ */
+ p = archive_entry_pathname(entry);
+ l = strlen(p);
+ if (S_ISREG(st.st_mode) && p[l-1] == '/') {
+ st.st_mode &= ~S_IFMT;
+ st.st_mode |= S_IFDIR;
+ }
+
+ /* Copy the final stat data into the entry. */
+ archive_entry_copy_stat(entry, &st);
+ }
+ return (r);
}
static int
@@ -421,8 +442,6 @@ tar_read_header(struct archive *a, struct tar *tar,
ssize_t bytes;
int err;
const void *h;
- const char *p;
- size_t l;
const struct archive_entry_header_ustar *header;
/* Read 512-byte header record */
@@ -513,16 +532,7 @@ tar_read_header(struct archive *a, struct tar *tar,
a->archive_format_name = "tar (non-POSIX)";
err = header_old_tar(a, tar, entry, st, h);
}
-
- /* "Regular" entry with trailing '/' is really directory. */
- p = archive_entry_pathname(entry);
- l = strlen(p);
- if (S_ISREG(st->st_mode) && p[l-1] == '/') {
- st->st_mode &= ~S_IFMT;
- st->st_mode |= S_IFDIR;
- }
}
- archive_entry_copy_stat(entry, st);
--tar->header_recursion_depth;
return (err);
}
OpenPOWER on IntegriCloud