fix(stat, mknod): replace custom (flawed in stat) logic with libc's.

Now uucore::fs reexports libc's major(), minor() and makedev() directives.
This commit is contained in:
Guillem L. Jara
2025-12-31 09:28:11 +01:00
parent 7c489120dc
commit c30593a40a
5 changed files with 31 additions and 25 deletions
+1
View File
@@ -86,6 +86,7 @@ listxattr
llistxattr
lossily
lstat
makedev
mebi
mebibytes
mergeable
+1 -1
View File
@@ -21,7 +21,7 @@ path = "src/mknod.rs"
[dependencies]
clap = { workspace = true }
libc = { workspace = true }
uucore = { workspace = true, features = ["mode"] }
uucore = { workspace = true, features = ["mode", "fs"] }
fluent = { workspace = true }
[features]
+2 -7
View File
@@ -13,6 +13,7 @@ use std::ffi::CString;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError, UUsageError, set_exit_code};
use uucore::format_usage;
use uucore::fs::makedev;
use uucore::translate;
const MODE_RW_UGO: mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
@@ -26,12 +27,6 @@ mod options {
pub const CONTEXT: &str = "context";
}
#[inline(always)]
fn makedev(maj: u64, min: u64) -> dev_t {
// pick up from <sys/sysmacros.h>
((min & 0xff) | ((maj & 0xfff) << 8) | ((min & !0xff) << 12) | ((maj & !0xfff) << 32)) as dev_t
}
#[derive(Clone, PartialEq)]
enum FileType {
Block,
@@ -145,7 +140,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
translate!("mknod-error-fifo-no-major-minor"),
));
}
(_, Some(&major), Some(&minor)) => makedev(major, minor),
(_, Some(&major), Some(&minor)) => makedev(major as _, minor as _),
_ => {
return Err(UUsageError::new(
1,
+7 -17
View File
@@ -9,7 +9,7 @@ use uucore::translate;
use clap::builder::ValueParser;
use uucore::display::Quotable;
use uucore::fs::display_permissions;
use uucore::fs::{display_permissions, major, minor};
use uucore::fsext::{
FsMeta, MetadataTimeField, StatFs, metadata_get_time, pretty_filetype, pretty_fstype,
read_fs_list, statfs,
@@ -301,16 +301,6 @@ fn group_num(s: &str) -> Cow<'_, str> {
res.into()
}
/// Keeps major part of an integer
fn major(n: u64) -> u64 {
(n >> 8) & 0xFF
}
// Keeps minor part of an integer
fn minor(n: u64) -> u64 {
n & 0xFF
}
struct Stater {
follow: bool,
show_fs: bool,
@@ -1075,8 +1065,8 @@ impl Stater {
}
}
// device number in decimal
'd' if flag.major => OutputType::Unsigned(major(meta.dev())),
'd' if flag.minor => OutputType::Unsigned(minor(meta.dev())),
'd' if flag.major => OutputType::Unsigned(major(meta.dev() as _) as u64),
'd' if flag.minor => OutputType::Unsigned(minor(meta.dev() as _) as u64),
'd' => OutputType::Unsigned(meta.dev()),
// device number in hex
'D' => OutputType::UnsignedHex(meta.dev()),
@@ -1115,10 +1105,10 @@ impl Stater {
's' => OutputType::Integer(meta.len() as i64),
// major device type in hex, for character/block device special
// files
't' => OutputType::UnsignedHex(major(meta.rdev())),
't' => OutputType::UnsignedHex(major(meta.rdev() as _) as u64),
// minor device type in hex, for character/block device special
// files
'T' => OutputType::UnsignedHex(minor(meta.rdev())),
'T' => OutputType::UnsignedHex(minor(meta.rdev() as _) as u64),
// user ID of owner
'u' => OutputType::Unsigned(meta.uid() as u64),
// user name of owner
@@ -1162,8 +1152,8 @@ impl Stater {
OutputType::Float(sec as f64 + nsec as f64 / 1_000_000_000.0)
}
'R' => OutputType::UnsignedHex(meta.rdev()),
'r' if flag.major => OutputType::Unsigned(major(meta.rdev())),
'r' if flag.minor => OutputType::Unsigned(minor(meta.rdev())),
'r' if flag.major => OutputType::Unsigned(major(meta.rdev() as _) as u64),
'r' if flag.minor => OutputType::Unsigned(minor(meta.rdev() as _) as u64),
'r' => OutputType::Unsigned(meta.rdev()),
_ => OutputType::Unknown,
};
+20
View File
@@ -13,6 +13,8 @@ use libc::{
S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR,
mkfifo, mode_t,
};
#[cfg(all(unix, not(target_os = "redox")))]
pub use libc::{major, makedev, minor};
use std::collections::HashSet;
use std::collections::VecDeque;
use std::env;
@@ -839,6 +841,24 @@ pub fn make_fifo(path: &Path) -> std::io::Result<()> {
}
}
// Redox's libc appears not to include the following utilities
#[cfg(target_os = "redox")]
pub fn major(dev: libc::dev_t) -> libc::c_uint {
(((dev >> 8) & 0xFFF) | ((dev >> 32) & 0xFFFFF000)) as _
}
#[cfg(target_os = "redox")]
pub fn minor(dev: libc::dev_t) -> libc::c_uint {
((dev & 0xFF) | ((dev >> 12) & 0xFFFFF00)) as _
}
#[cfg(target_os = "redox")]
pub fn makedev(maj: libc::c_uint, min: libc::c_uint) -> libc::dev_t {
let [maj, min] = [maj as libc::dev_t, min as libc::dev_t];
(min & 0xff) | ((maj & 0xfff) << 8) | ((min & !0xff) << 12) | ((maj & !0xfff) << 32)
}
#[cfg(test)]
mod tests {
// Note this useful idiom: importing names from outer (for mod tests) scope.