]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
fix(cpio): correct dev_t -> rmajor/rminor mapping
authorDavid Disseldorp <ddiss@suse.de>
Thu, 10 Feb 2022 19:08:11 +0000 (20:08 +0100)
committerJóhann B. Guðmundsson <johannbg@gmail.com>
Thu, 17 Feb 2022 19:28:33 +0000 (19:28 +0000)
dev_t -> major/minor number mapping is more complicated than the
incorrect major=(dev_t >> 8) minor=(dev_t & 0xff) mapping that we
currently perform. Fix mapping to match Linux / glibc behaviour.

Fixes: https://github.com/dracutdevs/dracut/issues/1695
Reported-by: Ethan Wu <ethanwu10@gmail.com>
Signed-off-by: David Disseldorp <ddiss@suse.de>
src/dracut-cpio/src/main.rs

index a1994b96fc98c97597beef736c248f2a6bf86e96..816fc5101ac19e302ee52c0c918bef1e18e84c2d 100644 (file)
@@ -361,9 +361,12 @@ fn archive_path<W: Seek + Write>(
         // no zero terminator for symlink target path
     }
 
+    // Linux kernel uses 32-bit dev_t, encoded as mmmM MMmm. glibc uses 64-bit
+    // MMMM Mmmm mmmM MMmm, which is compatible with the former.
     if ftype.is_block_device() || ftype.is_char_device() {
-        rmajor = (md.rdev() >> 8) as u32;
-        rminor = (md.rdev() & 0xff) as u32;
+        let rd = md.rdev();
+        rmajor = (((rd >> 32) & 0xfffff000) | ((rd >> 8) & 0x00000fff)) as u32;
+        rminor = (((rd >> 12) & 0xffffff00) | (rd & 0x000000ff)) as u32;
     }
 
     if ftype.is_file() {