cpio: Fix device number calculation.
authorTobias Geerinckx-Rice <me@tobias.gr>
Sun, 4 Jul 2021 02:26:01 +0000 (04:26 +0200)
committerTobias Geerinckx-Rice <me@tobias.gr>
Sun, 4 Jul 2021 02:35:35 +0000 (04:35 +0200)
“dev_t in glibc is a 64-bit quantity, with 32-bit major and minor
 numbers.”  — glibc's <bits/sysmacros.h>

The "tests/cpio.scm" was failing because (guix cpio) treated it as a
16-bit quantity instead, leading to header mismatches with the GNU cpio
reference output.

* guix/cpio.scm (device-number, device->major+minor): Use all the bits.

guix/cpio.scm

index c9932f5..8038a11 100644 (file)
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -153,15 +154,20 @@ denotes, similar to 'stat:type'."
           (else
            (error "unsupported file type" mode)))))
 
-(define (device-number major minor)               ;see <sys/sysmacros.h>
+(define (device-number major minor)     ; see glibc's <sys/sysmacros.h>
   "Return the device number for the device with MAJOR and MINOR, for use as
 the last argument of `mknod'."
-  (+ (* major 256) minor))
+  (logior (ash (logand #x00000fff major) 8)
+          (ash (logand #xfffff000 major) 32)
+               (logand #x000000ff minor)
+          (ash (logand #xffffff00 minor) 12)))
 
-(define (device->major+minor device)
+(define (device->major+minor device)     ; see glibc's <sys/sysmacros.h>
   "Return two values: the major and minor device numbers that make up DEVICE."
-  (values (ash device -8)
-          (logand device #xff)))
+  (values (logior (ash (logand #x00000000000fff00 device) -8)
+                  (ash (logand #xfffff00000000000 device) -32))
+          (logior      (logand #x00000000000000ff device)
+                  (ash (logand #x00000ffffff00000 device) -12))))
 
 (define* (file->cpio-header file #:optional (file-name file)
                             #:key (stat lstat))