summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-10-12 04:11:31 +0000
committerkientzle <kientzle@FreeBSD.org>2007-10-12 04:11:31 +0000
commitc2c3c21fbd0bf2438613a57927c47131c1d18584 (patch)
tree618f1cb77b35adb6ee46e91ba038bd19e0ba563f /lib
parent7f137794299c6358dee3eb8be2af419fcf98250d (diff)
downloadFreeBSD-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.c7
-rw-r--r--lib/libarchive/archive_write_set_format_cpio_newc.c7
-rw-r--r--lib/libarchive/test/test_write_format_cpio.c30
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));
OpenPOWER on IntegriCloud