Correct the cpio writers to not accept data for non-regular files.

In particular, the previous code led to archives that had
non-empty bodies following directory entries.  Not a fatal
problem, as bsdtar and GNU cpio are both happy to just skip
this bogus data, but it still shouldn't be there.

MFC after: 3 days
This commit is contained in:
kientzle 2007-10-12 04:11:31 +00:00
parent 7f13779429
commit c2c3c21fbd
3 changed files with 41 additions and 3 deletions

View File

@ -142,12 +142,17 @@ archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
format_octal(archive_entry_mtime(entry), &h.c_mtime, sizeof(h.c_mtime));
format_octal(pathlength, &h.c_namesize, sizeof(h.c_namesize));
/* Non-regular files don't store bodies. */
if (archive_entry_filetype(entry) != AE_IFREG)
archive_entry_set_size(entry, 0);
/* Symlinks get the link written as the body of the entry. */
p = archive_entry_symlink(entry);
if (p != NULL && *p != '\0')
format_octal(strlen(p), &h.c_filesize, sizeof(h.c_filesize));
else
format_octal(archive_entry_size(entry), &h.c_filesize, sizeof(h.c_filesize));
format_octal(archive_entry_size(entry),
&h.c_filesize, sizeof(h.c_filesize));
ret = (a->compressor.write)(a, &h, sizeof(h));
if (ret != ARCHIVE_OK)

View File

@ -148,12 +148,17 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry)
format_hex(pathlength, &h.c_namesize, sizeof(h.c_namesize));
format_hex(0, &h.c_checksum, sizeof(h.c_checksum));
/* Non-regular files don't store bodies. */
if (archive_entry_filetype(entry) != AE_IFREG)
archive_entry_set_size(entry, 0);
/* Symlinks get the link written as the body of the entry. */
p = archive_entry_symlink(entry);
if (p != NULL && *p != '\0')
format_hex(strlen(p), &h.c_filesize, sizeof(h.c_filesize));
else
format_hex(archive_entry_size(entry), &h.c_filesize, sizeof(h.c_filesize));
format_hex(archive_entry_size(entry),
&h.c_filesize, sizeof(h.c_filesize));
ret = (a->compressor.write)(a, &h, sizeof(h));
if (ret != ARCHIVE_OK)

View File

@ -66,6 +66,21 @@ test_format(int (*set_format)(struct archive *))
archive_entry_free(ae);
assertA(8 == archive_write_data(a, "12345678", 9));
/*
* Write a directory to it.
*/
assert((ae = archive_entry_new()) != NULL);
archive_entry_set_mtime(ae, 11, 110);
archive_entry_copy_pathname(ae, "dir");
archive_entry_set_mode(ae, S_IFDIR | 0755);
archive_entry_set_size(ae, 512);
assertA(0 == archive_write_header(a, ae));
assertEqualInt(0, archive_entry_size(ae));
archive_entry_free(ae);
assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9));
/* Close out the archive. */
assertA(0 == archive_write_close(a));
#if ARCHIVE_API_VERSION > 1
@ -95,8 +110,21 @@ test_format(int (*set_format)(struct archive *))
assertA(8 == archive_read_data(a, filedata, 10));
assert(0 == memcmp(filedata, "12345678", 8));
/*
* Read the dir entry back.
*/
assertA(0 == archive_read_next_header(a, &ae));
assert(11 == archive_entry_mtime(ae));
assert(0 == archive_entry_mtime_nsec(ae));
assert(0 == archive_entry_atime(ae));
assert(0 == archive_entry_ctime(ae));
assertEqualString("dir", archive_entry_pathname(ae));
assert((S_IFDIR | 0755) == archive_entry_mode(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualIntA(a, 0, archive_read_data(a, filedata, 10));
/* Verify the end of the archive. */
assert(1 == archive_read_next_header(a, &ae));
assertEqualIntA(a, 1, archive_read_next_header(a, &ae));
assert(0 == archive_read_close(a));
#if ARCHIVE_API_VERSION > 1
assert(0 == archive_read_finish(a));