diff options
author | kientzle <kientzle@FreeBSD.org> | 2007-10-12 04:11:31 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2007-10-12 04:11:31 +0000 |
commit | c2c3c21fbd0bf2438613a57927c47131c1d18584 (patch) | |
tree | 618f1cb77b35adb6ee46e91ba038bd19e0ba563f /lib | |
parent | 7f137794299c6358dee3eb8be2af419fcf98250d (diff) | |
download | FreeBSD-src-c2c3c21fbd0bf2438613a57927c47131c1d18584.zip FreeBSD-src-c2c3c21fbd0bf2438613a57927c47131c1d18584.tar.gz |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libarchive/archive_write_set_format_cpio.c | 7 | ||||
-rw-r--r-- | lib/libarchive/archive_write_set_format_cpio_newc.c | 7 | ||||
-rw-r--r-- | lib/libarchive/test/test_write_format_cpio.c | 30 |
3 files changed, 41 insertions, 3 deletions
diff --git a/lib/libarchive/archive_write_set_format_cpio.c b/lib/libarchive/archive_write_set_format_cpio.c index 80dbf38..ba23f32 100644 --- a/lib/libarchive/archive_write_set_format_cpio.c +++ b/lib/libarchive/archive_write_set_format_cpio.c @@ -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) diff --git a/lib/libarchive/archive_write_set_format_cpio_newc.c b/lib/libarchive/archive_write_set_format_cpio_newc.c index b585597..37dd35a 100644 --- a/lib/libarchive/archive_write_set_format_cpio_newc.c +++ b/lib/libarchive/archive_write_set_format_cpio_newc.c @@ -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) diff --git a/lib/libarchive/test/test_write_format_cpio.c b/lib/libarchive/test/test_write_format_cpio.c index 2ea40a3..886942e 100644 --- a/lib/libarchive/test/test_write_format_cpio.c +++ b/lib/libarchive/test/test_write_format_cpio.c @@ -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)); |