Skip to content

Commit c8b7972

Browse files
committed
builder: Add a set_rdev() convenience
Commonly one may be building tar archives from the filesystem in a custom way, or operating on a translation of a non-tar format which uses rdev, not split major/minor. Today one needs to replicate the nontrivial bit manipulations to split the device; but since we have that code anyways in our own "build from filesystem" code, let's just add it as a public API. Signed-off-by: Colin Walters <walters@verbum.org>
1 parent 97d5033 commit c8b7972

3 files changed

Lines changed: 24 additions & 5 deletions

File tree

src/builder.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,7 @@ fn append_special(
535535
prepare_header_path(dst, &mut header, path)?;
536536

537537
header.set_entry_type(entry_type);
538-
let dev_id = stat.rdev();
539-
let dev_major = ((dev_id >> 32) & 0xffff_f000) | ((dev_id >> 8) & 0x0000_0fff);
540-
let dev_minor = ((dev_id >> 12) & 0xffff_ff00) | ((dev_id) & 0x0000_00ff);
541-
header.set_device_major(dev_major as u32)?;
542-
header.set_device_minor(dev_minor as u32)?;
538+
header.set_rdev(stat.rdev())?;
543539

544540
header.set_cksum();
545541
dst.write_all(header.as_bytes())?;

src/header.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,17 @@ impl Header {
645645
}
646646
}
647647

648+
/// Encodes the device number into the major and minor fields of this header.
649+
///
650+
/// This function will return an error if this header format cannot encode a
651+
/// a device number.
652+
pub fn set_rdev(&mut self, rdev: libc::dev_t) -> io::Result<()> {
653+
let dev_major = ((rdev >> 32) & 0xffff_f000) | ((rdev >> 8) & 0x0000_0fff);
654+
self.set_device_major(dev_major as u32)?;
655+
let dev_minor = ((rdev >> 12) & 0xffff_ff00) | ((rdev) & 0x0000_00ff);
656+
self.set_device_minor(dev_minor as u32)
657+
}
658+
648659
/// Returns the device minor number, if present.
649660
///
650661
/// This field may not be present in all archives, and it may not be

tests/header/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,18 @@ fn dev_major_minor() {
100100
assert_eq!(t!(h.device_major()), Some(1));
101101
assert_eq!(t!(h.device_minor()), Some(2));
102102

103+
// Verify this is idempotent
104+
let onetwo_rdev = libc::makedev(1, 2);
105+
t!(h.set_rdev(onetwo_rdev));
106+
assert_eq!(t!(h.device_major()), Some(1));
107+
assert_eq!(t!(h.device_minor()), Some(2));
108+
109+
// And verify that changing the device works
110+
let nvme_rdev = libc::makedev(0x88, 0x6);
111+
t!(h.set_rdev(nvme_rdev));
112+
assert_eq!(t!(h.device_major()), Some(0x88));
113+
assert_eq!(t!(h.device_minor()), Some(0x6));
114+
103115
h = Header::new_ustar();
104116
t!(h.set_device_major(1));
105117
t!(h.set_device_minor(2));

0 commit comments

Comments
 (0)