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:
Tim Kientzle 2008-01-13 23:50:30 +00:00
parent e73e773084
commit a0751a90e6
2 changed files with 59 additions and 23 deletions

View File

@ -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);
}

View File

@ -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,