From: Michael Forney Date: Fri, 29 May 2020 21:54:05 +0000 (-0700) Subject: Fix rdev field in cpio format for device nodes X-Git-Tag: v3.5.0~33^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1ef7a57a7024af4ae165e07fa10f3984c41fb9f6;p=thirdparty%2Flibarchive.git Fix rdev field in cpio format for device nodes Currently, the rdev field is set from archive_entry_dev, which is the device number of the filesystem containing the device node, not the device itself. It should instead use archive_entry_rdev. Here's an example demonstrating the problem: $ ls -l /dev/null crw-rw-rw- 1 root root 1, 3 May 26 02:03 /dev/null $ bsdtar --format=cpio -cf null.cpio /dev/null bsdtar: Removing leading '/' from member names $ bsdtar -tvf null.cpio crw-rw-rw- 1 0 0 0,6 May 26 02:03 dev/null --- diff --git a/libarchive/archive_write_set_format_cpio.c b/libarchive/archive_write_set_format_cpio.c index 729f9c775..09fce23c6 100644 --- a/libarchive/archive_write_set_format_cpio.c +++ b/libarchive/archive_write_set_format_cpio.c @@ -348,7 +348,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size); if (archive_entry_filetype(entry) == AE_IFBLK || archive_entry_filetype(entry) == AE_IFCHR) - format_octal(archive_entry_dev(entry), h + c_rdev_offset, c_rdev_size); + format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size); else format_octal(0, h + c_rdev_offset, c_rdev_size); format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); diff --git a/libarchive/test/test_write_format_cpio.c b/libarchive/test/test_write_format_cpio.c index 9f7307f28..acf29673f 100644 --- a/libarchive/test/test_write_format_cpio.c +++ b/libarchive/test/test_write_format_cpio.c @@ -141,6 +141,17 @@ test_format(int (*set_format)(struct archive *)) archive_entry_free(ae); assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + /* + * Write a character device to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "tty0"); + archive_entry_set_mode(ae, S_IFCHR | 0600); + archive_entry_set_size(ae, 0); + archive_entry_set_rdev(ae, 1024); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); @@ -212,6 +223,15 @@ test_format(int (*set_format)(struct archive *)) assertEqualInt(0, archive_entry_size(ae)); assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + /* + * Read the character device entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("tty0", archive_entry_pathname(ae)); + assertEqualInt((S_IFCHR | 0600), archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1024, archive_entry_rdev(ae)); + /* Verify the end of the archive. */ assertEqualIntA(a, 1, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));