]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix rdev field in cpio format for device nodes 1388/head
authorMichael Forney <mforney@mforney.org>
Fri, 29 May 2020 21:54:05 +0000 (14:54 -0700)
committerMichael Forney <mforney@mforney.org>
Fri, 29 May 2020 22:11:07 +0000 (15:11 -0700)
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

libarchive/archive_write_set_format_cpio.c
libarchive/test/test_write_format_cpio.c

index 729f9c7755915febbb64e6d2c376c27d94b572d2..09fce23c68c43ec64eb9a605147d06688e8b3ffa 100644 (file)
@@ -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);
index 9f7307f28ca2d179d0451ceacf9a192c42c1f651..acf29673ffa12aa469ecd68b46fe23bad6bf2ccc 100644 (file)
@@ -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));