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
This commit is contained in:
parent
ea0f517b92
commit
8a95c5cb6e
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user