From 42d05bda7e4154e24c11ea59961ea94eea7d5ee1 Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 8 Jan 2026 17:46:49 +0900 Subject: [PATCH 01/20] refactor(mknod): replace unsafe libc calls with nix crate for safety - Switch from direct libc::mknod and libc::umask to nix::sys::stat::mknod and nix --- Cargo.lock | 2 +- src/uu/mknod/Cargo.toml | 2 +- src/uu/mknod/src/mknod.rs | 129 +++++++++++++++++++------------------- 3 files changed, 68 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b6dd40e885..1ac4fbb740c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3689,7 +3689,7 @@ version = "0.6.0" dependencies = [ "clap", "fluent", - "libc", + "nix", "uucore", ] diff --git a/src/uu/mknod/Cargo.toml b/src/uu/mknod/Cargo.toml index 2ea3daddc96..2bdcfe5ad91 100644 --- a/src/uu/mknod/Cargo.toml +++ b/src/uu/mknod/Cargo.toml @@ -21,9 +21,9 @@ path = "src/mknod.rs" [dependencies] clap = { workspace = true } -libc = { workspace = true } uucore = { workspace = true, features = ["mode", "fs"] } fluent = { workspace = true } +nix = { workspace = true } [features] selinux = ["uucore/selinux"] diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 50aa7075540..6a2149e9597 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -3,12 +3,10 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO +// spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag use clap::{Arg, ArgAction, Command, value_parser}; -use libc::{S_IFBLK, S_IFCHR, S_IFIFO, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; -use libc::{dev_t, mode_t}; -use std::ffi::CString; +use nix::sys::stat::{Mode, SFlag, mknod as nix_mknod, umask as nix_umask}; use uucore::display::Quotable; use uucore::error::{UResult, USimpleError, UUsageError, set_exit_code}; @@ -16,7 +14,7 @@ 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; +const MODE_RW_UGO: u32 = 0o666; mod options { pub const MODE: &str = "mode"; @@ -28,31 +26,33 @@ mod options { } #[derive(Clone, PartialEq)] -enum FileType { +pub enum FileType { Block, Character, Fifo, } impl FileType { - fn as_mode(&self) -> mode_t { + fn as_sflag(&self) -> SFlag { match self { - Self::Block => S_IFBLK, - Self::Character => S_IFCHR, - Self::Fifo => S_IFIFO, + Self::Block => SFlag::S_IFBLK, + Self::Character => SFlag::S_IFCHR, + Self::Fifo => SFlag::S_IFIFO, } } } /// Configuration for special inode creation. pub struct Config<'a> { - /// bitmask of inode mode (permissions and file type) - pub mode: mode_t, + /// Permission bits for the inode + pub mode: Mode, + + pub file_type: FileType, /// when false, the exact mode bits will be set pub use_umask: bool, - pub dev: dev_t, + pub dev: u64, /// Set security context (SELinux/SMACK). pub set_security_context: bool, @@ -62,59 +62,61 @@ pub struct Config<'a> { } fn mknod(file_name: &str, config: Config) -> i32 { - let c_str = CString::new(file_name).expect("Failed to convert to CString"); - - unsafe { - // set umask to 0 and store previous umask - let have_prev_umask = if config.use_umask { - None - } else { - Some(libc::umask(0)) - }; + // set umask to 0 and store previous umask + let have_prev_umask = if config.use_umask { + None + } else { + Some(nix_umask(Mode::empty())) + }; - let errno = libc::mknod(c_str.as_ptr(), config.mode, config.dev); + let mknod_err = nix_mknod( + file_name, + config.file_type.as_sflag(), + config.mode, + config.dev as _, + ) + .err(); + let errno = if mknod_err.is_some() { -1 } else { 0 }; - // set umask back to original value - if let Some(prev_umask) = have_prev_umask { - libc::umask(prev_umask); - } + // set umask back to original value + if let Some(prev_umask) = have_prev_umask { + nix_umask(prev_umask); + } - if errno == -1 { - let c_str = CString::new(uucore::execution_phrase().as_bytes()) - .expect("Failed to convert to CString"); - // shows the error from the mknod syscall - libc::perror(c_str.as_ptr()); - } + if let Some(err) = mknod_err { + eprintln!( + "{}: {}", + uucore::execution_phrase(), + std::io::Error::from(err) + ); + } - // Apply SELinux context if requested - #[cfg(feature = "selinux")] - if config.set_security_context { - if let Err(e) = uucore::selinux::set_selinux_security_context( - std::path::Path::new(file_name), - config.context, - ) { - // if it fails, delete the file - let _ = std::fs::remove_file(file_name); - eprintln!("{}: {e}", uucore::util_name()); - return 1; - } + // Apply SELinux context if requested + #[cfg(feature = "selinux")] + if config.set_security_context { + if let Err(e) = uucore::selinux::set_selinux_security_context( + std::path::Path::new(file_name), + config.context, + ) { + // if it fails, delete the file + let _ = std::fs::remove_dir(file_name); + eprintln!("{}: {}", uucore::util_name(), e); + return 1; } + } - // Apply SMACK context if requested - #[cfg(feature = "smack")] - if config.set_security_context { - if let Err(e) = - uucore::smack::set_smack_label_and_cleanup(file_name, config.context, |p| { - std::fs::remove_file(p) - }) - { - eprintln!("{}: {e}", uucore::util_name()); - return 1; - } + // Apply SMACK context if requested + #[cfg(feature = "smack")] + if config.set_security_context { + if let Err(e) = uucore::smack::set_smack_label_and_cleanup(file_name, config.context, |p| { + std::fs::remove_file(p) + }) { + eprintln!("{}: {}", uucore::util_name(), e); + return 1; } - - errno } + + errno } #[uucore::main] @@ -131,7 +133,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { parse_mode(str_mode).map_err(|e| USimpleError::new(1, e))? } }; - let mode = mode_permissions | file_type.as_mode(); + let mode = Mode::from_bits_truncate(mode_permissions as nix::libc::mode_t); let file_name = matches .get_one::("name") @@ -153,7 +155,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { translate!("mknod-error-fifo-no-major-minor"), )); } - (_, Some(&major), Some(&minor)) => makedev(major as _, minor as _), + (_, Some(&major), Some(&minor)) => makedev(major as _, minor as _) as u64, _ => { return Err(UUsageError::new( 1, @@ -164,6 +166,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let config = Config { mode, + file_type: file_type.clone(), use_umask, dev, set_security_context: set_security_context || context.is_some(), @@ -234,8 +237,8 @@ pub fn uu_app() -> Command { } #[allow(clippy::unnecessary_cast)] -fn parse_mode(str_mode: &str) -> Result { - let default_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; +fn parse_mode(str_mode: &str) -> Result { + let default_mode = MODE_RW_UGO; uucore::mode::parse_chmod(default_mode, str_mode, true, uucore::mode::get_umask()) .map_err(|e| { translate!( @@ -247,7 +250,7 @@ fn parse_mode(str_mode: &str) -> Result { if mode > 0o777 { Err(translate!("mknod-error-mode-permission-bits-only")) } else { - Ok(mode as mode_t) + Ok(mode) } }) } From 42dd2a194dafae9abf578446a66544f1c9efcc40 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 9 Jan 2026 19:29:11 +0900 Subject: [PATCH 02/20] refactor(mknod): make FileType enum private Changed the visibility of the FileType enum from public to private to encapsulate internal types and improve module encapsulation. --- src/uu/mknod/src/mknod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 6a2149e9597..3428032d38b 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -26,7 +26,7 @@ mod options { } #[derive(Clone, PartialEq)] -pub enum FileType { +enum FileType { Block, Character, Fifo, From b64dd7a27ef7ec5296d4e989f0cdf4257de5d313 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 9 Jan 2026 19:35:21 +0900 Subject: [PATCH 03/20] refactor(mknod): make Config struct private Remove the 'pub' visibility modifier from the Config struct to encapsulate it within the module, preventing external access and improving code organization. This change aligns with best practices for internal data structures that should not be part of the public API. --- src/uu/mknod/src/mknod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 3428032d38b..7bbfac3a36d 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -43,7 +43,7 @@ impl FileType { } /// Configuration for special inode creation. -pub struct Config<'a> { +struct Config<'a> { /// Permission bits for the inode pub mode: Mode, From 9d9ebe7ea7587557c17f464ad60398c49d29c34f Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 9 Jan 2026 19:42:46 +0900 Subject: [PATCH 04/20] refactor: conditionally compile SELinux/SMACK security context features Add #[cfg(any(feature = "selinux", feature = "smack"))] attributes to Config struct fields and related code in uumain() to make SELinux/SMACK support optional, preventing compilation errors when these features are disabled. This improves build flexibility without affecting core mknod functionality. --- src/uu/mknod/src/mknod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 7bbfac3a36d..1fd820fecb8 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -55,9 +55,11 @@ struct Config<'a> { pub dev: u64, /// Set security context (SELinux/SMACK). + #[cfg(any(feature = "selinux", feature = "smack"))] pub set_security_context: bool, /// Specific security context (SELinux/SMACK). + #[cfg(any(feature = "selinux", feature = "smack"))] pub context: Option<&'a String>, } @@ -140,7 +142,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .expect("Missing argument 'NAME'"); // Extract the security context related flags and options + #[cfg(any(feature = "selinux", feature = "smack"))] let set_security_context = matches.get_flag(options::SECURITY_CONTEXT); + #[cfg(any(feature = "selinux", feature = "smack"))] let context = matches.get_one::(options::CONTEXT); let dev = match ( @@ -169,7 +173,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { file_type: file_type.clone(), use_umask, dev, + #[cfg(any(feature = "selinux", feature = "smack"))] set_security_context: set_security_context || context.is_some(), + #[cfg(any(feature = "selinux", feature = "smack"))] context, }; From 558a12b7674f991d25ba41e8a08e9be64f3cbd3c Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 9 Jan 2026 19:49:54 +0900 Subject: [PATCH 05/20] refactor(mknod): remove lifetime from Config and own context field - Changed `struct Config<'a>` to `struct Config` to eliminate lifetime parameter - Updated `context` field from `Option<&'a String>` to `Option` for ownership - Modified function calls to use `config.context.as_ref()` for borrowing - Added `.cloned()` when retrieving context from arguments to own the value This resolves lifetime issues and simplifies the code by avoiding references in the struct. --- src/uu/mknod/src/mknod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 1fd820fecb8..27d85254dd5 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -43,7 +43,7 @@ impl FileType { } /// Configuration for special inode creation. -struct Config<'a> { +struct Config { /// Permission bits for the inode pub mode: Mode, @@ -60,7 +60,7 @@ struct Config<'a> { /// Specific security context (SELinux/SMACK). #[cfg(any(feature = "selinux", feature = "smack"))] - pub context: Option<&'a String>, + pub context: Option, } fn mknod(file_name: &str, config: Config) -> i32 { @@ -98,7 +98,7 @@ fn mknod(file_name: &str, config: Config) -> i32 { if config.set_security_context { if let Err(e) = uucore::selinux::set_selinux_security_context( std::path::Path::new(file_name), - config.context, + config.context.as_ref(), ) { // if it fails, delete the file let _ = std::fs::remove_dir(file_name); @@ -110,9 +110,13 @@ fn mknod(file_name: &str, config: Config) -> i32 { // Apply SMACK context if requested #[cfg(feature = "smack")] if config.set_security_context { - if let Err(e) = uucore::smack::set_smack_label_and_cleanup(file_name, config.context, |p| { + if let Err(e) = uucore::smack::set_smack_label_and_cleanup( + file_name, + config.context.as_ref(), + |p| { std::fs::remove_file(p) - }) { + }, + ) { eprintln!("{}: {}", uucore::util_name(), e); return 1; } @@ -145,7 +149,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { #[cfg(any(feature = "selinux", feature = "smack"))] let set_security_context = matches.get_flag(options::SECURITY_CONTEXT); #[cfg(any(feature = "selinux", feature = "smack"))] - let context = matches.get_one::(options::CONTEXT); + let context = matches.get_one::(options::CONTEXT).cloned(); let dev = match ( file_type, From c88d1687610e0ccd63c96615cf7b620933a2c7a0 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 9 Jan 2026 19:50:55 +0900 Subject: [PATCH 06/20] refactor(mknod): format SMACK context setting for code consistency Reformatted the SMACK label setting block in mknod.rs to remove unnecessary line breaks and indentation, improving readability and aligning with the project's coding style guidelines. No functional changes were made. --- src/uu/mknod/src/mknod.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 27d85254dd5..47d64d189d7 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -110,13 +110,11 @@ fn mknod(file_name: &str, config: Config) -> i32 { // Apply SMACK context if requested #[cfg(feature = "smack")] if config.set_security_context { - if let Err(e) = uucore::smack::set_smack_label_and_cleanup( - file_name, - config.context.as_ref(), - |p| { - std::fs::remove_file(p) - }, - ) { + if let Err(e) = + uucore::smack::set_smack_label_and_cleanup(file_name, config.context.as_ref(), |p| { + std::fs::remove_file(p) + }) + { eprintln!("{}: {}", uucore::util_name(), e); return 1; } From 00bd60646704b418c1d9303aa291389f2b6394cf Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 10 Jan 2026 08:27:03 +0900 Subject: [PATCH 07/20] refactor(mknod): make Config struct fields private for better encapsulation Changed the visibility of all fields in the Config struct from public to private to improve encapsulation and prevent direct external access, promoting better code organization and maintainability. --- src/uu/mknod/src/mknod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 47d64d189d7..5a3107e17b5 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -45,22 +45,22 @@ impl FileType { /// Configuration for special inode creation. struct Config { /// Permission bits for the inode - pub mode: Mode, + mode: Mode, - pub file_type: FileType, + file_type: FileType, /// when false, the exact mode bits will be set - pub use_umask: bool, + use_umask: bool, - pub dev: u64, + dev: u64, /// Set security context (SELinux/SMACK). #[cfg(any(feature = "selinux", feature = "smack"))] - pub set_security_context: bool, + set_security_context: bool, /// Specific security context (SELinux/SMACK). #[cfg(any(feature = "selinux", feature = "smack"))] - pub context: Option, + context: Option, } fn mknod(file_name: &str, config: Config) -> i32 { From 8a84c01245da63a3b75b46a2e47d74421d25e456 Mon Sep 17 00:00:00 2001 From: mattsu Date: Tue, 13 Jan 2026 08:25:36 +0900 Subject: [PATCH 08/20] refactor(mknod): replace hardcoded permission mode with symbolic constants Replace MODE_RW_UGO constant from octal 0o666 to bitwise OR of S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH for improved readability and maintainability. Added necessary import from nix::libc. --- src/uu/mknod/src/mknod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 5a3107e17b5..32c3e3403de 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -6,6 +6,7 @@ // spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag use clap::{Arg, ArgAction, Command, value_parser}; +use nix::libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; use nix::sys::stat::{Mode, SFlag, mknod as nix_mknod, umask as nix_umask}; use uucore::display::Quotable; @@ -14,7 +15,7 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; -const MODE_RW_UGO: u32 = 0o666; +const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; mod options { pub const MODE: &str = "mode"; From 6f05b58eccab2ad7d08b21705e4d45e43d659f4b Mon Sep 17 00:00:00 2001 From: mattsu <35655889+mattsu2020@users.noreply.github.com> Date: Mon, 12 Jan 2026 09:35:07 +0900 Subject: [PATCH 09/20] Update src/uu/mknod/src/mknod.rs Co-authored-by: Sylvestre Ledru --- src/uu/mknod/src/mknod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 32c3e3403de..061143fa873 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag +// spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag use clap::{Arg, ArgAction, Command, value_parser}; use nix::libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; From ee17f72a860a3ad13fc1f004064262da04fba5ac Mon Sep 17 00:00:00 2001 From: mattsu Date: Tue, 13 Jan 2026 08:32:18 +0900 Subject: [PATCH 10/20] fix(mknod): add explicit u32 cast to MODE_RW_UGO constant Wrap the bitwise OR expression in parentheses and cast to u32 to ensure type consistency and resolve potential compilation issues. --- src/uu/mknod/src/mknod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 061143fa873..0d6697578f5 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -15,7 +15,8 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; -const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; +const MODE_RW_UGO: u32 = + (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; mod options { pub const MODE: &str = "mode"; From 62d4cacdc43ac90a7b01026fb73300778ee1040b Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 15 Jan 2026 18:44:24 +0900 Subject: [PATCH 11/20] style(mknod): condense MODE_RW_UGO constant to single line Reformat the MODE_RW_UGO constant declaration for consistency and to adhere to Rust formatting guidelines. --- src/uu/mknod/src/mknod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 0d6697578f5..2c10b7ce0c2 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -15,8 +15,7 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; -const MODE_RW_UGO: u32 = - (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; +const MODE_RW_UGO: u32 = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; mod options { pub const MODE: &str = "mode"; From 7234b43085842d71c56ffd62e18d387f2eaf64d7 Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 15 Jan 2026 19:08:29 +0900 Subject: [PATCH 12/20] refactor(mknod): remove redundant cast in MODE_RW_UGO constant The bitwise OR operation on the file permission flags already yields a u32 value, making the explicit cast unnecessary and improving code clarity. --- src/uu/mknod/src/mknod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 2c10b7ce0c2..061143fa873 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -15,7 +15,7 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; -const MODE_RW_UGO: u32 = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; +const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; mod options { pub const MODE: &str = "mode"; From 3125995db131a2a90c4300fc6c622af1e563c580 Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 15 Jan 2026 19:33:40 +0900 Subject: [PATCH 13/20] fix(mknod): cast mode constants to u32 on android, macos, freebsd, redox Ensure MODE_RW_UGO is explicitly typed as u32 on specified platforms to resolve compilation errors where the bitwise OR expression doesn't implicitly cast. This maintains consistent behavior across all supported operating systems. --- src/uu/mknod/src/mknod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 061143fa873..e3e5a4bd82c 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -15,8 +15,22 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; +#[cfg(not(any( + target_os = "android", + target_os = "macos", + target_os = "freebsd", + target_os = "redox", +)))] const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; +#[cfg(any( + target_os = "android", + target_os = "macos", + target_os = "freebsd", + target_os = "redox", +))] +const MODE_RW_UGO: u32 = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; + mod options { pub const MODE: &str = "mode"; pub const TYPE: &str = "type"; From 0ec12198027fcb8a990525955569bf7418294ea7 Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 17 Jan 2026 12:06:03 +0900 Subject: [PATCH 14/20] refactor(mknod): unify MODE_RW_UGO type using mode_t Remove conditional compilation based on target OS for the MODE_RW_UGO constant, changing it to use the standard libc mode_t type for better portability and type safety. Update usages in uumain and parse_mode to cast to u32 as required by the functions. --- src/uu/mknod/src/mknod.rs | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index e3e5a4bd82c..cfe4dfeb512 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -6,7 +6,7 @@ // spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag use clap::{Arg, ArgAction, Command, value_parser}; -use nix::libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; +use nix::libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; use nix::sys::stat::{Mode, SFlag, mknod as nix_mknod, umask as nix_umask}; use uucore::display::Quotable; @@ -15,21 +15,8 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; -#[cfg(not(any( - target_os = "android", - target_os = "macos", - target_os = "freebsd", - target_os = "redox", -)))] -const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - -#[cfg(any( - target_os = "android", - target_os = "macos", - target_os = "freebsd", - target_os = "redox", -))] -const MODE_RW_UGO: u32 = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; +const MODE_RW_UGO: mode_t = + (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as mode_t; mod options { pub const MODE: &str = "mode"; @@ -146,7 +133,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let mut use_umask = true; let mode_permissions = match matches.get_one::("mode") { - None => MODE_RW_UGO, + None => MODE_RW_UGO as u32, Some(str_mode) => { use_umask = false; parse_mode(str_mode).map_err(|e| USimpleError::new(1, e))? @@ -261,7 +248,7 @@ pub fn uu_app() -> Command { #[allow(clippy::unnecessary_cast)] fn parse_mode(str_mode: &str) -> Result { - let default_mode = MODE_RW_UGO; + let default_mode = MODE_RW_UGO as u32; uucore::mode::parse_chmod(default_mode, str_mode, true, uucore::mode::get_umask()) .map_err(|e| { translate!( From 2afc561a4c5d248d5884837229f060671b9b0723 Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 17 Jan 2026 12:07:11 +0900 Subject: [PATCH 15/20] refactor(mknod): reorder libc imports and condense constant declaration - Moved `mode_t` to the end of the import list for consistency - Inlined the `MODE_RW_UGO` constant definition to a single line for brevity - No functional changes, improves code readability and style --- src/uu/mknod/src/mknod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index cfe4dfeb512..2b0f0dfd393 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -6,7 +6,7 @@ // spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag use clap::{Arg, ArgAction, Command, value_parser}; -use nix::libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; +use nix::libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, mode_t}; use nix::sys::stat::{Mode, SFlag, mknod as nix_mknod, umask as nix_umask}; use uucore::display::Quotable; @@ -15,8 +15,7 @@ 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) as mode_t; +const MODE_RW_UGO: mode_t = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as mode_t; mod options { pub const MODE: &str = "mode"; From 7a52edcbdcb483e9eb4dac62e31e28da9cb0852f Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 17 Jan 2026 12:18:18 +0900 Subject: [PATCH 16/20] refactor(mknod): replace unnecessary casts with u32::from for MODE_RW_UGO Replace `as u32` casts with `u32::from()` to fix clippy::unnecessary_cast lint warnings, improving code clarity and adhering to Rust best practices. This affects default mode handling in mknod utility. --- src/uu/mknod/src/mknod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 2b0f0dfd393..e9eac5351a0 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -132,7 +132,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let mut use_umask = true; let mode_permissions = match matches.get_one::("mode") { - None => MODE_RW_UGO as u32, + None => u32::from(MODE_RW_UGO), Some(str_mode) => { use_umask = false; parse_mode(str_mode).map_err(|e| USimpleError::new(1, e))? @@ -247,7 +247,7 @@ pub fn uu_app() -> Command { #[allow(clippy::unnecessary_cast)] fn parse_mode(str_mode: &str) -> Result { - let default_mode = MODE_RW_UGO as u32; + let default_mode = u32::from(MODE_RW_UGO); uucore::mode::parse_chmod(default_mode, str_mode, true, uucore::mode::get_umask()) .map_err(|e| { translate!( From c66ddfd72e22d602ff4626241c98752469f3aff3 Mon Sep 17 00:00:00 2001 From: mattsu Date: Mon, 19 Jan 2026 20:18:24 +0900 Subject: [PATCH 17/20] refactor: remove unnecessary u32::from() casts for MODE_RW_UGO in mknod MODE_RW_UGO is already a u32 constant, so explicit casting is redundant and can be safely removed to clean up the code. This change affects the default mode handling in uumain and the parse_mode function. --- src/uu/mknod/src/mknod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index e9eac5351a0..dd5b771edc7 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -132,7 +132,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let mut use_umask = true; let mode_permissions = match matches.get_one::("mode") { - None => u32::from(MODE_RW_UGO), + None => MODE_RW_UGO, Some(str_mode) => { use_umask = false; parse_mode(str_mode).map_err(|e| USimpleError::new(1, e))? @@ -247,7 +247,7 @@ pub fn uu_app() -> Command { #[allow(clippy::unnecessary_cast)] fn parse_mode(str_mode: &str) -> Result { - let default_mode = u32::from(MODE_RW_UGO); + let default_mode = MODE_RW_UGO; uucore::mode::parse_chmod(default_mode, str_mode, true, uucore::mode::get_umask()) .map_err(|e| { translate!( From 554ba40de668a918c5c447d72b9f4f8f4ee238df Mon Sep 17 00:00:00 2001 From: mattsu Date: Mon, 19 Jan 2026 20:29:40 +0900 Subject: [PATCH 18/20] fix(mknod): adjust MODE_RW_UGO type for cross-platform compatibility Refactor MODE_RW_UGO constant to use u32 instead of mode_t, with conditional compilation for android, macos, freebsd, and redox to avoid type casting issues. Also remove nix::libc::mode_t cast in mode creation to ensure consistent behavior across platforms. --- src/uu/mknod/src/mknod.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index dd5b771edc7..6912e148c78 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -15,7 +15,22 @@ 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) as mode_t; +#[cfg(not(any( + target_os = "android", + target_os = "macos", + target_os = "freebsd", + target_os = "redox", +)))] +const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + +#[cfg(any( + target_os = "android", + target_os = "macos", + target_os = "freebsd", + target_os = "redox", +))] +const MODE_RW_UGO: u32 = + (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; mod options { pub const MODE: &str = "mode"; @@ -138,7 +153,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { parse_mode(str_mode).map_err(|e| USimpleError::new(1, e))? } }; - let mode = Mode::from_bits_truncate(mode_permissions as nix::libc::mode_t); + let mode = Mode::from_bits_truncate(mode_permissions as mode_t); let file_name = matches .get_one::("name") From 44ebb42b13f5794002010f72546afd14adec92e6 Mon Sep 17 00:00:00 2001 From: mattsu Date: Mon, 19 Jan 2026 21:07:38 +0900 Subject: [PATCH 19/20] refactor(mknod): condense MODE_RW_UGO constant to single line This change improves code consistency by reformatting the constant definition under the `cfg` attribute to match the style of the preceding constant, placing it on a single line for better readability. --- src/uu/mknod/src/mknod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 6912e148c78..824594e7041 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -29,8 +29,7 @@ const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWO target_os = "freebsd", target_os = "redox", ))] -const MODE_RW_UGO: u32 = - (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; +const MODE_RW_UGO: u32 = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; mod options { pub const MODE: &str = "mode"; From cbff4d8289d557229d0dcf8dc8cb77327d850a74 Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 14 Feb 2026 20:08:23 +0900 Subject: [PATCH 20/20] fix(mknod): correct file removal and error handling Fixed incorrect file removal function call from `remove_dir` to `remove_file` when mknod fails, and updated error message formatting to use modern string interpolation syntax. --- src/uu/mknod/src/mknod.rs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 824594e7041..9b6ab45f648 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -15,20 +15,7 @@ use uucore::format_usage; use uucore::fs::makedev; use uucore::translate; -#[cfg(not(any( - target_os = "android", - target_os = "macos", - target_os = "freebsd", - target_os = "redox", -)))] -const MODE_RW_UGO: u32 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - -#[cfg(any( - target_os = "android", - target_os = "macos", - target_os = "freebsd", - target_os = "redox", -))] +#[allow(clippy::unnecessary_cast)] const MODE_RW_UGO: u32 = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) as u32; mod options { @@ -116,8 +103,8 @@ fn mknod(file_name: &str, config: Config) -> i32 { config.context.as_ref(), ) { // if it fails, delete the file - let _ = std::fs::remove_dir(file_name); - eprintln!("{}: {}", uucore::util_name(), e); + let _ = std::fs::remove_file(file_name); + eprintln!("{}: {e}", uucore::util_name()); return 1; } } @@ -130,7 +117,7 @@ fn mknod(file_name: &str, config: Config) -> i32 { std::fs::remove_file(p) }) { - eprintln!("{}: {}", uucore::util_name(), e); + eprintln!("{}: {e}", uucore::util_name()); return 1; } } @@ -259,7 +246,6 @@ pub fn uu_app() -> Command { ) } -#[allow(clippy::unnecessary_cast)] fn parse_mode(str_mode: &str) -> Result { let default_mode = MODE_RW_UGO; uucore::mode::parse_chmod(default_mode, str_mode, true, uucore::mode::get_umask())