diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 1343501bb..98404f89f 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -7,8 +7,6 @@ // spell-checker:ignore (ToDO) parsemode makedev sysmacros makenod newmode perror IFBLK IFCHR IFIFO -mod parsemode; - #[macro_use] extern crate uucore; @@ -98,7 +96,7 @@ for details about the options it supports.", let mut last_umask: mode_t = 0; let mut newmode: mode_t = MODE_RW_UGO; if matches.opt_present("mode") { - match parsemode::parse_mode(matches.opt_str("mode")) { + match uucore::mode::parse_mode(matches.opt_str("mode")) { Ok(parsed) => { if parsed > 0o777 { show_info!("mode must specify only file permission bits"); diff --git a/src/uu/mknod/src/parsemode.rs b/src/uu/mknod/src/parsemode.rs deleted file mode 100644 index 8f8f9af61..000000000 --- a/src/uu/mknod/src/parsemode.rs +++ /dev/null @@ -1,58 +0,0 @@ -// spell-checker:ignore (ToDO) fperm - -use libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; - -use uucore::mode; - -pub fn parse_mode(mode: Option) -> Result { - let fperm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - if let Some(mode) = mode { - let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; - let result = if mode.contains(arr) { - mode::parse_numeric(fperm as u32, mode.as_str()) - } else { - mode::parse_symbolic(fperm as u32, mode.as_str(), true) - }; - result.map(|mode| mode as mode_t) - } else { - Ok(fperm) - } -} - -#[cfg(test)] -mod test { - /// Test if the program is running under WSL - // ref: @@ - // ToDO: test on WSL2 which likely doesn't need special handling; plan change to `is_wsl_1()` if WSL2 is less needy - pub fn is_wsl() -> bool { - #[cfg(target_os = "linux")] - { - if let Ok(b) = std::fs::read("/proc/sys/kernel/osrelease") { - if let Ok(s) = std::str::from_utf8(&b) { - let a = s.to_ascii_lowercase(); - return a.contains("microsoft") || a.contains("wsl"); - } - } - } - false - } - - #[test] - fn symbolic_modes() { - assert_eq!(super::parse_mode(Some("u+x".to_owned())).unwrap(), 0o766); - assert_eq!( - super::parse_mode(Some("+x".to_owned())).unwrap(), - if !is_wsl() { 0o777 } else { 0o776 } - ); - assert_eq!(super::parse_mode(Some("a-w".to_owned())).unwrap(), 0o444); - assert_eq!(super::parse_mode(Some("g-r".to_owned())).unwrap(), 0o626); - } - - #[test] - fn numeric_modes() { - assert_eq!(super::parse_mode(Some("644".to_owned())).unwrap(), 0o644); - assert_eq!(super::parse_mode(Some("+100".to_owned())).unwrap(), 0o766); - assert_eq!(super::parse_mode(Some("-4".to_owned())).unwrap(), 0o662); - assert_eq!(super::parse_mode(None).unwrap(), 0o666); - } -} diff --git a/src/uucore/src/lib/features/mode.rs b/src/uucore/src/lib/features/mode.rs index 8b5e71799..1bb79ac03 100644 --- a/src/uucore/src/lib/features/mode.rs +++ b/src/uucore/src/lib/features/mode.rs @@ -7,6 +7,8 @@ // spell-checker:ignore (vars) fperm srwx +use libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; + pub fn parse_numeric(fperm: u32, mut mode: &str) -> Result { let (op, pos) = parse_op(mode, Some('='))?; mode = mode[pos..].trim().trim_start_matches('0'); @@ -129,3 +131,41 @@ fn parse_change(mode: &str, fperm: u32, considering_dir: bool) -> (u32, usize) { } (srwx, pos) } + +pub fn parse_mode(mode: Option) -> Result { + let fperm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + if let Some(mode) = mode { + let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; + let result = if mode.contains(arr) { + parse_numeric(fperm as u32, mode.as_str()) + } else { + parse_symbolic(fperm as u32, mode.as_str(), true) + }; + result.map(|mode| mode as mode_t) + } else { + Ok(fperm) + } +} + +#[cfg(test)] +mod test { + + #[test] + fn symbolic_modes() { + assert_eq!(super::parse_mode(Some("u+x".to_owned())).unwrap(), 0o766); + assert_eq!( + super::parse_mode(Some("+x".to_owned())).unwrap(), + if !crate::os::is_wsl_1() { 0o777 } else { 0o776 } + ); + assert_eq!(super::parse_mode(Some("a-w".to_owned())).unwrap(), 0o444); + assert_eq!(super::parse_mode(Some("g-r".to_owned())).unwrap(), 0o626); + } + + #[test] + fn numeric_modes() { + assert_eq!(super::parse_mode(Some("644".to_owned())).unwrap(), 0o644); + assert_eq!(super::parse_mode(Some("+100".to_owned())).unwrap(), 0o766); + assert_eq!(super::parse_mode(Some("-4".to_owned())).unwrap(), 0o662); + assert_eq!(super::parse_mode(None).unwrap(), 0o666); + } +} diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 324095b6a..208e9536c 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -26,6 +26,7 @@ mod mods; // core cross-platform modules // * cross-platform modules pub use crate::mods::coreopts; +pub use crate::mods::os; pub use crate::mods::panic; pub use crate::mods::ranges; diff --git a/src/uucore/src/lib/mods.rs b/src/uucore/src/lib/mods.rs index c73909dcc..74725e141 100644 --- a/src/uucore/src/lib/mods.rs +++ b/src/uucore/src/lib/mods.rs @@ -1,5 +1,6 @@ // mods ~ cross-platforms modules (core/bundler file) pub mod coreopts; +pub mod os; pub mod panic; pub mod ranges; diff --git a/src/uucore/src/lib/mods/os.rs b/src/uucore/src/lib/mods/os.rs new file mode 100644 index 000000000..da2002161 --- /dev/null +++ b/src/uucore/src/lib/mods/os.rs @@ -0,0 +1,30 @@ +/// Test if the program is running under WSL +// ref: @@ +pub fn is_wsl_1() -> bool { + #[cfg(target_os = "linux")] + { + if is_wsl_2() { + return false; + } + if let Ok(b) = std::fs::read("/proc/sys/kernel/osrelease") { + if let Ok(s) = std::str::from_utf8(&b) { + let a = s.to_ascii_lowercase(); + return a.contains("microsoft") || a.contains("wsl"); + } + } + } + false +} + +pub fn is_wsl_2() -> bool { + #[cfg(target_os = "linux")] + { + if let Ok(b) = std::fs::read("/proc/sys/kernel/osrelease") { + if let Ok(s) = std::str::from_utf8(&b) { + let a = s.to_ascii_lowercase(); + return a.contains("wsl2"); + } + } + } + false +} diff --git a/tests/by-util/test_chgrp.rs b/tests/by-util/test_chgrp.rs index 343b336a6..a7848b1b6 100644 --- a/tests/by-util/test_chgrp.rs +++ b/tests/by-util/test_chgrp.rs @@ -104,7 +104,7 @@ fn test_reference() { // skip for root or MS-WSL // * MS-WSL is bugged (as of 2019-12-25), allowing non-root accounts su-level privileges for `chgrp` // * for MS-WSL, succeeds and stdout == 'group of /etc retained as root' - if !(get_effective_gid() == 0 || is_wsl()) { + if !(get_effective_gid() == 0 || uucore::os::is_wsl_1()) { new_ucmd!() .arg("-v") .arg("--reference=/etc/passwd") diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index 0c66c563e..0ca0a74ea 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -128,7 +128,7 @@ fn test_date_set_invalid() { #[test] #[cfg(all(unix, not(target_os = "macos")))] fn test_date_set_permissions_error() { - if !(get_effective_uid() == 0 || is_wsl()) { + if !(get_effective_uid() == 0 || uucore::os::is_wsl_1()) { let result = new_ucmd!() .arg("--set") .arg("2020-03-11 21:45:00+08:00") diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 45704eb41..111f2dc90 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -56,7 +56,7 @@ fn _du_basics_subdir(s: &str) { #[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))] fn _du_basics_subdir(s: &str) { // MS-WSL linux has altered expected output - if !is_wsl() { + if !uucore::os::is_wsl_1() { assert_eq!(s, "8\tsubdir/deeper\n"); } else { assert_eq!(s, "0\tsubdir/deeper\n"); @@ -103,7 +103,7 @@ fn _du_soft_link(s: &str) { #[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))] fn _du_soft_link(s: &str) { // MS-WSL linux has altered expected output - if !is_wsl() { + if !uucore::os::is_wsl_1() { assert_eq!(s, "16\tsubdir/links\n"); } else { assert_eq!(s, "8\tsubdir/links\n"); @@ -144,7 +144,7 @@ fn _du_hard_link(s: &str) { #[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))] fn _du_hard_link(s: &str) { // MS-WSL linux has altered expected output - if !is_wsl() { + if !uucore::os::is_wsl_1() { assert_eq!(s, "16\tsubdir/links\n"); } else { assert_eq!(s, "8\tsubdir/links\n"); @@ -184,7 +184,7 @@ fn _du_d_flag(s: &str) { #[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))] fn _du_d_flag(s: &str) { // MS-WSL linux has altered expected output - if !is_wsl() { + if !uucore::os::is_wsl_1() { assert_eq!(s, "28\t./subdir\n36\t./\n"); } else { assert_eq!(s, "8\t./subdir\n8\t./\n"); diff --git a/tests/by-util/test_logname.rs b/tests/by-util/test_logname.rs index 8d1996e63..bd9d04a50 100644 --- a/tests/by-util/test_logname.rs +++ b/tests/by-util/test_logname.rs @@ -9,7 +9,7 @@ fn test_normal() { for (key, value) in env::vars() { println!("{}: {}", key, value); } - if (is_ci() || is_wsl()) && result.stderr_str().contains("error: no login name") { + if (is_ci() || uucore::os::is_wsl_1()) && result.stderr_str().contains("error: no login name") { // ToDO: investigate WSL failure // In the CI, some server are failing to return logname. // As seems to be a configuration issue, ignoring it diff --git a/tests/common/util.rs b/tests/common/util.rs index af3b6f1eb..29b8a4633 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -42,22 +42,6 @@ pub fn is_ci() -> bool { .eq_ignore_ascii_case("true") } -/// Test if the program is running under WSL -// ref: @@ -// ToDO: test on WSL2 which likely doesn't need special handling; plan change to `is_wsl_1()` if WSL2 is less needy -pub fn is_wsl() -> bool { - #[cfg(target_os = "linux")] - { - if let Ok(b) = std::fs::read("/proc/sys/kernel/osrelease") { - if let Ok(s) = std::str::from_utf8(&b) { - let a = s.to_ascii_lowercase(); - return a.contains("microsoft") || a.contains("wsl"); - } - } - } - false -} - /// Read a test scenario fixture, returning its bytes fn read_scenario_fixture>(tmpd: &Option>, file_rel_path: S) -> Vec { let tmpdir_path = tmpd.as_ref().unwrap().as_ref().path();