Since the tar bidder can never get called more than once, it
doesn't need to compensate for this situation. While here, fix a minor longstanding bug that empty tar archives (which begin with at least 512 zero bytes) never properly reported their format. In particular, this fixes the output of: bsdtar tvvf /dev/zero And, of course, a new test to verify that libarchive correctly recognizes the format of such files.
This commit is contained in:
parent
e73e773084
commit
a0751a90e6
@ -295,24 +295,8 @@ archive_read_format_tar_bid(struct archive_read *a)
|
||||
const void *h;
|
||||
const struct archive_entry_header_ustar *header;
|
||||
|
||||
/*
|
||||
* If we're already reading a non-tar file, don't
|
||||
* bother to bid.
|
||||
*/
|
||||
if (a->archive.archive_format != 0 &&
|
||||
(a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) !=
|
||||
ARCHIVE_FORMAT_TAR)
|
||||
return (0);
|
||||
bid = 0;
|
||||
|
||||
/*
|
||||
* If we're already reading a tar format, start the bid at 1 as
|
||||
* a failsafe.
|
||||
*/
|
||||
if ((a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
|
||||
ARCHIVE_FORMAT_TAR)
|
||||
bid++;
|
||||
|
||||
/* Now let's look at the actual header and see if it matches. */
|
||||
if (a->decompressor->read_ahead != NULL)
|
||||
bytes_read = (a->decompressor->read_ahead)(a, &h, 512);
|
||||
@ -324,13 +308,14 @@ archive_read_format_tar_bid(struct archive_read *a)
|
||||
return (0);
|
||||
|
||||
/* If it's an end-of-archive mark, we can handle it. */
|
||||
if ((*(const char *)h) == 0 && archive_block_is_null((const unsigned char *)h)) {
|
||||
/* If it's a known tar file, end-of-archive is definite. */
|
||||
if ((a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
|
||||
ARCHIVE_FORMAT_TAR)
|
||||
return (512);
|
||||
/* Empty archive? */
|
||||
return (1);
|
||||
if ((*(const char *)h) == 0
|
||||
&& archive_block_is_null((const unsigned char *)h)) {
|
||||
/*
|
||||
* Usually, I bid the number of bits verified, but
|
||||
* in this case, 4096 seems excessive so I picked 10 as
|
||||
* an arbitrary but reasonable-seeming value.
|
||||
*/
|
||||
return (10);
|
||||
}
|
||||
|
||||
/* If it's not an end-of-archive mark, it must have a valid checksum.*/
|
||||
@ -590,6 +575,10 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
if (bytes > 0)
|
||||
(a->decompressor->consume)(a, bytes);
|
||||
archive_set_error(&a->archive, 0, NULL);
|
||||
if (a->archive.archive_format_name == NULL) {
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR;
|
||||
a->archive.archive_format_name = "tar";
|
||||
}
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,52 @@ __FBSDID("$FreeBSD$");
|
||||
* '2' is a symlink, '5' is a dir, etc.
|
||||
*/
|
||||
|
||||
/* Empty archive. */
|
||||
static unsigned char archiveEmpty[] = {
|
||||
/* 512 zero bytes */
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
|
||||
};
|
||||
|
||||
static void verifyEmpty(void)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archiveEmpty, 512));
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
|
||||
failure("512 zero bytes should be recognized as a tar archive.");
|
||||
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR);
|
||||
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Single entry with a hardlink. */
|
||||
static unsigned char archive1[] = {
|
||||
'h','a','r','d','l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
@ -411,6 +457,7 @@ static void verify(unsigned char *d, size_t s,
|
||||
|
||||
DEFINE_TEST(test_read_format_tar)
|
||||
{
|
||||
verifyEmpty();
|
||||
verify(archive1, sizeof(archive1), verify1,
|
||||
ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
|
||||
verify(archive2, sizeof(archive2), verify2,
|
||||
|
Loading…
Reference in New Issue
Block a user