From da198dbb197c436e65d3c108ff9b9a53a2031338 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 19 Sep 2021 22:24:11 +0200 Subject: [PATCH 001/111] tests/util: add a convenience wrapper to run a ucmd with root permissions --- tests/common/util.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tests/common/util.rs b/tests/common/util.rs index f3cdec010..a7c6e464d 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1237,6 +1237,58 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< )) } +/// This is a convenience wrapper to run a ucmd with root permissions. +/// This runs 'sudo -E --non-interactive target/debug/coreutils util_name args` +/// This is primarily designed to run in the CICD environment where whoami is in $path +/// and where non-interactive sudo is possible. +/// To check if i) non-interactive sudo is possible and ii) if sudo works, this runs: +/// 'sudo -E --non-interactive whoami' first. +/// +/// Example: +/// +/// ```no_run +/// use crate::common::util::*; +/// #[test] +/// fn test_xyz() { +/// let ts = TestScenario::new("whoami"); +/// let expected = "root\n".to_string(); +/// if let Ok(result) = run_ucmd_as_root(&ts, &[]) { +/// result.stdout_is(expected); +/// } else { +/// print!("TEST SKIPPED"); +/// } +/// } +///``` +#[cfg(unix)] +pub fn run_ucmd_as_root( + ts: &TestScenario, + args: &[&str], +) -> std::result::Result { + if ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg("whoami") + .run() + .stdout_str() + .trim() + != "root" + { + Err("\"sudo whoami\" didn't return \"root\"".to_string()) + } else { + Ok(ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg(&ts.bin_path) + .arg(&ts.util_name) + .args(args) + .run()) + } +} + /// Sanity checks for test utils #[cfg(test)] mod tests { @@ -1523,4 +1575,20 @@ mod tests { std::assert_eq!(host_name_for("gwho"), "gwho"); } } + + #[test] + #[cfg(unix)] + fn test_run_ucmd_as_root() { + // We need non-interactive `sudo. + // CICD environment should allow non-interactive `sudo`. + // Return early if we can't guarantee non-interactive `sudo` + if !is_ci() { + return; + } + let ts = TestScenario::new("whoami"); + std::assert_eq!( + run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), + "root" + ); + } } From 4ef77232486f0c7e9a6b8e0ad88a966f96b79f6d Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Mon, 20 Sep 2021 00:20:06 +0200 Subject: [PATCH 002/111] Update util.rs add feature for `whoami` --- tests/common/util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/common/util.rs b/tests/common/util.rs index a7c6e464d..f056f3510 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1578,6 +1578,7 @@ mod tests { #[test] #[cfg(unix)] + #[cfg(feature = "whoami")] fn test_run_ucmd_as_root() { // We need non-interactive `sudo. // CICD environment should allow non-interactive `sudo`. From 1ccf55a3dc611c5de46b9fe8a479dc6d42c67d6d Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Tue, 21 Sep 2021 00:23:23 +0200 Subject: [PATCH 003/111] Update util.rs --- tests/common/util.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/common/util.rs b/tests/common/util.rs index f056f3510..928bc84f3 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1239,7 +1239,7 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< /// This is a convenience wrapper to run a ucmd with root permissions. /// This runs 'sudo -E --non-interactive target/debug/coreutils util_name args` -/// This is primarily designed to run in the CICD environment where whoami is in $path +/// This is primarily designed to run in an environment where whoami is in $path /// and where non-interactive sudo is possible. /// To check if i) non-interactive sudo is possible and ii) if sudo works, this runs: /// 'sudo -E --non-interactive whoami' first. @@ -1264,6 +1264,7 @@ pub fn run_ucmd_as_root( ts: &TestScenario, args: &[&str], ) -> std::result::Result { + // Apparently CICD environment has no `sudo`? if ts .cmd_keepenv("sudo") .env("LC_ALL", "C") @@ -1580,16 +1581,18 @@ mod tests { #[cfg(unix)] #[cfg(feature = "whoami")] fn test_run_ucmd_as_root() { - // We need non-interactive `sudo. - // CICD environment should allow non-interactive `sudo`. - // Return early if we can't guarantee non-interactive `sudo` - if !is_ci() { - return; + // Skip test if we can't guarantee non-interactive `sudo`. + if let Ok(_status) = Command::new("sudo") + .args(&["-E", "-v", "--non-interactive"]) + .status() + { + let ts = TestScenario::new("whoami"); + std::assert_eq!( + run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), + "root" + ); + } else { + print!("TEST SKIPPED"); } - let ts = TestScenario::new("whoami"); - std::assert_eq!( - run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), - "root" - ); } } From 8d1e340d803d98c706768a2b05551a1dfe0e4fc1 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 21 Apr 2022 15:24:52 +0200 Subject: [PATCH 004/111] df: remove unreachable code --- src/uu/df/src/df.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index b4f3457c4..8a4791422 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -382,12 +382,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } }; - // This can happen if paths are given as command-line arguments - // but none of the paths exist. - if filesystems.is_empty() { - return Ok(()); - } - println!("{}", Table::new(&opt, filesystems)); Ok(()) From 2d4552cce49ba51c5f90035934fc77ec765b05ed Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 15 Apr 2022 08:05:24 +0200 Subject: [PATCH 005/111] df: respect -t arg when specific file is provided Fixes #3325 --- src/uu/df/src/df.rs | 36 ++++++++++++++++++++++-------------- tests/by-util/test_df.rs | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index b4f3457c4..2b9c929c7 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -292,7 +292,7 @@ fn get_all_filesystems(opt: &Options) -> Vec { } /// For each path, get the filesystem that contains that path. -fn get_named_filesystems

(paths: &[P]) -> Vec +fn get_named_filesystems

(paths: &[P], opt: &Options) -> Vec where P: AsRef, { @@ -302,21 +302,35 @@ where // considered. The "lofs" filesystem is a loopback // filesystem present on Solaris and FreeBSD systems. It // is similar to a symbolic link. - let mounts: Vec = read_fs_list() + let mounts: Vec = filter_mount_list(read_fs_list(), opt) .into_iter() .filter(|mi| mi.fs_type != "lofs" && !mi.dummy) .collect(); + let mut result = vec![]; + + // this happens if the file system type doesn't exist + if mounts.is_empty() { + show!(USimpleError::new(1, "no file systems processed")); + return result; + } + // Convert each path into a `Filesystem`, which contains // both the mount information and usage information. - let mut result = vec![]; for path in paths { match Filesystem::from_path(&mounts, path) { Some(fs) => result.push(fs), - None => show!(USimpleError::new( - 1, - format!("{}: No such file or directory", path.as_ref().display()) - )), + None => { + // this happens if specified file system type != file system type of the file + if path.as_ref().exists() { + show!(USimpleError::new(1, "no file systems processed")); + } else { + show!(USimpleError::new( + 1, + format!("{}: No such file or directory", path.as_ref().display()) + )); + } + } } } result @@ -370,7 +384,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } Some(paths) => { let paths: Vec<&str> = paths.collect(); - let filesystems = get_named_filesystems(&paths); + let filesystems = get_named_filesystems(&paths, &opt); // This can happen if paths are given as command-line arguments // but none of the paths exist. @@ -382,12 +396,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } }; - // This can happen if paths are given as command-line arguments - // but none of the paths exist. - if filesystems.is_empty() { - return Ok(()); - } - println!("{}", Table::new(&opt, filesystems)); Ok(()) diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 3de3c677b..54c41e229 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -199,7 +199,42 @@ fn test_type_option() { new_ucmd!() .args(&["-t", fs_type, "-t", "nonexisting"]) .succeeds(); - new_ucmd!().args(&["-t", "nonexisting"]).fails(); + new_ucmd!() + .args(&["-t", "nonexisting"]) + .fails() + .stderr_contains("no file systems processed"); +} + +#[test] +fn test_type_option_with_file() { + let fs_type = new_ucmd!() + .args(&["--output=fstype", "."]) + .succeeds() + .stdout_move_str(); + let fs_type = fs_type.lines().nth(1).unwrap().trim(); + + new_ucmd!().args(&["-t", fs_type, "."]).succeeds(); + new_ucmd!() + .args(&["-t", "nonexisting", "."]) + .fails() + .stderr_contains("no file systems processed"); + + let fs_types = new_ucmd!() + .arg("--output=fstype") + .succeeds() + .stdout_move_str(); + let fs_types: Vec<_> = fs_types + .lines() + .skip(1) + .filter(|t| t.trim() != fs_type && t.trim() != "") + .collect(); + + if !fs_types.is_empty() { + new_ucmd!() + .args(&["-t", fs_types[0], "."]) + .fails() + .stderr_contains("no file systems processed"); + } } #[test] From 78dc90124ed44437abe17a52b81eb3e4be6f26e1 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Sat, 23 Apr 2022 16:56:06 +0200 Subject: [PATCH 006/111] df: simplify get_header() in test_block_size_1024 --- tests/by-util/test_df.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 54c41e229..0f47b8dbf 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -378,19 +378,11 @@ fn test_iuse_percentage() { #[test] fn test_block_size_1024() { fn get_header(block_size: u64) -> String { - // TODO When #3057 is resolved, we should just use - // - // new_ucmd!().arg("--output=size").succeeds().stdout_move_str(); - // - // instead of parsing the entire `df` table as a string. let output = new_ucmd!() - .args(&["-B", &format!("{}", block_size)]) + .args(&["-B", &format!("{}", block_size), "--output=size"]) .succeeds() .stdout_move_str(); - let first_line = output.lines().next().unwrap(); - let mut column_labels = first_line.split_whitespace(); - let size_column_label = column_labels.nth(1).unwrap(); - size_column_label.into() + output.lines().next().unwrap().to_string() } assert_eq!(get_header(1024), "1K-blocks"); From 0f13de4e1a4aa073e2afc810b74bb57868b21e91 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Sat, 23 Apr 2022 16:44:48 +0200 Subject: [PATCH 007/111] df: allow sizes with a suffix for --block-size Fixes #3416 --- src/uu/df/src/blocks.rs | 7 ++++--- tests/by-util/test_df.rs | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index 0943c9447..7783e5636 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -6,7 +6,8 @@ use crate::{OPT_BLOCKSIZE, OPT_HUMAN_READABLE_BINARY, OPT_HUMAN_READABLE_DECIMAL}; use clap::ArgMatches; use std::fmt; -use std::num::ParseIntError; + +use uucore::parse_size::{parse_size, ParseSizeError}; /// The first ten powers of 1024. const IEC_BASES: [u128; 10] = [ @@ -107,14 +108,14 @@ impl Default for BlockSize { } } -pub(crate) fn block_size_from_matches(matches: &ArgMatches) -> Result { +pub(crate) fn block_size_from_matches(matches: &ArgMatches) -> Result { if matches.is_present(OPT_HUMAN_READABLE_BINARY) { Ok(BlockSize::HumanReadableBinary) } else if matches.is_present(OPT_HUMAN_READABLE_DECIMAL) { Ok(BlockSize::HumanReadableDecimal) } else if matches.is_present(OPT_BLOCKSIZE) { let s = matches.value_of(OPT_BLOCKSIZE).unwrap(); - Ok(BlockSize::Bytes(s.parse()?)) + Ok(BlockSize::Bytes(parse_size(s)?)) } else { Ok(Default::default()) } diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 0f47b8dbf..31432f700 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -394,6 +394,31 @@ fn test_block_size_1024() { assert_eq!(get_header(34 * 1024 * 1024 * 1024), "34G-blocks"); } +#[test] +fn test_block_size_with_suffix() { + fn get_header(block_size: &str) -> String { + let output = new_ucmd!() + .args(&["-B", block_size, "--output=size"]) + .succeeds() + .stdout_move_str(); + output.lines().next().unwrap().to_string() + } + + assert_eq!(get_header("K"), "1K-blocks"); + assert_eq!(get_header("M"), "1M-blocks"); + assert_eq!(get_header("G"), "1G-blocks"); + assert_eq!(get_header("1K"), "1K-blocks"); + assert_eq!(get_header("1M"), "1M-blocks"); + assert_eq!(get_header("1G"), "1G-blocks"); + assert_eq!(get_header("1KiB"), "1K-blocks"); + assert_eq!(get_header("1MiB"), "1M-blocks"); + assert_eq!(get_header("1GiB"), "1G-blocks"); + // TODO enable the following asserts when #3193 is resolved + //assert_eq!(get_header("1KB"), "1kB-blocks"); + //assert_eq!(get_header("1MB"), "1MB-blocks"); + //assert_eq!(get_header("1GB"), "1GB-blocks"); +} + #[test] fn test_output_selects_columns() { let output = new_ucmd!() From 181ebd3996f17acb7ff446b2e2fb5d1a3fa28fcb Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 24 Apr 2022 20:39:39 +0200 Subject: [PATCH 008/111] Revert "df: remove trailing spaces in rightmost column" --- src/uu/df/src/table.rs | 13 ++----------- tests/by-util/test_df.rs | 8 ++++---- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/uu/df/src/table.rs b/src/uu/df/src/table.rs index abac3b549..6b64ce02c 100644 --- a/src/uu/df/src/table.rs +++ b/src/uu/df/src/table.rs @@ -401,21 +401,12 @@ impl fmt::Display for Table { while let Some(row) = row_iter.next() { let mut col_iter = row.iter().enumerate().peekable(); while let Some((i, elem)) = col_iter.next() { - let is_last_col = col_iter.peek().is_none(); - match self.alignments[i] { - Alignment::Left => { - if is_last_col { - // no trailing spaces in last column - write!(f, "{}", elem)?; - } else { - write!(f, "{: write!(f, "{: write!(f, "{:>width$}", elem, width = self.widths[i])?, } - if !is_last_col { + if col_iter.peek().is_some() { // column separator write!(f, " ")?; } diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 31432f700..61ddcec5d 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -425,7 +425,7 @@ fn test_output_selects_columns() { .args(&["--output=source"]) .succeeds() .stdout_move_str(); - assert_eq!(output.lines().next().unwrap(), "Filesystem"); + assert_eq!(output.lines().next().unwrap().trim_end(), "Filesystem"); let output = new_ucmd!() .args(&["--output=source,target"]) @@ -484,7 +484,7 @@ fn test_output_file_all_filesystems() { let mut lines = output.lines(); assert_eq!(lines.next().unwrap(), "File"); for line in lines { - assert_eq!(line, "-"); + assert_eq!(line, "- "); } } @@ -503,7 +503,7 @@ fn test_output_file_specific_files() { .succeeds() .stdout_move_str(); let actual: Vec<&str> = output.lines().collect(); - assert_eq!(actual, vec!["File", "a", "b", "c"]); + assert_eq!(actual, vec!["File", "a ", "b ", "c "]); } #[test] @@ -538,5 +538,5 @@ fn test_nonexistent_file() { .args(&["--output=file", "does-not-exist", "."]) .fails() .stderr_is("df: does-not-exist: No such file or directory\n") - .stdout_is("File\n.\n"); + .stdout_is("File\n. \n"); } From 363a2a5611d01fa1df50578310819411c39a3117 Mon Sep 17 00:00:00 2001 From: Ryan Zoeller Date: Sun, 24 Apr 2022 15:48:16 -0500 Subject: [PATCH 009/111] Upgrade nix to 0.24.1, ctrlc to 3.2.2 Limit nix features, which should help compile times slightly. Replace usage of deprecated nix functionality with std equivalent. --- Cargo.lock | 10 ++++------ Cargo.toml | 2 +- src/uu/cat/Cargo.toml | 2 +- src/uu/more/Cargo.toml | 2 +- src/uu/nice/Cargo.toml | 2 +- src/uu/tail/Cargo.toml | 2 +- src/uu/timeout/Cargo.toml | 2 +- src/uu/wc/Cargo.toml | 2 +- src/uu/yes/Cargo.toml | 2 +- src/uucore/Cargo.toml | 4 +++- src/uucore/src/lib/features/pipes.rs | 6 ++++-- 11 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b7a42339..a733800e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -649,9 +649,9 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf" +checksum = "b37feaa84e6861e00a1f5e5aa8da3ee56d605c9992d33e082786754828e20865" dependencies = [ "nix", "winapi 0.3.9", @@ -1139,15 +1139,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.1" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" dependencies = [ "bitflags", - "cc", "cfg-if 1.0.0", "libc", - "memoffset", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 17f686008..0aa2861f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -401,7 +401,7 @@ hex-literal = "0.3.1" rlimit = "0.8.3" [target.'cfg(unix)'.dev-dependencies] -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false, features = ["process", "signal", "user"] } rust-users = { version="0.10", package="users" } unix_socket = "0.5.0" diff --git a/src/uu/cat/Cargo.toml b/src/uu/cat/Cargo.toml index ddf129bdb..cdd15d501 100644 --- a/src/uu/cat/Cargo.toml +++ b/src/uu/cat/Cargo.toml @@ -22,7 +22,7 @@ uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=[ [target.'cfg(unix)'.dependencies] unix_socket = "0.5.0" -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false } [[bin]] name = "cat" diff --git a/src/uu/more/Cargo.toml b/src/uu/more/Cargo.toml index 9cc69f3c5..d28ec4377 100644 --- a/src/uu/more/Cargo.toml +++ b/src/uu/more/Cargo.toml @@ -23,7 +23,7 @@ unicode-width = "0.1.7" unicode-segmentation = "1.9.0" [target.'cfg(all(unix, not(target_os = "fuchsia")))'.dependencies] -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false } [[bin]] name = "more" diff --git a/src/uu/nice/Cargo.toml b/src/uu/nice/Cargo.toml index eeec708af..cc3a189f8 100644 --- a/src/uu/nice/Cargo.toml +++ b/src/uu/nice/Cargo.toml @@ -17,7 +17,7 @@ path = "src/nice.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } libc = "0.2.121" -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/tail/Cargo.toml b/src/uu/tail/Cargo.toml index 0df4e2d78..2e8fd3839 100644 --- a/src/uu/tail/Cargo.toml +++ b/src/uu/tail/Cargo.toml @@ -23,7 +23,7 @@ uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=[ winapi = { version="0.3", features=["fileapi", "handleapi", "processthreadsapi", "synchapi", "winbase"] } [target.'cfg(unix)'.dependencies] -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false } [[bin]] name = "tail" diff --git a/src/uu/timeout/Cargo.toml b/src/uu/timeout/Cargo.toml index 930185320..2ccd93419 100644 --- a/src/uu/timeout/Cargo.toml +++ b/src/uu/timeout/Cargo.toml @@ -17,7 +17,7 @@ path = "src/timeout.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } libc = "0.2.121" -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false, features = ["signal"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["process", "signals"] } [[bin]] diff --git a/src/uu/wc/Cargo.toml b/src/uu/wc/Cargo.toml index d8b589388..bd819f244 100644 --- a/src/uu/wc/Cargo.toml +++ b/src/uu/wc/Cargo.toml @@ -22,7 +22,7 @@ utf-8 = "0.7.6" unicode-width = "0.1.8" [target.'cfg(unix)'.dependencies] -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false } libc = "0.2" [[bin]] diff --git a/src/uu/yes/Cargo.toml b/src/uu/yes/Cargo.toml index d756f28f9..54675eba7 100644 --- a/src/uu/yes/Cargo.toml +++ b/src/uu/yes/Cargo.toml @@ -19,7 +19,7 @@ clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["pipes"] } [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] -nix = "0.23.1" +nix = { version = "0.24.1", default-features = false } [[bin]] name = "yes" diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 34fcdc103..2cf5dafb9 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -1,3 +1,5 @@ +# spell-checker:ignore (features) zerocopy + [package] name = "uucore" version = "0.0.13" @@ -35,7 +37,7 @@ os_display = "0.1.3" [target.'cfg(unix)'.dependencies] walkdir = { version="2.3.2", optional=true } -nix = { version="0.23.1", optional=true } +nix = { version = "0.24.1", optional = true, default-features = false, features = ["fs", "uio", "zerocopy"] } [dev-dependencies] clap = "3.1" diff --git a/src/uucore/src/lib/features/pipes.rs b/src/uucore/src/lib/features/pipes.rs index 87cbe9bf2..a76322de8 100644 --- a/src/uucore/src/lib/features/pipes.rs +++ b/src/uucore/src/lib/features/pipes.rs @@ -1,11 +1,13 @@ /// Thin pipe-related wrappers around functions from the `nix` crate. use std::fs::File; #[cfg(any(target_os = "linux", target_os = "android"))] +use std::io::IoSlice; +#[cfg(any(target_os = "linux", target_os = "android"))] use std::os::unix::io::AsRawFd; use std::os::unix::io::FromRawFd; #[cfg(any(target_os = "linux", target_os = "android"))] -use nix::{fcntl::SpliceFFlags, sys::uio::IoVec}; +use nix::fcntl::SpliceFFlags; pub use nix::{Error, Result}; @@ -63,7 +65,7 @@ pub fn splice_exact(source: &impl AsRawFd, target: &impl AsRawFd, len: usize) -> pub fn vmsplice(target: &impl AsRawFd, bytes: &[u8]) -> Result { nix::fcntl::vmsplice( target.as_raw_fd(), - &[IoVec::from_slice(bytes)], + &[IoSlice::new(bytes)], SpliceFFlags::empty(), ) } From a10f234854a9de793c8d0aa461b628bd05432407 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sun, 24 Apr 2022 23:18:04 +0200 Subject: [PATCH 010/111] uudoc: require a feature to build This is used to not build uudoc by default. See https://github.com/uutils/coreutils/issues/3411 --- Cargo.toml | 4 +++- build.rs | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 17f686008..061a79c2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -254,6 +254,7 @@ feat_os_windows_legacy = [ ## # * bypass/override ~ translate 'test' feature name to avoid dependency collision with rust core 'test' crate (o/w surfaces as compiler errors during testing) test = [ "uu_test" ] +uudoc = [ "zip" ] [workspace] @@ -265,7 +266,7 @@ lazy_static = { version="1.3" } textwrap = { version="0.15", features=["terminal_size"] } uucore = { version=">=0.0.11", package="uucore", path="src/uucore" } selinux = { version="0.2", optional = true } -zip = { version = "0.6.0", default_features=false, features=["deflate"] } +zip = { version = "0.6.0", optional=true, default_features=false, features=["deflate"] } # * uutils uu_test = { optional=true, version="0.0.13", package="uu_test", path="src/uu/test" } # @@ -415,3 +416,4 @@ path = "src/bin/coreutils.rs" [[bin]] name = "uudoc" path = "src/bin/uudoc.rs" +required-features = ["uudoc"] diff --git a/build.rs b/build.rs index 50b8cfa3f..3df8d891d 100644 --- a/build.rs +++ b/build.rs @@ -28,8 +28,9 @@ pub fn main() { if val == "1" && key.starts_with(ENV_FEATURE_PREFIX) { let krate = key[ENV_FEATURE_PREFIX.len()..].to_lowercase(); match krate.as_ref() { - "default" | "macos" | "unix" | "windows" | "selinux" => continue, // common/standard feature names + "default" | "macos" | "unix" | "windows" | "selinux" | "zip" => continue, // common/standard feature names "nightly" | "test_unimplemented" => continue, // crate-local custom features + "uudoc" => continue, // is not a utility "test" => continue, // over-ridden with 'uu_test' to avoid collision with rust core crate 'test' s if s.starts_with(FEATURE_PREFIX) => continue, // crate feature sets _ => {} // util feature name From 8f8aa61e6a505c831985da1cfd4d14640299e957 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Apr 2022 20:49:10 +0000 Subject: [PATCH 011/111] build(deps): bump z85 from 3.0.4 to 3.0.5 Bumps [z85](https://github.com/decafbad/z85) from 3.0.4 to 3.0.5. - [Release notes](https://github.com/decafbad/z85/releases) - [Commits](https://github.com/decafbad/z85/commits) --- updated-dependencies: - dependency-name: z85 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/uucore/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b7a42339..3a1f5604e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3226,9 +3226,9 @@ dependencies = [ [[package]] name = "z85" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af896e93db81340b74b65f74276a99b210c086f3d34ed0abf433182a462af856" +checksum = "2a599daf1b507819c1121f0bf87fa37eb19daac6aff3aefefd4e6e2e0f2020fc" [[package]] name = "zip" diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 34fcdc103..25322e937 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -28,7 +28,7 @@ time = { version="<= 0.1.43", optional=true } # * "problem" dependencies (pinned) data-encoding = { version="2.1", optional=true } data-encoding-macro = { version="0.1.12", optional=true } -z85 = { version="3.0.3", optional=true } +z85 = { version="3.0.5", optional=true } libc = { version="0.2.121", optional=true } once_cell = "1.10.0" os_display = "0.1.3" From 681f5c88e2b38b30f3e111e6ef6a3fe0ec70f7fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Apr 2022 19:35:08 +0000 Subject: [PATCH 012/111] build(deps): bump strum_macros from 0.23.1 to 0.24.0 Bumps [strum_macros](https://github.com/Peternator7/strum) from 0.23.1 to 0.24.0. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum_macros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 11 ++++------- src/uu/uniq/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b7a42339..ed3e62cc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -894,12 +894,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -1815,9 +1812,9 @@ checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" [[package]] name = "strum_macros" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" +checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" dependencies = [ "heck", "proc-macro2", diff --git a/src/uu/uniq/Cargo.toml b/src/uu/uniq/Cargo.toml index 1d534140b..cfb83513d 100644 --- a/src/uu/uniq/Cargo.toml +++ b/src/uu/uniq/Cargo.toml @@ -17,7 +17,7 @@ path = "src/uniq.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } strum = "0.24.0" -strum_macros = "0.23.1" +strum_macros = "0.24.0" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] From f3e5f31279e578d08adc68aca7ce25d593db4af3 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 20 Apr 2022 18:50:24 +0200 Subject: [PATCH 013/111] remove an old skipped crate for nix 0.21.0 --- deny.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/deny.toml b/deny.toml index 8b3057870..04c640822 100644 --- a/deny.toml +++ b/deny.toml @@ -84,8 +84,6 @@ skip = [ { name = "memchr", version = "=1.0.2" }, { name = "quote", version = "=0.3.15" }, { name = "unicode-xid", version = "=0.0.4" }, - # exacl - { name = "nix", version = "=0.21.0" }, ] # spell-checker: enable From 186199c5d731b423d8b9f53f7ee8d11bf102d4b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 21:08:13 +0000 Subject: [PATCH 014/111] build(deps): bump rand from 0.8.4 to 0.8.5 Bumps [rand](https://github.com/rust-random/rand) from 0.8.4 to 0.8.5. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/0.8.4...0.8.5) --- updated-dependencies: - dependency-name: rand dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8deb428a0..2768f3524 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1479,14 +1479,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -1508,15 +1507,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "rayon" version = "1.5.2" From 6fde02ecf67a3abbb6f7f67912d20fdfd0a879a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 21:08:43 +0000 Subject: [PATCH 015/111] build(deps): bump clap_complete from 3.1.1 to 3.1.2 Bumps [clap_complete](https://github.com/clap-rs/clap) from 3.1.1 to 3.1.2. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v3.1.1...clap_complete-v3.1.2) --- updated-dependencies: - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 230 +++++++++++++++++++++++++++-------------------------- 1 file changed, 118 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2768f3524..3bdfd1cfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -256,15 +256,15 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.8" +version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db" dependencies = [ "atty", "bitflags", + "clap_lex", "indexmap", "lazy_static", - "os_str_bytes", "strsim 0.10.0", "termcolor", "terminal_size", @@ -273,11 +273,20 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25" +checksum = "1506b87ee866f7a53a5131f7b31fba656170d797e873d0609884cfd56b8bbda8" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", +] + +[[package]] +name = "clap_lex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +dependencies = [ + "os_str_bytes", ] [[package]] @@ -307,7 +316,7 @@ version = "0.0.13" dependencies = [ "atty", "chrono", - "clap 3.1.8", + "clap 3.1.12", "clap_complete", "conv", "filetime", @@ -1268,9 +1277,6 @@ name = "os_str_bytes" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr 2.4.1", -] [[package]] name = "ouroboros" @@ -2027,7 +2033,7 @@ checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" name = "uu_arch" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "platform-info", "uucore", ] @@ -2036,7 +2042,7 @@ dependencies = [ name = "uu_base32" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2052,7 +2058,7 @@ dependencies = [ name = "uu_basename" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2060,7 +2066,7 @@ dependencies = [ name = "uu_basenc" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uu_base32", "uucore", ] @@ -2070,7 +2076,7 @@ name = "uu_cat" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.8", + "clap 3.1.12", "nix", "thiserror", "unix_socket", @@ -2081,7 +2087,7 @@ dependencies = [ name = "uu_chcon" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "fts-sys", "libc", "selinux", @@ -2093,7 +2099,7 @@ dependencies = [ name = "uu_chgrp" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2101,7 +2107,7 @@ dependencies = [ name = "uu_chmod" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2110,7 +2116,7 @@ dependencies = [ name = "uu_chown" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2118,7 +2124,7 @@ dependencies = [ name = "uu_chroot" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2126,7 +2132,7 @@ dependencies = [ name = "uu_cksum" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2134,7 +2140,7 @@ dependencies = [ name = "uu_comm" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2142,7 +2148,7 @@ dependencies = [ name = "uu_cp" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "exacl", "filetime", "ioctl-sys", @@ -2159,7 +2165,7 @@ dependencies = [ name = "uu_csplit" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "regex", "thiserror", "uucore", @@ -2171,7 +2177,7 @@ version = "0.0.13" dependencies = [ "atty", "bstr", - "clap 3.1.8", + "clap 3.1.12", "memchr 2.4.1", "uucore", ] @@ -2181,7 +2187,7 @@ name = "uu_date" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", "winapi 0.3.9", @@ -2192,7 +2198,7 @@ name = "uu_dd" version = "0.0.13" dependencies = [ "byte-unit", - "clap 3.1.8", + "clap 3.1.12", "gcd", "libc", "signal-hook", @@ -2203,7 +2209,7 @@ dependencies = [ name = "uu_df" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "number_prefix", "unicode-width", "uucore", @@ -2213,7 +2219,7 @@ dependencies = [ name = "uu_dir" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "selinux", "uu_ls", "uucore", @@ -2223,7 +2229,7 @@ dependencies = [ name = "uu_dircolors" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "glob", "uucore", ] @@ -2232,7 +2238,7 @@ dependencies = [ name = "uu_dirname" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2241,7 +2247,7 @@ name = "uu_du" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.8", + "clap 3.1.12", "glob", "uucore", "winapi 0.3.9", @@ -2251,7 +2257,7 @@ dependencies = [ name = "uu_echo" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2259,7 +2265,7 @@ dependencies = [ name = "uu_env" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "rust-ini", "uucore", ] @@ -2268,7 +2274,7 @@ dependencies = [ name = "uu_expand" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "unicode-width", "uucore", ] @@ -2277,7 +2283,7 @@ dependencies = [ name = "uu_expr" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "num-bigint", "num-traits", "onig", @@ -2288,7 +2294,7 @@ dependencies = [ name = "uu_factor" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "coz", "num-traits", "paste", @@ -2302,7 +2308,7 @@ dependencies = [ name = "uu_false" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2310,7 +2316,7 @@ dependencies = [ name = "uu_fmt" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "unicode-width", "uucore", ] @@ -2319,7 +2325,7 @@ dependencies = [ name = "uu_fold" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2327,7 +2333,7 @@ dependencies = [ name = "uu_groups" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2337,7 +2343,7 @@ version = "0.0.13" dependencies = [ "blake2b_simd", "blake3", - "clap 3.1.8", + "clap 3.1.12", "digest", "hex", "md-5", @@ -2353,7 +2359,7 @@ dependencies = [ name = "uu_head" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "memchr 2.4.1", "uucore", ] @@ -2362,7 +2368,7 @@ dependencies = [ name = "uu_hostid" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2371,7 +2377,7 @@ dependencies = [ name = "uu_hostname" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "hostname", "uucore", "winapi 0.3.9", @@ -2381,7 +2387,7 @@ dependencies = [ name = "uu_id" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "selinux", "uucore", ] @@ -2390,7 +2396,7 @@ dependencies = [ name = "uu_install" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "file_diff", "filetime", "libc", @@ -2401,7 +2407,7 @@ dependencies = [ name = "uu_join" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "memchr 2.4.1", "uucore", ] @@ -2410,7 +2416,7 @@ dependencies = [ name = "uu_kill" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2419,7 +2425,7 @@ dependencies = [ name = "uu_link" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2427,7 +2433,7 @@ dependencies = [ name = "uu_ln" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2435,7 +2441,7 @@ dependencies = [ name = "uu_logname" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2446,7 +2452,7 @@ version = "0.0.13" dependencies = [ "atty", "chrono", - "clap 3.1.8", + "clap 3.1.12", "glob", "lazy_static", "lscolors", @@ -2463,7 +2469,7 @@ dependencies = [ name = "uu_mkdir" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2471,7 +2477,7 @@ dependencies = [ name = "uu_mkfifo" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2480,7 +2486,7 @@ dependencies = [ name = "uu_mknod" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2489,7 +2495,7 @@ dependencies = [ name = "uu_mktemp" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "rand", "tempfile", "uucore", @@ -2500,7 +2506,7 @@ name = "uu_more" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.8", + "clap 3.1.12", "crossterm", "nix", "unicode-segmentation", @@ -2512,7 +2518,7 @@ dependencies = [ name = "uu_mv" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "fs_extra", "uucore", ] @@ -2521,7 +2527,7 @@ dependencies = [ name = "uu_nice" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "nix", "uucore", @@ -2531,7 +2537,7 @@ dependencies = [ name = "uu_nl" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "regex", "uucore", ] @@ -2541,7 +2547,7 @@ name = "uu_nohup" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2550,7 +2556,7 @@ dependencies = [ name = "uu_nproc" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "num_cpus", "uucore", @@ -2560,7 +2566,7 @@ dependencies = [ name = "uu_numfmt" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2569,7 +2575,7 @@ name = "uu_od" version = "0.0.13" dependencies = [ "byteorder", - "clap 3.1.8", + "clap 3.1.12", "half", "uucore", ] @@ -2578,7 +2584,7 @@ dependencies = [ name = "uu_paste" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2586,7 +2592,7 @@ dependencies = [ name = "uu_pathchk" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2595,7 +2601,7 @@ dependencies = [ name = "uu_pinky" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2604,7 +2610,7 @@ name = "uu_pr" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.8", + "clap 3.1.12", "itertools", "quick-error", "regex", @@ -2615,7 +2621,7 @@ dependencies = [ name = "uu_printenv" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2623,7 +2629,7 @@ dependencies = [ name = "uu_printf" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2631,7 +2637,7 @@ dependencies = [ name = "uu_ptx" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "regex", "uucore", ] @@ -2640,7 +2646,7 @@ dependencies = [ name = "uu_pwd" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2648,7 +2654,7 @@ dependencies = [ name = "uu_readlink" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2656,7 +2662,7 @@ dependencies = [ name = "uu_realpath" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2664,7 +2670,7 @@ dependencies = [ name = "uu_relpath" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2672,7 +2678,7 @@ dependencies = [ name = "uu_rm" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "remove_dir_all 0.7.0", "uucore", "walkdir", @@ -2683,7 +2689,7 @@ dependencies = [ name = "uu_rmdir" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2692,7 +2698,7 @@ dependencies = [ name = "uu_runcon" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "selinux", "thiserror", @@ -2704,7 +2710,7 @@ name = "uu_seq" version = "0.0.13" dependencies = [ "bigdecimal", - "clap 3.1.8", + "clap 3.1.12", "num-bigint", "num-traits", "uucore", @@ -2714,7 +2720,7 @@ dependencies = [ name = "uu_shred" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "rand", "uucore", ] @@ -2723,7 +2729,7 @@ dependencies = [ name = "uu_shuf" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "rand", "rand_core", "uucore", @@ -2733,7 +2739,7 @@ dependencies = [ name = "uu_sleep" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2742,7 +2748,7 @@ name = "uu_sort" version = "0.0.13" dependencies = [ "binary-heap-plus", - "clap 3.1.8", + "clap 3.1.12", "compare", "ctrlc", "fnv", @@ -2760,7 +2766,7 @@ dependencies = [ name = "uu_split" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "memchr 2.4.1", "uucore", ] @@ -2769,7 +2775,7 @@ dependencies = [ name = "uu_stat" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2777,7 +2783,7 @@ dependencies = [ name = "uu_stdbuf" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "tempfile", "uu_stdbuf_libstdbuf", "uucore", @@ -2797,7 +2803,7 @@ dependencies = [ name = "uu_sum" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2805,7 +2811,7 @@ dependencies = [ name = "uu_sync" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", "winapi 0.3.9", @@ -2815,7 +2821,7 @@ dependencies = [ name = "uu_tac" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "memchr 2.4.1", "memmap2", "regex", @@ -2826,7 +2832,7 @@ dependencies = [ name = "uu_tail" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "nix", "uucore", @@ -2837,7 +2843,7 @@ dependencies = [ name = "uu_tee" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "retain_mut", "uucore", @@ -2847,7 +2853,7 @@ dependencies = [ name = "uu_test" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "redox_syscall", "uucore", @@ -2857,7 +2863,7 @@ dependencies = [ name = "uu_timeout" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "nix", "uucore", @@ -2867,7 +2873,7 @@ dependencies = [ name = "uu_touch" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "filetime", "time", "uucore", @@ -2878,7 +2884,7 @@ dependencies = [ name = "uu_tr" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "nom", "uucore", ] @@ -2887,7 +2893,7 @@ dependencies = [ name = "uu_true" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2895,7 +2901,7 @@ dependencies = [ name = "uu_truncate" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2903,7 +2909,7 @@ dependencies = [ name = "uu_tsort" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2912,7 +2918,7 @@ name = "uu_tty" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", ] @@ -2921,7 +2927,7 @@ dependencies = [ name = "uu_uname" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "platform-info", "uucore", ] @@ -2930,7 +2936,7 @@ dependencies = [ name = "uu_unexpand" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "unicode-width", "uucore", ] @@ -2939,7 +2945,7 @@ dependencies = [ name = "uu_uniq" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "strum", "strum_macros", "uucore", @@ -2949,7 +2955,7 @@ dependencies = [ name = "uu_unlink" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2958,7 +2964,7 @@ name = "uu_uptime" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2966,7 +2972,7 @@ dependencies = [ name = "uu_users" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -2974,7 +2980,7 @@ dependencies = [ name = "uu_vdir" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "selinux", "uu_ls", "uucore", @@ -2985,7 +2991,7 @@ name = "uu_wc" version = "0.0.13" dependencies = [ "bytecount", - "clap 3.1.8", + "clap 3.1.12", "libc", "nix", "unicode-width", @@ -2997,7 +3003,7 @@ dependencies = [ name = "uu_who" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "uucore", ] @@ -3005,7 +3011,7 @@ dependencies = [ name = "uu_whoami" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "libc", "uucore", "winapi 0.3.9", @@ -3015,7 +3021,7 @@ dependencies = [ name = "uu_yes" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "nix", "uucore", ] @@ -3024,7 +3030,7 @@ dependencies = [ name = "uucore" version = "0.0.13" dependencies = [ - "clap 3.1.8", + "clap 3.1.12", "data-encoding", "data-encoding-macro", "dns-lookup", From 3cee681e822cd4faa0357f20d1af3a5586134534 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 07:15:58 +0000 Subject: [PATCH 016/111] build(deps): bump libc from 0.2.121 to 0.2.124 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.121 to 0.2.124. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.121...0.2.124) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/uu/chmod/Cargo.toml | 2 +- src/uu/cp/Cargo.toml | 2 +- src/uu/hostid/Cargo.toml | 2 +- src/uu/kill/Cargo.toml | 2 +- src/uu/logname/Cargo.toml | 2 +- src/uu/mkfifo/Cargo.toml | 2 +- src/uu/mknod/Cargo.toml | 2 +- src/uu/nice/Cargo.toml | 2 +- src/uu/nohup/Cargo.toml | 2 +- src/uu/nproc/Cargo.toml | 2 +- src/uu/pathchk/Cargo.toml | 2 +- src/uu/rmdir/Cargo.toml | 2 +- src/uu/sync/Cargo.toml | 2 +- src/uu/tail/Cargo.toml | 2 +- src/uu/tee/Cargo.toml | 2 +- src/uu/test/Cargo.toml | 2 +- src/uu/timeout/Cargo.toml | 2 +- src/uu/tty/Cargo.toml | 2 +- src/uu/whoami/Cargo.toml | 2 +- src/uucore/Cargo.toml | 2 +- 21 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bdfd1cfc..dbea8ccd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1015,9 +1015,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.121" +version = "0.2.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" [[package]] name = "libloading" diff --git a/src/uu/chmod/Cargo.toml b/src/uu/chmod/Cargo.toml index 66ba42736..9fab6011e 100644 --- a/src/uu/chmod/Cargo.toml +++ b/src/uu/chmod/Cargo.toml @@ -16,7 +16,7 @@ path = "src/chmod.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs", "mode"] } [[bin]] diff --git a/src/uu/cp/Cargo.toml b/src/uu/cp/Cargo.toml index 1aab9c37b..9e1141650 100644 --- a/src/uu/cp/Cargo.toml +++ b/src/uu/cp/Cargo.toml @@ -21,7 +21,7 @@ path = "src/cp.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } filetime = "0.2" -libc = "0.2.121" +libc = "0.2.124" quick-error = "2.0.1" selinux = { version="0.2", optional=true } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["entries", "fs", "perms", "mode"] } diff --git a/src/uu/hostid/Cargo.toml b/src/uu/hostid/Cargo.toml index f9c2555d4..0a2948459 100644 --- a/src/uu/hostid/Cargo.toml +++ b/src/uu/hostid/Cargo.toml @@ -16,7 +16,7 @@ path = "src/hostid.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/kill/Cargo.toml b/src/uu/kill/Cargo.toml index 561209eb3..354ad1d3f 100644 --- a/src/uu/kill/Cargo.toml +++ b/src/uu/kill/Cargo.toml @@ -16,7 +16,7 @@ path = "src/kill.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["signals"] } [[bin]] diff --git a/src/uu/logname/Cargo.toml b/src/uu/logname/Cargo.toml index 34ca9355a..22b976dd6 100644 --- a/src/uu/logname/Cargo.toml +++ b/src/uu/logname/Cargo.toml @@ -15,7 +15,7 @@ edition = "2021" path = "src/logname.rs" [dependencies] -libc = "0.2.121" +libc = "0.2.124" clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } diff --git a/src/uu/mkfifo/Cargo.toml b/src/uu/mkfifo/Cargo.toml index bb2ced83e..a6c801747 100644 --- a/src/uu/mkfifo/Cargo.toml +++ b/src/uu/mkfifo/Cargo.toml @@ -16,7 +16,7 @@ path = "src/mkfifo.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/mknod/Cargo.toml b/src/uu/mknod/Cargo.toml index 2f9a5cea0..53cc62313 100644 --- a/src/uu/mknod/Cargo.toml +++ b/src/uu/mknod/Cargo.toml @@ -17,7 +17,7 @@ path = "src/mknod.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "^0.2.121" +libc = "^0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["mode"] } [[bin]] diff --git a/src/uu/nice/Cargo.toml b/src/uu/nice/Cargo.toml index cc3a189f8..ab4b6c700 100644 --- a/src/uu/nice/Cargo.toml +++ b/src/uu/nice/Cargo.toml @@ -16,7 +16,7 @@ path = "src/nice.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" nix = { version = "0.24.1", default-features = false } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } diff --git a/src/uu/nohup/Cargo.toml b/src/uu/nohup/Cargo.toml index fb2aed634..26e5fd7ae 100644 --- a/src/uu/nohup/Cargo.toml +++ b/src/uu/nohup/Cargo.toml @@ -16,7 +16,7 @@ path = "src/nohup.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" atty = "0.2" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/nproc/Cargo.toml b/src/uu/nproc/Cargo.toml index 7980f5c2a..80c1cb38b 100644 --- a/src/uu/nproc/Cargo.toml +++ b/src/uu/nproc/Cargo.toml @@ -15,7 +15,7 @@ edition = "2021" path = "src/nproc.rs" [dependencies] -libc = "0.2.121" +libc = "0.2.124" num_cpus = "1.10" clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/pathchk/Cargo.toml b/src/uu/pathchk/Cargo.toml index 09a14e0a6..44cab8559 100644 --- a/src/uu/pathchk/Cargo.toml +++ b/src/uu/pathchk/Cargo.toml @@ -16,7 +16,7 @@ path = "src/pathchk.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/rmdir/Cargo.toml b/src/uu/rmdir/Cargo.toml index 5a6ccee6d..b61def5ad 100644 --- a/src/uu/rmdir/Cargo.toml +++ b/src/uu/rmdir/Cargo.toml @@ -17,7 +17,7 @@ path = "src/rmdir.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } -libc = "0.2.121" +libc = "0.2.124" [[bin]] name = "rmdir" diff --git a/src/uu/sync/Cargo.toml b/src/uu/sync/Cargo.toml index a4d66aff5..ece7a5930 100644 --- a/src/uu/sync/Cargo.toml +++ b/src/uu/sync/Cargo.toml @@ -16,7 +16,7 @@ path = "src/sync.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["wide"] } winapi = { version = "0.3", features = ["errhandlingapi", "fileapi", "handleapi", "std", "winbase", "winerror"] } diff --git a/src/uu/tail/Cargo.toml b/src/uu/tail/Cargo.toml index 2e8fd3839..eebbf9606 100644 --- a/src/uu/tail/Cargo.toml +++ b/src/uu/tail/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tail.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] } [target.'cfg(windows)'.dependencies] diff --git a/src/uu/tee/Cargo.toml b/src/uu/tee/Cargo.toml index 80af45ea6..d018ee4a7 100644 --- a/src/uu/tee/Cargo.toml +++ b/src/uu/tee/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tee.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" retain_mut = "=0.1.2" # ToDO: [2021-01-01; rivy; maint/MinSRV] ~ v0.1.5 uses const generics which aren't stabilized until rust v1.51.0 uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["libc"] } diff --git a/src/uu/test/Cargo.toml b/src/uu/test/Cargo.toml index 6e2f4f789..6bd1cfc90 100644 --- a/src/uu/test/Cargo.toml +++ b/src/uu/test/Cargo.toml @@ -16,7 +16,7 @@ path = "src/test.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [target.'cfg(target_os = "redox")'.dependencies] diff --git a/src/uu/timeout/Cargo.toml b/src/uu/timeout/Cargo.toml index 2ccd93419..e555cb1b7 100644 --- a/src/uu/timeout/Cargo.toml +++ b/src/uu/timeout/Cargo.toml @@ -16,7 +16,7 @@ path = "src/timeout.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" nix = { version = "0.24.1", default-features = false, features = ["signal"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["process", "signals"] } diff --git a/src/uu/tty/Cargo.toml b/src/uu/tty/Cargo.toml index c27309008..2f3438558 100644 --- a/src/uu/tty/Cargo.toml +++ b/src/uu/tty/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tty.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.121" +libc = "0.2.124" atty = "0.2" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/whoami/Cargo.toml b/src/uu/whoami/Cargo.toml index 2400801a4..2655fe892 100644 --- a/src/uu/whoami/Cargo.toml +++ b/src/uu/whoami/Cargo.toml @@ -22,7 +22,7 @@ uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=[ winapi = { version = "0.3", features = ["lmcons"] } [target.'cfg(unix)'.dependencies] -libc = "0.2.121" +libc = "0.2.124" [[bin]] name = "whoami" diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 8d90ecd44..6f74b238a 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -31,7 +31,7 @@ time = { version="<= 0.1.43", optional=true } data-encoding = { version="2.1", optional=true } data-encoding-macro = { version="0.1.12", optional=true } z85 = { version="3.0.5", optional=true } -libc = { version="0.2.121", optional=true } +libc = { version="0.2.124", optional=true } once_cell = "1.10.0" os_display = "0.1.3" From 7a7311f5f6cfa2a48ec969cc25aeca519a05b929 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 10:36:05 +0000 Subject: [PATCH 017/111] build(deps): bump pretty_assertions from 1.0.0 to 1.2.1 Bumps [pretty_assertions](https://github.com/colin-kiegel/rust-pretty-assertions) from 1.0.0 to 1.2.1. - [Release notes](https://github.com/colin-kiegel/rust-pretty-assertions/releases) - [Changelog](https://github.com/colin-kiegel/rust-pretty-assertions/blob/main/CHANGELOG.md) - [Commits](https://github.com/colin-kiegel/rust-pretty-assertions/compare/v1.0.0...v1.2.1) --- updated-dependencies: - dependency-name: pretty_assertions dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bdfd1cfc..c6c758147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1408,9 +1408,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_assertions" -version = "1.0.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0cfe1b2403f172ba0f234e500906ee0a3e493fb81092dac23ebefe129301cc" +checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" dependencies = [ "ansi_term", "ctor", From 38a8fa6a776c4c251370b662ff79cc1b7731a5c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Apr 2022 06:44:04 +0000 Subject: [PATCH 018/111] build(deps): bump retain_mut from 0.1.2 to 0.1.7 Bumps [retain_mut](https://github.com/upsuper/retain_mut) from 0.1.2 to 0.1.7. - [Release notes](https://github.com/upsuper/retain_mut/releases) - [Commits](https://github.com/upsuper/retain_mut/commits) --- updated-dependencies: - dependency-name: retain_mut dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/uu/tee/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 191ad8923..a24abb936 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1608,9 +1608,9 @@ dependencies = [ [[package]] name = "retain_mut" -version = "0.1.2" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53552c6c49e1e13f1a203ef0080ab3bbef0beb570a528993e83df057a9d9bba1" +checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086" [[package]] name = "rlimit" diff --git a/src/uu/tee/Cargo.toml b/src/uu/tee/Cargo.toml index d018ee4a7..7257d9854 100644 --- a/src/uu/tee/Cargo.toml +++ b/src/uu/tee/Cargo.toml @@ -17,7 +17,7 @@ path = "src/tee.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } libc = "0.2.124" -retain_mut = "=0.1.2" # ToDO: [2021-01-01; rivy; maint/MinSRV] ~ v0.1.5 uses const generics which aren't stabilized until rust v1.51.0 +retain_mut = "=0.1.7" # ToDO: [2021-01-01; rivy; maint/MinSRV] ~ v0.1.5 uses const generics which aren't stabilized until rust v1.51.0 uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["libc"] } [[bin]] From 88752ecc3eefd4b8206f6f55ecd318a94d90fe81 Mon Sep 17 00:00:00 2001 From: ndd7xv Date: Tue, 26 Apr 2022 20:02:59 -0400 Subject: [PATCH 019/111] fix -h and --help discrepancies addresses https://github.com/uutils/coreutils/issues/3370 --- src/uu/cp/src/cp.rs | 68 +++++++++++++++++++-------------- src/uu/false/src/false.rs | 2 +- src/uu/pr/src/pr.rs | 2 +- src/uu/sort/src/sort.rs | 5 +-- src/uu/true/src/true.rs | 2 +- src/uu/unexpand/src/unexpand.rs | 2 +- util/build-gnu.sh | 2 - 7 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index df9cb0293..913cf2769 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -469,37 +469,49 @@ pub fn uu_app<'a>() -> Command<'a> { #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let matches = uu_app() - .after_help(&*format!( - "{}\n{}", - LONG_HELP, - backup_control::BACKUP_CONTROL_LONG_HELP - )) - .try_get_matches_from(args)?; + let after_help = &*format!( + "{}\n{}", + LONG_HELP, + backup_control::BACKUP_CONTROL_LONG_HELP + ); + let matches = uu_app().after_help(after_help).try_get_matches_from(args); - let options = Options::from_matches(&matches)?; + // The error is parsed here because we do not want version or help being printed to stderr. + if let Err(e) = matches { + let mut app = uu_app().after_help(after_help); - if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup { - show_usage_error!("options --backup and --no-clobber are mutually exclusive"); - return Err(ExitCode(EXIT_ERR).into()); - } - - let paths: Vec = matches - .values_of(options::PATHS) - .map(|v| v.map(ToString::to_string).collect()) - .unwrap_or_default(); - - let (sources, target) = parse_path_args(&paths, &options)?; - - if let Err(error) = copy(&sources, &target, &options) { - match error { - // Error::NotAllFilesCopied is non-fatal, but the error - // code should still be EXIT_ERR as does GNU cp - Error::NotAllFilesCopied => {} - // Else we caught a fatal bubbled-up error, log it to stderr - _ => show_error!("{}", error), + match e.kind() { + clap::ErrorKind::DisplayHelp => { + app.print_help()?; + } + clap::ErrorKind::DisplayVersion => println!("{}", app.render_version()), + _ => return Err(Box::new(e)), }; - set_exit_code(EXIT_ERR); + } else if let Ok(matches) = matches { + let options = Options::from_matches(&matches)?; + + if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup { + show_usage_error!("options --backup and --no-clobber are mutually exclusive"); + return Err(ExitCode(EXIT_ERR).into()); + } + + let paths: Vec = matches + .values_of(options::PATHS) + .map(|v| v.map(ToString::to_string).collect()) + .unwrap_or_default(); + + let (sources, target) = parse_path_args(&paths, &options)?; + + if let Err(error) = copy(&sources, &target, &options) { + match error { + // Error::NotAllFilesCopied is non-fatal, but the error + // code should still be EXIT_ERR as does GNU cp + Error::NotAllFilesCopied => {} + // Else we caught a fatal bubbled-up error, log it to stderr + _ => show_error!("{}", error), + }; + set_exit_code(EXIT_ERR); + } } Ok(()) diff --git a/src/uu/false/src/false.rs b/src/uu/false/src/false.rs index 687235f70..0ee6128b2 100644 --- a/src/uu/false/src/false.rs +++ b/src/uu/false/src/false.rs @@ -28,7 +28,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if let Ok(matches) = command.try_get_matches_from_mut(args) { let error = if matches.index_of("help").is_some() { - command.print_long_help() + command.print_help() } else if matches.index_of("version").is_some() { writeln!(std::io::stdout(), "{}", command.render_version()) } else { diff --git a/src/uu/pr/src/pr.rs b/src/uu/pr/src/pr.rs index e18d29730..ca12f0be0 100644 --- a/src/uu/pr/src/pr.rs +++ b/src/uu/pr/src/pr.rs @@ -399,7 +399,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } if matches.is_present(options::HELP) { - command.print_long_help()?; + command.print_help()?; return Ok(()); } diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 77d81c54c..141a7dd2c 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -1272,6 +1272,7 @@ pub fn uu_app<'a>() -> Command<'a> { Command::new(uucore::util_name()) .version(crate_version!()) .about(ABOUT) + .after_help(LONG_HELP_KEYS) .override_usage(format_usage(USAGE)) .infer_long_args(true) .arg( @@ -1421,7 +1422,6 @@ pub fn uu_app<'a>() -> Command<'a> { .short('k') .long(options::KEY) .help("sort by a key") - .long_help(LONG_HELP_KEYS) .multiple_occurrences(true) .number_of_values(1) .takes_value(true), @@ -1466,8 +1466,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::COMPRESS_PROG) .long(options::COMPRESS_PROG) - .help("compress temporary files with PROG, decompress with PROG -d") - .long_help("PROG has to take input from stdin and output to stdout") + .help("compress temporary files with PROG, decompress with PROG -d; PROG has to take input from stdin and output to stdout") .value_name("PROG"), ) .arg( diff --git a/src/uu/true/src/true.rs b/src/uu/true/src/true.rs index 57c3d2af5..7742e9ee1 100644 --- a/src/uu/true/src/true.rs +++ b/src/uu/true/src/true.rs @@ -22,7 +22,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if let Ok(matches) = command.try_get_matches_from_mut(args) { let error = if matches.index_of("help").is_some() { - command.print_long_help() + command.print_help() } else if matches.index_of("version").is_some() { writeln!(std::io::stdout(), "{}", command.render_version()) } else { diff --git a/src/uu/unexpand/src/unexpand.rs b/src/uu/unexpand/src/unexpand.rs index 910ff91d3..70a763f3b 100644 --- a/src/uu/unexpand/src/unexpand.rs +++ b/src/uu/unexpand/src/unexpand.rs @@ -127,7 +127,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::TABS) .short('t') .long(options::TABS) - .long_help("use comma separated LIST of tab positions or have tabs N characters apart instead of 8 (enables -a)") + .help("use comma separated LIST of tab positions or have tabs N characters apart instead of 8 (enables -a)") .takes_value(true) ) .arg( diff --git a/util/build-gnu.sh b/util/build-gnu.sh index 0aad35ff1..6f0ec32f7 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -183,8 +183,6 @@ sed -i -e "s~ sed -n \"1s/'\\\/'/'OPT'/p\" < err >> pat || framework_failure_~ sed -i -e "s/rcexp=1$/rcexp=2\n case \"\$prg\" in chcon|runcon) return;; esac/" -e "s/rcexp=125 ;;/rcexp=2 ;;\ncp|truncate|pr) rcexp=1;;/" tests/misc/usage_vs_getopt.sh # GNU has option=[SUFFIX], clap is sed -i -e "s/cat opts/sed -i -e \"s| <.\*>$||g\" opts/" tests/misc/usage_vs_getopt.sh -# Strip empty lines for the diff - see https://github.com/uutils/coreutils/issues/3370 -sed -i -e "s~out 2>err1~out 2>err1\nsed '/^$/d' out > out\nsed '/^$/d' help > help~" tests/misc/usage_vs_getopt.sh # for some reasons, some stuff are duplicated, strip that sed -i -e "s/provoked error./provoked error\ncat pat |sort -u > pat/" tests/misc/usage_vs_getopt.sh From c6ad2441424d546c6ade98d9f5b9f27926e4c30c Mon Sep 17 00:00:00 2001 From: Michael Kefeder Date: Thu, 28 Apr 2022 16:46:10 +0200 Subject: [PATCH 020/111] tests/ptx: verify output width is handled correctly --- tests/by-util/test_ptx.rs | 16 +++++++++++++ .../gnu_ext_disabled_output_width_50.expected | 24 +++++++++++++++++++ .../gnu_ext_disabled_output_width_70.expected | 24 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 tests/fixtures/ptx/gnu_ext_disabled_output_width_50.expected create mode 100644 tests/fixtures/ptx/gnu_ext_disabled_output_width_70.expected diff --git a/tests/by-util/test_ptx.rs b/tests/by-util/test_ptx.rs index c17d473f5..e990cac73 100644 --- a/tests/by-util/test_ptx.rs +++ b/tests/by-util/test_ptx.rs @@ -71,3 +71,19 @@ fn gnu_ext_disabled_ignore_and_only_file() { .succeeds() .stdout_only_fixture("gnu_ext_disabled_ignore_and_only_file.expected"); } + +#[test] +fn gnu_ext_disabled_output_width_50() { + new_ucmd!() + .args(&["-G", "-w", "50", "input"]) + .succeeds() + .stdout_only_fixture("gnu_ext_disabled_output_width_50.expected"); +} + +#[test] +fn gnu_ext_disabled_output_width_70() { + new_ucmd!() + .args(&["-G", "-w", "70", "input"]) + .succeeds() + .stdout_only_fixture("gnu_ext_disabled_output_width_70.expected"); +} diff --git a/tests/fixtures/ptx/gnu_ext_disabled_output_width_50.expected b/tests/fixtures/ptx/gnu_ext_disabled_output_width_50.expected new file mode 100644 index 000000000..c71b0508c --- /dev/null +++ b/tests/fixtures/ptx/gnu_ext_disabled_output_width_50.expected @@ -0,0 +1,24 @@ +.xx "" "" """quotes"", for roff" "" +.xx "" "and some other like" "%a, b#, c$c" "" +.xx "" "maybe" "also~or^" "" +.xx "%a, b#, c$c" "" "and some other like" "" +.xx "" "oh," "and back\slash" "" +.xx "" "some other like %a," "b#, c$c" "and" +.xx "" "oh, and" "back\slash" "" +.xx "" "other like %a, b#," "c$c" "and some" +.xx "" "let's check special" "characters:" "" +.xx "characters:" "let's" "check special" "" +.xx "" """quotes""," "for roff" "" +.xx "" "{brackets}" "for tex" "" +.xx "" "" "hello world!" "" +.xx "characters:" "" "let's check special" "" +.xx "" "and some other" "like %a, b#, c$c" "" +.xx "" "" "maybe also~or^" "" +.xx "" "" "oh, and back\slash" "" +.xx "" "and some" "other like %a, b#, c$c" "" +.xx "" """quotes"", for" "roff" "" +.xx "b#, c$c" "and" "some other like %a," "" +.xx "" "let's check" "special characters:" "" +.xx "" "{brackets} for" "tex" "" +.xx "" "hello" "world!" "" +.xx "" "" "{brackets} for tex" "" diff --git a/tests/fixtures/ptx/gnu_ext_disabled_output_width_70.expected b/tests/fixtures/ptx/gnu_ext_disabled_output_width_70.expected new file mode 100644 index 000000000..3886e087d --- /dev/null +++ b/tests/fixtures/ptx/gnu_ext_disabled_output_width_70.expected @@ -0,0 +1,24 @@ +.xx "" "" """quotes"", for roff" "" +.xx "" "and some other like" "%a, b#, c$c" "" +.xx "" "maybe" "also~or^" "" +.xx "" "" "and some other like %a, b#, c$c" "" +.xx "" "oh," "and back\slash" "" +.xx "" "and some other like %a," "b#, c$c" "" +.xx "" "oh, and" "back\slash" "" +.xx "" "and some other like %a, b#," "c$c" "" +.xx "" "let's check special" "characters:" "" +.xx "" "let's" "check special characters:" "" +.xx "" """quotes""," "for roff" "" +.xx "" "{brackets}" "for tex" "" +.xx "" "" "hello world!" "" +.xx "" "" "let's check special characters:" "" +.xx "" "and some other" "like %a, b#, c$c" "" +.xx "" "" "maybe also~or^" "" +.xx "" "" "oh, and back\slash" "" +.xx "" "and some" "other like %a, b#, c$c" "" +.xx "" """quotes"", for" "roff" "" +.xx "" "and" "some other like %a, b#, c$c" "" +.xx "" "let's check" "special characters:" "" +.xx "" "{brackets} for" "tex" "" +.xx "" "hello" "world!" "" +.xx "" "" "{brackets} for tex" "" From b0567670d104c4b0595ec45f916c6235f5f6c087 Mon Sep 17 00:00:00 2001 From: Michael Kefeder Date: Thu, 28 Apr 2022 16:51:06 +0200 Subject: [PATCH 021/111] ptx: implement breakfile option --- src/uu/ptx/src/ptx.rs | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index 86a123530..64fe421ad 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -88,6 +88,17 @@ fn read_word_filter_file( Ok(words) } +fn read_char_filter_file( + matches: &clap::ArgMatches, + option: &str, +) -> std::io::Result> { + let filename = matches.value_of(option).expect("parsing options failed!"); + let mut reader = File::open(filename)?; + let mut buffer = String::new(); + reader.read_to_string(&mut buffer)?; + Ok(buffer.chars().collect()) +} + #[derive(Debug)] struct WordFilter { only_specified: bool, @@ -113,9 +124,23 @@ impl WordFilter { } else { (false, HashSet::new()) }; - if matches.is_present(options::BREAK_FILE) { - return Err(PtxError::NotImplemented("-b").into()); - } + let break_set: Option> = if matches.is_present(options::BREAK_FILE) + && !matches.is_present(options::WORD_REGEXP) + { + let chars = + read_char_filter_file(matches, options::BREAK_FILE).map_err_context(String::new)?; + let mut hs: HashSet = if config.gnu_ext { + HashSet::new() // really only chars found in file + } else { + // GNU off means at least these are considered + [' ', '\t', '\n'].iter().cloned().collect() + }; + hs.extend(chars); + Some(hs) + } else { + // if -W takes precedence or default + None + }; // Ignore empty string regex from cmd-line-args let arg_reg: Option = if matches.is_present(options::WORD_REGEXP) { match matches.value_of(options::WORD_REGEXP) { @@ -134,7 +159,17 @@ impl WordFilter { let reg = match arg_reg { Some(arg_reg) => arg_reg, None => { - if config.gnu_ext { + if break_set.is_some() { + format!( + "[^{}]+", + break_set + .unwrap() + .into_iter() + .map(|c| c.to_string()) + .collect::>() + .join("") + ) + } else if config.gnu_ext { "\\w+".to_owned() } else { "[^ \t\n]+".to_owned() From adfe4b22893609c4478a9bf30b4846d57249deac Mon Sep 17 00:00:00 2001 From: naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:01:27 +0000 Subject: [PATCH 022/111] chore: Set permissions for GitHub actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much. - Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com> --- .github/workflows/GnuTests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index d306092c6..7bc0f26d4 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -8,6 +8,10 @@ on: [push, pull_request] jobs: gnu: + permissions: + actions: read # for dawidd6/action-download-artifact to query and download artifacts + contents: read # for actions/checkout to fetch code + pull-requests: read # for dawidd6/action-download-artifact to query commit hash name: Run GNU tests runs-on: ubuntu-latest steps: From 994dedd6d97ff0cedc9b190e355f1e612c497638 Mon Sep 17 00:00:00 2001 From: Michael Kefeder Date: Fri, 29 Apr 2022 10:15:06 +0200 Subject: [PATCH 023/111] tests/ptx: added breakfile option tests --- tests/by-util/test_ptx.rs | 16 ++++++++ tests/fixtures/ptx/break_file | 1 + .../ptx/gnu_ext_disabled_break_file.expected | 41 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/fixtures/ptx/break_file create mode 100644 tests/fixtures/ptx/gnu_ext_disabled_break_file.expected diff --git a/tests/by-util/test_ptx.rs b/tests/by-util/test_ptx.rs index e990cac73..75c96e42e 100644 --- a/tests/by-util/test_ptx.rs +++ b/tests/by-util/test_ptx.rs @@ -87,3 +87,19 @@ fn gnu_ext_disabled_output_width_70() { .succeeds() .stdout_only_fixture("gnu_ext_disabled_output_width_70.expected"); } + +#[test] +fn gnu_ext_disabled_break_file() { + new_ucmd!() + .args(&["-G", "-b", "break_file", "input"]) + .succeeds() + .stdout_only_fixture("gnu_ext_disabled_break_file.expected"); +} + +#[test] +fn gnu_ext_disabled_empty_word_regexp_ignores_break_file() { + new_ucmd!() + .args(&["-G", "-b", "break_file", "-R", "-W", "", "input"]) + .succeeds() + .stdout_only_fixture("gnu_ext_disabled_rightward_no_ref.expected"); +} diff --git a/tests/fixtures/ptx/break_file b/tests/fixtures/ptx/break_file new file mode 100644 index 000000000..4c992d40a --- /dev/null +++ b/tests/fixtures/ptx/break_file @@ -0,0 +1 @@ +abc_e diff --git a/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected b/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected new file mode 100644 index 000000000..7afce1861 --- /dev/null +++ b/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected @@ -0,0 +1,41 @@ +.xx "" "" """quotes"", for roff" "" +.xx "" "and some other like %a, b" "#, c$c" "" +.xx "" "and some other like %a, b#, c" "$c" "" +.xx "" "and some other like" "%a, b#, c$c" "" +.xx "" "and some other like %a" ", b#, c$c" "" +.xx "" """quotes""," "for roff" "" +.xx "" "{brackets}" "for tex" "" +.xx "" "" "hello world!" "" +.xx "" "let's c" "heck special characters:" "" +.xx "" "let's check special c" "haracters:" "" +.xx "" "let's check spec" "ial characters:" "" +.xx "" "let's chec" "k special characters:" "" +.xx "" "{brac" "kets} for tex" "" +.xx "" "oh, and bac" "k\slash" "" +.xx "" "" "let's check special characters:" "" +.xx "" "let's check specia" "l characters:" "" +.xx "" "and some other" "like %a, b#, c$c" "" +.xx "" "he" "llo world!" "" +.xx "" "maybe a" "lso~or^" "" +.xx "" "" "maybe also~or^" "" +.xx "" "a" "nd some other like %a, b#, c$c" "" +.xx "" "oh, a" "nd back\slash" "" +.xx "" "" "oh, and back\slash" "" +.xx "" "and some" "other like %a, b#, c$c" "" +.xx "" "let's check special cha" "racters:" "" +.xx "" "{b" "rackets} for tex" "" +.xx "" "and some othe" "r like %a, b#, c$c" "" +.xx "" """quotes"", for" "roff" "" +.xx "" "let's check special characte" "rs:" "" +.xx "" """quote" "s"", for roff" "" +.xx "" "oh, and back\sla" "sh" "" +.xx "" "and" "some other like %a, b#, c$c" "" +.xx "" "let's check" "special characters:" "" +.xx "" "let's check special charac" "ters:" "" +.xx "" "{brackets} for" "tex" "" +.xx "" "le" "t's check special characters:" "" +.xx "" "{bracke" "ts} for tex" "" +.xx "" "hello" "world!" "" +.xx "" "{brackets} for te" "x" "" +.xx "" "ma" "ybe also~or^" "" +.xx "" "" "{brackets} for tex" "" From 4889128edefa9293a15e7c8febce35ede94ef1b0 Mon Sep 17 00:00:00 2001 From: Michael Kefeder Date: Fri, 29 Apr 2022 10:57:36 +0200 Subject: [PATCH 024/111] ptx: add documentation to read_char_filter_file function --- src/uu/ptx/src/ptx.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index 64fe421ad..c273b976c 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -88,6 +88,7 @@ fn read_word_filter_file( Ok(words) } +/// reads contents of file as unique set of characters to be used with the break-file option fn read_char_filter_file( matches: &clap::ArgMatches, option: &str, From 023fc96aab29a1df3b79ebd8de27afbe0850cf5f Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 28 Apr 2022 09:10:20 +0200 Subject: [PATCH 025/111] df: fix "Size" column header Fixes #3193 --- src/uu/df/src/blocks.rs | 101 ++++++++++++++++++++++++++++----------- tests/by-util/test_df.rs | 7 ++- 2 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index 7783e5636..efeae2a70 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -26,6 +26,22 @@ const IEC_BASES: [u128; 10] = [ /// Suffixes for the first nine multi-byte unit suffixes. const SUFFIXES: [char; 9] = ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; +const SI_BASES: [u128; 10] = [ + 1, + 1_000, + 1_000_000, + 1_000_000_000, + 1_000_000_000_000, + 1_000_000_000_000_000, + 1_000_000_000_000_000_000, + 1_000_000_000_000_000_000_000, + 1_000_000_000_000_000_000_000_000, + 1_000_000_000_000_000_000_000_000_000, +]; + +// we use "kB" instead of "KB" because of GNU df +const SI_SUFFIXES: [&str; 9] = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + /// Convert a multiple of 1024 into a string like "12K" or "34M". /// /// # Examples @@ -57,6 +73,37 @@ fn to_magnitude_and_suffix_1024(n: u128) -> Result { Err(()) } +/// Convert a number, except multiples of 1024, into a string like "12kB" or "34MB". +/// +/// Powers of 1000 become "1kB", "1MB", "1GB", etc. +/// +/// The returned string has a maximum length of 5 chars, for example: "1.1kB", "999kB", "1MB". +fn to_magnitude_and_suffix_not_powers_of_1024(n: u128) -> Result { + let mut i = 0; + + while SI_BASES[i + 1] - SI_BASES[i] < n && i < SI_SUFFIXES.len() { + i += 1; + } + + let quot = n / SI_BASES[i]; + let rem = n % SI_BASES[i]; + let suffix = SI_SUFFIXES[i]; + + if rem == 0 { + Ok(format!("{}{}", quot, suffix)) + } else { + let tenths_place = rem / (SI_BASES[i] / 10); + + if rem % (SI_BASES[i] / 10) == 0 { + Ok(format!("{}.{}{}", quot, tenths_place, suffix)) + } else if tenths_place + 1 == 10 { + Ok(format!("{}{}", quot + 1, suffix)) + } else { + Ok(format!("{}.{}{}", quot, tenths_place + 1, suffix)) + } + } +} + /// Convert a number into a magnitude and a multi-byte unit suffix. /// /// # Errors @@ -66,8 +113,7 @@ fn to_magnitude_and_suffix(n: u128) -> Result { if n % 1024 == 0 { to_magnitude_and_suffix_1024(n) } else { - // TODO Implement this, probably using code from `numfmt`. - Ok("1kB".into()) + to_magnitude_and_suffix_not_powers_of_1024(n) } } @@ -153,36 +199,33 @@ mod tests { ); } - // TODO We have not yet implemented this behavior, but when we do, - // uncomment this test. + #[test] + fn test_to_magnitude_and_suffix_not_powers_of_1024() { + assert_eq!(to_magnitude_and_suffix(1).unwrap(), "1B"); + assert_eq!(to_magnitude_and_suffix(999).unwrap(), "999B"); - // #[test] - // fn test_to_magnitude_and_suffix_not_powers_of_1024() { - // assert_eq!(to_magnitude_and_suffix(1).unwrap(), "1B"); - // assert_eq!(to_magnitude_and_suffix(999).unwrap(), "999B"); + assert_eq!(to_magnitude_and_suffix(1000).unwrap(), "1kB"); + assert_eq!(to_magnitude_and_suffix(1001).unwrap(), "1.1kB"); + assert_eq!(to_magnitude_and_suffix(1023).unwrap(), "1.1kB"); + assert_eq!(to_magnitude_and_suffix(1025).unwrap(), "1.1kB"); + assert_eq!(to_magnitude_and_suffix(999_000).unwrap(), "999kB"); - // assert_eq!(to_magnitude_and_suffix(1000).unwrap(), "1kB"); - // assert_eq!(to_magnitude_and_suffix(1001).unwrap(), "1.1kB"); - // assert_eq!(to_magnitude_and_suffix(1023).unwrap(), "1.1kB"); - // assert_eq!(to_magnitude_and_suffix(1025).unwrap(), "1.1kB"); - // assert_eq!(to_magnitude_and_suffix(999_000).unwrap(), "999kB"); + assert_eq!(to_magnitude_and_suffix(999_001).unwrap(), "1MB"); + assert_eq!(to_magnitude_and_suffix(999_999).unwrap(), "1MB"); + assert_eq!(to_magnitude_and_suffix(1_000_000).unwrap(), "1MB"); + assert_eq!(to_magnitude_and_suffix(1_000_001).unwrap(), "1.1MB"); + assert_eq!(to_magnitude_and_suffix(1_100_000).unwrap(), "1.1MB"); + assert_eq!(to_magnitude_and_suffix(1_100_001).unwrap(), "1.2MB"); + assert_eq!(to_magnitude_and_suffix(1_900_000).unwrap(), "1.9MB"); + assert_eq!(to_magnitude_and_suffix(1_900_001).unwrap(), "2MB"); + assert_eq!(to_magnitude_and_suffix(9_900_000).unwrap(), "9.9MB"); + assert_eq!(to_magnitude_and_suffix(9_900_001).unwrap(), "10MB"); + assert_eq!(to_magnitude_and_suffix(999_000_000).unwrap(), "999MB"); - // assert_eq!(to_magnitude_and_suffix(999_001).unwrap(), "1MB"); - // assert_eq!(to_magnitude_and_suffix(999_999).unwrap(), "1MB"); - // assert_eq!(to_magnitude_and_suffix(1_000_000).unwrap(), "1MB"); - // assert_eq!(to_magnitude_and_suffix(1_000_001).unwrap(), "1.1MB"); - // assert_eq!(to_magnitude_and_suffix(1_100_000).unwrap(), "1.1MB"); - // assert_eq!(to_magnitude_and_suffix(1_100_001).unwrap(), "1.2MB"); - // assert_eq!(to_magnitude_and_suffix(1_900_000).unwrap(), "1.9MB"); - // assert_eq!(to_magnitude_and_suffix(1_900_001).unwrap(), "2MB"); - // assert_eq!(to_magnitude_and_suffix(9_900_000).unwrap(), "9.9MB"); - // assert_eq!(to_magnitude_and_suffix(9_900_001).unwrap(), "10MB"); - // assert_eq!(to_magnitude_and_suffix(999_000_000).unwrap(), "999MB"); - - // assert_eq!(to_magnitude_and_suffix(999_000_001).unwrap(), "1GB"); - // assert_eq!(to_magnitude_and_suffix(1_000_000_000).unwrap(), "1GB"); - // // etc. - // } + assert_eq!(to_magnitude_and_suffix(999_000_001).unwrap(), "1GB"); + assert_eq!(to_magnitude_and_suffix(1_000_000_000).unwrap(), "1GB"); + assert_eq!(to_magnitude_and_suffix(1_000_000_001).unwrap(), "1.1GB"); + } #[test] fn test_block_size_display() { diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 61ddcec5d..ce820bb92 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -413,10 +413,9 @@ fn test_block_size_with_suffix() { assert_eq!(get_header("1KiB"), "1K-blocks"); assert_eq!(get_header("1MiB"), "1M-blocks"); assert_eq!(get_header("1GiB"), "1G-blocks"); - // TODO enable the following asserts when #3193 is resolved - //assert_eq!(get_header("1KB"), "1kB-blocks"); - //assert_eq!(get_header("1MB"), "1MB-blocks"); - //assert_eq!(get_header("1GB"), "1GB-blocks"); + assert_eq!(get_header("1KB"), "1kB-blocks"); + assert_eq!(get_header("1MB"), "1MB-blocks"); + assert_eq!(get_header("1GB"), "1GB-blocks"); } #[test] From 83a64f4afed34f4d0c885ea00d4971cdd9ffdaeb Mon Sep 17 00:00:00 2001 From: Michael Kefeder Date: Sat, 30 Apr 2022 10:01:11 +0200 Subject: [PATCH 026/111] ptx: escape regular expression character class special chars --- src/uu/ptx/src/ptx.rs | 8 +++++++- tests/fixtures/ptx/break_file | 2 +- tests/fixtures/ptx/gnu_ext_disabled_break_file.expected | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index c273b976c..c3bedb266 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -31,6 +31,8 @@ const ABOUT: &str = "\ Mandatory arguments to long options are mandatory for short options too.\n\ With no FILE, or when FILE is -, read standard input. Default is '-F /'."; +const REGEX_CHARCLASS: &str = "^-]\\"; + #[derive(Debug)] enum OutFormat { Dumb, @@ -166,7 +168,11 @@ impl WordFilter { break_set .unwrap() .into_iter() - .map(|c| c.to_string()) + .map(|c| if REGEX_CHARCLASS.contains(c) { + format!("\\{}", c) + } else { + c.to_string() + }) .collect::>() .join("") ) diff --git a/tests/fixtures/ptx/break_file b/tests/fixtures/ptx/break_file index 4c992d40a..499598c20 100644 --- a/tests/fixtures/ptx/break_file +++ b/tests/fixtures/ptx/break_file @@ -1 +1 @@ -abc_e +abc_e^-]\ diff --git a/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected b/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected index 7afce1861..7ea13471d 100644 --- a/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected +++ b/tests/fixtures/ptx/gnu_ext_disabled_break_file.expected @@ -29,6 +29,7 @@ .xx "" "let's check special characte" "rs:" "" .xx "" """quote" "s"", for roff" "" .xx "" "oh, and back\sla" "sh" "" +.xx "" "oh, and back\" "slash" "" .xx "" "and" "some other like %a, b#, c$c" "" .xx "" "let's check" "special characters:" "" .xx "" "let's check special charac" "ters:" "" From 95ba8c45b2898876fdd0b3b279d2729ba0a6cc2f Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sun, 1 May 2022 13:48:51 +0200 Subject: [PATCH 027/111] dir, vdir: fix incorrect regex in tests --- tests/by-util/test_dir.rs | 4 ++-- tests/by-util/test_vdir.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/by-util/test_dir.rs b/tests/by-util/test_dir.rs index 3ec416bb2..8c586a628 100644 --- a/tests/by-util/test_dir.rs +++ b/tests/by-util/test_dir.rs @@ -31,7 +31,7 @@ fn test_default_output() { scene .ucmd() .succeeds() - .stdout_does_not_match(&Regex::new("[rwx][^some-file1]").unwrap()); + .stdout_does_not_match(&Regex::new("[rwx-]{10}.*some-file1$").unwrap()); } #[test] @@ -51,5 +51,5 @@ fn test_long_output() { .ucmd() .arg("-l") .succeeds() - .stdout_matches(&Regex::new("[rwx][^some-file1]").unwrap()); + .stdout_matches(&Regex::new("[rwx-]{10}.*some-file1$").unwrap()); } diff --git a/tests/by-util/test_vdir.rs b/tests/by-util/test_vdir.rs index 01c540095..41bce1c40 100644 --- a/tests/by-util/test_vdir.rs +++ b/tests/by-util/test_vdir.rs @@ -31,7 +31,7 @@ fn test_default_output() { scene .ucmd() .succeeds() - .stdout_matches(&Regex::new("[rwx][^some-file1]").unwrap()); + .stdout_matches(&Regex::new("[rwx-]{10}.*some-file1$").unwrap()); } #[test] @@ -51,5 +51,5 @@ fn test_column_output() { .ucmd() .arg("-C") .succeeds() - .stdout_does_not_match(&Regex::new("[rwx][^some-file1]").unwrap()); + .stdout_does_not_match(&Regex::new("[rwx-]{10}.*some-file1$").unwrap()); } From ca670148f2bf1a247e784f732f241b8278d81291 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 27 Apr 2022 08:43:03 +0200 Subject: [PATCH 028/111] build(deps): bump time from 0.1.43 to 0.3.9 Bumps [time](https://github.com/time-rs/time) from 0.1.43 to 0.3.9. - [Release notes](https://github.com/time-rs/time/releases) - [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md) - [Commits](https://github.com/time-rs/time/compare/v0.1.43...v0.3.9) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 29 +++-- Cargo.toml | 2 +- deny.toml | 3 + src/uu/install/Cargo.toml | 3 + src/uu/pinky/src/pinky.rs | 10 +- src/uu/touch/Cargo.toml | 2 +- src/uu/touch/src/touch.rs | 154 ++++++++++++++++++--------- src/uu/uptime/src/uptime.rs | 6 +- src/uu/who/src/who.rs | 10 +- src/uucore/Cargo.toml | 4 +- src/uucore/src/lib/features/fsext.rs | 12 ++- src/uucore/src/lib/features/utmpx.rs | 14 +-- tests/by-util/test_mv.rs | 6 +- tests/by-util/test_touch.rs | 86 ++++++++------- 14 files changed, 218 insertions(+), 123 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 191ad8923..497d7ab42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,7 +224,7 @@ dependencies = [ "libc", "num-integer", "num-traits", - "time", + "time 0.1.44", "winapi 0.3.9", ] @@ -335,7 +335,7 @@ dependencies = [ "sha1", "tempfile", "textwrap 0.15.0", - "time", + "time 0.3.9", "unindent", "unix_socket", "users", @@ -1213,6 +1213,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -1944,16 +1953,17 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi", "winapi 0.3.9", ] [[package]] -name = "typenum" +< String { thread_local! { - static NOW: time::Tm = time::now() + static NOW: time::OffsetDateTime = time::OffsetDateTime::now_local().unwrap(); } NOW.with(|n| { - let duration = n.to_timespec().sec - when; + let duration = n.unix_timestamp() - when; if duration < 60 { // less than 1min " ".to_owned() @@ -242,7 +242,11 @@ fn idle_string(when: i64) -> String { } fn time_string(ut: &Utmpx) -> String { - time::strftime("%b %e %H:%M", &ut.login_time()).unwrap() // LC_ALL=C + // "%b %e %H:%M" + let time_format: Vec = + time::format_description::parse("[month repr:short] [day padding:space] [hour]:[minute]") + .unwrap(); + ut.login_time().format(&time_format).unwrap() // LC_ALL=C } fn gecos_to_fullname(pw: &Passwd) -> Option { diff --git a/src/uu/touch/Cargo.toml b/src/uu/touch/Cargo.toml index 646b65f50..aa747ae78 100644 --- a/src/uu/touch/Cargo.toml +++ b/src/uu/touch/Cargo.toml @@ -17,7 +17,7 @@ path = "src/touch.rs" [dependencies] filetime = "0.2.1" clap = { version = "3.1", features = ["wrap_help", "cargo"] } -time = "0.1.40" +time = { version = "0.3", features = ["parsing", "formatting", "local-offset", "macros"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["libc"] } [target.'cfg(target_os = "windows")'.dependencies] diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index ff08a1b59..75cd38a7a 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -17,6 +17,7 @@ use clap::{crate_version, Arg, ArgGroup, Command}; use filetime::*; use std::fs::{self, File}; use std::path::{Path, PathBuf}; +use time::macros::{format_description, time}; use uucore::display::Quotable; use uucore::error::{FromIo, UError, UResult, USimpleError}; use uucore::format_usage; @@ -41,14 +42,13 @@ pub mod options { static ARG_FILES: &str = "files"; -fn to_local(mut tm: time::Tm) -> time::Tm { - tm.tm_utcoff = time::now().tm_utcoff; - tm +fn to_local(tm: time::PrimitiveDateTime) -> time::OffsetDateTime { + // TODO: handle error getting now + tm.assume_offset(time::OffsetDateTime::now_local().unwrap().offset()) } -fn local_tm_to_filetime(tm: time::Tm) -> FileTime { - let ts = tm.to_timespec(); - FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32) +fn local_dt_to_filetime(dt: time::OffsetDateTime) -> FileTime { + FileTime::from_unix_time(dt.unix_timestamp(), dt.nanosecond()) } #[uucore::main] @@ -62,7 +62,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { Try 'touch --help' for more information."##, ) })?; - let (mut atime, mut mtime) = if let Some(reference) = matches.value_of_os(options::sources::REFERENCE) { stat(Path::new(reference), !matches.is_present(options::NO_DEREF))? @@ -72,7 +71,7 @@ Try 'touch --help' for more information."##, } else if let Some(current) = matches.value_of(options::sources::CURRENT) { parse_timestamp(current)? } else { - local_tm_to_filetime(time::now()) + local_dt_to_filetime(time::OffsetDateTime::now_local().unwrap()) }; (timestamp, timestamp) }; @@ -248,38 +247,80 @@ fn stat(path: &Path, follow: bool) -> UResult<(FileTime, FileTime)> { )) } -fn parse_date(str: &str) -> UResult { +const POSIX_LOCALE_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[weekday repr:short] [month repr:short] [day padding:space] [hour]:[minute]:[second] [year]" +); + +const ISO_8601_FORMAT: &[time::format_description::FormatItem] = + format_description!("[year]-[month]-[day]"); + +fn parse_date(s: &str) -> UResult { // This isn't actually compatible with GNU touch, but there doesn't seem to // be any simple specification for what format this parameter allows and I'm // not about to implement GNU parse_datetime. // http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y - let formats = vec!["%c", "%F"]; - for f in formats { - if let Ok(tm) = time::strptime(str, f) { - return Ok(local_tm_to_filetime(to_local(tm))); + + // TODO: match on char count? + + // "The preferred date and time representation for the current locale." + // "(In the POSIX locale this is equivalent to %a %b %e %H:%M:%S %Y.)" + // time 0.1.43 parsed this as 'a b e T Y' + // which is equivalent to the POSIX locale: %a %b %e %H:%M:%S %Y + // Tue Dec 3 ... + // ("%c", POSIX_LOCALE_FORMAT), + if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &POSIX_LOCALE_FORMAT) { + return Ok(local_dt_to_filetime(to_local(parsed))); + } + + // "Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99)" + // ("%F", ISO_8601_FORMAT), + if let Ok(parsed) = time::Date::parse(s, &ISO_8601_FORMAT) { + return Ok(local_dt_to_filetime(to_local( + time::PrimitiveDateTime::new(parsed, time!(00:00)), + ))); + } + + // "@%s" is "The number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC). (TZ) (Calculated from mktime(tm).)" + if s.bytes().next() == Some(b'@') { + if let Ok(ts) = &s[1..].parse::() { + // Don't convert to local time in this case - seconds since epoch are not time-zone dependent + return Ok(local_dt_to_filetime( + time::OffsetDateTime::from_unix_timestamp(*ts).unwrap(), + )); } } - if let Ok(tm) = time::strptime(str, "@%s") { - // Don't convert to local time in this case - seconds since epoch are not time-zone dependent - return Ok(local_tm_to_filetime(tm)); - } - - Err(USimpleError::new( - 1, - format!("Unable to parse date: {}", str), - )) + Err(USimpleError::new(1, format!("Unable to parse date: {}", s))) } +// "%Y%m%d%H%M.%S" 15 chars +const YYYYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full][month repr:numerical padding:zero][day][hour][minute].[second]" +); + +// "%Y%m%d%H%M" 12 chars +const YYYYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = + format_description!("[year repr:full][month repr:numerical padding:zero][day][hour][minute]"); + +// "%y%m%d%H%M.%S" 13 chars +const YYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = + format_description!("[year repr:last_two padding:none][month][day][hour][minute].[second]"); + +// "%y%m%d%H%M" 10 chars +const YYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = + format_description!("[year repr:last_two padding:none][month padding:zero][day padding:zero][hour repr:24 padding:zero][minute padding:zero]"); + fn parse_timestamp(s: &str) -> UResult { - let now = time::now(); - let (format, ts) = match s.chars().count() { - 15 => ("%Y%m%d%H%M.%S", s.to_owned()), - 12 => ("%Y%m%d%H%M", s.to_owned()), - 13 => ("%y%m%d%H%M.%S", s.to_owned()), - 10 => ("%y%m%d%H%M", s.to_owned()), - 11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)), - 8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)), + // TODO: handle error + let now = time::OffsetDateTime::now_utc(); + + let (mut format, mut ts) = match s.chars().count() { + 15 => (YYYYMMDDHHMM_DOT_SS_FORMAT, s.to_owned()), + 12 => (YYYYMMDDHHMM_FORMAT, s.to_owned()), + 13 => (YYMMDDHHMM_DOT_SS_FORMAT, s.to_owned()), + 10 => (YYMMDDHHMM_FORMAT, s.to_owned()), + 11 => (YYYYMMDDHHMM_DOT_SS_FORMAT, format!("{}{}", now.year(), s)), + 8 => (YYYYMMDDHHMM_FORMAT, format!("{}{}", now.year(), s)), _ => { return Err(USimpleError::new( 1, @@ -287,30 +328,39 @@ fn parse_timestamp(s: &str) -> UResult { )) } }; - - let tm = time::strptime(&ts, format) - .map_err(|_| USimpleError::new(1, format!("invalid date format {}", s.quote())))?; - - let mut local = to_local(tm); - local.tm_isdst = -1; - let ft = local_tm_to_filetime(local); - - // We have to check that ft is valid time. Due to daylight saving - // time switch, local time can jump from 1:59 AM to 3:00 AM, - // in which case any time between 2:00 AM and 2:59 AM is not valid. - // Convert back to local time and see if we got the same value back. - let ts = time::Timespec { - sec: ft.unix_seconds(), - nsec: 0, - }; - let tm2 = time::at(ts); - if tm.tm_hour != tm2.tm_hour { - return Err(USimpleError::new( - 1, - format!("invalid date format {}", s.quote()), - )); + // workaround time returning Err(TryFromParsed(InsufficientInformation)) for year w/ + // repr:last_two + // https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1ccfac7c07c5d1c7887a11decf0e1996 + if s.chars().count() == 10 { + format = YYYYMMDDHHMM_FORMAT; + ts = "20".to_owned() + &ts; + } else if s.chars().count() == 13 { + format = YYYYMMDDHHMM_DOT_SS_FORMAT; + ts = "20".to_owned() + &ts; } + let tm = time::PrimitiveDateTime::parse(&ts, &format) + .map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?; + + let local = to_local(tm); + let ft = local_dt_to_filetime(local); + + // // We have to check that ft is valid time. Due to daylight saving + // // time switch, local time can jump from 1:59 AM to 3:00 AM, + // // in which case any time between 2:00 AM and 2:59 AM is not valid. + // // Convert back to local time and see if we got the same value back. + // let ts = time::Timespec { + // sec: ft.unix_seconds(), + // nsec: 0, + // }; + // let tm2 = time::at(ts); + // if tm.tm_hour != tm2.tm_hour { + // return Err(USimpleError::new( + // 1, + // format!("invalid date format {}", s.quote()), + // )); + // } + Ok(ft) } diff --git a/src/uu/uptime/src/uptime.rs b/src/uu/uptime/src/uptime.rs index a93344dbc..5c64cb5af 100644 --- a/src/uu/uptime/src/uptime.rs +++ b/src/uu/uptime/src/uptime.rs @@ -111,9 +111,9 @@ fn process_utmpx() -> (Option, usize) { match line.record_type() { USER_PROCESS => nusers += 1, BOOT_TIME => { - let t = line.login_time().to_timespec(); - if t.sec > 0 { - boot_time = Some(t.sec as time_t); + let dt = line.login_time(); + if dt.second() > 0 { + boot_time = Some(dt.second() as time_t); } } _ => continue, diff --git a/src/uu/who/src/who.rs b/src/uu/who/src/who.rs index 6e21ac912..47d96a381 100644 --- a/src/uu/who/src/who.rs +++ b/src/uu/who/src/who.rs @@ -275,10 +275,10 @@ struct Who { fn idle_string<'a>(when: i64, boottime: i64) -> Cow<'a, str> { thread_local! { - static NOW: time::Tm = time::now() + static NOW: time::OffsetDateTime = time::OffsetDateTime::now_local().unwrap(); } NOW.with(|n| { - let now = n.to_timespec().sec; + let now = n.unix_timestamp(); if boottime < when && now - 24 * 3600 < when && when <= now { let seconds_idle = now - when; if seconds_idle < 60 { @@ -298,7 +298,11 @@ fn idle_string<'a>(when: i64, boottime: i64) -> Cow<'a, str> { } fn time_string(ut: &Utmpx) -> String { - time::strftime("%b %e %H:%M", &ut.login_time()).unwrap() // LC_ALL=C + // "%b %e %H:%M" + let time_format: Vec = + time::format_description::parse("[month repr:short] [day padding:space] [hour]:[minute]") + .unwrap(); + ut.login_time().format(&time_format).unwrap() // LC_ALL=C } #[inline] diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 6f74b238a..5b363376d 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -26,7 +26,7 @@ wild = "2.0" # * optional itertools = { version="0.10.0", optional=true } thiserror = { version="1.0", optional=true } -time = { version="<= 0.1.43", optional=true } +time = { version="<= 0.3.10", optional=true, features = ["formatting", "local-offset", "macros"] } # * "problem" dependencies (pinned) data-encoding = { version="2.1", optional=true } data-encoding-macro = { version="0.1.12", optional=true } @@ -62,6 +62,6 @@ process = ["libc"] ringbuffer = [] signals = [] utf8 = [] -utmpx = ["time", "libc", "dns-lookup"] +utmpx = ["time", "time/macros", "libc", "dns-lookup"] wide = [] pipes = ["nix"] diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index eeaf54061..838bfd4b5 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -12,6 +12,7 @@ // spell-checker:ignore (arch) bitrig ; (fs) cifs smbfs extern crate time; +use time::macros::format_description; pub use crate::*; // import macros from `../../macros.rs` @@ -63,7 +64,6 @@ fn LPWSTR2String(buf: &[u16]) -> String { String::from_utf16(&buf[..len]).unwrap() } -use self::time::Timespec; #[cfg(unix)] use libc::{ mode_t, strerror, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, @@ -732,11 +732,17 @@ where } } +// match strftime "%Y-%m-%d %H:%M:%S.%f %z" +const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond] [offset_hour][offset_minute]"); + pub fn pretty_time(sec: i64, nsec: i64) -> String { // sec == seconds since UNIX_EPOCH // nsec == nanoseconds since (UNIX_EPOCH + sec) - let tm = time::at(Timespec::new(sec, nsec as i32)); - let res = time::strftime("%Y-%m-%d %H:%M:%S.%f %z", &tm).unwrap(); + let ts_nanos: i128 = (sec * 1_000_000_000 + nsec).into(); + // TODO: return errors to caller + let tm = time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos).unwrap(); + + let res = tm.format(&PRETTY_DATETIME_FORMAT).unwrap(); if res.ends_with(" -0000") { res.replace(" -0000", " +0000") } else { diff --git a/src/uucore/src/lib/features/utmpx.rs b/src/uucore/src/lib/features/utmpx.rs index 302d03d71..dc66eae09 100644 --- a/src/uucore/src/lib/features/utmpx.rs +++ b/src/uucore/src/lib/features/utmpx.rs @@ -32,7 +32,6 @@ //! ``` pub extern crate time; -use self::time::{Timespec, Tm}; use std::ffi::CString; use std::io::Result as IOResult; @@ -189,11 +188,14 @@ impl Utmpx { chars2string!(self.inner.ut_line) } /// A.K.A. ut.ut_tv - pub fn login_time(&self) -> Tm { - time::at(Timespec::new( - self.inner.ut_tv.tv_sec as i64, - self.inner.ut_tv.tv_usec as i32, - )) + pub fn login_time(&self) -> time::OffsetDateTime { + let ts_nanos: i128 = (self.inner.ut_tv.tv_sec as i64 * 1_000_000_000 as i64 + + self.inner.ut_tv.tv_usec as i64 * 1_000 as i64) + .into(); + let local_offset = time::OffsetDateTime::now_local().unwrap().offset(); + time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos) + .unwrap() + .to_offset(local_offset) } /// A.K.A. ut.ut_exit /// diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index c4ec03d95..06f4d5259 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -595,9 +595,9 @@ fn test_mv_update_option() { at.touch(file_a); at.touch(file_b); - let ts = time::now().to_timespec(); - let now = FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32); - let later = FileTime::from_unix_time(ts.sec as i64 + 3600, ts.nsec as u32); + let ts = time::OffsetDateTime::now_local().unwrap(); + let now = FileTime::from_unix_time(ts.unix_timestamp(), ts.nanosecond()); + let later = FileTime::from_unix_time(ts.unix_timestamp() as i64 + 3600, ts.nanosecond() as u32); filetime::set_file_times(at.plus_as_string(file_a), now, now).unwrap(); filetime::set_file_times(at.plus_as_string(file_b), now, later).unwrap(); diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 6e5d656c4..6de635831 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -4,6 +4,7 @@ extern crate touch; use self::touch::filetime::{self, FileTime}; extern crate time; +use time::macros::{datetime, format_description}; use crate::common::util::*; use std::fs::remove_file; @@ -32,11 +33,18 @@ fn set_file_times(at: &AtPath, path: &str, atime: FileTime, mtime: FileTime) { // Adjusts for local timezone fn str_to_filetime(format: &str, s: &str) -> FileTime { - let mut tm = time::strptime(s, format).unwrap(); - tm.tm_utcoff = time::now().tm_utcoff; - tm.tm_isdst = -1; // Unknown flag DST - let ts = tm.to_timespec(); - FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32) + let format_description = match format { + "%y%m%d%H%M" => format_description!("[year repr:last_two][month][day][hour][minute]"), + "%y%m%d%H%M.%S" => { + format_description!("[year repr:last_two][month][day][hour][minute].[second]") + } + "%Y%m%d%H%M" => format_description!("[year][month][day][hour][minute]"), + "%Y%m%d%H%M.%S" => format_description!("[year][month][day][hour][minute].[second]"), + _ => panic!("unexpected dt format"), + }; + let tm = time::PrimitiveDateTime::parse(&s, &format_description).unwrap(); + let offset_dt = tm.assume_offset(time::OffsetDateTime::now_local().unwrap().offset()); + FileTime::from_unix_time(offset_dt.unix_timestamp(), tm.nanosecond()) } #[test] @@ -83,7 +91,10 @@ fn test_touch_set_mdhm_time() { let start_of_year = str_to_filetime( "%Y%m%d%H%M", - &format!("{}01010000", 1900 + time::now().tm_year), + &format!( + "{}01010000", + time::OffsetDateTime::now_local().unwrap().year() + ), ); let (atime, mtime) = get_file_times(&at, file); assert_eq!(atime, mtime); @@ -104,7 +115,7 @@ fn test_touch_set_mdhms_time() { let start_of_year = str_to_filetime( "%Y%m%d%H%M.%S", - &format!("{}01010000.00", 1900 + time::now().tm_year), + &format!("{}01010000.00", time::OffsetDateTime::now_utc().year()), ); let (atime, mtime) = get_file_times(&at, file); assert_eq!(atime, mtime); @@ -123,7 +134,7 @@ fn test_touch_set_ymdhm_time() { assert!(at.file_exists(file)); - let start_of_year = str_to_filetime("%y%m%d%H%M", "1501010000"); + let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); let (atime, mtime) = get_file_times(&at, file); assert_eq!(atime, mtime); assert_eq!(atime.unix_seconds() - start_of_year.unix_seconds(), 45240); @@ -141,7 +152,7 @@ fn test_touch_set_ymdhms_time() { assert!(at.file_exists(file)); - let start_of_year = str_to_filetime("%y%m%d%H%M.%S", "1501010000.00"); + let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00"); let (atime, mtime) = get_file_times(&at, file); assert_eq!(atime, mtime); assert_eq!(atime.unix_seconds() - start_of_year.unix_seconds(), 45296); @@ -430,18 +441,18 @@ fn test_touch_mtime_dst_succeeds() { assert_eq!(target_time, mtime); } -// is_dst_switch_hour returns true if timespec ts is just before the switch -// to Daylight Saving Time. -// For example, in EST (UTC-5), Timespec { sec: 1583647200, nsec: 0 } -// for March 8 2020 01:00:00 AM -// is just before the switch because on that day clock jumps by 1 hour, -// so 1 minute after 01:59:00 is 03:00:00. -fn is_dst_switch_hour(ts: time::Timespec) -> bool { - let ts_after = ts + time::Duration::hours(1); - let tm = time::at(ts); - let tm_after = time::at(ts_after); - tm_after.tm_hour == tm.tm_hour + 2 -} +// // is_dst_switch_hour returns true if timespec ts is just before the switch +// // to Daylight Saving Time. +// // For example, in EST (UTC-5), Timespec { sec: 1583647200, nsec: 0 } +// // for March 8 2020 01:00:00 AM +// // is just before the switch because on that day clock jumps by 1 hour, +// // so 1 minute after 01:59:00 is 03:00:00. +// fn is_dst_switch_hour(ts: time::Timespec) -> bool { +// let ts_after = ts + time::Duration::hours(1); +// let tm = time::at(ts); +// let tm_after = time::at(ts_after); +// tm_after.tm_hour == tm.tm_hour + 2 +// } // get_dst_switch_hour returns date string for which touch -m -t fails. // For example, in EST (UTC-5), that will be "202003080200" so @@ -450,23 +461,24 @@ fn is_dst_switch_hour(ts: time::Timespec) -> bool { // In other locales it will be a different date/time, and in some locales // it doesn't exist at all, in which case this function will return None. fn get_dst_switch_hour() -> Option { - let now = time::now(); + let now = time::OffsetDateTime::now_local().unwrap(); + // Start from January 1, 2020, 00:00. - let mut tm = time::strptime("20200101-0000", "%Y%m%d-%H%M").unwrap(); - tm.tm_isdst = -1; - tm.tm_utcoff = now.tm_utcoff; - let mut ts = tm.to_timespec(); - // Loop through all hours in year 2020 until we find the hour just - // before the switch to DST. - for _i in 0..(366 * 24) { - if is_dst_switch_hour(ts) { - let mut tm = time::at(ts); - tm.tm_hour += 1; - let s = time::strftime("%Y%m%d%H%M", &tm).unwrap(); - return Some(s); - } - ts = ts + time::Duration::hours(1); - } + let tm = datetime!(2020-01-01 00:00 UTC); + tm.to_offset(now.offset()); + + // let mut ts = tm.to_timespec(); + // // Loop through all hours in year 2020 until we find the hour just + // // before the switch to DST. + // for _i in 0..(366 * 24) { + // // if is_dst_switch_hour(ts) { + // // let mut tm = time::at(ts); + // // tm.tm_hour += 1; + // // let s = time::strftime("%Y%m%d%H%M", &tm).unwrap(); + // // return Some(s); + // // } + // ts = ts + time::Duration::hours(1); + // } None } From f810b55d8660abf98e4d0aad1842a123b3160932 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 23 Apr 2022 22:05:43 +0200 Subject: [PATCH 029/111] build in verbose mode (cfg isn't used) --- .github/workflows/CICD.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 967e77b60..fbe04a1db 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -384,7 +384,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils + args: -v ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils env: RUSTFLAGS: "-Awarnings" From 3a576f2441bb29162576d49170f42241dc0e3581 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 23 Apr 2022 21:32:35 +0200 Subject: [PATCH 030/111] time: Various fixes --- .cargo/config | 9 +++++++++ .github/workflows/CICD.yml | 2 +- Cargo.lock | 30 +++++++++++++++++++++++++--- src/uu/touch/src/touch.rs | 3 +-- src/uucore/src/lib/features/fsext.rs | 2 +- src/uucore/src/lib/features/utmpx.rs | 4 ++-- tests/by-util/test_cp.rs | 12 +++++------ tests/by-util/test_touch.rs | 26 ++++++++++++++++++++---- 8 files changed, 69 insertions(+), 19 deletions(-) diff --git a/.cargo/config b/.cargo/config index 0a8fd3d00..26008597f 100644 --- a/.cargo/config +++ b/.cargo/config @@ -9,3 +9,12 @@ rustflags = [ "-Wclippy::single_char_pattern", "-Wclippy::explicit_iter_loop", ] + +[build] +# See https://github.com/time-rs/time/issues/293#issuecomment-1005002386. The +# unsoundness here is not in the `time` library, but in the Rust stdlib, and as +# such it needs to be fixed there. +rustflags = "--cfg unsound_local_offset" + +[target.'cfg(target_os = "linux")'] +rustflags = ["--cfg", "unsound_local_offset"] diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index fbe04a1db..04acd4c18 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -386,7 +386,7 @@ jobs: command: test args: -v ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils env: - RUSTFLAGS: "-Awarnings" + RUSTFLAGS: "-Awarnings --cfg unsound_local_offset" deps: name: Dependencies diff --git a/Cargo.lock b/Cargo.lock index 497d7ab42..69a83941b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -871,7 +871,7 @@ checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.10.0+wasi-snapshot-preview1", ] [[package]] @@ -985,6 +985,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "keccak" version = "0.1.0" @@ -1958,12 +1964,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] [[package]] -< time::OffsetDateTime { - let ts_nanos: i128 = (self.inner.ut_tv.tv_sec as i64 * 1_000_000_000 as i64 - + self.inner.ut_tv.tv_usec as i64 * 1_000 as i64) + let ts_nanos: i128 = (self.inner.ut_tv.tv_sec as i64 * 1_000_000_000_i64 + + self.inner.ut_tv.tv_usec as i64 * 1_000_i64) .into(); let local_offset = time::OffsetDateTime::now_local().unwrap().offset(); time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos) diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 079e966be..90e85b76a 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -1032,8 +1032,8 @@ fn test_cp_no_deref_folder_to_folder() { #[cfg(target_os = "linux")] fn test_cp_archive() { let (at, mut ucmd) = at_and_ucmd!(); - let ts = time::now().to_timespec(); - let previous = FileTime::from_unix_time(ts.sec as i64 - 3600, ts.nsec as u32); + let ts = time::OffsetDateTime::now_local().unwrap(); + let previous = FileTime::from_unix_time(ts.unix_timestamp() - 3600, ts.nanosecond() as u32); // set the file creation/modification an hour ago filetime::set_file_times( at.plus_as_string(TEST_HELLO_WORLD_SOURCE), @@ -1135,8 +1135,8 @@ fn test_cp_archive_recursive() { #[cfg(any(target_os = "linux", target_os = "android"))] fn test_cp_preserve_timestamps() { let (at, mut ucmd) = at_and_ucmd!(); - let ts = time::now().to_timespec(); - let previous = FileTime::from_unix_time(ts.sec as i64 - 3600, ts.nsec as u32); + let ts = time::OffsetDateTime::now_local().unwrap(); + let previous = FileTime::from_unix_time(ts.unix_timestamp() - 3600, ts.nanosecond()); // set the file creation/modification an hour ago filetime::set_file_times( at.plus_as_string(TEST_HELLO_WORLD_SOURCE), @@ -1168,8 +1168,8 @@ fn test_cp_preserve_timestamps() { #[cfg(any(target_os = "linux", target_os = "android"))] fn test_cp_no_preserve_timestamps() { let (at, mut ucmd) = at_and_ucmd!(); - let ts = time::now().to_timespec(); - let previous = FileTime::from_unix_time(ts.sec as i64 - 3600, ts.nsec as u32); + let ts = time::OffsetDateTime::now_local().unwrap(); + let previous = FileTime::from_unix_time(ts.unix_timestamp() - 3600, ts.nanosecond()); // set the file creation/modification an hour ago filetime::set_file_times( at.plus_as_string(TEST_HELLO_WORLD_SOURCE), diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 6de635831..2c538d8b4 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -1,4 +1,10 @@ -// spell-checker:ignore (formats) cymdhm cymdhms mdhm mdhms ymdhm ymdhms +// spell-checker:ignore (formats) cymdhm cymdhms mdhm mdhms ymdhm ymdhms datetime mktime + +// This test relies on +// --cfg unsound_local_offset +// https://github.com/time-rs/time/blob/deb8161b84f355b31e39ce09e40c4d6ce3fea837/src/sys/local_offset_at/unix.rs#L112-L120= +// See https://github.com/time-rs/time/issues/293#issuecomment-946382614= +// Defined in .cargo/config extern crate touch; use self::touch::filetime::{self, FileTime}; @@ -42,8 +48,14 @@ fn str_to_filetime(format: &str, s: &str) -> FileTime { "%Y%m%d%H%M.%S" => format_description!("[year][month][day][hour][minute].[second]"), _ => panic!("unexpected dt format"), }; - let tm = time::PrimitiveDateTime::parse(&s, &format_description).unwrap(); - let offset_dt = tm.assume_offset(time::OffsetDateTime::now_local().unwrap().offset()); + let tm = time::PrimitiveDateTime::parse(s, &format_description).unwrap(); + let d = match time::OffsetDateTime::now_local() { + Ok(now) => now, + Err(e) => { + panic!("Error {} retrieving the OffsetDateTime::now_local", e); + } + }; + let offset_dt = tm.assume_offset(d.offset()); FileTime::from_unix_time(offset_dt.unix_timestamp(), tm.nanosecond()) } @@ -461,7 +473,13 @@ fn test_touch_mtime_dst_succeeds() { // In other locales it will be a different date/time, and in some locales // it doesn't exist at all, in which case this function will return None. fn get_dst_switch_hour() -> Option { - let now = time::OffsetDateTime::now_local().unwrap(); + //let now = time::OffsetDateTime::now_local().unwrap(); + let now = match time::OffsetDateTime::now_local() { + Ok(now) => now, + Err(e) => { + panic!("Error {} retrieving the OffsetDateTime::now_local", e); + } + }; // Start from January 1, 2020, 00:00. let tm = datetime!(2020-01-01 00:00 UTC); From e23dd687155c91e50d1c9f90dbfe7d9ef047657a Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 24 Apr 2022 09:50:39 +0200 Subject: [PATCH 031/111] time: Force the display of the tz sign --- src/uucore/src/lib/features/fsext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 75a0c2f97..0d64661ee 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -733,7 +733,7 @@ where } // match strftime "%Y-%m-%d %H:%M:%S.%f %z" -const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond] [offset_hour][offset_minute]"); +const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond] [offset_hour sign:mandatory][offset_minute]"); pub fn pretty_time(sec: i64, nsec: i64) -> String { // sec == seconds since UNIX_EPOCH From 326dc5080d74dd79406fa828e1754d50e78e9e8e Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 24 Apr 2022 09:50:58 +0200 Subject: [PATCH 032/111] stat: add a test to verify time easily --- tests/by-util/test_stat.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 90ad2d12a..6140f5017 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -283,6 +283,25 @@ fn test_char() { ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } +#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))] +#[test] +fn test_date() { + // Just test the date for the time 0.3 change + let args = [ + "-c", + #[cfg(any(target_os = "linux", target_os = "android"))] + "%z", + #[cfg(target_os = "linux")] + "/dev/pts/ptmx", + #[cfg(any(target_vendor = "apple"))] + "%z", + #[cfg(any(target_os = "android", target_vendor = "apple"))] + "/dev/ptmx", + ]; + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); +} #[cfg(unix)] #[test] fn test_multi_files() { From 10eaaae2723f61f8588dabcb78df9ec57f7ce80c Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 24 Apr 2022 09:51:15 +0200 Subject: [PATCH 033/111] time: take in account the local tz --- src/uucore/src/lib/features/fsext.rs | 29 ++++++++++++++++++++++++---- tests/by-util/test_stat.rs | 17 +++++++++++++++- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 0d64661ee..3f5b2b77c 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -13,6 +13,7 @@ extern crate time; use time::macros::format_description; +use time::UtcOffset; pub use crate::*; // import macros from `../../macros.rs` @@ -733,16 +734,36 @@ where } // match strftime "%Y-%m-%d %H:%M:%S.%f %z" -const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond] [offset_hour sign:mandatory][offset_minute]"); +const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond digits:9] [offset_hour sign:mandatory][offset_minute]"); pub fn pretty_time(sec: i64, nsec: i64) -> String { // sec == seconds since UNIX_EPOCH // nsec == nanoseconds since (UNIX_EPOCH + sec) let ts_nanos: i128 = (sec * 1_000_000_000 + nsec).into(); - // TODO: return errors to caller - let tm = time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos).unwrap(); - let res = tm.format(&PRETTY_DATETIME_FORMAT).unwrap(); + // Return the date in UTC + let tm = match time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos) { + Ok(tm) => tm, + Err(e) => { + panic!("error: {}", e); + } + }; + + // Get the offset to convert to local time + // Because of DST (daylight saving), we get the local time back when + // the date was set + let local_offset = match UtcOffset::local_offset_at(tm) { + Ok(lo) => lo, + Err(e) => { + panic!("error: {}", e); + } + }; + + // Include the conversion to local time + let res = tm + .to_offset(local_offset) + .format(&PRETTY_DATETIME_FORMAT) + .unwrap(); if res.ends_with(" -0000") { res.replace(" -0000", " +0000") } else { diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 6140f5017..0871a48fe 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -292,7 +292,22 @@ fn test_date() { #[cfg(any(target_os = "linux", target_os = "android"))] "%z", #[cfg(target_os = "linux")] - "/dev/pts/ptmx", + "/bin/sh", + #[cfg(any(target_vendor = "apple"))] + "%z", + #[cfg(any(target_os = "android", target_vendor = "apple"))] + "/bin/sh", + ]; + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); + // Just test the date for the time 0.3 change + let args = [ + "-c", + #[cfg(any(target_os = "linux", target_os = "android"))] + "%z", + #[cfg(target_os = "linux")] + "/dev/ptmx", #[cfg(any(target_vendor = "apple"))] "%z", #[cfg(any(target_os = "android", target_vendor = "apple"))] From 3b3585bbe548a5259944685f3114c84730155929 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 27 Apr 2022 08:43:59 +0200 Subject: [PATCH 034/111] add time 0.1.44 to cargo deny And no longer ignore RUSTSEC-2022-0013 --- deny.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 1d790456f..f659910e8 100644 --- a/deny.toml +++ b/deny.toml @@ -12,7 +12,6 @@ yanked = "warn" notice = "warn" ignore = [ "RUSTSEC-2020-0159", - "RUSTSEC-2022-0013", "RUSTSEC-2020-0071", #"RUSTSEC-0000-0000", ] @@ -87,6 +86,8 @@ skip = [ { name = "memchr", version = "=1.0.2" }, { name = "quote", version = "=0.3.15" }, { name = "unicode-xid", version = "=0.0.4" }, + # chrono + { name = "time", version = "=0.1.44" }, ] # spell-checker: enable From c009e1bed8a5b9c5eef667584fcf2b632dcdfaa2 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Thu, 28 Apr 2022 00:06:07 +0200 Subject: [PATCH 035/111] workaround the tests/touch/60-seconds test to skip leap second --- src/uu/touch/src/touch.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index a3a344ad4..e74aaa700 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -337,7 +337,12 @@ fn parse_timestamp(s: &str) -> UResult { format = YYYYMMDDHHMM_DOT_SS_FORMAT; ts = "20".to_owned() + &ts; } - + if (format == YYYYMMDDHHMM_DOT_SS_FORMAT || format == YYMMDDHHMM_DOT_SS_FORMAT) + && ts.ends_with(".60") + { + // Work around to disable leap seconds + ts = ts.replace(".60", ".59"); + } let tm = time::PrimitiveDateTime::parse(&ts, &format) .map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?; From 2b11d773952fb45de8fa0a4360b67c160f24ed49 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Thu, 28 Apr 2022 08:22:48 +0200 Subject: [PATCH 036/111] time: Improve the l&f --- src/uu/touch/src/touch.rs | 24 ++++++++++++++++-------- src/uucore/Cargo.toml | 2 +- src/uucore/src/lib/features/fsext.rs | 7 ++++++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index e74aaa700..9a4c0fe5d 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -247,7 +247,8 @@ fn stat(path: &Path, follow: bool) -> UResult<(FileTime, FileTime)> { } const POSIX_LOCALE_FORMAT: &[time::format_description::FormatItem] = format_description!( - "[weekday repr:short] [month repr:short] [day padding:space] [hour]:[minute]:[second] [year]" + "[weekday repr:short] [month repr:short] [day padding:space] \ + [hour]:[minute]:[second] [year]" ); const ISO_8601_FORMAT: &[time::format_description::FormatItem] = @@ -294,20 +295,27 @@ fn parse_date(s: &str) -> UResult { // "%Y%m%d%H%M.%S" 15 chars const YYYYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( - "[year repr:full][month repr:numerical padding:zero][day][hour][minute].[second]" + "[year repr:full][month repr:numerical padding:zero]\ + [day][hour][minute].[second]" ); // "%Y%m%d%H%M" 12 chars -const YYYYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = - format_description!("[year repr:full][month repr:numerical padding:zero][day][hour][minute]"); +const YYYYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full][month repr:numerical padding:zero]\ + [day][hour][minute]" +); // "%y%m%d%H%M.%S" 13 chars -const YYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = - format_description!("[year repr:last_two padding:none][month][day][hour][minute].[second]"); +const YYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:last_two padding:none][month][day]\ + [hour][minute].[second]" +); // "%y%m%d%H%M" 10 chars -const YYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = - format_description!("[year repr:last_two padding:none][month padding:zero][day padding:zero][hour repr:24 padding:zero][minute padding:zero]"); +const YYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:last_two padding:none][month padding:zero][day padding:zero]\ + [hour repr:24 padding:zero][minute padding:zero]" +); fn parse_timestamp(s: &str) -> UResult { // TODO: handle error diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 5b363376d..c86a8cf07 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -26,7 +26,7 @@ wild = "2.0" # * optional itertools = { version="0.10.0", optional=true } thiserror = { version="1.0", optional=true } -time = { version="<= 0.3.10", optional=true, features = ["formatting", "local-offset", "macros"] } +time = { version="<= 0.3", optional=true, features = ["formatting", "local-offset", "macros"] } # * "problem" dependencies (pinned) data-encoding = { version="2.1", optional=true } data-encoding-macro = { version="0.1.12", optional=true } diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 3f5b2b77c..3d7ca1c1f 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -734,7 +734,12 @@ where } // match strftime "%Y-%m-%d %H:%M:%S.%f %z" -const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond digits:9] [offset_hour sign:mandatory][offset_minute]"); +const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!( + "\ +[year]-[month]-[day padding:zero] \ +[hour]:[minute]:[second].[subsecond digits:9] \ +[offset_hour sign:mandatory][offset_minute]" +); pub fn pretty_time(sec: i64, nsec: i64) -> String { // sec == seconds since UNIX_EPOCH From 31c28eeaa98854797eb432aa6c890002c5133b0b Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 29 Apr 2022 10:28:49 +0200 Subject: [PATCH 037/111] fix gnu/tests/touch/60-seconds --- src/uu/touch/src/touch.rs | 18 ++++++++++++++---- tests/by-util/test_touch.rs | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 9a4c0fe5d..331867b5f 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -17,6 +17,7 @@ use filetime::*; use std::fs::{self, File}; use std::path::{Path, PathBuf}; use time::macros::{format_description, time}; +use time::Duration; use uucore::display::Quotable; use uucore::error::{FromIo, UError, UResult, USimpleError}; use uucore::format_usage; @@ -345,16 +346,25 @@ fn parse_timestamp(s: &str) -> UResult { format = YYYYMMDDHHMM_DOT_SS_FORMAT; ts = "20".to_owned() + &ts; } - if (format == YYYYMMDDHHMM_DOT_SS_FORMAT || format == YYMMDDHHMM_DOT_SS_FORMAT) + + let leap_sec = if (format == YYYYMMDDHHMM_DOT_SS_FORMAT || format == YYMMDDHHMM_DOT_SS_FORMAT) && ts.ends_with(".60") { // Work around to disable leap seconds + // Used in gnu/tests/touch/60-seconds ts = ts.replace(".60", ".59"); - } + true + } else { + false + }; + let tm = time::PrimitiveDateTime::parse(&ts, &format) .map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?; - - let local = to_local(tm); + let mut local = to_local(tm); + if leap_sec { + // We are dealing with a leap second, add it + local = local.saturating_add(Duration::SECOND); + } let ft = local_dt_to_filetime(local); // // We have to check that ft is valid time. Due to daylight saving diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 2c538d8b4..d23fb090e 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -603,3 +603,21 @@ fn test_no_dereference_no_file() { .stderr_contains("setting times of 'not-a-file-1': No such file or directory") .stderr_contains("setting times of 'not-a-file-2': No such file or directory"); } + +#[test] +fn test_touch_leap_second() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "test_touch_leap_sec"; + + ucmd.args(&["-t", "197001010000.60", file]) + .succeeds() + .no_stderr(); + + assert!(at.file_exists(file)); + + let epoch = str_to_filetime("%Y%m%d%H%M", "197001010000"); + let (atime, mtime) = get_file_times(&at, file); + assert_eq!(atime, mtime); + assert_eq!(atime.unix_seconds() - epoch.unix_seconds(), 60); + assert_eq!(mtime.unix_seconds() - epoch.unix_seconds(), 60); +} From 9d81d6fef2729db4765529cf4b3b195a4b513626 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 29 Apr 2022 10:32:28 +0200 Subject: [PATCH 038/111] touch: add support of -d '1970-01-01 18:43:33.023456789' --- deny.toml | 2 +- src/uu/touch/src/touch.rs | 74 +++++++++++++++++++++++-------------- tests/by-util/test_touch.rs | 36 ++++++++++++++++++ 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/deny.toml b/deny.toml index f659910e8..8154bbf90 100644 --- a/deny.toml +++ b/deny.toml @@ -64,7 +64,7 @@ highlight = "all" # spell-checker: disable skip = [ # getrandom - { name = "wasi", version="0.10.2+wasi-snapshot-preview1" }, + { name = "wasi", version="0.10.0+wasi-snapshot-preview1" }, # blake2d_simd { name = "arrayvec", version = "=0.7.2" }, # flimit/unix_socket diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 331867b5f..5264401ef 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -6,7 +6,7 @@ // For the full copyright and license information, please view the LICENSE file // that was distributed with this source code. -// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm clapv PWSTR lpszfilepath hresult mktime YYYYMMDDHHMM YYMMDDHHMM DATETIME subsecond +// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm clapv PWSTR lpszfilepath hresult mktime YYYYMMDDHHMM YYMMDDHHMM DATETIME YYYYMMDDHHMMS pub extern crate filetime; #[macro_use] @@ -255,6 +255,41 @@ const POSIX_LOCALE_FORMAT: &[time::format_description::FormatItem] = format_desc const ISO_8601_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day]"); +// "%Y%m%d%H%M.%S" 15 chars +const YYYYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full][month repr:numerical padding:zero]\ + [day][hour][minute].[second]" +); + +// "%Y-%m-%d %H:%M:%S.%SS" 12 chars +const YYYYMMDDHHMMSS_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full]-[month repr:numerical padding:zero]-\ + [day] [hour]:[minute]:[second].[subsecond]" +); +// "%Y-%m-%d %H:%M:%S" 12 chars +const YYYYMMDDHHMMS_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full]-[month repr:numerical padding:zero]-\ + [day] [hour]:[minute]:[second]" +); + +// "%Y%m%d%H%M" 12 chars +const YYYYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full][month repr:numerical padding:zero]\ + [day][hour][minute]" +); + +// "%y%m%d%H%M.%S" 13 chars +const YYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:last_two padding:none][month][day]\ + [hour][minute].[second]" +); + +// "%y%m%d%H%M" 10 chars +const YYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:last_two padding:none][month padding:zero][day padding:zero]\ + [hour repr:24 padding:zero][minute padding:zero]" +); + fn parse_date(s: &str) -> UResult { // This isn't actually compatible with GNU touch, but there doesn't seem to // be any simple specification for what format this parameter allows and I'm @@ -269,8 +304,17 @@ fn parse_date(s: &str) -> UResult { // which is equivalent to the POSIX locale: %a %b %e %H:%M:%S %Y // Tue Dec 3 ... // ("%c", POSIX_LOCALE_FORMAT), - if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &POSIX_LOCALE_FORMAT) { - return Ok(local_dt_to_filetime(to_local(parsed))); + // + // But also support other format found in the GNU tests like + // in tests/misc/stat-nanoseconds.sh + for fmt in [ + POSIX_LOCALE_FORMAT, + YYYYMMDDHHMMS_FORMAT, + YYYYMMDDHHMMSS_FORMAT, + ] { + if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &fmt) { + return Ok(local_dt_to_filetime(to_local(parsed))); + } } // "Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99)" @@ -294,30 +338,6 @@ fn parse_date(s: &str) -> UResult { Err(USimpleError::new(1, format!("Unable to parse date: {}", s))) } -// "%Y%m%d%H%M.%S" 15 chars -const YYYYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( - "[year repr:full][month repr:numerical padding:zero]\ - [day][hour][minute].[second]" -); - -// "%Y%m%d%H%M" 12 chars -const YYYYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( - "[year repr:full][month repr:numerical padding:zero]\ - [day][hour][minute]" -); - -// "%y%m%d%H%M.%S" 13 chars -const YYMMDDHHMM_DOT_SS_FORMAT: &[time::format_description::FormatItem] = format_description!( - "[year repr:last_two padding:none][month][day]\ - [hour][minute].[second]" -); - -// "%y%m%d%H%M" 10 chars -const YYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( - "[year repr:last_two padding:none][month padding:zero][day padding:zero]\ - [hour repr:24 padding:zero][minute padding:zero]" -); - fn parse_timestamp(s: &str) -> UResult { // TODO: handle error let now = time::OffsetDateTime::now_utc(); diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index d23fb090e..ed62692f4 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -427,6 +427,42 @@ fn test_touch_set_date3() { assert_eq!(mtime, expected); } +#[test] +fn test_touch_set_date4() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "test_touch_set_date"; + + ucmd.args(&["-d", "1970-01-01 18:43:33", file]) + .succeeds() + .no_stderr(); + + assert!(at.file_exists(file)); + + let expected = FileTime::from_unix_time(60213, 0); + let (atime, mtime) = get_file_times(&at, file); + assert_eq!(atime, mtime); + assert_eq!(atime, expected); + assert_eq!(mtime, expected); +} + +#[test] +fn test_touch_set_date5() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "test_touch_set_date"; + + ucmd.args(&["-d", "1970-01-01 18:43:33.023456789", file]) + .succeeds() + .no_stderr(); + + assert!(at.file_exists(file)); + + let expected = FileTime::from_unix_time(60213, 023456789); + let (atime, mtime) = get_file_times(&at, file); + assert_eq!(atime, mtime); + assert_eq!(atime, expected); + assert_eq!(mtime, expected); +} + #[test] fn test_touch_set_date_wrong_format() { let (_at, mut ucmd) = at_and_ucmd!(); From 417b4a22d093c225c78d4fffca17b8926a261912 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 1 May 2022 17:07:29 +0200 Subject: [PATCH 039/111] GNU CI: show the new error --- .github/workflows/GnuTests.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index d306092c6..fedd6e4d5 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -170,6 +170,8 @@ jobs: REPO_DEFAULT_BRANCH='${{ steps.vars.outputs.repo_default_branch }}' if test -f "${REF_LOG_FILE}"; then echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")" + REF_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) + NEW_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) REF_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) NEW_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) for LINE in ${REF_FAILING} @@ -186,6 +188,21 @@ jobs: have_new_failures="true" fi done + for LINE in ${REF_ERROR} + do + if ! grep -Fxq ${LINE}<<<"${NEW_ERROR}"; then + echo "::warning ::Congrats! The gnu test ${LINE} is no longer ERROR!" + fi + done + for LINE in ${NEW_ERROR} + do + if ! grep -Fxq ${LINE}<<<"${REF_ERROR}" + then + echo "::error ::GNU test failed: ${LINE}. ${LINE} is passing on '${{ steps.vars.outputs.repo_default_branch }}'. Maybe you have to rebase?" + have_new_failures="true" + fi + done + else echo "::warning ::Skipping test failure comparison; no prior reference test logs are available." fi From ae65dcc7d2affbf6b50145ed38f58e04f2bd1b86 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 1 May 2022 17:07:29 +0200 Subject: [PATCH 040/111] GNU CI: show the new error --- .github/workflows/GnuTests.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index d306092c6..f2b0ddd45 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -170,6 +170,8 @@ jobs: REPO_DEFAULT_BRANCH='${{ steps.vars.outputs.repo_default_branch }}' if test -f "${REF_LOG_FILE}"; then echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")" + REF_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) + NEW_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) REF_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) NEW_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) for LINE in ${REF_FAILING} @@ -186,6 +188,21 @@ jobs: have_new_failures="true" fi done + for LINE in ${REF_ERROR} + do + if ! grep -Fxq ${LINE}<<<"${NEW_ERROR}"; then + echo "::warning ::Congrats! The gnu test ${LINE} is no longer ERROR!" + fi + done + for LINE in ${NEW_ERROR} + do + if ! grep -Fxq ${LINE}<<<"${REF_ERROR}" + then + echo "::error ::GNU test error: ${LINE}. ${LINE} is passing on '${{ steps.vars.outputs.repo_default_branch }}'. Maybe you have to rebase?" + have_new_failures="true" + fi + done + else echo "::warning ::Skipping test failure comparison; no prior reference test logs are available." fi From aa6aefbd64aa2acf2ce1644e1d003a6947d2790a Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 1 May 2022 12:03:02 -0400 Subject: [PATCH 041/111] mktemp: respect path given in template argument Fix a bug in `mktemp` where it was not respecting the path given by the positional argument. Previously, it would place the temporary file whose name is induced by a given template in the `/tmp` directory, like this: $ mktemp XXX /tmp/LJr $ mktemp d/XXX /tmp/d/IhS After this commit, it respects the directory given in the template argument: $ mktemp XXX LJr $ mktemp d/XXX d/IhS Fixes #3440. --- src/uu/mktemp/src/mktemp.rs | 44 +++++++++++++++++++---- tests/by-util/test_mktemp.rs | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 7 deletions(-) diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index 54283b9af..f999d6675 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -79,7 +79,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let template = matches.value_of(ARG_TEMPLATE).unwrap(); let tmpdir = matches.value_of(OPT_TMPDIR).unwrap_or_default(); - let (template, mut tmpdir) = if matches.is_present(OPT_TMPDIR) + // Treat the template string as a path to get the directory + // containing the last component. + let path = PathBuf::from(template); + + let (template, tmpdir) = if matches.is_present(OPT_TMPDIR) && !PathBuf::from(tmpdir).is_dir() // if a temp dir is provided, it must be an actual path && tmpdir.contains("XXX") // If this is a template, it has to contain at least 3 X @@ -97,8 +101,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let tmp = env::temp_dir(); (tmpdir, tmp) } else if !matches.is_present(OPT_TMPDIR) { - let tmp = env::temp_dir(); - (template, tmp) + // In this case, the command line was `mktemp -t XXX`, so we + // treat the argument `XXX` as though it were a filename + // regardless of whether it has path separators in it. + if matches.is_present(OPT_T) { + let tmp = env::temp_dir(); + (template, tmp) + // In this case, the command line was `mktemp XXX`, so we need + // to parse out the parent directory and the filename from the + // argument `XXX`, since it may be include path separators. + } else { + let tmp = match path.parent() { + None => PathBuf::from("."), + Some(d) => PathBuf::from(d), + }; + let filename = path.file_name(); + let template = filename.unwrap().to_str().unwrap(); + (template, tmp) + } } else { (template, PathBuf::from(tmpdir)) }; @@ -113,10 +133,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { return Err(MkTempError::InvalidTemplate(template.into()).into()); } - if matches.is_present(OPT_T) { - tmpdir = env::temp_dir(); - } - let res = if dry_run { dry_exec(tmpdir, prefix, rand, suffix) } else { @@ -272,5 +288,19 @@ fn exec(dir: &Path, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> .map_err(|e| MkTempError::PersistError(e.file.path().to_path_buf()))? .1 }; + + // Get just the last component of the path to the created + // temporary file or directory. + let filename = path.file_name(); + let filename = filename.unwrap().to_str().unwrap(); + + // Join the directory to the path to get the path to print. We + // cannot use the path returned by the `Builder` because it gives + // the absolute path and we need to return a filename that matches + // the template given on the command-line which might be a + // relative path. + let mut path = dir.to_path_buf(); + path.push(filename); + println_verbatim(path).map_err_context(|| "failed to print directory name".to_owned()) } diff --git a/tests/by-util/test_mktemp.rs b/tests/by-util/test_mktemp.rs index e824df061..13d7c8e21 100644 --- a/tests/by-util/test_mktemp.rs +++ b/tests/by-util/test_mktemp.rs @@ -411,3 +411,71 @@ fn test_mktemp_directory_tmpdir() { result.no_stderr().stdout_contains("apt-key-gpghome."); assert!(PathBuf::from(result.stdout_str().trim()).is_dir()); } + +/// Decide whether a string matches a given template. +/// +/// In the template, the character `'X'` is treated as a wildcard, +/// that is, it matches anything. All other characters in `template` +/// and `s` must match exactly. +/// +/// # Examples +/// +/// ```rust,ignore +/// # These all match. +/// assert!(matches_template("abc", "abc")); +/// assert!(matches_template("aXc", "abc")); +/// assert!(matches_template("XXX", "abc")); +/// +/// # None of these match +/// assert!(matches_template("abc", "abcd")); +/// assert!(matches_template("abc", "ab")); +/// assert!(matches_template("aXc", "abd")); +/// assert!(matches_template("XXX", "abcd")); +/// ``` +/// +fn matches_template(template: &str, s: &str) -> bool { + if template.len() != s.len() { + return false; + } + for (a, b) in template.chars().zip(s.chars()) { + if !(a == 'X' || a == b) { + return false; + } + } + true +} + +/// An assertion that uses [`matches_template`] and adds a helpful error message. +macro_rules! assert_matches_template { + ($template:expr, $s:expr) => {{ + assert!( + matches_template($template, $s), + "\"{}\" != \"{}\"", + $template, + $s + ); + }}; +} + +/// Test that the file is created in the directory given by the template. +#[test] +fn test_respect_template() { + let (at, mut ucmd) = at_and_ucmd!(); + let template = "XXX"; + let result = ucmd.arg(template).succeeds(); + let filename = result.no_stderr().stdout_str().trim_end(); + assert_matches_template!(template, filename); + assert!(at.file_exists(filename)); +} + +/// Test that the file is created in the directory given by the template. +#[test] +fn test_respect_template_directory() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkdir("d"); + let template = "d/XXX"; + let result = ucmd.arg(template).succeeds(); + let filename = result.no_stderr().stdout_str().trim_end(); + assert_matches_template!(template, filename); + assert!(at.file_exists(filename)); +} From 0314f3ed8e6b0560fa67d2d6cf48133161334575 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 1 May 2022 12:51:40 +0200 Subject: [PATCH 042/111] GNU testsuite: no need to rerun the GNU build At least, two use cases: * when hacking on test update * when we want to rebuild only Rust coreutils with the right option Indeed, the GNU code should not cache often in this case --- util/build-gnu.sh | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/util/build-gnu.sh b/util/build-gnu.sh index 6f0ec32f7..83993fde9 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -62,14 +62,23 @@ for binary in $(./build-aux/gen-lists-of-programs.sh --list-progs); do } done -./bootstrap -./configure --quiet --disable-gcc-warnings -#Add timeout to to protect against hangs -sed -i 's|^"\$@|/usr/bin/timeout 600 "\$@|' build-aux/test-driver -# Change the PATH in the Makefile to test the uutils coreutils instead of the GNU coreutils -sed -i "s/^[[:blank:]]*PATH=.*/ PATH='${UU_BUILD_DIR//\//\\/}\$(PATH_SEPARATOR)'\"\$\$PATH\" \\\/" Makefile -sed -i 's| tr | /usr/bin/tr |' tests/init.sh -make -j "$(nproc)" +if test -f gnu-built; then + echo "GNU build already found. Skip" + echo "'rm -f $(pwd)/gnu-built' to force the build" + echo "Note: the customization of the tests will still happen" + exit 0 +else + ./bootstrap + ./configure --quiet --disable-gcc-warnings + #Add timeout to to protect against hangs + sed -i 's|^"\$@|/usr/bin/timeout 600 "\$@|' build-aux/test-driver + # Change the PATH in the Makefile to test the uutils coreutils instead of the GNU coreutils + sed -i "s/^[[:blank:]]*PATH=.*/ PATH='${UU_BUILD_DIR//\//\\/}\$(PATH_SEPARATOR)'\"\$\$PATH\" \\\/" Makefile + sed -i 's| tr | /usr/bin/tr |' tests/init.sh + make -j "$(nproc)" + touch gnu-built +fi + # Handle generated factor tests t_first=00 t_max=36 From 2e60dce11a04c69b697b884020185e85fda14061 Mon Sep 17 00:00:00 2001 From: Hanif Ariffin Date: Fri, 4 Feb 2022 19:29:24 +0800 Subject: [PATCH 043/111] printf: Default left-justify integer conversion to 1 width When using left-justify with integer conversion (like `printf '%-o'`), default the minimum width to 1. Closes: https://github.com/uutils/coreutils/issues/3050 Signed-off-by: Hanif Ariffin --- src/uucore/src/lib/features/tokenize/sub.rs | 6 +++++- tests/by-util/test_printf.rs | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/tokenize/sub.rs b/src/uucore/src/lib/features/tokenize/sub.rs index f8b5b5caf..216953a43 100644 --- a/src/uucore/src/lib/features/tokenize/sub.rs +++ b/src/uucore/src/lib/features/tokenize/sub.rs @@ -152,7 +152,11 @@ impl SubParser { if parser.min_width_is_asterisk { CanAsterisk::Asterisk } else { - CanAsterisk::Fixed(parser.min_width_tmp.map(|x| x.parse::().unwrap())) + CanAsterisk::Fixed( + parser + .min_width_tmp + .map(|x| x.parse::().unwrap_or(1)), + ) }, if parser.second_field_is_asterisk { CanAsterisk::Asterisk diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index d5be4cd17..77f64750c 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -446,6 +446,14 @@ fn sub_any_specifiers_after_period() { .stdout_only("3"); } +#[test] +fn unspecified_left_justify_is_1_width() { + new_ucmd!() + .args(&["%-o"]) //spell-checker:disable-line + .succeeds() + .stdout_only("0"); +} + #[test] fn sub_any_specifiers_after_second_param() { new_ucmd!() From e991838ca8072b58ceccc3e9fd3b784cb0f61a71 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 19 Sep 2021 22:24:11 +0200 Subject: [PATCH 044/111] tests/util: add a convenience wrapper to run a ucmd with root permissions --- tests/common/util.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tests/common/util.rs b/tests/common/util.rs index 5a669fcd4..47f8eb842 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1362,6 +1362,58 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< )) } +/// This is a convenience wrapper to run a ucmd with root permissions. +/// This runs 'sudo -E --non-interactive target/debug/coreutils util_name args` +/// This is primarily designed to run in the CICD environment where whoami is in $path +/// and where non-interactive sudo is possible. +/// To check if i) non-interactive sudo is possible and ii) if sudo works, this runs: +/// 'sudo -E --non-interactive whoami' first. +/// +/// Example: +/// +/// ```no_run +/// use crate::common::util::*; +/// #[test] +/// fn test_xyz() { +/// let ts = TestScenario::new("whoami"); +/// let expected = "root\n".to_string(); +/// if let Ok(result) = run_ucmd_as_root(&ts, &[]) { +/// result.stdout_is(expected); +/// } else { +/// print!("TEST SKIPPED"); +/// } +/// } +///``` +#[cfg(unix)] +pub fn run_ucmd_as_root( + ts: &TestScenario, + args: &[&str], +) -> std::result::Result { + if ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg("whoami") + .run() + .stdout_str() + .trim() + != "root" + { + Err("\"sudo whoami\" didn't return \"root\"".to_string()) + } else { + Ok(ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg(&ts.bin_path) + .arg(&ts.util_name) + .args(args) + .run()) + } +} + /// Sanity checks for test utils #[cfg(test)] mod tests { @@ -1712,4 +1764,20 @@ mod tests { std::assert_eq!(host_name_for("gwho"), "gwho"); } } + + #[test] + #[cfg(unix)] + fn test_run_ucmd_as_root() { + // We need non-interactive `sudo. + // CICD environment should allow non-interactive `sudo`. + // Return early if we can't guarantee non-interactive `sudo` + if !is_ci() { + return; + } + let ts = TestScenario::new("whoami"); + std::assert_eq!( + run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), + "root" + ); + } } From de01b11a7d2a332153a2db948e4d8ef4f1f493c2 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Mon, 20 Sep 2021 00:20:06 +0200 Subject: [PATCH 045/111] Update util.rs add feature for `whoami` --- tests/common/util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/common/util.rs b/tests/common/util.rs index 47f8eb842..a0eb12459 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1767,6 +1767,7 @@ mod tests { #[test] #[cfg(unix)] + #[cfg(feature = "whoami")] fn test_run_ucmd_as_root() { // We need non-interactive `sudo. // CICD environment should allow non-interactive `sudo`. From bab7ba8a527f441e6cccb543b5fc5f64cbef4e04 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Tue, 21 Sep 2021 00:23:23 +0200 Subject: [PATCH 046/111] Update util.rs --- tests/common/util.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/common/util.rs b/tests/common/util.rs index a0eb12459..05cc6937a 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1364,7 +1364,7 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< /// This is a convenience wrapper to run a ucmd with root permissions. /// This runs 'sudo -E --non-interactive target/debug/coreutils util_name args` -/// This is primarily designed to run in the CICD environment where whoami is in $path +/// This is primarily designed to run in an environment where whoami is in $path /// and where non-interactive sudo is possible. /// To check if i) non-interactive sudo is possible and ii) if sudo works, this runs: /// 'sudo -E --non-interactive whoami' first. @@ -1389,6 +1389,7 @@ pub fn run_ucmd_as_root( ts: &TestScenario, args: &[&str], ) -> std::result::Result { + // Apparently CICD environment has no `sudo`? if ts .cmd_keepenv("sudo") .env("LC_ALL", "C") @@ -1769,16 +1770,18 @@ mod tests { #[cfg(unix)] #[cfg(feature = "whoami")] fn test_run_ucmd_as_root() { - // We need non-interactive `sudo. - // CICD environment should allow non-interactive `sudo`. - // Return early if we can't guarantee non-interactive `sudo` - if !is_ci() { - return; + // Skip test if we can't guarantee non-interactive `sudo`. + if let Ok(_status) = Command::new("sudo") + .args(&["-E", "-v", "--non-interactive"]) + .status() + { + let ts = TestScenario::new("whoami"); + std::assert_eq!( + run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), + "root" + ); + } else { + print!("TEST SKIPPED"); } - let ts = TestScenario::new("whoami"); - std::assert_eq!( - run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), - "root" - ); } } From eaad6c5286d435285fefea0a84913ecdbc0df356 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 30 Jan 2022 10:05:05 +0100 Subject: [PATCH 047/111] more comment mostly to retrigger the ci :) --- tests/common/util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/common/util.rs b/tests/common/util.rs index 05cc6937a..34bdc72f3 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1363,6 +1363,7 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< } /// This is a convenience wrapper to run a ucmd with root permissions. +/// It can be used to test programs when being root is needed /// This runs 'sudo -E --non-interactive target/debug/coreutils util_name args` /// This is primarily designed to run in an environment where whoami is in $path /// and where non-interactive sudo is possible. From 3078ca8346fd15b89aab74916c048da877c33dfd Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 1 May 2022 20:18:33 +0200 Subject: [PATCH 048/111] Add CHARCLASS to the spell ignore --- src/uu/ptx/src/ptx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index c3bedb266..2f253b580 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -5,7 +5,7 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -// spell-checker:ignore (ToDOs) corasick memchr Roff trunc oset iset +// spell-checker:ignore (ToDOs) corasick memchr Roff trunc oset iset CHARCLASS use clap::{crate_version, Arg, Command}; use regex::Regex; From 08816a4f0596636f3b763e99561a15260a919b03 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 1 May 2022 16:51:25 -0400 Subject: [PATCH 049/111] fixup! mktemp: respect path given in template argument --- tests/by-util/test_mktemp.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/by-util/test_mktemp.rs b/tests/by-util/test_mktemp.rs index 13d7c8e21..c28efc37b 100644 --- a/tests/by-util/test_mktemp.rs +++ b/tests/by-util/test_mktemp.rs @@ -473,7 +473,10 @@ fn test_respect_template() { fn test_respect_template_directory() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("d"); + #[cfg(not(windows))] let template = "d/XXX"; + #[cfg(windows)] + let template = r"d\XXX"; let result = ucmd.arg(template).succeeds(); let filename = result.no_stderr().stdout_str().trim_end(); assert_matches_template!(template, filename); From 0dc3eafaa43789acd73985eb4079f2a02f32b576 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 06:36:27 +0000 Subject: [PATCH 050/111] build(deps): bump clap_complete from 3.1.2 to 3.1.3 Bumps [clap_complete](https://github.com/clap-rs/clap) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v3.1.2...clap_complete-v3.1.3) --- updated-dependencies: - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a24abb936..a99566220 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -273,9 +273,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1506b87ee866f7a53a5131f7b31fba656170d797e873d0609884cfd56b8bbda8" +checksum = "1d7ca9141e27e6ebc52e3c378b0c07f3cea52db46ed1cc5861735fb697b56356" dependencies = [ "clap 3.1.12", ] From de6aa6de9b2df29c81b117dcabb8ef1c9ff2f5fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 06:36:41 +0000 Subject: [PATCH 051/111] build(deps): bump libc from 0.2.124 to 0.2.125 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.124 to 0.2.125. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.124...0.2.125) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/uu/chmod/Cargo.toml | 2 +- src/uu/cp/Cargo.toml | 2 +- src/uu/hostid/Cargo.toml | 2 +- src/uu/kill/Cargo.toml | 2 +- src/uu/logname/Cargo.toml | 2 +- src/uu/mkfifo/Cargo.toml | 2 +- src/uu/mknod/Cargo.toml | 2 +- src/uu/nice/Cargo.toml | 2 +- src/uu/nohup/Cargo.toml | 2 +- src/uu/nproc/Cargo.toml | 2 +- src/uu/pathchk/Cargo.toml | 2 +- src/uu/rmdir/Cargo.toml | 2 +- src/uu/sync/Cargo.toml | 2 +- src/uu/tail/Cargo.toml | 2 +- src/uu/tee/Cargo.toml | 2 +- src/uu/test/Cargo.toml | 2 +- src/uu/timeout/Cargo.toml | 2 +- src/uu/tty/Cargo.toml | 2 +- src/uu/whoami/Cargo.toml | 2 +- src/uucore/Cargo.toml | 2 +- 21 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a24abb936..2a46b14ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1015,9 +1015,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.124" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "libloading" diff --git a/src/uu/chmod/Cargo.toml b/src/uu/chmod/Cargo.toml index 9fab6011e..df0b089fa 100644 --- a/src/uu/chmod/Cargo.toml +++ b/src/uu/chmod/Cargo.toml @@ -16,7 +16,7 @@ path = "src/chmod.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs", "mode"] } [[bin]] diff --git a/src/uu/cp/Cargo.toml b/src/uu/cp/Cargo.toml index 9e1141650..f9036101a 100644 --- a/src/uu/cp/Cargo.toml +++ b/src/uu/cp/Cargo.toml @@ -21,7 +21,7 @@ path = "src/cp.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } filetime = "0.2" -libc = "0.2.124" +libc = "0.2.125" quick-error = "2.0.1" selinux = { version="0.2", optional=true } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["entries", "fs", "perms", "mode"] } diff --git a/src/uu/hostid/Cargo.toml b/src/uu/hostid/Cargo.toml index 0a2948459..d29160b21 100644 --- a/src/uu/hostid/Cargo.toml +++ b/src/uu/hostid/Cargo.toml @@ -16,7 +16,7 @@ path = "src/hostid.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/kill/Cargo.toml b/src/uu/kill/Cargo.toml index 354ad1d3f..24347a90a 100644 --- a/src/uu/kill/Cargo.toml +++ b/src/uu/kill/Cargo.toml @@ -16,7 +16,7 @@ path = "src/kill.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["signals"] } [[bin]] diff --git a/src/uu/logname/Cargo.toml b/src/uu/logname/Cargo.toml index 22b976dd6..fe7f2f738 100644 --- a/src/uu/logname/Cargo.toml +++ b/src/uu/logname/Cargo.toml @@ -15,7 +15,7 @@ edition = "2021" path = "src/logname.rs" [dependencies] -libc = "0.2.124" +libc = "0.2.125" clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } diff --git a/src/uu/mkfifo/Cargo.toml b/src/uu/mkfifo/Cargo.toml index a6c801747..821d67d53 100644 --- a/src/uu/mkfifo/Cargo.toml +++ b/src/uu/mkfifo/Cargo.toml @@ -16,7 +16,7 @@ path = "src/mkfifo.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/mknod/Cargo.toml b/src/uu/mknod/Cargo.toml index 53cc62313..88c9e3fb0 100644 --- a/src/uu/mknod/Cargo.toml +++ b/src/uu/mknod/Cargo.toml @@ -17,7 +17,7 @@ path = "src/mknod.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "^0.2.124" +libc = "^0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["mode"] } [[bin]] diff --git a/src/uu/nice/Cargo.toml b/src/uu/nice/Cargo.toml index ab4b6c700..9b6ca52bd 100644 --- a/src/uu/nice/Cargo.toml +++ b/src/uu/nice/Cargo.toml @@ -16,7 +16,7 @@ path = "src/nice.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" nix = { version = "0.24.1", default-features = false } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } diff --git a/src/uu/nohup/Cargo.toml b/src/uu/nohup/Cargo.toml index 26e5fd7ae..ba38a7ecd 100644 --- a/src/uu/nohup/Cargo.toml +++ b/src/uu/nohup/Cargo.toml @@ -16,7 +16,7 @@ path = "src/nohup.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" atty = "0.2" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/nproc/Cargo.toml b/src/uu/nproc/Cargo.toml index 80c1cb38b..f52f2d0db 100644 --- a/src/uu/nproc/Cargo.toml +++ b/src/uu/nproc/Cargo.toml @@ -15,7 +15,7 @@ edition = "2021" path = "src/nproc.rs" [dependencies] -libc = "0.2.124" +libc = "0.2.125" num_cpus = "1.10" clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/pathchk/Cargo.toml b/src/uu/pathchk/Cargo.toml index 44cab8559..dd8b83076 100644 --- a/src/uu/pathchk/Cargo.toml +++ b/src/uu/pathchk/Cargo.toml @@ -16,7 +16,7 @@ path = "src/pathchk.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [[bin]] diff --git a/src/uu/rmdir/Cargo.toml b/src/uu/rmdir/Cargo.toml index b61def5ad..0894fa411 100644 --- a/src/uu/rmdir/Cargo.toml +++ b/src/uu/rmdir/Cargo.toml @@ -17,7 +17,7 @@ path = "src/rmdir.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } -libc = "0.2.124" +libc = "0.2.125" [[bin]] name = "rmdir" diff --git a/src/uu/sync/Cargo.toml b/src/uu/sync/Cargo.toml index ece7a5930..f6e57391d 100644 --- a/src/uu/sync/Cargo.toml +++ b/src/uu/sync/Cargo.toml @@ -16,7 +16,7 @@ path = "src/sync.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["wide"] } winapi = { version = "0.3", features = ["errhandlingapi", "fileapi", "handleapi", "std", "winbase", "winerror"] } diff --git a/src/uu/tail/Cargo.toml b/src/uu/tail/Cargo.toml index eebbf9606..7006ddb67 100644 --- a/src/uu/tail/Cargo.toml +++ b/src/uu/tail/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tail.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] } [target.'cfg(windows)'.dependencies] diff --git a/src/uu/tee/Cargo.toml b/src/uu/tee/Cargo.toml index 7257d9854..07ee9e33b 100644 --- a/src/uu/tee/Cargo.toml +++ b/src/uu/tee/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tee.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" retain_mut = "=0.1.7" # ToDO: [2021-01-01; rivy; maint/MinSRV] ~ v0.1.5 uses const generics which aren't stabilized until rust v1.51.0 uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["libc"] } diff --git a/src/uu/test/Cargo.toml b/src/uu/test/Cargo.toml index 6bd1cfc90..58f891541 100644 --- a/src/uu/test/Cargo.toml +++ b/src/uu/test/Cargo.toml @@ -16,7 +16,7 @@ path = "src/test.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } [target.'cfg(target_os = "redox")'.dependencies] diff --git a/src/uu/timeout/Cargo.toml b/src/uu/timeout/Cargo.toml index e555cb1b7..d285c3214 100644 --- a/src/uu/timeout/Cargo.toml +++ b/src/uu/timeout/Cargo.toml @@ -16,7 +16,7 @@ path = "src/timeout.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" nix = { version = "0.24.1", default-features = false, features = ["signal"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["process", "signals"] } diff --git a/src/uu/tty/Cargo.toml b/src/uu/tty/Cargo.toml index 2f3438558..da6446ab0 100644 --- a/src/uu/tty/Cargo.toml +++ b/src/uu/tty/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tty.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } -libc = "0.2.124" +libc = "0.2.125" atty = "0.2" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/whoami/Cargo.toml b/src/uu/whoami/Cargo.toml index 2655fe892..253e2ba1b 100644 --- a/src/uu/whoami/Cargo.toml +++ b/src/uu/whoami/Cargo.toml @@ -22,7 +22,7 @@ uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=[ winapi = { version = "0.3", features = ["lmcons"] } [target.'cfg(unix)'.dependencies] -libc = "0.2.124" +libc = "0.2.125" [[bin]] name = "whoami" diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 6f74b238a..56e582bf8 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -31,7 +31,7 @@ time = { version="<= 0.1.43", optional=true } data-encoding = { version="2.1", optional=true } data-encoding-macro = { version="0.1.12", optional=true } z85 = { version="3.0.5", optional=true } -libc = { version="0.2.124", optional=true } +libc = { version="0.2.125", optional=true } once_cell = "1.10.0" os_display = "0.1.3" From a1e5f8e53f037c14ae356c4567ec459214622be2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 13:03:18 +0000 Subject: [PATCH 052/111] build(deps): bump memchr from 2.4.1 to 2.5.0 Bumps [memchr](https://github.com/BurntSushi/memchr) from 2.4.1 to 2.5.0. - [Release notes](https://github.com/BurntSushi/memchr/releases) - [Commits](https://github.com/BurntSushi/memchr/compare/2.4.1...2.5.0) --- updated-dependencies: - dependency-name: memchr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 30 +++++++++++++++--------------- src/uu/sort/Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a24abb936..2f33f716a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ - "memchr 2.4.1", + "memchr 2.5.0", ] [[package]] @@ -163,7 +163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", - "memchr 2.4.1", + "memchr 2.5.0", "regex-automata", ] @@ -1015,9 +1015,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.124" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "libloading" @@ -1082,9 +1082,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" @@ -1160,7 +1160,7 @@ version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ - "memchr 2.4.1", + "memchr 2.5.0", "minimal-lexical", ] @@ -1568,7 +1568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", - "memchr 2.4.1", + "memchr 2.5.0", "regex-syntax", ] @@ -2178,7 +2178,7 @@ dependencies = [ "atty", "bstr", "clap 3.1.12", - "memchr 2.4.1", + "memchr 2.5.0", "uucore", ] @@ -2347,7 +2347,7 @@ dependencies = [ "digest", "hex", "md-5", - "memchr 2.4.1", + "memchr 2.5.0", "regex", "sha1", "sha2", @@ -2360,7 +2360,7 @@ name = "uu_head" version = "0.0.13" dependencies = [ "clap 3.1.12", - "memchr 2.4.1", + "memchr 2.5.0", "uucore", ] @@ -2408,7 +2408,7 @@ name = "uu_join" version = "0.0.13" dependencies = [ "clap 3.1.12", - "memchr 2.4.1", + "memchr 2.5.0", "uucore", ] @@ -2753,7 +2753,7 @@ dependencies = [ "ctrlc", "fnv", "itertools", - "memchr 2.4.1", + "memchr 2.5.0", "ouroboros", "rand", "rayon", @@ -2767,7 +2767,7 @@ name = "uu_split" version = "0.0.13" dependencies = [ "clap 3.1.12", - "memchr 2.4.1", + "memchr 2.5.0", "uucore", ] @@ -2822,7 +2822,7 @@ name = "uu_tac" version = "0.0.13" dependencies = [ "clap 3.1.12", - "memchr 2.4.1", + "memchr 2.5.0", "memmap2", "regex", "uucore", diff --git a/src/uu/sort/Cargo.toml b/src/uu/sort/Cargo.toml index 69f7f7468..3c8be6a50 100644 --- a/src/uu/sort/Cargo.toml +++ b/src/uu/sort/Cargo.toml @@ -21,7 +21,7 @@ compare = "0.1.0" ctrlc = { version = "3.0", features = ["termination"] } fnv = "1.0.7" itertools = "0.10.0" -memchr = "2.4.0" +memchr = "2.5.0" ouroboros = "0.15.0" rand = "0.8" rayon = "1.5" From 1acbc0009e6fb2c5b92d8df15eda4b8eb1858dd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 13:06:15 +0000 Subject: [PATCH 053/111] build(deps): bump thiserror from 1.0.30 to 1.0.31 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.30 to 1.0.31. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.30...1.0.31) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a46b14ec..14ba065c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -273,9 +273,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1506b87ee866f7a53a5131f7b31fba656170d797e873d0609884cfd56b8bbda8" +checksum = "1d7ca9141e27e6ebc52e3c378b0c07f3cea52db46ed1cc5861735fb697b56356" dependencies = [ "clap 3.1.12", ] @@ -1924,18 +1924,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote 1.0.14", From 15412f100a1fc14e72a4c48de495de9dec66a168 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Sat, 30 Apr 2022 15:36:50 +0200 Subject: [PATCH 054/111] df: show "block-size argument too large" error --- src/uu/df/src/df.rs | 21 +++++++++++++++------ tests/by-util/test_df.rs | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index 2b9c929c7..b86b11f37 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -14,6 +14,7 @@ mod table; use uucore::display::Quotable; use uucore::error::{UError, UResult, USimpleError}; use uucore::fsext::{read_fs_list, MountInfo}; +use uucore::parse_size::ParseSizeError; use uucore::{format_usage, show}; use clap::{crate_version, Arg, ArgMatches, Command}; @@ -105,7 +106,8 @@ impl Default for Options { #[derive(Debug)] enum OptionsError { - InvalidBlockSize, + BlockSizeTooLarge(String), + InvalidBlockSize(String), /// An error getting the columns to display in the output table. ColumnError(ColumnError), @@ -116,11 +118,14 @@ enum OptionsError { impl fmt::Display for OptionsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - // TODO This should include the raw string provided as the argument. - // // TODO This needs to vary based on whether `--block-size` // or `-B` were provided. - Self::InvalidBlockSize => write!(f, "invalid --block-size argument"), + Self::BlockSizeTooLarge(s) => { + write!(f, "--block-size argument {} too large", s.quote()) + } + // TODO This needs to vary based on whether `--block-size` + // or `-B` were provided. + Self::InvalidBlockSize(s) => write!(f, "invalid --block-size argument {}", s), Self::ColumnError(ColumnError::MultipleColumns(s)) => write!( f, "option --output: field {} used more than once", @@ -155,8 +160,12 @@ impl Options { Ok(Self { show_local_fs: matches.is_present(OPT_LOCAL), show_all_fs: matches.is_present(OPT_ALL), - block_size: block_size_from_matches(matches) - .map_err(|_| OptionsError::InvalidBlockSize)?, + block_size: block_size_from_matches(matches).map_err(|e| match e { + ParseSizeError::SizeTooBig(_) => OptionsError::BlockSizeTooLarge( + matches.value_of(OPT_BLOCKSIZE).unwrap().to_string(), + ), + ParseSizeError::ParseFailure(s) => OptionsError::InvalidBlockSize(s), + })?, include, exclude, show_total: matches.is_present(OPT_TOTAL), diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 61ddcec5d..90781eb64 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -419,6 +419,30 @@ fn test_block_size_with_suffix() { //assert_eq!(get_header("1GB"), "1GB-blocks"); } +#[test] +fn test_too_large_block_size() { + fn run_command(size: &str) { + new_ucmd!() + .arg(format!("--block-size={}", size)) + .fails() + .stderr_contains(format!("--block-size argument '{}' too large", size)); + } + + let too_large_sizes = vec!["1Y", "1Z"]; + + for size in too_large_sizes { + run_command(size); + } +} + +#[test] +fn test_invalid_block_size() { + new_ucmd!() + .arg("--block-size=x") + .fails() + .stderr_contains("invalid --block-size argument 'x'"); +} + #[test] fn test_output_selects_columns() { let output = new_ucmd!() From badf947f8a343d40a7660d5fc490e149340b56e5 Mon Sep 17 00:00:00 2001 From: anastygnome Date: Mon, 2 May 2022 08:28:23 +0200 Subject: [PATCH 055/111] Do not dereference symlink even when dangling (fix #3364) Fixes an issue with cp not copying symlinks in spite of the -P (no dereference option) Fix issue #3364 Performance improvements Avoid useless read from metadata and reuse previous dest information Signed-off-by: anastygnome --- src/uu/cp/src/cp.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index 913cf2769..ce85b58bc 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -992,7 +992,9 @@ fn copy_directory( } // if no-dereference is enabled and this is a symlink, copy it as a file - if !options.dereference && fs::symlink_metadata(root).unwrap().file_type().is_symlink() { + if !options.dereference && fs::symlink_metadata(root).unwrap().file_type().is_symlink() + // replace by is_symlink in rust>=1.58 + { return copy_file(root, target, options, symlinked_files); } @@ -1036,6 +1038,7 @@ fn copy_directory( { let p = or_continue!(path); let is_symlink = fs::symlink_metadata(p.path())?.file_type().is_symlink(); + // replace by is_symlink in rust >=1.58 let path = current_dir.join(&p.path()); let local_to_root_parent = match root_parent { @@ -1288,7 +1291,7 @@ fn copy_file( // Fail if dest is a dangling symlink or a symlink this program created previously if fs::symlink_metadata(dest) - .map(|m| m.file_type().is_symlink()) + .map(|m| m.file_type().is_symlink()) // replace by is_symlink in rust>=1.58 .unwrap_or(false) { if FileInformation::from_path(dest, false) @@ -1301,7 +1304,7 @@ fn copy_file( dest.display() ))); } - if !dest.exists() { + if options.dereference && !dest.exists() { return Err(Error::Error(format!( "not writing through dangling symlink '{}'", dest.display() @@ -1535,7 +1538,7 @@ fn copy_link( } else { // we always need to remove the file to be able to create a symlink, // even if it is writeable. - if dest.exists() { + if dest.is_file() { fs::remove_file(dest)?; } dest.into() From 70c451fa61cb342b8a4646c4ad053ebe1ec0f608 Mon Sep 17 00:00:00 2001 From: anastygnome Date: Mon, 2 May 2022 08:20:46 +0200 Subject: [PATCH 056/111] Add test for copying dangling symlink copy with dereference Signed-off-by: anastygnome --- tests/by-util/test_cp.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 079e966be..cdcaf2760 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -1506,6 +1506,18 @@ fn test_copy_through_dangling_symlink() { .stderr_only("cp: not writing through dangling symlink 'target'"); } +#[test] +fn test_copy_through_dangling_symlink_no_dereference() { + let (at, mut ucmd) = at_and_ucmd!(); + at.symlink_file("no-such-file", "dangle"); + ucmd.arg("-P") + .arg("dangle") + .arg("d2") + .succeeds() + .no_stderr() + .no_stdout(); +} + #[test] #[cfg(unix)] fn test_cp_archive_on_nonexistent_file() { From a4e3f37aaf3ab7f553276e02dd87d4feafdbf226 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 21:30:25 +0000 Subject: [PATCH 057/111] build(deps): bump clap from 3.1.12 to 3.1.15 Bumps [clap](https://github.com/clap-rs/clap) from 3.1.12 to 3.1.15. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v3.1.12...v3.1.15) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 216 ++++++++++++++++++++++++++--------------------------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ad9da7ba..ee06b62eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.12" +version = "3.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db" +checksum = "85a35a599b11c089a7f49105658d089b8f2cf0882993c17daf6de15285c2c35d" dependencies = [ "atty", "bitflags", @@ -277,14 +277,14 @@ version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7ca9141e27e6ebc52e3c378b0c07f3cea52db46ed1cc5861735fb697b56356" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", ] [[package]] name = "clap_lex" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" dependencies = [ "os_str_bytes", ] @@ -316,7 +316,7 @@ version = "0.0.13" dependencies = [ "atty", "chrono", - "clap 3.1.12", + "clap 3.1.15", "clap_complete", "conv", "filetime", @@ -2033,7 +2033,7 @@ checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" name = "uu_arch" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "platform-info", "uucore", ] @@ -2042,7 +2042,7 @@ dependencies = [ name = "uu_base32" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2058,7 +2058,7 @@ dependencies = [ name = "uu_basename" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2066,7 +2066,7 @@ dependencies = [ name = "uu_basenc" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uu_base32", "uucore", ] @@ -2076,7 +2076,7 @@ name = "uu_cat" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.12", + "clap 3.1.15", "nix", "thiserror", "unix_socket", @@ -2087,7 +2087,7 @@ dependencies = [ name = "uu_chcon" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "fts-sys", "libc", "selinux", @@ -2099,7 +2099,7 @@ dependencies = [ name = "uu_chgrp" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2107,7 +2107,7 @@ dependencies = [ name = "uu_chmod" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2116,7 +2116,7 @@ dependencies = [ name = "uu_chown" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2124,7 +2124,7 @@ dependencies = [ name = "uu_chroot" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2132,7 +2132,7 @@ dependencies = [ name = "uu_cksum" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2140,7 +2140,7 @@ dependencies = [ name = "uu_comm" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2148,7 +2148,7 @@ dependencies = [ name = "uu_cp" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "exacl", "filetime", "ioctl-sys", @@ -2165,7 +2165,7 @@ dependencies = [ name = "uu_csplit" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "regex", "thiserror", "uucore", @@ -2177,7 +2177,7 @@ version = "0.0.13" dependencies = [ "atty", "bstr", - "clap 3.1.12", + "clap 3.1.15", "memchr 2.5.0", "uucore", ] @@ -2187,7 +2187,7 @@ name = "uu_date" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", "winapi 0.3.9", @@ -2198,7 +2198,7 @@ name = "uu_dd" version = "0.0.13" dependencies = [ "byte-unit", - "clap 3.1.12", + "clap 3.1.15", "gcd", "libc", "signal-hook", @@ -2209,7 +2209,7 @@ dependencies = [ name = "uu_df" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "number_prefix", "unicode-width", "uucore", @@ -2219,7 +2219,7 @@ dependencies = [ name = "uu_dir" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "selinux", "uu_ls", "uucore", @@ -2229,7 +2229,7 @@ dependencies = [ name = "uu_dircolors" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "glob", "uucore", ] @@ -2238,7 +2238,7 @@ dependencies = [ name = "uu_dirname" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2247,7 +2247,7 @@ name = "uu_du" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.12", + "clap 3.1.15", "glob", "uucore", "winapi 0.3.9", @@ -2257,7 +2257,7 @@ dependencies = [ name = "uu_echo" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2265,7 +2265,7 @@ dependencies = [ name = "uu_env" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "rust-ini", "uucore", ] @@ -2274,7 +2274,7 @@ dependencies = [ name = "uu_expand" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "unicode-width", "uucore", ] @@ -2283,7 +2283,7 @@ dependencies = [ name = "uu_expr" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "num-bigint", "num-traits", "onig", @@ -2294,7 +2294,7 @@ dependencies = [ name = "uu_factor" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "coz", "num-traits", "paste", @@ -2308,7 +2308,7 @@ dependencies = [ name = "uu_false" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2316,7 +2316,7 @@ dependencies = [ name = "uu_fmt" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "unicode-width", "uucore", ] @@ -2325,7 +2325,7 @@ dependencies = [ name = "uu_fold" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2333,7 +2333,7 @@ dependencies = [ name = "uu_groups" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2343,7 +2343,7 @@ version = "0.0.13" dependencies = [ "blake2b_simd", "blake3", - "clap 3.1.12", + "clap 3.1.15", "digest", "hex", "md-5", @@ -2359,7 +2359,7 @@ dependencies = [ name = "uu_head" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "memchr 2.5.0", "uucore", ] @@ -2368,7 +2368,7 @@ dependencies = [ name = "uu_hostid" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2377,7 +2377,7 @@ dependencies = [ name = "uu_hostname" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "hostname", "uucore", "winapi 0.3.9", @@ -2387,7 +2387,7 @@ dependencies = [ name = "uu_id" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "selinux", "uucore", ] @@ -2396,7 +2396,7 @@ dependencies = [ name = "uu_install" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "file_diff", "filetime", "libc", @@ -2407,7 +2407,7 @@ dependencies = [ name = "uu_join" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "memchr 2.5.0", "uucore", ] @@ -2416,7 +2416,7 @@ dependencies = [ name = "uu_kill" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2425,7 +2425,7 @@ dependencies = [ name = "uu_link" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2433,7 +2433,7 @@ dependencies = [ name = "uu_ln" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2441,7 +2441,7 @@ dependencies = [ name = "uu_logname" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2452,7 +2452,7 @@ version = "0.0.13" dependencies = [ "atty", "chrono", - "clap 3.1.12", + "clap 3.1.15", "glob", "lazy_static", "lscolors", @@ -2469,7 +2469,7 @@ dependencies = [ name = "uu_mkdir" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2477,7 +2477,7 @@ dependencies = [ name = "uu_mkfifo" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2486,7 +2486,7 @@ dependencies = [ name = "uu_mknod" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2495,7 +2495,7 @@ dependencies = [ name = "uu_mktemp" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "rand", "tempfile", "uucore", @@ -2506,7 +2506,7 @@ name = "uu_more" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.12", + "clap 3.1.15", "crossterm", "nix", "unicode-segmentation", @@ -2518,7 +2518,7 @@ dependencies = [ name = "uu_mv" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "fs_extra", "uucore", ] @@ -2527,7 +2527,7 @@ dependencies = [ name = "uu_nice" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "nix", "uucore", @@ -2537,7 +2537,7 @@ dependencies = [ name = "uu_nl" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "regex", "uucore", ] @@ -2547,7 +2547,7 @@ name = "uu_nohup" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2556,7 +2556,7 @@ dependencies = [ name = "uu_nproc" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "num_cpus", "uucore", @@ -2566,7 +2566,7 @@ dependencies = [ name = "uu_numfmt" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2575,7 +2575,7 @@ name = "uu_od" version = "0.0.13" dependencies = [ "byteorder", - "clap 3.1.12", + "clap 3.1.15", "half", "uucore", ] @@ -2584,7 +2584,7 @@ dependencies = [ name = "uu_paste" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2592,7 +2592,7 @@ dependencies = [ name = "uu_pathchk" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2601,7 +2601,7 @@ dependencies = [ name = "uu_pinky" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2610,7 +2610,7 @@ name = "uu_pr" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.12", + "clap 3.1.15", "itertools", "quick-error", "regex", @@ -2621,7 +2621,7 @@ dependencies = [ name = "uu_printenv" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2629,7 +2629,7 @@ dependencies = [ name = "uu_printf" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2637,7 +2637,7 @@ dependencies = [ name = "uu_ptx" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "regex", "uucore", ] @@ -2646,7 +2646,7 @@ dependencies = [ name = "uu_pwd" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2654,7 +2654,7 @@ dependencies = [ name = "uu_readlink" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2662,7 +2662,7 @@ dependencies = [ name = "uu_realpath" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2670,7 +2670,7 @@ dependencies = [ name = "uu_relpath" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2678,7 +2678,7 @@ dependencies = [ name = "uu_rm" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "remove_dir_all 0.7.0", "uucore", "walkdir", @@ -2689,7 +2689,7 @@ dependencies = [ name = "uu_rmdir" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2698,7 +2698,7 @@ dependencies = [ name = "uu_runcon" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "selinux", "thiserror", @@ -2710,7 +2710,7 @@ name = "uu_seq" version = "0.0.13" dependencies = [ "bigdecimal", - "clap 3.1.12", + "clap 3.1.15", "num-bigint", "num-traits", "uucore", @@ -2720,7 +2720,7 @@ dependencies = [ name = "uu_shred" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "rand", "uucore", ] @@ -2729,7 +2729,7 @@ dependencies = [ name = "uu_shuf" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "rand", "rand_core", "uucore", @@ -2739,7 +2739,7 @@ dependencies = [ name = "uu_sleep" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2748,7 +2748,7 @@ name = "uu_sort" version = "0.0.13" dependencies = [ "binary-heap-plus", - "clap 3.1.12", + "clap 3.1.15", "compare", "ctrlc", "fnv", @@ -2766,7 +2766,7 @@ dependencies = [ name = "uu_split" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "memchr 2.5.0", "uucore", ] @@ -2775,7 +2775,7 @@ dependencies = [ name = "uu_stat" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2783,7 +2783,7 @@ dependencies = [ name = "uu_stdbuf" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "tempfile", "uu_stdbuf_libstdbuf", "uucore", @@ -2803,7 +2803,7 @@ dependencies = [ name = "uu_sum" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2811,7 +2811,7 @@ dependencies = [ name = "uu_sync" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", "winapi 0.3.9", @@ -2821,7 +2821,7 @@ dependencies = [ name = "uu_tac" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "memchr 2.5.0", "memmap2", "regex", @@ -2832,7 +2832,7 @@ dependencies = [ name = "uu_tail" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "nix", "uucore", @@ -2843,7 +2843,7 @@ dependencies = [ name = "uu_tee" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "retain_mut", "uucore", @@ -2853,7 +2853,7 @@ dependencies = [ name = "uu_test" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "redox_syscall", "uucore", @@ -2863,7 +2863,7 @@ dependencies = [ name = "uu_timeout" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "nix", "uucore", @@ -2873,7 +2873,7 @@ dependencies = [ name = "uu_touch" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "filetime", "time", "uucore", @@ -2884,7 +2884,7 @@ dependencies = [ name = "uu_tr" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "nom", "uucore", ] @@ -2893,7 +2893,7 @@ dependencies = [ name = "uu_true" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2901,7 +2901,7 @@ dependencies = [ name = "uu_truncate" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2909,7 +2909,7 @@ dependencies = [ name = "uu_tsort" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2918,7 +2918,7 @@ name = "uu_tty" version = "0.0.13" dependencies = [ "atty", - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", ] @@ -2927,7 +2927,7 @@ dependencies = [ name = "uu_uname" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "platform-info", "uucore", ] @@ -2936,7 +2936,7 @@ dependencies = [ name = "uu_unexpand" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "unicode-width", "uucore", ] @@ -2945,7 +2945,7 @@ dependencies = [ name = "uu_uniq" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "strum", "strum_macros", "uucore", @@ -2955,7 +2955,7 @@ dependencies = [ name = "uu_unlink" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2964,7 +2964,7 @@ name = "uu_uptime" version = "0.0.13" dependencies = [ "chrono", - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2972,7 +2972,7 @@ dependencies = [ name = "uu_users" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -2980,7 +2980,7 @@ dependencies = [ name = "uu_vdir" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "selinux", "uu_ls", "uucore", @@ -2991,7 +2991,7 @@ name = "uu_wc" version = "0.0.13" dependencies = [ "bytecount", - "clap 3.1.12", + "clap 3.1.15", "libc", "nix", "unicode-width", @@ -3003,7 +3003,7 @@ dependencies = [ name = "uu_who" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "uucore", ] @@ -3011,7 +3011,7 @@ dependencies = [ name = "uu_whoami" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "libc", "uucore", "winapi 0.3.9", @@ -3021,7 +3021,7 @@ dependencies = [ name = "uu_yes" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "nix", "uucore", ] @@ -3030,7 +3030,7 @@ dependencies = [ name = "uucore" version = "0.0.13" dependencies = [ - "clap 3.1.12", + "clap 3.1.15", "data-encoding", "data-encoding-macro", "dns-lookup", From 3e30569c2f1c6dc30c904a2c2ecd893e0e5733e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 May 2022 06:13:02 +0000 Subject: [PATCH 058/111] build(deps): bump xattr from 0.2.2 to 0.2.3 Bumps [xattr](https://github.com/Stebalien/xattr) from 0.2.2 to 0.2.3. - [Release notes](https://github.com/Stebalien/xattr/releases) - [Commits](https://github.com/Stebalien/xattr/commits) --- updated-dependencies: - dependency-name: xattr dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/uu/cp/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee06b62eb..b503b60d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3208,9 +3208,9 @@ checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" [[package]] name = "xattr" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] diff --git a/src/uu/cp/Cargo.toml b/src/uu/cp/Cargo.toml index f9036101a..3f3c2e317 100644 --- a/src/uu/cp/Cargo.toml +++ b/src/uu/cp/Cargo.toml @@ -34,7 +34,7 @@ ioctl-sys = "0.8" winapi = { version="0.3", features=["fileapi"] } [target.'cfg(unix)'.dependencies] -xattr="0.2.1" +xattr="0.2.3" exacl= { version = "0.8.0", optional=true } [[bin]] From 9bd883169dcf7ae7142dca372c516c83114da73c Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 4 May 2022 09:37:09 +0200 Subject: [PATCH 059/111] df: set min width of "Used" column to 5 --- src/uu/df/src/columns.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uu/df/src/columns.rs b/src/uu/df/src/columns.rs index bd8cab438..70b660a0b 100644 --- a/src/uu/df/src/columns.rs +++ b/src/uu/df/src/columns.rs @@ -197,6 +197,7 @@ impl Column { match column { // 14 = length of "Filesystem" plus 4 spaces Self::Source => 14, + Self::Used => 5, // the shortest headers have a length of 4 chars so we use that as the minimum width _ => 4, } From 88a62c4922e61f5896a163997143fb2d9ce4d660 Mon Sep 17 00:00:00 2001 From: Ackerley Tng Date: Tue, 3 May 2022 08:22:05 -0700 Subject: [PATCH 060/111] du: use common error methods with show! instead of set_exit_code --- src/uu/du/src/du.rs | 30 ++++++++---------------------- tests/by-util/test_du.rs | 4 +--- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index ff7a5a5b7..b29a938a4 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -20,7 +20,7 @@ use std::fs::File; use std::fs::Metadata; use std::io::BufRead; use std::io::BufReader; -use std::io::{ErrorKind, Result}; +use std::io::Result; use std::iter; #[cfg(not(windows))] use std::os::unix::fs::MetadataExt; @@ -34,7 +34,8 @@ use std::str::FromStr; use std::time::{Duration, UNIX_EPOCH}; use std::{error::Error, fmt::Display}; use uucore::display::{print_verbatim, Quotable}; -use uucore::error::{set_exit_code, UError, UResult}; +use uucore::error::FromIo; +use uucore::error::{UError, UResult}; use uucore::format_usage; use uucore::parse_size::{parse_size, ParseSizeError}; use uucore::InvalidEncodingHandling; @@ -102,7 +103,6 @@ const UNITS: [(char, u32); 6] = [('E', 6), ('P', 5), ('T', 4), ('G', 3), ('M', 2 struct Options { all: bool, - util_name: String, max_depth: Option, total: bool, separate_dirs: bool, @@ -309,13 +309,9 @@ fn du( let read = match fs::read_dir(&my_stat.path) { Ok(read) => read, Err(e) => { - eprintln!( - "{}: cannot read directory {}: {}", - options.util_name, - my_stat.path.quote(), - e + show!( + e.map_err_context(|| format!("cannot read directory {}", my_stat.path.quote())) ); - set_exit_code(1); return Box::new(iter::once(my_stat)); } }; @@ -368,18 +364,9 @@ fn du( } } } - Err(error) => match error.kind() { - ErrorKind::PermissionDenied => { - let description = format!("cannot access {}", entry.path().quote()); - let error_message = "Permission denied"; - show_error_custom_description!(description, "{}", error_message); - set_exit_code(1); - } - _ => { - set_exit_code(1); - show_error!("cannot access {}: {}", entry.path().quote(), error); - } - }, + Err(e) => show!( + e.map_err_context(|| format!("cannot access {}", entry.path().quote())) + ), } } Err(error) => show_error!("{}", error), @@ -567,7 +554,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let options = Options { all: matches.is_present(options::ALL), - util_name: uucore::util_name().to_owned(), max_depth, total: matches.is_present(options::TOTAL), separate_dirs: matches.is_present(options::SEPARATE_DIRS), diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 254e75166..bf506c8b5 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -435,9 +435,7 @@ fn test_du_no_permission() { ts.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).succeeds(); let result = ts.ucmd().arg(SUB_DIR_LINKS).fails(); - result.stderr_contains( - "du: cannot read directory 'subdir/links': Permission denied (os error 13)", - ); + result.stderr_contains("du: cannot read directory 'subdir/links': Permission denied"); #[cfg(any(target_os = "linux", target_os = "android"))] { From 7b84261df42278a23bed2239cc8cb93126503ec0 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 30 Apr 2022 11:25:53 +0200 Subject: [PATCH 061/111] uucore/error: add custom exit codes for clap errors This allows us to use clap errors as UResult and specify the exit code for invalid arguments per util. --- src/uucore/src/lib/mods/error.rs | 73 +++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/src/uucore/src/lib/mods/error.rs b/src/uucore/src/lib/mods/error.rs index dbe4d5bc1..1af6ef781 100644 --- a/src/uucore/src/lib/mods/error.rs +++ b/src/uucore/src/lib/mods/error.rs @@ -617,12 +617,75 @@ impl From for Box { } } -/// Implementations for clap::Error -impl UError for clap::Error { +/// A wrapper for `clap::Error` that implements [`UError`] +/// +/// Contains a custom error code. When `Display::fmt` is called on this struct +/// the [`clap::Error`] will be printed _directly to `stdout` or `stderr`_. +/// This is because `clap` only supports colored output when it prints directly. +/// +/// [`ClapErrorWrapper`] is generally created by calling the +/// [`UClapError::with_exit_code`] method on [`clap::Error`] or using the [`From`] +/// implementation from [`clap::Error`] to `Box`, which constructs +/// a [`ClapErrorWrapper`] with an exit code of `1`. +/// +/// ```rust +/// use uucore::error::{ClapErrorWrapper, UError, UClapError}; +/// let command = clap::Command::new("test"); +/// let result: Result<_, ClapErrorWrapper> = command.try_get_matches().with_exit_code(125); +/// +/// let command = clap::Command::new("test"); +/// let result: Result<_, Box> = command.try_get_matches().map_err(Into::into); +/// ``` +#[derive(Debug)] +pub struct ClapErrorWrapper { + code: i32, + error: clap::Error, +} + +/// Extension trait for `clap::Error` to adjust the exit code. +pub trait UClapError { + fn with_exit_code(self, code: i32) -> T; +} + +impl From for Box { + fn from(e: clap::Error) -> Self { + Box::new(ClapErrorWrapper { code: 1, error: e }) + } +} + +impl UClapError for clap::Error { + fn with_exit_code(self, code: i32) -> ClapErrorWrapper { + ClapErrorWrapper { code, error: self } + } +} + +impl UClapError> + for Result +{ + fn with_exit_code(self, code: i32) -> Result { + self.map_err(|e| e.with_exit_code(code)) + } +} + +impl UError for ClapErrorWrapper { fn code(&self) -> i32 { - match self.kind() { - clap::ErrorKind::DisplayHelp | clap::ErrorKind::DisplayVersion => 0, - _ => 1, + // If the error is a DisplayHelp or DisplayVersion variant, + // we don't want to apply the custom error code, but leave + // it 0. + if let clap::ErrorKind::DisplayHelp | clap::ErrorKind::DisplayVersion = self.error.kind() { + 0 + } else { + self.code } } } + +impl Error for ClapErrorWrapper {} + +// This is abuse of the Display trait +impl Display for ClapErrorWrapper { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + self.error.print().unwrap(); + Ok(()) + } +} From 8df253da69a9826056a8f556e772a549a8900c3f Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 30 Apr 2022 11:28:22 +0200 Subject: [PATCH 062/111] cat: set exit code for invalid arguments to 1 instead of 2 --- src/uu/cat/src/cat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index edba1b8d0..67de917f7 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -188,7 +188,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .collect_str(InvalidEncodingHandling::Ignore) .accept_any(); - let matches = uu_app().get_matches_from(args); + let matches = uu_app().try_get_matches_from(args)?; let number_mode = if matches.is_present(options::NUMBER_NONBLANK) { NumberingMode::NonEmpty From 1bb85acc71b8276c910d850ea79d98f5009c0691 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 30 Apr 2022 22:45:17 +0200 Subject: [PATCH 063/111] nice: set exit code for clap errors to 125 --- src/uu/nice/src/nice.rs | 4 ++-- tests/by-util/test_nice.rs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/uu/nice/src/nice.rs b/src/uu/nice/src/nice.rs index b75dd979e..e78de828b 100644 --- a/src/uu/nice/src/nice.rs +++ b/src/uu/nice/src/nice.rs @@ -17,7 +17,7 @@ use std::ptr; use clap::{crate_version, Arg, Command}; use uucore::{ - error::{set_exit_code, UResult, USimpleError, UUsageError}, + error::{set_exit_code, UClapError, UResult, USimpleError, UUsageError}, format_usage, }; @@ -35,7 +35,7 @@ const USAGE: &str = "{} [OPTIONS] [COMMAND [ARGS]]"; #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let matches = uu_app().get_matches_from(args); + let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?; let mut niceness = unsafe { nix::errno::Errno::clear(); diff --git a/tests/by-util/test_nice.rs b/tests/by-util/test_nice.rs index 2b53ed437..036723cde 100644 --- a/tests/by-util/test_nice.rs +++ b/tests/by-util/test_nice.rs @@ -58,3 +58,8 @@ fn test_command_where_command_takes_n_flag() { .run() .stdout_is("a"); } + +#[test] +fn test_invalid_argument() { + new_ucmd!().arg("--invalid").fails().code_is(125); +} From 24097262589b7cdb48ab166407b1a35e11618337 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sun, 1 May 2022 20:51:25 +0200 Subject: [PATCH 064/111] base: set exit code to 1 for clap errors --- src/uu/base32/src/base_common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/base32/src/base_common.rs b/src/uu/base32/src/base_common.rs index 100c85b1f..148bad2f8 100644 --- a/src/uu/base32/src/base_common.rs +++ b/src/uu/base32/src/base_common.rs @@ -90,7 +90,7 @@ pub fn parse_base_cmd_args(args: impl uucore::Args, about: &str, usage: &str) -> let arg_list = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); - Config::from(&command.get_matches_from(arg_list)) + Config::from(&command.try_get_matches_from(arg_list)?) } pub fn base_app<'a>(about: &'a str, usage: &'a str) -> Command<'a> { From c7b7f19559c84feafa9959495d4f1fb0e44d9935 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 4 May 2022 19:10:28 +0200 Subject: [PATCH 065/111] cp: use new clap error mechanism --- src/uu/cp/src/cp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index ce85b58bc..1b47b7828 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -57,7 +57,7 @@ use std::path::{Path, PathBuf, StripPrefixError}; use std::str::FromStr; use std::string::ToString; use uucore::backup_control::{self, BackupMode}; -use uucore::error::{set_exit_code, ExitCode, UError, UResult}; +use uucore::error::{set_exit_code, ExitCode, UClapError, UError, UResult}; use uucore::fs::{canonicalize, MissingHandling, ResolveMode}; use walkdir::WalkDir; @@ -485,7 +485,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { app.print_help()?; } clap::ErrorKind::DisplayVersion => println!("{}", app.render_version()), - _ => return Err(Box::new(e)), + _ => return Err(Box::new(e.with_exit_code(1))), }; } else if let Ok(matches) = matches { let options = Options::from_matches(&matches)?; From 46e029f34c02a3ad0bb663d070bfb75a4ff9acb9 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 20 Apr 2022 08:06:24 +0200 Subject: [PATCH 066/111] df: refactor HumanReadable handling The refactoring consists of three parts: 1) Introduction of SizeFormat & HumanReadable enums 2) Addition of a size_format field to the options struct 3) Movement of header logic from BlockSize to Header --- src/uu/df/src/blocks.rs | 79 ++++++++++++++++++++++------------------- src/uu/df/src/df.rs | 12 +++++++ src/uu/df/src/table.rs | 47 ++++++++++++------------ 3 files changed, 80 insertions(+), 58 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index efeae2a70..f49650472 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -3,7 +3,7 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. //! Types for representing and displaying block sizes. -use crate::{OPT_BLOCKSIZE, OPT_HUMAN_READABLE_BINARY, OPT_HUMAN_READABLE_DECIMAL}; +use crate::OPT_BLOCKSIZE; use clap::ArgMatches; use std::fmt; @@ -117,14 +117,46 @@ fn to_magnitude_and_suffix(n: u128) -> Result { } } +/// A mode to use in condensing the display of a large number of bytes. +pub(crate) enum SizeFormat { + HumanReadable(HumanReadable), + StaticBlockSize, +} + +impl Default for SizeFormat { + fn default() -> Self { + Self::StaticBlockSize + } +} + +/// A mode to use in condensing the human readable display of a large number +/// of bytes. +/// +/// The [`HumanReadable::Decimal`] and[`HumanReadable::Binary`] variants +/// represent dynamic block sizes: as the number of bytes increases, the +/// divisor increases as well (for example, from 1 to 1,000 to 1,000,000 +/// and so on in the case of [`HumanReadable::Decimal`]). +#[derive(Clone, Copy)] +pub(crate) enum HumanReadable { + /// Use the largest divisor corresponding to a unit, like B, K, M, G, etc. + /// + /// This variant represents powers of 1,000. Contrast with + /// [`HumanReadable::Binary`], which represents powers of + /// 1,024. + Decimal, + + /// Use the largest divisor corresponding to a unit, like B, K, M, G, etc. + /// + /// This variant represents powers of 1,024. Contrast with + /// [`HumanReadable::Decimal`], which represents powers + /// of 1,000. + Binary, +} + /// A block size to use in condensing the display of a large number of bytes. /// /// The [`BlockSize::Bytes`] variant represents a static block -/// size. The [`BlockSize::HumanReadableDecimal`] and -/// [`BlockSize::HumanReadableBinary`] variants represent dynamic -/// block sizes: as the number of bytes increases, the divisor -/// increases as well (for example, from 1 to 1,000 to 1,000,000 and -/// so on in the case of [`BlockSize::HumanReadableDecimal`]). +/// size. /// /// The default variant is `Bytes(1024)`. pub(crate) enum BlockSize { @@ -132,20 +164,6 @@ pub(crate) enum BlockSize { /// /// The number must be positive. Bytes(u64), - - /// Use the largest divisor corresponding to a unit, like B, K, M, G, etc. - /// - /// This variant represents powers of 1,000. Contrast with - /// [`BlockSize::HumanReadableBinary`], which represents powers of - /// 1,024. - HumanReadableDecimal, - - /// Use the largest divisor corresponding to a unit, like B, K, M, G, etc. - /// - /// This variant represents powers of 1,024. Contrast with - /// [`BlockSize::HumanReadableDecimal`], which represents powers - /// of 1,000. - HumanReadableBinary, } impl Default for BlockSize { @@ -155,11 +173,7 @@ impl Default for BlockSize { } pub(crate) fn block_size_from_matches(matches: &ArgMatches) -> Result { - if matches.is_present(OPT_HUMAN_READABLE_BINARY) { - Ok(BlockSize::HumanReadableBinary) - } else if matches.is_present(OPT_HUMAN_READABLE_DECIMAL) { - Ok(BlockSize::HumanReadableDecimal) - } else if matches.is_present(OPT_BLOCKSIZE) { + if matches.is_present(OPT_BLOCKSIZE) { let s = matches.value_of(OPT_BLOCKSIZE).unwrap(); Ok(BlockSize::Bytes(parse_size(s)?)) } else { @@ -170,10 +184,8 @@ pub(crate) fn block_size_from_matches(matches: &ArgMatches) -> Result fmt::Result { match self { - Self::HumanReadableBinary => write!(f, "Size"), - Self::HumanReadableDecimal => write!(f, "Size"), Self::Bytes(n) => match to_magnitude_and_suffix(*n as u128) { - Ok(s) => write!(f, "{}-blocks", s), + Ok(s) => write!(f, "{}", s), Err(_) => Err(fmt::Error), }, } @@ -229,13 +241,8 @@ mod tests { #[test] fn test_block_size_display() { - assert_eq!(format!("{}", BlockSize::HumanReadableBinary), "Size"); - assert_eq!(format!("{}", BlockSize::HumanReadableDecimal), "Size"); - assert_eq!(format!("{}", BlockSize::Bytes(1024)), "1K-blocks"); - assert_eq!(format!("{}", BlockSize::Bytes(2 * 1024)), "2K-blocks"); - assert_eq!( - format!("{}", BlockSize::Bytes(3 * 1024 * 1024)), - "3M-blocks" - ); + assert_eq!(format!("{}", BlockSize::Bytes(1024)), "1K"); + assert_eq!(format!("{}", BlockSize::Bytes(2 * 1024)), "2K"); + assert_eq!(format!("{}", BlockSize::Bytes(3 * 1024 * 1024)), "3M"); } } diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index b86b11f37..344314198 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -11,6 +11,7 @@ mod columns; mod filesystem; mod table; +use blocks::{HumanReadable, SizeFormat}; use uucore::display::Quotable; use uucore::error::{UError, UResult, USimpleError}; use uucore::fsext::{read_fs_list, MountInfo}; @@ -62,6 +63,7 @@ static OUTPUT_FIELD_LIST: [&str; 12] = [ struct Options { show_local_fs: bool, show_all_fs: bool, + size_format: SizeFormat, block_size: BlockSize, /// Optional list of filesystem types to include in the output table. @@ -89,6 +91,7 @@ impl Default for Options { show_local_fs: Default::default(), show_all_fs: Default::default(), block_size: Default::default(), + size_format: Default::default(), include: Default::default(), exclude: Default::default(), show_total: Default::default(), @@ -166,6 +169,15 @@ impl Options { ), ParseSizeError::ParseFailure(s) => OptionsError::InvalidBlockSize(s), })?, + size_format: { + if matches.is_present(OPT_HUMAN_READABLE_BINARY) { + SizeFormat::HumanReadable(HumanReadable::Binary) + } else if matches.is_present(OPT_HUMAN_READABLE_DECIMAL) { + SizeFormat::HumanReadable(HumanReadable::Decimal) + } else { + SizeFormat::StaticBlockSize + } + }, include, exclude, show_total: matches.is_present(OPT_TOTAL), diff --git a/src/uu/df/src/table.rs b/src/uu/df/src/table.rs index 6b64ce02c..64c5033ed 100644 --- a/src/uu/df/src/table.rs +++ b/src/uu/df/src/table.rs @@ -10,6 +10,7 @@ use number_prefix::NumberPrefix; use unicode_width::UnicodeWidthStr; +use crate::blocks::{HumanReadable, SizeFormat}; use crate::columns::{Alignment, Column}; use crate::filesystem::Filesystem; use crate::{BlockSize, Options}; @@ -213,15 +214,10 @@ impl<'a> RowFormatter<'a> { } /// Get a human readable string giving the scaled version of the input number. - /// - /// The scaling factor is defined in the `options` field. - /// - /// This function is supposed to be used by `scaled_bytes()` and `scaled_inodes()` only. - fn scaled_human_readable(&self, size: u64) -> String { - let number_prefix = match self.options.block_size { - BlockSize::HumanReadableDecimal => NumberPrefix::decimal(size as f64), - BlockSize::HumanReadableBinary => NumberPrefix::binary(size as f64), - _ => unreachable!(), + fn scaled_human_readable(&self, size: u64, human_readable: HumanReadable) -> String { + let number_prefix = match human_readable { + HumanReadable::Decimal => NumberPrefix::decimal(size as f64), + HumanReadable::Binary => NumberPrefix::binary(size as f64), }; match number_prefix { NumberPrefix::Standalone(bytes) => bytes.to_string(), @@ -233,10 +229,12 @@ impl<'a> RowFormatter<'a> { /// /// The scaling factor is defined in the `options` field. fn scaled_bytes(&self, size: u64) -> String { - if let BlockSize::Bytes(d) = self.options.block_size { - (size / d).to_string() - } else { - self.scaled_human_readable(size) + match self.options.size_format { + SizeFormat::HumanReadable(h) => self.scaled_human_readable(size, h), + SizeFormat::StaticBlockSize => { + let BlockSize::Bytes(d) = self.options.block_size; + (size / d).to_string() + } } } @@ -244,10 +242,9 @@ impl<'a> RowFormatter<'a> { /// /// The scaling factor is defined in the `options` field. fn scaled_inodes(&self, size: u64) -> String { - if let BlockSize::Bytes(_) = self.options.block_size { - size.to_string() - } else { - self.scaled_human_readable(size) + match self.options.size_format { + SizeFormat::HumanReadable(h) => self.scaled_human_readable(size, h), + SizeFormat::StaticBlockSize => size.to_string(), } } @@ -305,7 +302,12 @@ impl Header { for column in &options.columns { let header = match column { Column::Source => String::from("Filesystem"), - Column::Size => options.block_size.to_string(), + Column::Size => match options.size_format { + SizeFormat::HumanReadable(_) => String::from("Size"), + SizeFormat::StaticBlockSize => { + format!("{}-blocks", options.block_size) + } + }, Column::Used => String::from("Used"), Column::Avail => String::from("Available"), Column::Pcent => String::from("Use%"), @@ -424,6 +426,7 @@ impl fmt::Display for Table { #[cfg(test)] mod tests { + use crate::blocks::{HumanReadable, SizeFormat}; use crate::columns::Column; use crate::table::{Header, Row, RowFormatter}; use crate::{BlockSize, Options}; @@ -523,7 +526,7 @@ mod tests { #[test] fn test_header_with_human_readable_binary() { let options = Options { - block_size: BlockSize::HumanReadableBinary, + size_format: SizeFormat::HumanReadable(HumanReadable::Binary), ..Default::default() }; assert_eq!( @@ -542,7 +545,7 @@ mod tests { #[test] fn test_header_with_human_readable_si() { let options = Options { - block_size: BlockSize::HumanReadableDecimal, + size_format: SizeFormat::HumanReadable(HumanReadable::Decimal), ..Default::default() }; assert_eq!( @@ -689,7 +692,7 @@ mod tests { #[test] fn test_row_formatter_with_human_readable_si() { let options = Options { - block_size: BlockSize::HumanReadableDecimal, + size_format: SizeFormat::HumanReadable(HumanReadable::Decimal), columns: COLUMNS_WITH_FS_TYPE.to_vec(), ..Default::default() }; @@ -730,7 +733,7 @@ mod tests { #[test] fn test_row_formatter_with_human_readable_binary() { let options = Options { - block_size: BlockSize::HumanReadableBinary, + size_format: SizeFormat::HumanReadable(HumanReadable::Binary), columns: COLUMNS_WITH_FS_TYPE.to_vec(), ..Default::default() }; From 00a3ec2d1f68e1c6d11f6f1d27651d2e1ae6dbf0 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 4 May 2022 16:11:03 +0200 Subject: [PATCH 067/111] df: implement Default for Row for unit tests --- src/uu/df/src/table.rs | 113 +++++++++++++---------------------------- 1 file changed, 34 insertions(+), 79 deletions(-) diff --git a/src/uu/df/src/table.rs b/src/uu/df/src/table.rs index 6b64ce02c..0d57bc93b 100644 --- a/src/uu/df/src/table.rs +++ b/src/uu/df/src/table.rs @@ -446,6 +446,30 @@ mod tests { Column::Target, ]; + impl Default for Row { + fn default() -> Self { + Self { + file: Some("/path/to/file".to_string()), + fs_device: "my_device".to_string(), + fs_type: "my_type".to_string(), + fs_mount: "my_mount".to_string(), + + bytes: 100, + bytes_used: 25, + bytes_avail: 75, + bytes_usage: Some(0.25), + + #[cfg(target_os = "macos")] + bytes_capacity: Some(0.5), + + inodes: 10, + inodes_used: 2, + inodes_free: 8, + inodes_usage: Some(0.2), + } + } + } + #[test] fn test_default_header() { let options = Default::default(); @@ -565,9 +589,7 @@ mod tests { ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), - fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), bytes: 100, @@ -575,13 +597,7 @@ mod tests { bytes_avail: 75, bytes_usage: Some(0.25), - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - - inodes: 10, - inodes_used: 2, - inodes_free: 8, - inodes_usage: Some(0.2), + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); assert_eq!( @@ -598,7 +614,6 @@ mod tests { ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -608,13 +623,7 @@ mod tests { bytes_avail: 75, bytes_usage: Some(0.25), - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - - inodes: 10, - inodes_used: 2, - inodes_free: 8, - inodes_usage: Some(0.2), + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); assert_eq!( @@ -631,23 +640,15 @@ mod tests { ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), - fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), - bytes: 100, - bytes_used: 25, - bytes_avail: 75, - bytes_usage: Some(0.25), - - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - inodes: 10, inodes_used: 2, inodes_free: 8, inodes_usage: Some(0.2), + + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); assert_eq!( @@ -664,23 +665,9 @@ mod tests { ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), - fs_device: "my_device".to_string(), - fs_type: "my_type".to_string(), - fs_mount: "my_mount".to_string(), - bytes: 100, - bytes_used: 25, - bytes_avail: 75, - bytes_usage: Some(0.25), - - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - inodes: 10, - inodes_used: 2, - inodes_free: 8, - inodes_usage: Some(0.2), + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); assert_eq!(fmt.get_values(), vec!("1", "10")); @@ -694,7 +681,6 @@ mod tests { ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -704,13 +690,7 @@ mod tests { bytes_avail: 3000, bytes_usage: Some(0.25), - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - - inodes: 10, - inodes_used: 2, - inodes_free: 8, - inodes_usage: Some(0.2), + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); assert_eq!( @@ -735,7 +715,6 @@ mod tests { ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -745,13 +724,7 @@ mod tests { bytes_avail: 3072, bytes_usage: Some(0.25), - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - - inodes: 10, - inodes_used: 2, - inodes_free: 8, - inodes_usage: Some(0.2), + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); assert_eq!( @@ -771,32 +744,14 @@ mod tests { #[test] fn test_row_formatter_with_round_up_usage() { let options = Options { - block_size: BlockSize::Bytes(1), + columns: vec![Column::Pcent], ..Default::default() }; let row = Row { - file: Some("/path/to/file".to_string()), - fs_device: "my_device".to_string(), - fs_type: "my_type".to_string(), - fs_mount: "my_mount".to_string(), - - bytes: 100, - bytes_used: 25, - bytes_avail: 75, bytes_usage: Some(0.251), - - #[cfg(target_os = "macos")] - bytes_capacity: Some(0.5), - - inodes: 10, - inodes_used: 2, - inodes_free: 8, - inodes_usage: Some(0.2), + ..Default::default() }; let fmt = RowFormatter::new(&row, &options); - assert_eq!( - fmt.get_values(), - vec!("my_device", "100", "25", "75", "26%", "my_mount") - ); + assert_eq!(fmt.get_values(), vec!("26%")); } } From 24f78ddb9ecf28eaa33ec0b37350bd9711d982d1 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 5 May 2022 13:55:38 +0200 Subject: [PATCH 068/111] docs: remove duplicate "at", add missing newline --- docs/src/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 3ea5d913a..c51fbb198 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -5,7 +5,7 @@ utilities in [Rust](https://www.rust-lang.org). It is available for Linux, Windows, Mac and other platforms. The API reference for `uucore`, the library of functions shared between -various utils, is hosted at at +various utils, is hosted at [docs.rs](https://docs.rs/uucore/latest/uucore/). uutils is licensed under the [MIT License](https://github.com/uutils/coreutils/blob/main/LICENSE). @@ -17,4 +17,4 @@ uutils is licensed under the [MIT License](https://github.com/uutils/coreutils/b * [Discord](https://discord.gg/wQVJbvJ) > Note: This manual is automatically generated from the source code and is -> a work in progress. \ No newline at end of file +> a work in progress. From f5ffa9412940d4fe74b89d2931eb7ccf8198f8d0 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Thu, 5 May 2022 19:53:38 +0200 Subject: [PATCH 069/111] test_stat: add tests for issues with stdin * add tests for: https://github.com/uutils/coreutils/issues/3485 * add test for: https://github.com/uutils/coreutils/pull/3280 --- tests/by-util/test_stat.rs | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 90ad2d12a..53e83bef6 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -311,3 +311,58 @@ fn test_printf() { let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } + +#[cfg(unix)] +#[test] +#[cfg(disable_until_fixed)] +fn test_stdin_pipe_fifo1() { + // $ echo | stat - + // File: - + // Size: 0 Blocks: 0 IO Block: 4096 fifo + // use std::process::{Command, Stdio}; + new_ucmd!() + .arg("-") + .set_stdin(std::process::Stdio::piped()) + .run() + .no_stderr() + .stdout_contains("fifo") + .stdout_contains("File: -") + .succeeded(); +} + +#[cfg(unix)] +#[test] +#[cfg(disable_until_fixed)] +fn test_stdin_pipe_fifo2() { + // $ stat - + // File: - + // Size: 0 Blocks: 0 IO Block: 1024 character special file + new_ucmd!() + .arg("-") + .run() + .no_stderr() + .stdout_contains("character special file") + .stdout_contains("File: -") + .succeeded(); +} + +#[cfg(unix)] +#[test] +#[cfg(disable_until_fixed)] +fn test_stdin_redirect() { + // $ touch f && stat - < f + // File: - + // Size: 0 Blocks: 0 IO Block: 4096 regular empty file + + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + at.touch("f"); + new_ucmd!() + .arg("-") + .set_stdin(std::fs::File::open("f").unwrap()) + .run() + .no_stderr() + .stdout_contains("regular empty file") + .stdout_contains("File: -") + .succeeded(); +} From e70b99dad0b01758b71faf76a31094541f23112f Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 29 Apr 2022 10:32:28 +0200 Subject: [PATCH 070/111] touch: add support of -d '1970-01-01 18:43:33.023456789' --- src/uu/touch/src/touch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 5264401ef..1d90ed4d7 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -6,7 +6,7 @@ // For the full copyright and license information, please view the LICENSE file // that was distributed with this source code. -// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm clapv PWSTR lpszfilepath hresult mktime YYYYMMDDHHMM YYMMDDHHMM DATETIME YYYYMMDDHHMMS +// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm clapv PWSTR lpszfilepath hresult mktime YYYYMMDDHHMM YYMMDDHHMM DATETIME YYYYMMDDHHMMS subsecond pub extern crate filetime; #[macro_use] From 65d0f5ba9f0ba9a4271d293fd0e7538c6a502783 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 2 May 2022 22:32:37 +0200 Subject: [PATCH 071/111] to_local: manage the error --- src/uu/touch/src/touch.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 1d90ed4d7..8e8e4c458 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -43,8 +43,13 @@ pub mod options { static ARG_FILES: &str = "files"; fn to_local(tm: time::PrimitiveDateTime) -> time::OffsetDateTime { - // TODO: handle error getting now - tm.assume_offset(time::OffsetDateTime::now_local().unwrap().offset()) + let offset = match time::OffsetDateTime::now_local() { + Ok(lo) => lo.offset(), + Err(e) => { + panic!("error: {}", e); + } + }; + tm.assume_offset(offset) } fn local_dt_to_filetime(dt: time::OffsetDateTime) -> FileTime { From e691330f02f02c6ac5fae05d82a24d75a22fb3e8 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Thu, 5 May 2022 17:58:37 -0400 Subject: [PATCH 072/111] mktemp: return MkTempError from parse_template() Change the return type of the `parse_template()` helper function in the `mktemp` program so that it returns `Result<..., MkTempError>` instead of `UResult<...>`. This separates the lower level helper function from the higher level `UResult` abstraction and will make it easier to refactor this code in future commits. --- src/uu/mktemp/src/mktemp.rs | 69 ++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index f999d6675..b14318679 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -205,20 +205,41 @@ pub fn uu_app<'a>() -> Command<'a> { ) } +/// Parse a template string into prefix, suffix, and random components. +/// +/// `temp` is the template string, with three or more consecutive `X`s +/// representing a placeholder for randomly generated characters (for +/// example, `"abc_XXX.txt"`). If `temp` ends in an `X`, then a suffix +/// can be specified by `suffix` instead. +/// +/// # Errors +/// +/// * If there are fewer than three consecutive `X`s in `temp`. +/// * If `suffix` is a [`Some`] object but `temp` does not end in `X`. +/// * If the suffix (specified either way) contains a path separator. +/// +/// # Examples +/// +/// ```rust,ignore +/// assert_eq!(parse_template("XXX", None).unwrap(), ("", 3, "")); +/// assert_eq!(parse_template("abcXXX", None).unwrap(), ("abc", 3, "")); +/// assert_eq!(parse_template("XXXdef", None).unwrap(), ("", 3, "def")); +/// assert_eq!(parse_template("abcXXXdef", None).unwrap(), ("abc", 3, "def")); +/// ``` fn parse_template<'a>( temp: &'a str, suffix: Option<&'a str>, -) -> UResult<(&'a str, usize, &'a str)> { +) -> Result<(&'a str, usize, &'a str), MkTempError> { let right = match temp.rfind('X') { Some(r) => r + 1, - None => return Err(MkTempError::TooFewXs(temp.into()).into()), + None => return Err(MkTempError::TooFewXs(temp.into())), }; let left = temp[..right].rfind(|c| c != 'X').map_or(0, |i| i + 1); let prefix = &temp[..left]; let rand = right - left; if rand < 3 { - return Err(MkTempError::TooFewXs(temp.into()).into()); + return Err(MkTempError::TooFewXs(temp.into())); } let mut suf = &temp[right..]; @@ -227,12 +248,12 @@ fn parse_template<'a>( if suf.is_empty() { suf = s; } else { - return Err(MkTempError::MustEndInX(temp.into()).into()); + return Err(MkTempError::MustEndInX(temp.into())); } }; if suf.chars().any(is_separator) { - return Err(MkTempError::ContainsDirSeparator(suf.into()).into()); + return Err(MkTempError::ContainsDirSeparator(suf.into())); } Ok((prefix, rand, suf)) @@ -304,3 +325,41 @@ fn exec(dir: &Path, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> println_verbatim(path).map_err_context(|| "failed to print directory name".to_owned()) } + +#[cfg(test)] +mod tests { + use crate::parse_template; + + #[test] + fn test_parse_template_no_suffix() { + assert_eq!(parse_template("XXX", None).unwrap(), ("", 3, "")); + assert_eq!(parse_template("abcXXX", None).unwrap(), ("abc", 3, "")); + assert_eq!(parse_template("XXXdef", None).unwrap(), ("", 3, "def")); + assert_eq!( + parse_template("abcXXXdef", None).unwrap(), + ("abc", 3, "def") + ); + } + + #[test] + fn test_parse_template_suffix() { + assert_eq!(parse_template("XXX", Some("def")).unwrap(), ("", 3, "def")); + assert_eq!( + parse_template("abcXXX", Some("def")).unwrap(), + ("abc", 3, "def") + ); + } + + #[test] + fn test_parse_template_errors() { + // TODO This should be an error as well, but we are not + // catching it just yet. A future commit will correct this. + // + // assert!(parse_template("a/bXXX", None).is_err()); + // + assert!(parse_template("XXXa/b", None).is_err()); + assert!(parse_template("XX", None).is_err()); + assert!(parse_template("XXXabc", Some("def")).is_err()); + assert!(parse_template("XXX", Some("a/b")).is_err()); + } +} From 608b1afde51542222e8ab64c1681013249e083c2 Mon Sep 17 00:00:00 2001 From: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com> Date: Thu, 5 May 2022 19:38:10 -0500 Subject: [PATCH 073/111] chore: Included githubactions in the dependabot config This should help with keeping the GitHub actions updated on new releases. This will also help with keeping it secure. Dependabot helps in keeping the supply chain secure https://docs.github.com/en/code-security/dependabot GitHub actions up to date https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot https://github.com/ossf/scorecard/blob/main/docs/checks.md#dependency-update-tool Signed-off-by: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com> --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ef7519b88..cfcddbb14 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,8 @@ updates: schedule: interval: "daily" open-pull-requests-limit: 5 + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 5 From be1f41e24cf2dba128abcb5ee181b58b07008741 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 6 May 2022 08:02:22 +0200 Subject: [PATCH 074/111] df: set names for arg values & add missing space --- src/uu/df/src/df.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index 344314198..d9fb1be7b 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -445,6 +445,7 @@ pub fn uu_app<'a>() -> Command<'a> { .short('B') .long("block-size") .takes_value(true) + .value_name("SIZE") .overrides_with_all(&[OPT_KILO, OPT_BLOCKSIZE]) .help( "scale sizes by SIZE before printing them; e.g.\ @@ -501,6 +502,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(OPT_OUTPUT) .long("output") .takes_value(true) + .value_name("FIELD_LIST") .min_values(0) .require_equals(true) .use_value_delimiter(true) @@ -510,7 +512,7 @@ pub fn uu_app<'a>() -> Command<'a> { .default_values(&["source", "size", "used", "avail", "pcent", "target"]) .conflicts_with_all(&[OPT_INODES, OPT_PORTABILITY, OPT_PRINT_TYPE]) .help( - "use the output format defined by FIELD_LIST,\ + "use the output format defined by FIELD_LIST, \ or print all fields if FIELD_LIST is omitted.", ), ) @@ -533,6 +535,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long("type") .allow_invalid_utf8(true) .takes_value(true) + .value_name("TYPE") .multiple_occurrences(true) .help("limit listing to file systems of type TYPE"), ) @@ -549,6 +552,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long("exclude-type") .allow_invalid_utf8(true) .takes_value(true) + .value_name("TYPE") .use_value_delimiter(true) .multiple_occurrences(true) .help("limit listing to file systems not of type TYPE"), From 97c59d78578cf9402946b1bd4fad7777da496362 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 06:29:14 +0000 Subject: [PATCH 075/111] build(deps): bump num-traits from 0.2.14 to 0.2.15 Bumps [num-traits](https://github.com/rust-num/num-traits) from 0.2.14 to 0.2.15. - [Release notes](https://github.com/rust-num/num-traits/releases) - [Changelog](https://github.com/rust-num/num-traits/blob/master/RELEASES.md) - [Commits](https://github.com/rust-num/num-traits/compare/num-traits-0.2.14...num-traits-0.2.15) --- updated-dependencies: - dependency-name: num-traits dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/uu/expr/Cargo.toml | 2 +- src/uu/factor/Cargo.toml | 4 ++-- src/uu/seq/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b503b60d5..4f73fe91e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1196,9 +1196,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] diff --git a/src/uu/expr/Cargo.toml b/src/uu/expr/Cargo.toml index c4a1bae4a..9ea8008af 100644 --- a/src/uu/expr/Cargo.toml +++ b/src/uu/expr/Cargo.toml @@ -17,7 +17,7 @@ path = "src/expr.rs" [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } num-bigint = "0.4.0" -num-traits = "0.2.14" +num-traits = "0.2.15" onig = { version = "~6.3", default-features = false } uucore = { version=">=0.0.11", package="uucore", path="../../uucore" } diff --git a/src/uu/factor/Cargo.toml b/src/uu/factor/Cargo.toml index e1620ed90..242616718 100644 --- a/src/uu/factor/Cargo.toml +++ b/src/uu/factor/Cargo.toml @@ -12,12 +12,12 @@ categories = ["command-line-utilities"] edition = "2021" [build-dependencies] -num-traits = "0.2.13" # used in src/numerics.rs, which is included by build.rs +num-traits = "0.2.15" # used in src/numerics.rs, which is included by build.rs [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } coz = { version = "0.1.3", optional = true } -num-traits = "0.2.13" # Needs at least version 0.2.13 for "OverflowingAdd" +num-traits = "0.2.13" # Needs at least version 0.2.15 for "OverflowingAdd" rand = { version = "0.8", features = ["small_rng"] } smallvec = "1.7" # TODO(nicoo): Use `union` feature, requires Rust 1.49 or later. uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore" } diff --git a/src/uu/seq/Cargo.toml b/src/uu/seq/Cargo.toml index ad8bba5b6..67226093d 100644 --- a/src/uu/seq/Cargo.toml +++ b/src/uu/seq/Cargo.toml @@ -19,7 +19,7 @@ path = "src/seq.rs" bigdecimal = "0.3" clap = { version = "3.1", features = ["wrap_help", "cargo"] } num-bigint = "0.4.0" -num-traits = "0.2.14" +num-traits = "0.2.15" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["memo"] } [[bin]] From a60f6dc67eca2591639f7f6e90d4f21ae3602eb4 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 4 May 2022 22:36:21 +0200 Subject: [PATCH 076/111] Update num-traits for real --- src/uu/factor/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/factor/Cargo.toml b/src/uu/factor/Cargo.toml index 242616718..20a21ac00 100644 --- a/src/uu/factor/Cargo.toml +++ b/src/uu/factor/Cargo.toml @@ -17,7 +17,7 @@ num-traits = "0.2.15" # used in src/numerics.rs, which is included by build.rs [dependencies] clap = { version = "3.1", features = ["wrap_help", "cargo"] } coz = { version = "0.1.3", optional = true } -num-traits = "0.2.13" # Needs at least version 0.2.15 for "OverflowingAdd" +num-traits = "0.2.15" # Needs at least version 0.2.15 for "OverflowingAdd" rand = { version = "0.8", features = ["small_rng"] } smallvec = "1.7" # TODO(nicoo): Use `union` feature, requires Rust 1.49 or later. uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore" } From 06ef89b3d822dccbf0dfff1683486498c6fcfc6f Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Thu, 5 May 2022 22:48:37 +0200 Subject: [PATCH 077/111] touch: improve the -d option support of other dates --- src/uu/touch/src/touch.rs | 25 +++++++++++++++++-------- tests/by-util/test_touch.rs | 10 ++++++++-- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 8e8e4c458..c082aed23 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -16,7 +16,7 @@ use clap::{crate_version, Arg, ArgGroup, Command}; use filetime::*; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use time::macros::{format_description, time}; +use time::macros::{format_description, offset, time}; use time::Duration; use uucore::display::Quotable; use uucore::error::{FromIo, UError, UResult, USimpleError}; @@ -42,6 +42,7 @@ pub mod options { static ARG_FILES: &str = "files"; +// Convert a date/time to a date with a TZ offset fn to_local(tm: time::PrimitiveDateTime) -> time::OffsetDateTime { let offset = match time::OffsetDateTime::now_local() { Ok(lo) => lo.offset(), @@ -52,10 +53,18 @@ fn to_local(tm: time::PrimitiveDateTime) -> time::OffsetDateTime { tm.assume_offset(offset) } +// Convert a date/time with a TZ offset into a FileTime fn local_dt_to_filetime(dt: time::OffsetDateTime) -> FileTime { FileTime::from_unix_time(dt.unix_timestamp(), dt.nanosecond()) } +// Convert a date/time, considering that the input is in UTC time +// Used for touch -d 1970-01-01 18:43:33.023456789 for example +fn dt_to_filename(tm: time::PrimitiveDateTime) -> FileTime { + let dt = tm.assume_offset(offset!(UTC)); + local_dt_to_filetime(dt) +} + #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { let matches = uu_app().get_matches_from(args); @@ -310,15 +319,15 @@ fn parse_date(s: &str) -> UResult { // Tue Dec 3 ... // ("%c", POSIX_LOCALE_FORMAT), // - // But also support other format found in the GNU tests like + if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &POSIX_LOCALE_FORMAT) { + return Ok(local_dt_to_filetime(to_local(parsed))); + } + + // Also support other formats found in the GNU tests like // in tests/misc/stat-nanoseconds.sh - for fmt in [ - POSIX_LOCALE_FORMAT, - YYYYMMDDHHMMS_FORMAT, - YYYYMMDDHHMMSS_FORMAT, - ] { + for fmt in [YYYYMMDDHHMMS_FORMAT, YYYYMMDDHHMMSS_FORMAT] { if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &fmt) { - return Ok(local_dt_to_filetime(to_local(parsed))); + return Ok(dt_to_filename(parsed)); } } diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index ed62692f4..9b8eebbf0 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -438,7 +438,7 @@ fn test_touch_set_date4() { assert!(at.file_exists(file)); - let expected = FileTime::from_unix_time(60213, 0); + let expected = FileTime::from_unix_time(67413, 0); let (atime, mtime) = get_file_times(&at, file); assert_eq!(atime, mtime); assert_eq!(atime, expected); @@ -456,7 +456,13 @@ fn test_touch_set_date5() { assert!(at.file_exists(file)); - let expected = FileTime::from_unix_time(60213, 023456789); + // Slightly different result on Windows for nano seconds + // TODO: investigate + #[cfg(windows)] + let expected = FileTime::from_unix_time(67413, 23456700); + #[cfg(not(windows))] + let expected = FileTime::from_unix_time(67413, 23456789); + let (atime, mtime) = get_file_times(&at, file); assert_eq!(atime, mtime); assert_eq!(atime, expected); From 5a3933a882ae0daec84bad9fc3c517e1bda58011 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 6 May 2022 15:37:52 +0200 Subject: [PATCH 078/111] df: fix "Size" header for multiples of 1000 & 1024 --- src/uu/df/src/blocks.rs | 11 +++++++++-- tests/by-util/test_df.rs | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index f49650472..e964a208a 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -73,7 +73,7 @@ fn to_magnitude_and_suffix_1024(n: u128) -> Result { Err(()) } -/// Convert a number, except multiples of 1024, into a string like "12kB" or "34MB". +/// Convert a number into a string like "12kB" or "34MB". /// /// Powers of 1000 become "1kB", "1MB", "1GB", etc. /// @@ -110,7 +110,7 @@ fn to_magnitude_and_suffix_not_powers_of_1024(n: u128) -> Result { /// /// If the number is too large to represent. fn to_magnitude_and_suffix(n: u128) -> Result { - if n % 1024 == 0 { + if n % 1024 == 0 && n % 1000 != 0 { to_magnitude_and_suffix_1024(n) } else { to_magnitude_and_suffix_not_powers_of_1024(n) @@ -239,6 +239,13 @@ mod tests { assert_eq!(to_magnitude_and_suffix(1_000_000_001).unwrap(), "1.1GB"); } + #[test] + fn test_to_magnitude_and_suffix_multiples_of_1000_and_1024() { + assert_eq!(to_magnitude_and_suffix(128_000).unwrap(), "128kB"); + assert_eq!(to_magnitude_and_suffix(1000 * 1024).unwrap(), "1.1MB"); + assert_eq!(to_magnitude_and_suffix(1_000_000_000_000).unwrap(), "1TB"); + } + #[test] fn test_block_size_display() { assert_eq!(format!("{}", BlockSize::Bytes(1024)), "1K"); diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index f03a71a7b..511956ec4 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -392,6 +392,11 @@ fn test_block_size_1024() { assert_eq!(get_header(2 * 1024 * 1024), "2M-blocks"); assert_eq!(get_header(1024 * 1024 * 1024), "1G-blocks"); assert_eq!(get_header(34 * 1024 * 1024 * 1024), "34G-blocks"); + + // multiples of both 1024 and 1000 + assert_eq!(get_header(128_000), "128kB-blocks"); + assert_eq!(get_header(1000 * 1024), "1.1MB-blocks"); + assert_eq!(get_header(1_000_000_000_000), "1TB-blocks"); } #[test] From 39520a84ab7ca2515913b0621d91d60f05775fd7 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 6 May 2022 23:54:12 +0200 Subject: [PATCH 079/111] fix the GNU error detection --- .github/workflows/GnuTests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index f2b0ddd45..3a152be22 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -170,8 +170,8 @@ jobs: REPO_DEFAULT_BRANCH='${{ steps.vars.outputs.repo_default_branch }}' if test -f "${REF_LOG_FILE}"; then echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")" - REF_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) - NEW_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) + REF_ERROR=$(sed -n "s/^ERROR: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) + NEW_ERROR=$(sed -n "s/^ERROR: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) REF_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) NEW_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) for LINE in ${REF_FAILING} From a640ed64896b0fc5ff35362f1e2b27ead8d8c7f0 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 6 May 2022 23:54:12 +0200 Subject: [PATCH 080/111] fix the GNU error detection --- .github/workflows/GnuTests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index a20ddd8a8..c8d3c8b94 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -174,8 +174,8 @@ jobs: REPO_DEFAULT_BRANCH='${{ steps.vars.outputs.repo_default_branch }}' if test -f "${REF_LOG_FILE}"; then echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")" - REF_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) - NEW_ERROR=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) + REF_ERROR=$(sed -n "s/^ERROR: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) + NEW_ERROR=$(sed -n "s/^ERROR: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) REF_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort) NEW_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort) for LINE in ${REF_FAILING} From 79e5d80e3eec820063d82725b7237ce92707b674 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Fri, 6 May 2022 14:01:23 +0200 Subject: [PATCH 081/111] stat: improve handling of stdin/fifo (fix #3485) * fix https://github.com/uutils/coreutils/issues/3485 * improve the workaround from #3280 * add tests --- src/uu/stat/src/stat.rs | 81 ++++++++++++++++------------ src/uucore/src/lib/features/fsext.rs | 5 +- tests/by-util/test_stat.rs | 34 +++++++++--- 3 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/uu/stat/src/stat.rs b/src/uu/stat/src/stat.rs index cebc6c108..41c9ae4a9 100644 --- a/src/uu/stat/src/stat.rs +++ b/src/uu/stat/src/stat.rs @@ -19,7 +19,9 @@ use uucore::{entries, format_usage}; use clap::{crate_version, Arg, ArgMatches, Command}; use std::borrow::Cow; use std::convert::AsRef; +use std::ffi::{OsStr, OsString}; use std::os::unix::fs::{FileTypeExt, MetadataExt}; +use std::os::unix::prelude::OsStrExt; use std::path::Path; use std::{cmp, fs, iter}; @@ -221,7 +223,7 @@ pub struct Stater { follow: bool, show_fs: bool, from_user: bool, - files: Vec, + files: Vec, mount_list: Option>, default_tokens: Vec, default_dev_tokens: Vec, @@ -471,24 +473,10 @@ impl Stater { } fn new(matches: &ArgMatches) -> UResult { - let mut files: Vec = matches - .values_of(ARG_FILES) - .map(|v| v.map(ToString::to_string).collect()) + let files = matches + .values_of_os(ARG_FILES) + .map(|v| v.map(OsString::from).collect()) .unwrap_or_default(); - #[cfg(unix)] - if files.contains(&String::from("-")) { - let redirected_path = Path::new("/dev/stdin") - .canonicalize() - .expect("unable to canonicalize /dev/stdin") - .into_os_string() - .into_string() - .unwrap(); - for file in &mut files { - if file == "-" { - *file = redirected_path.clone(); - } - } - } let format_str = if matches.is_present(options::PRINTF) { matches .value_of(options::PRINTF) @@ -550,19 +538,37 @@ impl Stater { } fn exec(&self) -> i32 { + let mut stdin_is_fifo = false; + if cfg!(unix) { + if let Ok(md) = fs::metadata("/dev/stdin") { + stdin_is_fifo = md.file_type().is_fifo(); + } + } + let mut ret = 0; for f in &self.files { - ret |= self.do_stat(f.as_str()); + ret |= self.do_stat(f, stdin_is_fifo); } ret } - fn do_stat(&self, file: &str) -> i32 { - if !self.show_fs { - let result = if self.follow { - fs::metadata(file) + fn do_stat(&self, file: &OsStr, stdin_is_fifo: bool) -> i32 { + let display_name = file.to_string_lossy(); + let file: OsString = if cfg!(unix) && display_name.eq("-") { + if let Ok(p) = Path::new("/dev/stdin").canonicalize() { + p.into_os_string() } else { - fs::symlink_metadata(file) + OsString::from("/dev/stdin") + } + } else { + OsString::from(file) + }; + + if !self.show_fs { + let result = if self.follow || stdin_is_fifo && display_name.eq("-") { + fs::metadata(&file) + } else { + fs::symlink_metadata(&file) }; match result { Ok(meta) => { @@ -658,28 +664,32 @@ impl Stater { // mount point 'm' => { - arg = self.find_mount_point(file).unwrap(); + arg = self.find_mount_point(&file).unwrap(); output_type = OutputType::Str; } // file name 'n' => { - arg = file.to_owned(); + arg = display_name.to_string(); output_type = OutputType::Str; } // quoted file name with dereference if symbolic link 'N' => { if file_type.is_symlink() { - let dst = match fs::read_link(file) { + let dst = match fs::read_link(&file) { Ok(path) => path, Err(e) => { println!("{}", e); return 1; } }; - arg = format!("{} -> {}", file.quote(), dst.quote()); + arg = format!( + "{} -> {}", + display_name.quote(), + dst.quote() + ); } else { - arg = file.to_string(); + arg = display_name.to_string(); } output_type = OutputType::Str; } @@ -771,12 +781,16 @@ impl Stater { } } Err(e) => { - show_error!("cannot stat {}: {}", file.quote(), e); + show_error!("cannot stat {}: {}", display_name.quote(), e); return 1; } } } else { - match statfs(file) { + #[cfg(unix)] + let p = file.as_bytes(); + #[cfg(not(unix))] + let p = file.into_string().unwrap(); + match statfs(p) { Ok(meta) => { let tokens = &self.default_tokens; @@ -829,7 +843,7 @@ impl Stater { } // file name 'n' => { - arg = file.to_owned(); + arg = display_name.to_string(); output_type = OutputType::Str; } // block size (for faster transfers) @@ -866,7 +880,7 @@ impl Stater { Err(e) => { show_error!( "cannot read file system information for {}: {}", - file.quote(), + display_name.quote(), e ); return 1; @@ -1028,6 +1042,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(ARG_FILES) .multiple_occurrences(true) .takes_value(true) + .allow_invalid_utf8(true) .min_values(1), ) } diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index eeaf54061..511c1dd2c 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -84,6 +84,7 @@ use std::ffi::CString; use std::io::Error as IOError; #[cfg(unix)] use std::mem; +#[cfg(not(unix))] use std::path::Path; use std::time::UNIX_EPOCH; @@ -708,9 +709,9 @@ impl FsMeta for StatFs { } #[cfg(unix)] -pub fn statfs>(path: P) -> Result +pub fn statfs

(path: P) -> Result where - Vec: From

, + P: Into>, { match CString::new(path) { Ok(p) => { diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 53e83bef6..c3ffb3be5 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -312,9 +312,21 @@ fn test_printf() { ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } -#[cfg(unix)] #[test] -#[cfg(disable_until_fixed)] +#[cfg(unix)] +fn test_pipe_fifo() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkfifo("FIFO"); + ucmd.arg("FIFO") + .run() + .no_stderr() + .stdout_contains("fifo") + .stdout_contains("File: FIFO") + .succeeded(); +} + +#[test] +#[cfg(target_os = "linux")] fn test_stdin_pipe_fifo1() { // $ echo | stat - // File: - @@ -328,17 +340,26 @@ fn test_stdin_pipe_fifo1() { .stdout_contains("fifo") .stdout_contains("File: -") .succeeded(); + + new_ucmd!() + .args(&["-L", "-"]) + .set_stdin(std::process::Stdio::piped()) + .run() + .no_stderr() + .stdout_contains("fifo") + .stdout_contains("File: -") + .succeeded(); } -#[cfg(unix)] #[test] -#[cfg(disable_until_fixed)] +#[cfg(target_os = "linux")] fn test_stdin_pipe_fifo2() { // $ stat - // File: - // Size: 0 Blocks: 0 IO Block: 1024 character special file new_ucmd!() .arg("-") + .set_stdin(std::process::Stdio::null()) .run() .no_stderr() .stdout_contains("character special file") @@ -346,9 +367,8 @@ fn test_stdin_pipe_fifo2() { .succeeded(); } -#[cfg(unix)] #[test] -#[cfg(disable_until_fixed)] +#[cfg(target_os = "linux")] fn test_stdin_redirect() { // $ touch f && stat - < f // File: - @@ -359,7 +379,7 @@ fn test_stdin_redirect() { at.touch("f"); new_ucmd!() .arg("-") - .set_stdin(std::fs::File::open("f").unwrap()) + .set_stdin(std::fs::File::open(at.plus("f")).unwrap()) .run() .no_stderr() .stdout_contains("regular empty file") From f668b69a2caa4e257128442a9ee6fae082ba768f Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 5 May 2022 10:53:40 +0200 Subject: [PATCH 082/111] df: use blocksize of 512 if POSIXLY_CORRECT is set --- src/uu/df/src/blocks.rs | 19 +++++++++++++++++-- src/uu/df/src/df.rs | 8 ++++++++ tests/by-util/test_df.rs | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index e964a208a..bb6e06333 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -5,7 +5,7 @@ //! Types for representing and displaying block sizes. use crate::OPT_BLOCKSIZE; use clap::ArgMatches; -use std::fmt; +use std::{env, fmt}; use uucore::parse_size::{parse_size, ParseSizeError}; @@ -159,6 +159,7 @@ pub(crate) enum HumanReadable { /// size. /// /// The default variant is `Bytes(1024)`. +#[derive(Debug, PartialEq)] pub(crate) enum BlockSize { /// A fixed number of bytes. /// @@ -168,7 +169,11 @@ pub(crate) enum BlockSize { impl Default for BlockSize { fn default() -> Self { - Self::Bytes(1024) + if env::var("POSIXLY_CORRECT").is_ok() { + Self::Bytes(512) + } else { + Self::Bytes(1024) + } } } @@ -195,6 +200,8 @@ impl fmt::Display for BlockSize { #[cfg(test)] mod tests { + use std::env; + use crate::blocks::{to_magnitude_and_suffix, BlockSize}; #[test] @@ -252,4 +259,12 @@ mod tests { assert_eq!(format!("{}", BlockSize::Bytes(2 * 1024)), "2K"); assert_eq!(format!("{}", BlockSize::Bytes(3 * 1024 * 1024)), "3M"); } + + #[test] + fn test_default_block_size() { + assert_eq!(BlockSize::Bytes(1024), BlockSize::default()); + env::set_var("POSIXLY_CORRECT", "1"); + assert_eq!(BlockSize::Bytes(512), BlockSize::default()); + env::remove_var("POSIXLY_CORRECT"); + } } diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index d9fb1be7b..192cbcadf 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -32,6 +32,13 @@ use crate::table::Table; static ABOUT: &str = "Show information about the file system on which each FILE resides,\n\ or all file systems by default."; const USAGE: &str = "{} [OPTION]... [FILE]..."; +const LONG_HELP: &str = "Display values are in units of the first available SIZE from --block-size, +and the DF_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environment variables. +Otherwise, units default to 1024 bytes (or 512 if POSIXLY_CORRECT is set). + +SIZE is an integer and optional unit (example: 10M is 10*1024*1024). +Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB,... (powers +of 1000)."; static OPT_HELP: &str = "help"; static OPT_ALL: &str = "all"; @@ -427,6 +434,7 @@ pub fn uu_app<'a>() -> Command<'a> { .version(crate_version!()) .about(ABOUT) .override_usage(format_usage(USAGE)) + .after_help(LONG_HELP) .infer_long_args(true) .arg( Arg::new(OPT_HELP) diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 511956ec4..81a9eef72 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -375,6 +375,26 @@ fn test_iuse_percentage() { } } +#[test] +fn test_default_block_size() { + let output = new_ucmd!() + .arg("--output=size") + .succeeds() + .stdout_move_str(); + let header = output.lines().next().unwrap().to_string(); + + assert_eq!(header, "1K-blocks"); + + let output = new_ucmd!() + .arg("--output=size") + .env("POSIXLY_CORRECT", "1") + .succeeds() + .stdout_move_str(); + let header = output.lines().next().unwrap().to_string(); + + assert_eq!(header, "512B-blocks"); +} + #[test] fn test_block_size_1024() { fn get_header(block_size: u64) -> String { From 087d4b14fc205107d557d3300b63d29849888642 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 8 May 2022 21:27:08 +0200 Subject: [PATCH 083/111] Do not use the Rust/touch for tests/ls/abmon-align.sh --- util/build-gnu.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/build-gnu.sh b/util/build-gnu.sh index 83993fde9..942aa9d87 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -137,7 +137,8 @@ sed -i 's|chmod |/usr/bin/chmod |' tests/du/inacc-dir.sh tests/tail-2/tail-n0f.s sed -i 's|sort |/usr/bin/sort |' tests/ls/hyperlink.sh tests/misc/test-N.sh sed -i 's|split |/usr/bin/split |' tests/misc/factor-parallel.sh sed -i 's|id -|/usr/bin/id -|' tests/misc/runcon-no-reorder.sh -sed -i 's|touch |/usr/bin/touch |' tests/cp/preserve-link.sh tests/cp/reflink-perm.sh tests/ls/block-size.sh tests/mv/update.sh tests/misc/ls-time.sh tests/misc/stat-nanoseconds.sh tests/misc/time-style.sh tests/misc/test-N.sh +# tests/ls/abmon-align.sh - https://github.com/uutils/coreutils/issues/3505 +sed -i 's|touch |/usr/bin/touch |' tests/cp/preserve-link.sh tests/cp/reflink-perm.sh tests/ls/block-size.sh tests/mv/update.sh tests/misc/ls-time.sh tests/misc/stat-nanoseconds.sh tests/misc/time-style.sh tests/misc/test-N.sh tests/ls/abmon-align.sh sed -i 's|ln -|/usr/bin/ln -|' tests/cp/link-deref.sh sed -i 's|cp |/usr/bin/cp |' tests/mv/hard-2.sh sed -i 's|paste |/usr/bin/paste |' tests/misc/od-endian.sh From d5569847bd682f0df1eab95316fa9c81afe83676 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 8 May 2022 21:31:42 +0200 Subject: [PATCH 084/111] also support for tests/touch/no-rights.sh format --- src/uu/touch/src/touch.rs | 15 ++++++++++++++- tests/by-util/test_touch.rs | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index c082aed23..5444c8c10 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -280,12 +280,20 @@ const YYYYMMDDHHMMSS_FORMAT: &[time::format_description::FormatItem] = format_de "[year repr:full]-[month repr:numerical padding:zero]-\ [day] [hour]:[minute]:[second].[subsecond]" ); + // "%Y-%m-%d %H:%M:%S" 12 chars const YYYYMMDDHHMMS_FORMAT: &[time::format_description::FormatItem] = format_description!( "[year repr:full]-[month repr:numerical padding:zero]-\ [day] [hour]:[minute]:[second]" ); +// "%Y-%m-%d %H:%M" 12 chars +// Used for example in tests/touch/no-rights.sh +const YYYY_MM_DD_HH_MM_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year repr:full]-[month repr:numerical padding:zero]-\ + [day] [hour]:[minute]" +); + // "%Y%m%d%H%M" 12 chars const YYYYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_description!( "[year repr:full][month repr:numerical padding:zero]\ @@ -325,7 +333,12 @@ fn parse_date(s: &str) -> UResult { // Also support other formats found in the GNU tests like // in tests/misc/stat-nanoseconds.sh - for fmt in [YYYYMMDDHHMMS_FORMAT, YYYYMMDDHHMMSS_FORMAT] { + // or tests/touch/no-rights.sh + for fmt in [ + YYYYMMDDHHMMS_FORMAT, + YYYYMMDDHHMMSS_FORMAT, + YYYY_MM_DD_HH_MM_FORMAT, + ] { if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &fmt) { return Ok(dt_to_filename(parsed)); } diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 9b8eebbf0..5417a0dbe 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -469,6 +469,25 @@ fn test_touch_set_date5() { assert_eq!(mtime, expected); } +#[test] +fn test_touch_set_date6() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "test_touch_set_date"; + + ucmd.args(&["-d", "2000-01-01 00:00", file]) + .succeeds() + .no_stderr(); + + assert!(at.file_exists(file)); + + let expected = FileTime::from_unix_time(946684800, 0); + + let (atime, mtime) = get_file_times(&at, file); + assert_eq!(atime, mtime); + assert_eq!(atime, expected); + assert_eq!(mtime, expected); +} + #[test] fn test_touch_set_date_wrong_format() { let (_at, mut ucmd) = at_and_ucmd!(); From f65d72e334f73aedb38c6e149480733f433f0e8a Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 8 May 2022 21:52:12 +0200 Subject: [PATCH 085/111] also support for tests/touch/relative.sh --- src/uu/touch/src/touch.rs | 8 ++++++++ tests/by-util/test_touch.rs | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 5444c8c10..f71eb81d0 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -312,6 +312,13 @@ const YYMMDDHHMM_FORMAT: &[time::format_description::FormatItem] = format_descri [hour repr:24 padding:zero][minute padding:zero]" ); +// "%Y-%m-%d %H:%M +offset" +// Used for example in tests/touch/relative.sh +const YYYYMMDDHHMM_OFFSET_FORMAT: &[time::format_description::FormatItem] = format_description!( + "[year]-[month]-[day] [hour repr:24]:[minute] \ + [offset_hour sign:mandatory][offset_minute]" +); + fn parse_date(s: &str) -> UResult { // This isn't actually compatible with GNU touch, but there doesn't seem to // be any simple specification for what format this parameter allows and I'm @@ -338,6 +345,7 @@ fn parse_date(s: &str) -> UResult { YYYYMMDDHHMMS_FORMAT, YYYYMMDDHHMMSS_FORMAT, YYYY_MM_DD_HH_MM_FORMAT, + YYYYMMDDHHMM_OFFSET_FORMAT, ] { if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &fmt) { return Ok(dt_to_filename(parsed)); diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 5417a0dbe..346e27919 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -488,6 +488,25 @@ fn test_touch_set_date6() { assert_eq!(mtime, expected); } +#[test] +fn test_touch_set_date7() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "test_touch_set_date"; + + ucmd.args(&["-d", "2004-01-16 12:00 +0000", file]) + .succeeds() + .no_stderr(); + + assert!(at.file_exists(file)); + + let expected = FileTime::from_unix_time(1074254400, 0); + + let (atime, mtime) = get_file_times(&at, file); + assert_eq!(atime, mtime); + assert_eq!(atime, expected); + assert_eq!(mtime, expected); +} + #[test] fn test_touch_set_date_wrong_format() { let (_at, mut ucmd) = at_and_ucmd!(); From ece9ccdbfb48fe2cc1e3de8c13be159ad7fda839 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 10 May 2022 13:49:29 +0200 Subject: [PATCH 086/111] Add missing \# interpreter line --- util/android-commands.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/util/android-commands.sh b/util/android-commands.sh index 2a4fca416..0a245a004 100755 --- a/util/android-commands.sh +++ b/util/android-commands.sh @@ -1,3 +1,4 @@ +#!/bin/bash # spell-checker:ignore termux keyevent sdcard binutils unmatch adb's dumpsys logcat pkill # There are three shells: the host's, adb, and termux. Only adb lets us run From 7d8b1de213602e2476b5bf013bd871dc05d01071 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 10 May 2022 13:54:16 +0200 Subject: [PATCH 087/111] uniq: Disable one of the gnu test for failing too often See: https://github.com/uutils/coreutils/issues/3509 --- tests/by-util/test_uniq.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/by-util/test_uniq.rs b/tests/by-util/test_uniq.rs index b3f5fcd68..77ad10b32 100644 --- a/tests/by-util/test_uniq.rs +++ b/tests/by-util/test_uniq.rs @@ -680,6 +680,9 @@ fn gnu_tests() { stderr: None, exit: None, }, + /* + Disable as it fails too often. See: + https://github.com/uutils/coreutils/issues/3509 TestCase { name: "112", args: &["-D", "-c"], @@ -687,7 +690,7 @@ fn gnu_tests() { stdout: Some(""), stderr: Some("uniq: printing all duplicated lines and repeat counts is meaningless"), exit: Some(1), - }, + },*/ TestCase { name: "113", args: &["--all-repeated=separate"], From 12d7d9846abc825e95e95b00d2ce00e50b22068b Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Tue, 10 May 2022 13:46:22 +0200 Subject: [PATCH 088/111] test/util: improve `run_ucmd_as_root` for CICD * ensure that `fn run_no_wait` is only invoked if the system running the test has `sudo` in $path Previously, if run inside CICD, calling `fn run_ucmd_as_root` would provoke `fn run_no_wait` to panic because there's no `sudo`. --- tests/common/util.rs | 87 +++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/tests/common/util.rs b/tests/common/util.rs index 34bdc72f3..d601b90d8 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1370,6 +1370,8 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< /// To check if i) non-interactive sudo is possible and ii) if sudo works, this runs: /// 'sudo -E --non-interactive whoami' first. /// +/// This return an `Err()` if run inside CICD because there's no 'sudo'. +/// /// Example: /// /// ```no_run @@ -1381,7 +1383,7 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< /// if let Ok(result) = run_ucmd_as_root(&ts, &[]) { /// result.stdout_is(expected); /// } else { -/// print!("TEST SKIPPED"); +/// println!("TEST SKIPPED"); /// } /// } ///``` @@ -1390,29 +1392,37 @@ pub fn run_ucmd_as_root( ts: &TestScenario, args: &[&str], ) -> std::result::Result { - // Apparently CICD environment has no `sudo`? - if ts - .cmd_keepenv("sudo") - .env("LC_ALL", "C") - .arg("-E") - .arg("--non-interactive") - .arg("whoami") - .run() - .stdout_str() - .trim() - != "root" - { - Err("\"sudo whoami\" didn't return \"root\"".to_string()) - } else { - Ok(ts - .cmd_keepenv("sudo") + if !is_ci() { + // check if we can run 'sudo' + log_info("run", "sudo -E --non-interactive whoami"); + match Command::new("sudo") .env("LC_ALL", "C") - .arg("-E") - .arg("--non-interactive") - .arg(&ts.bin_path) - .arg(&ts.util_name) - .args(args) - .run()) + .args(&["-E", "--non-interactive", "whoami"]) + .output() + { + Ok(output) if String::from_utf8_lossy(&output.stdout).eq("root\n") => { + // we can run sudo and we're root + // run ucmd as root: + Ok(ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg(&ts.bin_path) + .arg(&ts.util_name) + .args(args) + .run()) + } + Ok(output) + if String::from_utf8_lossy(&output.stderr).eq("sudo: a password is required\n") => + { + Err("Cannot run non-interactive sudo".to_string()) + } + Ok(_output) => Err("\"sudo whoami\" didn't return \"root\"".to_string()), + Err(e) => Err(format!("{}: {}", UUTILS_WARNING, e)), + } + } else { + Err(format!("{}: {}", UUTILS_INFO, "cannot run inside CI")) } } @@ -1771,18 +1781,27 @@ mod tests { #[cfg(unix)] #[cfg(feature = "whoami")] fn test_run_ucmd_as_root() { - // Skip test if we can't guarantee non-interactive `sudo`. - if let Ok(_status) = Command::new("sudo") - .args(&["-E", "-v", "--non-interactive"]) - .status() - { - let ts = TestScenario::new("whoami"); - std::assert_eq!( - run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), - "root" - ); + if !is_ci() { + // Skip test if we can't guarantee non-interactive `sudo`, or if we're not "root" + if let Ok(output) = Command::new("sudo") + .env("LC_ALL", "C") + .args(&["-E", "--non-interactive", "whoami"]) + .output() + { + if output.status.success() && String::from_utf8_lossy(&output.stdout).eq("root\n") { + let ts = TestScenario::new("whoami"); + std::assert_eq!( + run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), + "root" + ); + } else { + println!("TEST SKIPPED (we're not root)"); + } + } else { + println!("TEST SKIPPED (cannot run sudo)"); + } } else { - print!("TEST SKIPPED"); + println!("TEST SKIPPED (cannot run inside CI)"); } } } From eeec680c37bbc842723d59c2a7cc3c4b865e3225 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 06:38:03 +0000 Subject: [PATCH 089/111] build(deps): bump codecov/codecov-action from 1 to 3 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 1 to 3. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v1...v3) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 2 +- .github/workflows/GnuTests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 04acd4c18..ebe82e47a 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -1100,7 +1100,7 @@ jobs: grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" echo ::set-output name=report::${COVERAGE_REPORT_FILE} - name: Upload coverage results (to Codecov.io) - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 # if: steps.vars.outputs.HAS_CODECOV_TOKEN with: # token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index c8d3c8b94..75cb60d89 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -293,7 +293,7 @@ jobs: grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" echo ::set-output name=report::${COVERAGE_REPORT_FILE} - name: Upload coverage results (to Codecov.io) - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: file: ${{ steps.coverage.outputs.report }} flags: gnutests From 376f6a158b17fdf4b469903877957f8d162d0fc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 06:38:05 +0000 Subject: [PATCH 090/111] build(deps): bump EndBug/add-and-commit from 7 to 9 Bumps [EndBug/add-and-commit](https://github.com/EndBug/add-and-commit) from 7 to 9. - [Release notes](https://github.com/EndBug/add-and-commit/releases) - [Changelog](https://github.com/EndBug/add-and-commit/blob/main/CHANGELOG.md) - [Commits](https://github.com/EndBug/add-and-commit/compare/v7...v9) --- updated-dependencies: - dependency-name: EndBug/add-and-commit dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/FixPR.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/FixPR.yml b/.github/workflows/FixPR.yml index 2a5382e27..00e0a608d 100644 --- a/.github/workflows/FixPR.yml +++ b/.github/workflows/FixPR.yml @@ -80,7 +80,7 @@ jobs: ## * using the 'stable' toolchain is necessary to avoid "unexpected '--filter-platform'" errors RUSTUP_TOOLCHAIN=stable cargo-tree tree --locked --all --no-dev-dependencies --no-indent --features ${{ matrix.job.features }} | grep -vE "$PWD" | sort --unique - name: Commit any changes (to '${{ env.BRANCH_TARGET }}') - uses: EndBug/add-and-commit@v7 + uses: EndBug/add-and-commit@v9 with: branch: ${{ env.BRANCH_TARGET }} default_author: github_actions @@ -130,7 +130,7 @@ jobs: # `cargo fmt` of tests find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- - name: Commit any changes (to '${{ env.BRANCH_TARGET }}') - uses: EndBug/add-and-commit@v7 + uses: EndBug/add-and-commit@v9 with: branch: ${{ env.BRANCH_TARGET }} default_author: github_actions From 372d460d7a24c3bccad817a9ba9ff9eac71b6f53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 06:38:08 +0000 Subject: [PATCH 091/111] build(deps): bump actions/cache from 2 to 3 Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 04acd4c18..5d49ed363 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -859,7 +859,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: AVD cache - uses: actions/cache@v2 + uses: actions/cache@v3 id: avd-cache with: path: | From fd057574d7fbd8381f9f63c2f9c939f7055c9e6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 06:38:11 +0000 Subject: [PATCH 092/111] build(deps): bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 34 +++++++++++++++++----------------- .github/workflows/FixPR.yml | 4 ++-- .github/workflows/GnuTests.yml | 8 ++++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 04acd4c18..c6b7f10a8 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -24,7 +24,7 @@ jobs: name: Style/cargo-deny runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: EmbarkStudios/cargo-deny-action@v1 style_deps: @@ -43,7 +43,7 @@ jobs: - { os: macos-latest , features: "feat_Tier1,feat_require_unix,feat_require_unix_utmpx" } - { os: windows-latest , features: feat_os_windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -101,7 +101,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -165,7 +165,7 @@ jobs: - { os: macos-latest , features: feat_os_macos } - { os: windows-latest , features: feat_os_windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -223,7 +223,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -275,7 +275,7 @@ jobs: # - { os: macos-latest , features: feat_os_macos } # - { os: windows-latest , features: feat_os_windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -320,7 +320,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -397,7 +397,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Install `rust` toolchain uses: actions-rs/toolchain@v1 @@ -422,7 +422,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Install `rust` toolchain uses: actions-rs/toolchain@v1 @@ -452,7 +452,7 @@ jobs: - { os: macos-latest , features: feat_os_macos } - { os: windows-latest , features: feat_os_windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Install `rust` toolchain uses: actions-rs/toolchain@v1 @@ -478,7 +478,7 @@ jobs: - { os: macos-latest , features: feat_os_macos } - { os: windows-latest , features: feat_os_windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Install `rust` toolchain uses: actions-rs/toolchain@v1 @@ -502,7 +502,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Install dependencies shell: bash @@ -568,7 +568,7 @@ jobs: - { os: windows-latest , target: x86_64-pc-windows-gnu , features: feat_os_windows } ## note: requires rust >= 1.43.0 to link correctly - { os: windows-latest , target: x86_64-pc-windows-msvc , features: feat_os_windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize workflow variables id: vars @@ -820,7 +820,7 @@ jobs: job: - { os: ubuntu-latest } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Install/setup prerequisites shell: bash @@ -857,7 +857,7 @@ jobs: env: TERMUX: v0.118.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: AVD cache uses: actions/cache@v2 id: avd-cache @@ -911,7 +911,7 @@ jobs: env: mem: 2048 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Prepare, build and test ## spell-checker:ignore (ToDO) sshfs usesh vmactions @@ -979,7 +979,7 @@ jobs: - { os: macos-latest , features: macos } - { os: windows-latest , features: windows } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 # - name: Reattach HEAD ## may be needed for accurate code coverage info # run: git checkout ${{ github.head_ref }} diff --git a/.github/workflows/FixPR.yml b/.github/workflows/FixPR.yml index 2a5382e27..67e914746 100644 --- a/.github/workflows/FixPR.yml +++ b/.github/workflows/FixPR.yml @@ -28,7 +28,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize job variables id: vars @@ -100,7 +100,7 @@ jobs: job: - { os: ubuntu-latest , features: feat_os_unix } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v1 - name: Initialize job variables id: vars diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index c8d3c8b94..ef919dde9 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -41,11 +41,11 @@ jobs: TEST_FULL_SUMMARY_FILE='gnu-full-result.json' outputs SUITE_LOG_FILE TEST_FILESET_PREFIX TEST_FILESET_SUFFIX TEST_LOGS_GLOB TEST_SUMMARY_FILE TEST_FULL_SUMMARY_FILE - name: Checkout code (uutil) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: '${{ steps.vars.outputs.path_UUTILS }}' - name: Checkout code (GNU coreutils) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: 'coreutils/coreutils' path: '${{ steps.vars.outputs.path_GNU }}' @@ -229,11 +229,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code uutil - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: 'uutils' - name: Checkout GNU coreutils - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: 'coreutils/coreutils' path: 'gnu' From 28c6403ffa78d29ea75862f65ac03743d35ab4d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 06:38:13 +0000 Subject: [PATCH 093/111] build(deps): bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 4 ++-- .github/workflows/GnuTests.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 04acd4c18..0e4a4807d 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -534,7 +534,7 @@ jobs: --arg size "$SIZE" \ --arg multisize "$SIZEMULTI" \ '{($date): { sha: $sha, size: $size, multisize: $multisize, }}' > size-result.json - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: size-result path: size-result.json @@ -762,7 +762,7 @@ jobs: args: --target=${{ matrix.job.target }} ${{ steps.vars.outputs.CARGO_TEST_OPTIONS}} ${{ matrix.job.cargo-options }} ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }} toolchain: ${{ env.RUST_MIN_SRV }} - name: Archive executable artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ${{ env.PROJECT_NAME }}-${{ matrix.job.target }} path: target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }} diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index c8d3c8b94..24b362a04 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -146,22 +146,22 @@ jobs: # Compress logs before upload (fails otherwise) gzip ${{ steps.vars.outputs.TEST_LOGS_GLOB }} - name: Reserve SHA1/ID of 'test-summary' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: "${{ steps.summary.outputs.HASH }}" path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}" - name: Reserve test results summary - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-summary path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}" - name: Reserve test logs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-logs path: "${{ steps.vars.outputs.TEST_LOGS_GLOB }}" - name: Upload full json results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: gnu-full-result.json path: ${{ steps.vars.outputs.TEST_FULL_SUMMARY_FILE }} From d906f09e6ed84c83360b26caff70b1e15cde9406 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Fri, 6 May 2022 14:01:23 +0200 Subject: [PATCH 094/111] stat: improve handling of stdin/fifo (fix #3485) * fix https://github.com/uutils/coreutils/issues/3485 * improve the workaround from #3280 * add tests --- src/uu/stat/src/stat.rs | 81 ++++++++++++++++------------ src/uucore/src/lib/features/fsext.rs | 5 +- tests/by-util/test_stat.rs | 34 +++++++++--- 3 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/uu/stat/src/stat.rs b/src/uu/stat/src/stat.rs index cebc6c108..41c9ae4a9 100644 --- a/src/uu/stat/src/stat.rs +++ b/src/uu/stat/src/stat.rs @@ -19,7 +19,9 @@ use uucore::{entries, format_usage}; use clap::{crate_version, Arg, ArgMatches, Command}; use std::borrow::Cow; use std::convert::AsRef; +use std::ffi::{OsStr, OsString}; use std::os::unix::fs::{FileTypeExt, MetadataExt}; +use std::os::unix::prelude::OsStrExt; use std::path::Path; use std::{cmp, fs, iter}; @@ -221,7 +223,7 @@ pub struct Stater { follow: bool, show_fs: bool, from_user: bool, - files: Vec, + files: Vec, mount_list: Option>, default_tokens: Vec, default_dev_tokens: Vec, @@ -471,24 +473,10 @@ impl Stater { } fn new(matches: &ArgMatches) -> UResult { - let mut files: Vec = matches - .values_of(ARG_FILES) - .map(|v| v.map(ToString::to_string).collect()) + let files = matches + .values_of_os(ARG_FILES) + .map(|v| v.map(OsString::from).collect()) .unwrap_or_default(); - #[cfg(unix)] - if files.contains(&String::from("-")) { - let redirected_path = Path::new("/dev/stdin") - .canonicalize() - .expect("unable to canonicalize /dev/stdin") - .into_os_string() - .into_string() - .unwrap(); - for file in &mut files { - if file == "-" { - *file = redirected_path.clone(); - } - } - } let format_str = if matches.is_present(options::PRINTF) { matches .value_of(options::PRINTF) @@ -550,19 +538,37 @@ impl Stater { } fn exec(&self) -> i32 { + let mut stdin_is_fifo = false; + if cfg!(unix) { + if let Ok(md) = fs::metadata("/dev/stdin") { + stdin_is_fifo = md.file_type().is_fifo(); + } + } + let mut ret = 0; for f in &self.files { - ret |= self.do_stat(f.as_str()); + ret |= self.do_stat(f, stdin_is_fifo); } ret } - fn do_stat(&self, file: &str) -> i32 { - if !self.show_fs { - let result = if self.follow { - fs::metadata(file) + fn do_stat(&self, file: &OsStr, stdin_is_fifo: bool) -> i32 { + let display_name = file.to_string_lossy(); + let file: OsString = if cfg!(unix) && display_name.eq("-") { + if let Ok(p) = Path::new("/dev/stdin").canonicalize() { + p.into_os_string() } else { - fs::symlink_metadata(file) + OsString::from("/dev/stdin") + } + } else { + OsString::from(file) + }; + + if !self.show_fs { + let result = if self.follow || stdin_is_fifo && display_name.eq("-") { + fs::metadata(&file) + } else { + fs::symlink_metadata(&file) }; match result { Ok(meta) => { @@ -658,28 +664,32 @@ impl Stater { // mount point 'm' => { - arg = self.find_mount_point(file).unwrap(); + arg = self.find_mount_point(&file).unwrap(); output_type = OutputType::Str; } // file name 'n' => { - arg = file.to_owned(); + arg = display_name.to_string(); output_type = OutputType::Str; } // quoted file name with dereference if symbolic link 'N' => { if file_type.is_symlink() { - let dst = match fs::read_link(file) { + let dst = match fs::read_link(&file) { Ok(path) => path, Err(e) => { println!("{}", e); return 1; } }; - arg = format!("{} -> {}", file.quote(), dst.quote()); + arg = format!( + "{} -> {}", + display_name.quote(), + dst.quote() + ); } else { - arg = file.to_string(); + arg = display_name.to_string(); } output_type = OutputType::Str; } @@ -771,12 +781,16 @@ impl Stater { } } Err(e) => { - show_error!("cannot stat {}: {}", file.quote(), e); + show_error!("cannot stat {}: {}", display_name.quote(), e); return 1; } } } else { - match statfs(file) { + #[cfg(unix)] + let p = file.as_bytes(); + #[cfg(not(unix))] + let p = file.into_string().unwrap(); + match statfs(p) { Ok(meta) => { let tokens = &self.default_tokens; @@ -829,7 +843,7 @@ impl Stater { } // file name 'n' => { - arg = file.to_owned(); + arg = display_name.to_string(); output_type = OutputType::Str; } // block size (for faster transfers) @@ -866,7 +880,7 @@ impl Stater { Err(e) => { show_error!( "cannot read file system information for {}: {}", - file.quote(), + display_name.quote(), e ); return 1; @@ -1028,6 +1042,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(ARG_FILES) .multiple_occurrences(true) .takes_value(true) + .allow_invalid_utf8(true) .min_values(1), ) } diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 3d7ca1c1f..787684e93 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -85,6 +85,7 @@ use std::ffi::CString; use std::io::Error as IOError; #[cfg(unix)] use std::mem; +#[cfg(not(unix))] use std::path::Path; use std::time::UNIX_EPOCH; @@ -709,9 +710,9 @@ impl FsMeta for StatFs { } #[cfg(unix)] -pub fn statfs>(path: P) -> Result +pub fn statfs

(path: P) -> Result where - Vec: From

, + P: Into>, { match CString::new(path) { Ok(p) => { diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index f1a687981..14aba96fc 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -346,9 +346,21 @@ fn test_printf() { ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } -#[cfg(unix)] #[test] -#[cfg(disable_until_fixed)] +#[cfg(unix)] +fn test_pipe_fifo() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkfifo("FIFO"); + ucmd.arg("FIFO") + .run() + .no_stderr() + .stdout_contains("fifo") + .stdout_contains("File: FIFO") + .succeeded(); +} + +#[test] +#[cfg(target_os = "linux")] fn test_stdin_pipe_fifo1() { // $ echo | stat - // File: - @@ -362,17 +374,26 @@ fn test_stdin_pipe_fifo1() { .stdout_contains("fifo") .stdout_contains("File: -") .succeeded(); + + new_ucmd!() + .args(&["-L", "-"]) + .set_stdin(std::process::Stdio::piped()) + .run() + .no_stderr() + .stdout_contains("fifo") + .stdout_contains("File: -") + .succeeded(); } -#[cfg(unix)] #[test] -#[cfg(disable_until_fixed)] +#[cfg(target_os = "linux")] fn test_stdin_pipe_fifo2() { // $ stat - // File: - // Size: 0 Blocks: 0 IO Block: 1024 character special file new_ucmd!() .arg("-") + .set_stdin(std::process::Stdio::null()) .run() .no_stderr() .stdout_contains("character special file") @@ -380,9 +401,8 @@ fn test_stdin_pipe_fifo2() { .succeeded(); } -#[cfg(unix)] #[test] -#[cfg(disable_until_fixed)] +#[cfg(target_os = "linux")] fn test_stdin_redirect() { // $ touch f && stat - < f // File: - @@ -393,7 +413,7 @@ fn test_stdin_redirect() { at.touch("f"); new_ucmd!() .arg("-") - .set_stdin(std::fs::File::open("f").unwrap()) + .set_stdin(std::fs::File::open(at.plus("f")).unwrap()) .run() .no_stderr() .stdout_contains("regular empty file") From f9a5d758f0dfe86d2cbe10e50f7dce04fded3101 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 May 2022 21:16:35 +0000 Subject: [PATCH 095/111] build(deps): bump clap_complete from 3.1.3 to 3.1.4 Bumps [clap_complete](https://github.com/clap-rs/clap) from 3.1.3 to 3.1.4. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v3.1.3...clap_complete-v3.1.4) --- updated-dependencies: - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1079f8a65..608654e69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -273,9 +273,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7ca9141e27e6ebc52e3c378b0c07f3cea52db46ed1cc5861735fb697b56356" +checksum = "da92e6facd8d73c22745a5d3cbb59bdf8e46e3235c923e516527d8e81eec14a4" dependencies = [ "clap 3.1.15", ] From b2eb4e83917e13511b070c4a7f2c494bf1224e2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 May 2022 21:16:50 +0000 Subject: [PATCH 096/111] build(deps): bump unindent from 0.1.8 to 0.1.9 Bumps [unindent](https://github.com/dtolnay/indoc) from 0.1.8 to 0.1.9. - [Release notes](https://github.com/dtolnay/indoc/releases) - [Commits](https://github.com/dtolnay/indoc/compare/0.1.8...0.1.9) --- updated-dependencies: - dependency-name: unindent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1079f8a65..d25d27e0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2027,9 +2027,9 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "unindent" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514672a55d7380da379785a4d70ca8386c8883ff7eaae877be4d2081cebe73d8" +checksum = "52fee519a3e570f7df377a06a1a7775cdbfb7aa460be7e08de2b1f0e69973a44" [[package]] name = "unix_socket" From 2874f1895097f112daf6d40b999da434681590bd Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Thu, 5 May 2022 18:05:16 -0400 Subject: [PATCH 097/111] mktemp: error on path separator in template prefix Correct the error that arises from a path separator in the prefix portion of a template argument provided to `mktemp`. Before this commit, the error message was incorrect: $ mktemp -t a/bXXX mktemp: failed to create file via template 'a/bXXX': No such file or directory (os error 2) at path "/tmp/a/bege" After this commit, the error message is correct: $ mktemp -t a/bXXX mktemp: invalid template, 'a/bXXX', contains directory separator The code was failing to check for a path separator in the prefix portion of the template. --- src/uu/mktemp/src/mktemp.rs | 28 ++++++++++++++++++++-------- tests/by-util/test_mktemp.rs | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index b14318679..94def4874 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -41,7 +41,12 @@ enum MkTempError { PersistError(PathBuf), MustEndInX(String), TooFewXs(String), - ContainsDirSeparator(String), + + /// The template prefix contains a path separator (e.g. `"a/bXXX"`). + PrefixContainsDirSeparator(String), + + /// The template suffix contains a path separator (e.g. `"XXXa/b"`). + SuffixContainsDirSeparator(String), InvalidTemplate(String), } @@ -56,7 +61,14 @@ impl Display for MkTempError { PersistError(p) => write!(f, "could not persist file {}", p.quote()), MustEndInX(s) => write!(f, "with --suffix, template {} must end in X", s.quote()), TooFewXs(s) => write!(f, "too few X's in template {}", s.quote()), - ContainsDirSeparator(s) => { + PrefixContainsDirSeparator(s) => { + write!( + f, + "invalid template, {}, contains directory separator", + s.quote() + ) + } + SuffixContainsDirSeparator(s) => { write!( f, "invalid suffix {}, contains directory separator", @@ -252,8 +264,12 @@ fn parse_template<'a>( } }; + if prefix.chars().any(is_separator) { + return Err(MkTempError::PrefixContainsDirSeparator(temp.into())); + } + if suf.chars().any(is_separator) { - return Err(MkTempError::ContainsDirSeparator(suf.into())); + return Err(MkTempError::SuffixContainsDirSeparator(suf.into())); } Ok((prefix, rand, suf)) @@ -352,11 +368,7 @@ mod tests { #[test] fn test_parse_template_errors() { - // TODO This should be an error as well, but we are not - // catching it just yet. A future commit will correct this. - // - // assert!(parse_template("a/bXXX", None).is_err()); - // + assert!(parse_template("a/bXXX", None).is_err()); assert!(parse_template("XXXa/b", None).is_err()); assert!(parse_template("XX", None).is_err()); assert!(parse_template("XXXabc", Some("def")).is_err()); diff --git a/tests/by-util/test_mktemp.rs b/tests/by-util/test_mktemp.rs index c28efc37b..9fce0e591 100644 --- a/tests/by-util/test_mktemp.rs +++ b/tests/by-util/test_mktemp.rs @@ -2,6 +2,8 @@ use crate::common::util::*; +use uucore::display::Quotable; + use std::path::PathBuf; use tempfile::tempdir; @@ -482,3 +484,15 @@ fn test_respect_template_directory() { assert_matches_template!(template, filename); assert!(at.file_exists(filename)); } + +/// Test that a template with a path separator is invalid. +#[test] +fn test_template_path_separator() { + new_ucmd!() + .args(&["-t", "a/bXXX"]) + .fails() + .stderr_only(format!( + "mktemp: invalid template, {}, contains directory separator\n", + "a/bXXX".quote() + )); +} From e26fed61b34caec8a5e1325275e1e5a5bfa2152a Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Tue, 10 May 2022 07:34:01 +0200 Subject: [PATCH 098/111] df: implement POSIX conform header line It also fixes #3195 --- src/uu/df/src/blocks.rs | 9 +++++ src/uu/df/src/df.rs | 18 ++++++++++ src/uu/df/src/table.rs | 66 +++++++++++++++++++++++++++--------- tests/by-util/test_df.rs | 73 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 147 insertions(+), 19 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index bb6e06333..9a7e5c580 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -167,6 +167,15 @@ pub(crate) enum BlockSize { Bytes(u64), } +impl BlockSize { + /// Returns the associated value + pub(crate) fn as_u64(&self) -> u64 { + match *self { + Self::Bytes(n) => n, + } + } +} + impl Default for BlockSize { fn default() -> Self { if env::var("POSIXLY_CORRECT").is_ok() { diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index 192cbcadf..a11dcf7a0 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -12,6 +12,7 @@ mod filesystem; mod table; use blocks::{HumanReadable, SizeFormat}; +use table::HeaderMode; use uucore::display::Quotable; use uucore::error::{UError, UResult, USimpleError}; use uucore::fsext::{read_fs_list, MountInfo}; @@ -72,6 +73,7 @@ struct Options { show_all_fs: bool, size_format: SizeFormat, block_size: BlockSize, + header_mode: HeaderMode, /// Optional list of filesystem types to include in the output table. /// @@ -99,6 +101,7 @@ impl Default for Options { show_all_fs: Default::default(), block_size: Default::default(), size_format: Default::default(), + header_mode: Default::default(), include: Default::default(), exclude: Default::default(), show_total: Default::default(), @@ -176,6 +179,21 @@ impl Options { ), ParseSizeError::ParseFailure(s) => OptionsError::InvalidBlockSize(s), })?, + header_mode: { + if matches.is_present(OPT_HUMAN_READABLE_BINARY) + || matches.is_present(OPT_HUMAN_READABLE_DECIMAL) + { + HeaderMode::HumanReadable + } else if matches.is_present(OPT_PORTABILITY) { + HeaderMode::PosixPortability + // is_present() doesn't work here, it always returns true because OPT_OUTPUT has + // default values and hence is always present + } else if matches.occurrences_of(OPT_OUTPUT) > 0 { + HeaderMode::Output + } else { + HeaderMode::Default + } + }, size_format: { if matches.is_present(OPT_HUMAN_READABLE_BINARY) { SizeFormat::HumanReadable(HumanReadable::Binary) diff --git a/src/uu/df/src/table.rs b/src/uu/df/src/table.rs index 5309da38f..a9a37cfeb 100644 --- a/src/uu/df/src/table.rs +++ b/src/uu/df/src/table.rs @@ -289,6 +289,23 @@ impl<'a> RowFormatter<'a> { } } +/// A HeaderMode defines what header labels should be shown. +pub(crate) enum HeaderMode { + Default, + // the user used -h or -H + HumanReadable, + // the user used -P + PosixPortability, + // the user used --output + Output, +} + +impl Default for HeaderMode { + fn default() -> Self { + Self::Default + } +} + /// The data of the header row. struct Header {} @@ -302,15 +319,22 @@ impl Header { for column in &options.columns { let header = match column { Column::Source => String::from("Filesystem"), - Column::Size => match options.size_format { - SizeFormat::HumanReadable(_) => String::from("Size"), - SizeFormat::StaticBlockSize => { - format!("{}-blocks", options.block_size) + Column::Size => match options.header_mode { + HeaderMode::HumanReadable => String::from("Size"), + HeaderMode::PosixPortability => { + format!("{}-blocks", options.block_size.as_u64()) } + _ => format!("{}-blocks", options.block_size), }, Column::Used => String::from("Used"), - Column::Avail => String::from("Available"), - Column::Pcent => String::from("Use%"), + Column::Avail => match options.header_mode { + HeaderMode::HumanReadable | HeaderMode::Output => String::from("Avail"), + _ => String::from("Available"), + }, + Column::Pcent => match options.header_mode { + HeaderMode::PosixPortability => String::from("Capacity"), + _ => String::from("Use%"), + }, Column::Target => String::from("Mounted on"), Column::Itotal => String::from("Inodes"), Column::Iused => String::from("IUsed"), @@ -428,7 +452,7 @@ mod tests { use crate::blocks::{HumanReadable, SizeFormat}; use crate::columns::Column; - use crate::table::{Header, Row, RowFormatter}; + use crate::table::{Header, HeaderMode, Row, RowFormatter}; use crate::{BlockSize, Options}; const COLUMNS_WITH_FS_TYPE: [Column; 7] = [ @@ -548,37 +572,49 @@ mod tests { } #[test] - fn test_header_with_human_readable_binary() { + fn test_human_readable_header() { let options = Options { - size_format: SizeFormat::HumanReadable(HumanReadable::Binary), + header_mode: HeaderMode::HumanReadable, + ..Default::default() + }; + assert_eq!( + Header::get_headers(&options), + vec!("Filesystem", "Size", "Used", "Avail", "Use%", "Mounted on") + ); + } + + #[test] + fn test_posix_portability_header() { + let options = Options { + header_mode: HeaderMode::PosixPortability, ..Default::default() }; assert_eq!( Header::get_headers(&options), vec!( "Filesystem", - "Size", + "1024-blocks", "Used", "Available", - "Use%", + "Capacity", "Mounted on" ) ); } #[test] - fn test_header_with_human_readable_si() { + fn test_output_header() { let options = Options { - size_format: SizeFormat::HumanReadable(HumanReadable::Decimal), + header_mode: HeaderMode::Output, ..Default::default() }; assert_eq!( Header::get_headers(&options), vec!( "Filesystem", - "Size", + "1K-blocks", "Used", - "Available", + "Avail", "Use%", "Mounted on" ) diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 81a9eef72..3c5bfdeea 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -73,7 +73,7 @@ fn test_df_output() { "Filesystem", "Size", "Used", - "Available", + "Avail", "Capacity", "Use%", "Mounted", @@ -84,7 +84,7 @@ fn test_df_output() { "Filesystem", "Size", "Used", - "Available", + "Avail", "Use%", "Mounted", "on", @@ -107,7 +107,7 @@ fn test_df_output_overridden() { "Filesystem", "Size", "Used", - "Available", + "Avail", "Capacity", "Use%", "Mounted", @@ -118,7 +118,7 @@ fn test_df_output_overridden() { "Filesystem", "Size", "Used", - "Available", + "Avail", "Use%", "Mounted", "on", @@ -134,6 +134,46 @@ fn test_df_output_overridden() { assert_eq!(actual, expected); } +#[test] +fn test_default_headers() { + let expected = if cfg!(target_os = "macos") { + vec![ + "Filesystem", + "1K-blocks", + "Used", + "Available", + "Capacity", + "Use%", + "Mounted", + "on", + ] + } else { + vec![ + "Filesystem", + "1K-blocks", + "Used", + "Available", + "Use%", + "Mounted", + "on", + ] + }; + let output = new_ucmd!().succeeds().stdout_move_str(); + let actual = output.lines().take(1).collect::>()[0]; + let actual = actual.split_whitespace().collect::>(); + assert_eq!(actual, expected); +} + +#[test] +fn test_precedence_of_human_readable_header_over_output_header() { + let output = new_ucmd!() + .args(&["-H", "--output=size"]) + .succeeds() + .stdout_move_str(); + let header = output.lines().next().unwrap().to_string(); + assert_eq!(header.trim(), "Size"); +} + #[test] fn test_total_option_with_single_dash() { // These should fail because `-total` should have two dashes, @@ -443,6 +483,31 @@ fn test_block_size_with_suffix() { assert_eq!(get_header("1GB"), "1GB-blocks"); } +#[test] +fn test_block_size_in_posix_portability_mode() { + fn get_header(block_size: &str) -> String { + let output = new_ucmd!() + .args(&["-P", "-B", block_size]) + .succeeds() + .stdout_move_str(); + output + .lines() + .next() + .unwrap() + .to_string() + .split_whitespace() + .nth(1) + .unwrap() + .to_string() + } + + assert_eq!(get_header("1024"), "1024-blocks"); + assert_eq!(get_header("1K"), "1024-blocks"); + assert_eq!(get_header("1KB"), "1000-blocks"); + assert_eq!(get_header("1M"), "1048576-blocks"); + assert_eq!(get_header("1MB"), "1000000-blocks"); +} + #[test] fn test_too_large_block_size() { fn run_command(size: &str) { From a6b100a5ca044496e6cc649ea5cccb4e87c5db0b Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Tue, 10 May 2022 09:34:33 +0200 Subject: [PATCH 099/111] df: show error if provided block size is zero --- src/uu/df/src/blocks.rs | 13 +++++++++++-- tests/by-util/test_df.rs | 10 ++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/uu/df/src/blocks.rs b/src/uu/df/src/blocks.rs index bb6e06333..8759d161f 100644 --- a/src/uu/df/src/blocks.rs +++ b/src/uu/df/src/blocks.rs @@ -7,7 +7,10 @@ use crate::OPT_BLOCKSIZE; use clap::ArgMatches; use std::{env, fmt}; -use uucore::parse_size::{parse_size, ParseSizeError}; +use uucore::{ + display::Quotable, + parse_size::{parse_size, ParseSizeError}, +}; /// The first ten powers of 1024. const IEC_BASES: [u128; 10] = [ @@ -180,7 +183,13 @@ impl Default for BlockSize { pub(crate) fn block_size_from_matches(matches: &ArgMatches) -> Result { if matches.is_present(OPT_BLOCKSIZE) { let s = matches.value_of(OPT_BLOCKSIZE).unwrap(); - Ok(BlockSize::Bytes(parse_size(s)?)) + let bytes = parse_size(s)?; + + if bytes > 0 { + Ok(BlockSize::Bytes(bytes)) + } else { + Err(ParseSizeError::ParseFailure(format!("{}", s.quote()))) + } } else { Ok(Default::default()) } diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 81a9eef72..5f48f1106 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -465,6 +465,16 @@ fn test_invalid_block_size() { .arg("--block-size=x") .fails() .stderr_contains("invalid --block-size argument 'x'"); + + new_ucmd!() + .arg("--block-size=0") + .fails() + .stderr_contains("invalid --block-size argument '0'"); + + new_ucmd!() + .arg("--block-size=0K") + .fails() + .stderr_contains("invalid --block-size argument '0K'"); } #[test] From 08b6dd497521e71cc3d0c743061c611686b0f819 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 8 May 2022 23:02:32 -0400 Subject: [PATCH 100/111] uucore(perms): better support nameless uids, gids Update the `wrap_chown()` function to support user IDs and group IDs that do not correspond to named users or groups, respectively. Before this commit, the result from `uid2usr()` and `gid2grp()` calls were unwrapped because we assumed a user name or group name, respectively, existed. However, this is not always true: for example, running the command `sudo chown 12345 f` works even if there is no named user with ID 12345. This commit expands `wrap_chown()` to work even if no name exists for the user or group. --- src/uucore/src/lib/features/perms.rs | 34 ++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs index d8e345313..ed9e1c001 100644 --- a/src/uucore/src/lib/features/perms.rs +++ b/src/uucore/src/lib/features/perms.rs @@ -92,22 +92,25 @@ pub fn wrap_chown>( ); if level == VerbosityLevel::Verbose { out = if verbosity.groups_only { + let gid = meta.gid(); format!( "{}\nfailed to change group of {} from {} to {}", out, path.quote(), - entries::gid2grp(meta.gid()).unwrap(), - entries::gid2grp(dest_gid).unwrap() + entries::gid2grp(gid).unwrap_or(gid.to_string()), + entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) ) } else { + let uid = meta.uid(); + let gid = meta.gid(); format!( "{}\nfailed to change ownership of {} from {}:{} to {}:{}", out, path.quote(), - entries::uid2usr(meta.uid()).unwrap(), - entries::gid2grp(meta.gid()).unwrap(), - entries::uid2usr(dest_uid).unwrap(), - entries::gid2grp(dest_gid).unwrap() + entries::uid2usr(uid).unwrap_or(uid.to_string()), + entries::gid2grp(gid).unwrap_or(gid.to_string()), + entries::uid2usr(dest_uid).unwrap_or(dest_uid.to_string()), + entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) ) }; }; @@ -119,21 +122,24 @@ pub fn wrap_chown>( if changed { match verbosity.level { VerbosityLevel::Changes | VerbosityLevel::Verbose => { + let gid = meta.gid(); out = if verbosity.groups_only { format!( "changed group of {} from {} to {}", path.quote(), - entries::gid2grp(meta.gid()).unwrap(), - entries::gid2grp(dest_gid).unwrap() + entries::gid2grp(gid).unwrap_or(gid.to_string()), + entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) ) } else { + let gid = meta.gid(); + let uid = meta.uid(); format!( "changed ownership of {} from {}:{} to {}:{}", path.quote(), - entries::uid2usr(meta.uid()).unwrap(), - entries::gid2grp(meta.gid()).unwrap(), - entries::uid2usr(dest_uid).unwrap(), - entries::gid2grp(dest_gid).unwrap() + entries::uid2usr(uid).unwrap_or(uid.to_string()), + entries::gid2grp(gid).unwrap_or(gid.to_string()), + entries::uid2usr(dest_uid).unwrap_or(dest_uid.to_string()), + entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) ) }; } @@ -150,8 +156,8 @@ pub fn wrap_chown>( format!( "ownership of {} retained as {}:{}", path.quote(), - entries::uid2usr(dest_uid).unwrap(), - entries::gid2grp(dest_gid).unwrap() + entries::uid2usr(dest_uid).unwrap_or(dest_uid.to_string()), + entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) ) }; } From 55550e1a6ec98e8657bb7b0807f2675424f4fc78 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sat, 23 Apr 2022 12:39:43 -0400 Subject: [PATCH 101/111] chown: allow setting arbitrary numeric user ID Update `chown` to allow setting the owner of a file to a numeric user ID regardless of whether a corresponding username exists on the system. For example, $ touch f && sudo chown 12345 f succeeds even though there is no named user with ID 12345. Fixes #3380. --- src/uu/chown/src/chown.rs | 15 +++++++++++---- tests/by-util/test_chown.rs | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 3add9df1f..c58696121 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -197,10 +197,17 @@ fn parse_spec(spec: &str, sep: char) -> UResult<(Option, Option)> { // So, try to parse it this way return parse_spec(spec, '.'); } else { - return Err(USimpleError::new( - 1, - format!("invalid user: {}", spec.quote()), - )); + // It's possible that the `user` string contains a + // numeric user ID, in which case, we respect that. + match user.parse() { + Ok(uid) => uid, + Err(_) => { + return Err(USimpleError::new( + 1, + format!("invalid user: {}", spec.quote()), + )) + } + } } } }) diff --git a/tests/by-util/test_chown.rs b/tests/by-util/test_chown.rs index 4470260f4..05a10fb65 100644 --- a/tests/by-util/test_chown.rs +++ b/tests/by-util/test_chown.rs @@ -418,6 +418,29 @@ fn test_chown_only_user_id() { .stderr_contains(&"failed to change"); } +/// Test for setting the owner to a user ID for a user that does not exist. +/// +/// For example: +/// +/// $ touch f && chown 12345 f +/// +/// succeeds with exit status 0 and outputs nothing. The owner of the +/// file is set to 12345, even though no user with that ID exists. +/// +/// This test must be run as root, because only the root user can +/// transfer ownership of a file. +#[test] +fn test_chown_only_user_id_nonexistent_user() { + let ts = TestScenario::new(util_name!()); + let at = ts.fixtures.clone(); + at.touch("f"); + if let Ok(result) = run_ucmd_as_root(&ts, &["12345", "f"]) { + result.success().no_stdout().no_stderr(); + } else { + print!("Test skipped; requires root user"); + } +} + #[test] // FixME: stderr = chown: ownership of 'test_chown_file1' retained as cuuser:wheel #[cfg(not(target_os = "freebsd"))] From 163df8abc1954fee060d354c775ed1f4ff99f66c Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Mon, 9 May 2022 10:19:57 -0400 Subject: [PATCH 102/111] fixup! chown: allow setting arbitrary numeric user ID --- src/uu/chown/src/chown.rs | 47 +++++++++++++++++++++++++++---------- tests/by-util/test_chown.rs | 23 ++++++++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index c58696121..18c64d60e 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -167,17 +167,18 @@ pub fn uu_app<'a>() -> Command<'a> { ) } -/// Parse the username and groupname +/// Parse the owner/group specifier string into a user ID and a group ID. /// -/// In theory, it should be username:groupname -/// but ... -/// it can user.name:groupname -/// or username.groupname +/// The `spec` can be of the form: /// -/// # Arguments +/// * `"owner:group"`, +/// * `"owner"`, +/// * `":group"`, /// -/// * `spec` - The input from the user -/// * `sep` - Should be ':' or '.' +/// and the owner or group can be specified either as an ID or a +/// name. The `sep` argument specifies which character to use as a +/// separator between the owner and group; calling code should set +/// this to `':'`. fn parse_spec(spec: &str, sep: char) -> UResult<(Option, Option)> { assert!(['.', ':'].contains(&sep)); let mut args = spec.splitn(2, sep); @@ -215,11 +216,18 @@ fn parse_spec(spec: &str, sep: char) -> UResult<(Option, Option)> { None }; let gid = if !group.is_empty() { - Some( - Group::locate(group) - .map_err(|_| USimpleError::new(1, format!("invalid group: {}", spec.quote())))? - .gid, - ) + Some(match Group::locate(group) { + Ok(g) => g.gid, + Err(_) => match group.parse() { + Ok(gid) => gid, + Err(_) => { + return Err(USimpleError::new( + 1, + format!("invalid group: {}", spec.quote()), + )); + } + }, + }) } else { None }; @@ -238,4 +246,17 @@ mod test { assert!(format!("{}", parse_spec("::", ':').err().unwrap()).starts_with("invalid group: ")); assert!(format!("{}", parse_spec("..", ':').err().unwrap()).starts_with("invalid group: ")); } + + /// Test for parsing IDs that don't correspond to a named user or group. + #[test] + fn test_parse_spec_nameless_ids() { + // This assumes that there is no named user with ID 12345. + assert!(matches!(parse_spec("12345", ':'), Ok((Some(12345), None)))); + // This assumes that there is no named group with ID 54321. + assert!(matches!(parse_spec(":54321", ':'), Ok((None, Some(54321))))); + assert!(matches!( + parse_spec("12345:54321", ':'), + Ok((Some(12345), Some(54321))) + )); + } } diff --git a/tests/by-util/test_chown.rs b/tests/by-util/test_chown.rs index 05a10fb65..ef3fc0d33 100644 --- a/tests/by-util/test_chown.rs +++ b/tests/by-util/test_chown.rs @@ -484,6 +484,29 @@ fn test_chown_only_group_id() { .stderr_contains(&"failed to change"); } +/// Test for setting the group to a group ID for a group that does not exist. +/// +/// For example: +/// +/// $ touch f && chown :12345 f +/// +/// succeeds with exit status 0 and outputs nothing. The group of the +/// file is set to 12345, even though no group with that ID exists. +/// +/// This test must be run as root, because only the root user can +/// transfer ownership of a file. +#[test] +fn test_chown_only_group_id_nonexistent_group() { + let ts = TestScenario::new(util_name!()); + let at = ts.fixtures.clone(); + at.touch("f"); + if let Ok(result) = run_ucmd_as_root(&ts, &[":12345", "f"]) { + result.success().no_stdout().no_stderr(); + } else { + print!("Test skipped; requires root user"); + } +} + #[test] fn test_chown_owner_group_id() { // test chown 1111:1111 file.txt From f56903493c3717401dc2191584844f9c510e2340 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Mon, 9 May 2022 20:29:11 -0400 Subject: [PATCH 103/111] WIP Trying to diagnose 'invalid group: 1001:121' error in CI environment --- src/uu/chown/src/chown.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 18c64d60e..9d2cad1c3 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -220,7 +220,8 @@ fn parse_spec(spec: &str, sep: char) -> UResult<(Option, Option)> { Ok(g) => g.gid, Err(_) => match group.parse() { Ok(gid) => gid, - Err(_) => { + Err(e) => { + eprintln!("error {}, user {}, group {}, uid {:?}", e, user, group, uid); return Err(USimpleError::new( 1, format!("invalid group: {}", spec.quote()), From 3029d83a36af853a95cebdd8363a41c3143659ab Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Mon, 9 May 2022 20:47:46 -0400 Subject: [PATCH 104/111] Revert "WIP Trying to diagnose 'invalid group: 1001:121' error in CI environment" This reverts commit 291fb3ad71a0e93705509a352fd95de7539402ed. --- src/uu/chown/src/chown.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 9d2cad1c3..18c64d60e 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -220,8 +220,7 @@ fn parse_spec(spec: &str, sep: char) -> UResult<(Option, Option)> { Ok(g) => g.gid, Err(_) => match group.parse() { Ok(gid) => gid, - Err(e) => { - eprintln!("error {}, user {}, group {}, uid {:?}", e, user, group, uid); + Err(_) => { return Err(USimpleError::new( 1, format!("invalid group: {}", spec.quote()), From 5713de4d937ac7e03cbf32e926fb4044bd782d67 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Mon, 9 May 2022 20:50:20 -0400 Subject: [PATCH 105/111] fixup! uucore(perms): better support nameless uids, gids --- src/uucore/src/lib/features/perms.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs index ed9e1c001..edb714646 100644 --- a/src/uucore/src/lib/features/perms.rs +++ b/src/uucore/src/lib/features/perms.rs @@ -97,8 +97,8 @@ pub fn wrap_chown>( "{}\nfailed to change group of {} from {} to {}", out, path.quote(), - entries::gid2grp(gid).unwrap_or(gid.to_string()), - entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) + entries::gid2grp(gid).unwrap_or_else(|_| gid.to_string()), + entries::gid2grp(dest_gid).unwrap_or_else(|_| dest_gid.to_string()) ) } else { let uid = meta.uid(); @@ -107,10 +107,10 @@ pub fn wrap_chown>( "{}\nfailed to change ownership of {} from {}:{} to {}:{}", out, path.quote(), - entries::uid2usr(uid).unwrap_or(uid.to_string()), - entries::gid2grp(gid).unwrap_or(gid.to_string()), - entries::uid2usr(dest_uid).unwrap_or(dest_uid.to_string()), - entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) + entries::uid2usr(uid).unwrap_or_else(|_| uid.to_string()), + entries::gid2grp(gid).unwrap_or_else(|_| gid.to_string()), + entries::uid2usr(dest_uid).unwrap_or_else(|_| dest_uid.to_string()), + entries::gid2grp(dest_gid).unwrap_or_else(|_| dest_gid.to_string()) ) }; }; @@ -127,8 +127,8 @@ pub fn wrap_chown>( format!( "changed group of {} from {} to {}", path.quote(), - entries::gid2grp(gid).unwrap_or(gid.to_string()), - entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) + entries::gid2grp(gid).unwrap_or_else(|_| gid.to_string()), + entries::gid2grp(dest_gid).unwrap_or_else(|_| dest_gid.to_string()) ) } else { let gid = meta.gid(); @@ -136,10 +136,10 @@ pub fn wrap_chown>( format!( "changed ownership of {} from {}:{} to {}:{}", path.quote(), - entries::uid2usr(uid).unwrap_or(uid.to_string()), - entries::gid2grp(gid).unwrap_or(gid.to_string()), - entries::uid2usr(dest_uid).unwrap_or(dest_uid.to_string()), - entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) + entries::uid2usr(uid).unwrap_or_else(|_| uid.to_string()), + entries::gid2grp(gid).unwrap_or_else(|_| gid.to_string()), + entries::uid2usr(dest_uid).unwrap_or_else(|_| dest_uid.to_string()), + entries::gid2grp(dest_gid).unwrap_or_else(|_| dest_gid.to_string()) ) }; } @@ -156,8 +156,8 @@ pub fn wrap_chown>( format!( "ownership of {} retained as {}:{}", path.quote(), - entries::uid2usr(dest_uid).unwrap_or(dest_uid.to_string()), - entries::gid2grp(dest_gid).unwrap_or(dest_gid.to_string()) + entries::uid2usr(dest_uid).unwrap_or_else(|_| dest_uid.to_string()), + entries::gid2grp(dest_gid).unwrap_or_else(|_| dest_gid.to_string()) ) }; } From 598dc79b69d9eb6b711fd45b4b4fa7dd18d75413 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 12 May 2022 10:11:24 +0200 Subject: [PATCH 106/111] df: test default blocksize in POSIX mode --- tests/by-util/test_df.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 157818d95..9ff8e103d 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -435,6 +435,30 @@ fn test_default_block_size() { assert_eq!(header, "512B-blocks"); } +#[test] +fn test_default_block_size_in_posix_portability_mode() { + fn get_header(s: &str) -> String { + s.lines() + .next() + .unwrap() + .to_string() + .split_whitespace() + .nth(1) + .unwrap() + .to_string() + } + + let output = new_ucmd!().arg("-P").succeeds().stdout_move_str(); + assert_eq!(get_header(&output), "1024-blocks"); + + let output = new_ucmd!() + .arg("-P") + .env("POSIXLY_CORRECT", "1") + .succeeds() + .stdout_move_str(); + assert_eq!(get_header(&output), "512-blocks"); +} + #[test] fn test_block_size_1024() { fn get_header(block_size: u64) -> String { From 369026a92f1b0c3e3b17706e2061b98447f7ee9a Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Thu, 12 May 2022 22:34:08 +0200 Subject: [PATCH 107/111] tr: remove duplicate line from clap::Command --- src/uu/tr/src/tr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index dd8edc518..93465429f 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -143,7 +143,6 @@ pub fn uu_app<'a>() -> Command<'a> { .about(ABOUT) .override_usage(format_usage(USAGE)) .infer_long_args(true) - .infer_long_args(true) .arg( Arg::new(options::COMPLEMENT) .visible_short_alias('C') From fa94591b723b52a6b6435c876e1b42c61ed24929 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Thu, 12 May 2022 19:22:50 +0200 Subject: [PATCH 108/111] test_stat: expand scope for stdin tests On Android and macOS all/some tests for stdin fail with: `cannot stat '-': No such file or directory` Apparently the `/dev/stdin` redirect workaround doesn't work for these targets. --- tests/by-util/test_stat.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 14aba96fc..681850467 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -360,12 +360,11 @@ fn test_pipe_fifo() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(all(unix, not(target_os = "android")))] fn test_stdin_pipe_fifo1() { // $ echo | stat - // File: - // Size: 0 Blocks: 0 IO Block: 4096 fifo - // use std::process::{Command, Stdio}; new_ucmd!() .arg("-") .set_stdin(std::process::Stdio::piped()) @@ -374,7 +373,6 @@ fn test_stdin_pipe_fifo1() { .stdout_contains("fifo") .stdout_contains("File: -") .succeeded(); - new_ucmd!() .args(&["-L", "-"]) .set_stdin(std::process::Stdio::piped()) @@ -386,7 +384,7 @@ fn test_stdin_pipe_fifo1() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(all(unix, not(target_os = "android")))] fn test_stdin_pipe_fifo2() { // $ stat - // File: - @@ -402,16 +400,15 @@ fn test_stdin_pipe_fifo2() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] fn test_stdin_redirect() { // $ touch f && stat - < f // File: - // Size: 0 Blocks: 0 IO Block: 4096 regular empty file - let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; at.touch("f"); - new_ucmd!() + ts.ucmd() .arg("-") .set_stdin(std::fs::File::open(at.plus("f")).unwrap()) .run() From 5d628310fc522e1e23983044ed1e41cc6111f882 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 May 2022 06:45:15 +0000 Subject: [PATCH 109/111] build(deps): bump vmactions/freebsd-vm from 0.1.5 to 0.1.6 Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 0.1.5 to 0.1.6. - [Release notes](https://github.com/vmactions/freebsd-vm/releases) - [Commits](https://github.com/vmactions/freebsd-vm/compare/v0.1.5...v0.1.6) --- updated-dependencies: - dependency-name: vmactions/freebsd-vm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 079dc1f29..c58b725c4 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -915,7 +915,7 @@ jobs: - uses: Swatinem/rust-cache@v1 - name: Prepare, build and test ## spell-checker:ignore (ToDO) sshfs usesh vmactions - uses: vmactions/freebsd-vm@v0.1.5 + uses: vmactions/freebsd-vm@v0.1.6 with: usesh: true # sync: sshfs From 0acfa07d7707897e64ba3783cdc370f4e102388d Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Thu, 12 May 2022 22:53:25 +0200 Subject: [PATCH 110/111] all: add value hints --- src/uu/base32/src/base_common.rs | 7 ++++++- src/uu/basename/src/basename.rs | 1 + src/uu/cat/src/cat.rs | 3 ++- src/uu/chcon/src/chcon.rs | 3 +++ src/uu/chgrp/src/chgrp.rs | 1 + src/uu/chmod/src/chmod.rs | 4 +++- src/uu/chown/src/chown.rs | 1 + src/uu/chroot/src/chroot.rs | 2 ++ src/uu/cksum/src/cksum.rs | 3 ++- src/uu/comm/src/comm.rs | 12 ++++++++++-- src/uu/cp/src/cp.rs | 4 +++- src/uu/csplit/src/csplit.rs | 7 ++++++- src/uu/cut/src/cut.rs | 3 ++- src/uu/date/src/date.rs | 2 ++ src/uu/dd/src/dd.rs | 2 ++ src/uu/df/src/df.rs | 6 +++++- src/uu/dircolors/src/dircolors.rs | 1 + src/uu/dirname/src/dirname.rs | 7 ++++++- src/uu/du/src/du.rs | 2 ++ src/uu/env/src/env.rs | 2 ++ src/uu/expand/src/expand.rs | 1 + src/uu/fmt/src/fmt.rs | 3 ++- src/uu/fold/src/fold.rs | 3 ++- src/uu/groups/src/groups.rs | 3 ++- src/uu/hashsum/src/hashsum.rs | 1 + src/uu/head/src/head.rs | 6 +++++- src/uu/hostname/src/hostname.rs | 6 +++++- src/uu/id/src/id.rs | 3 ++- src/uu/install/src/install.rs | 11 ++++++++++- src/uu/join/src/join.rs | 2 ++ src/uu/link/src/link.rs | 1 + src/uu/ln/src/ln.rs | 2 ++ src/uu/ls/src/ls.rs | 3 ++- src/uu/mkdir/src/mkdir.rs | 3 ++- src/uu/mkfifo/src/mkfifo.rs | 3 ++- src/uu/mknod/src/mknod.rs | 3 ++- src/uu/mktemp/src/mktemp.rs | 3 ++- src/uu/more/src/more.rs | 3 ++- src/uu/mv/src/mv.rs | 6 ++++-- src/uu/nice/src/nice.rs | 6 +++++- src/uu/nl/src/nl.rs | 3 ++- src/uu/nohup/src/nohup.rs | 3 ++- src/uu/od/src/od.rs | 3 ++- src/uu/paste/src/paste.rs | 3 ++- src/uu/pathchk/src/pathchk.rs | 3 ++- src/uu/pinky/src/pinky.rs | 3 ++- src/uu/pr/src/pr.rs | 1 + src/uu/ptx/src/ptx.rs | 12 ++++++++---- src/uu/readlink/src/readlink.rs | 3 ++- src/uu/realpath/src/realpath.rs | 3 ++- src/uu/relpath/src/relpath.rs | 13 +++++++++++-- src/uu/rm/src/rm.rs | 1 + src/uu/rmdir/src/rmdir.rs | 3 ++- src/uu/runcon/src/runcon.rs | 3 ++- src/uu/shred/src/shred.rs | 3 ++- src/uu/shuf/src/shuf.rs | 12 +++++++++--- src/uu/sort/src/sort.rs | 15 ++++++++++----- src/uu/split/src/split.rs | 9 ++++++--- src/uu/stat/src/stat.rs | 3 ++- src/uu/stdbuf/src/stdbuf.rs | 3 ++- src/uu/sum/src/sum.rs | 3 ++- src/uu/sync/src/sync.rs | 3 ++- src/uu/tac/src/tac.rs | 3 ++- src/uu/tail/src/tail.rs | 3 ++- src/uu/tee/src/tee.rs | 6 +++++- src/uu/timeout/src/timeout.rs | 1 + src/uu/touch/src/touch.rs | 6 ++++-- src/uu/truncate/src/truncate.rs | 4 +++- src/uu/tsort/src/tsort.rs | 7 ++++++- src/uu/unexpand/src/unexpand.rs | 7 ++++++- src/uu/uniq/src/uniq.rs | 3 ++- src/uu/unlink/src/unlink.rs | 3 ++- src/uu/users/src/users.rs | 7 ++++++- src/uu/wc/src/wc.rs | 6 ++++-- src/uu/who/src/who.rs | 3 ++- src/uucore/src/lib/features/perms.rs | 1 + 76 files changed, 240 insertions(+), 73 deletions(-) diff --git a/src/uu/base32/src/base_common.rs b/src/uu/base32/src/base_common.rs index 148bad2f8..90221f4f6 100644 --- a/src/uu/base32/src/base_common.rs +++ b/src/uu/base32/src/base_common.rs @@ -123,7 +123,12 @@ pub fn base_app<'a>(about: &'a str, usage: &'a str) -> Command<'a> { ) // "multiple" arguments are used to check whether there is more than one // file passed in. - .arg(Arg::new(options::FILE).index(1).multiple_occurrences(true)) + .arg( + Arg::new(options::FILE) + .index(1) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), + ) } pub fn get_input<'a>(config: &Config, stdin_ref: &'a Stdin) -> UResult> { diff --git a/src/uu/basename/src/basename.rs b/src/uu/basename/src/basename.rs index 7b0a0a486..242a6a6e9 100644 --- a/src/uu/basename/src/basename.rs +++ b/src/uu/basename/src/basename.rs @@ -102,6 +102,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::NAME) .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath) .hide(true), ) .arg( diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index 67de917f7..cd10b5251 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -249,7 +249,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::SHOW_ALL) diff --git a/src/uu/chcon/src/chcon.rs b/src/uu/chcon/src/chcon.rs index e49191ea3..3458a4cca 100644 --- a/src/uu/chcon/src/chcon.rs +++ b/src/uu/chcon/src/chcon.rs @@ -197,6 +197,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::REFERENCE) .takes_value(true) .value_name("RFILE") + .value_hint(clap::ValueHint::FilePath) .conflicts_with_all(&[options::USER, options::ROLE, options::TYPE, options::RANGE]) .help( "Use security context of RFILE, rather than specifying \ @@ -210,6 +211,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::USER) .takes_value(true) .value_name("USER") + .value_hint(clap::ValueHint::Username) .help("Set user USER in the target security context.") .allow_invalid_utf8(true), ) @@ -294,6 +296,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new("FILE") .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath) .min_values(1) .allow_invalid_utf8(true), ) diff --git a/src/uu/chgrp/src/chgrp.rs b/src/uu/chgrp/src/chgrp.rs index d7e8baafe..015f09982 100644 --- a/src/uu/chgrp/src/chgrp.rs +++ b/src/uu/chgrp/src/chgrp.rs @@ -113,6 +113,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::REFERENCE) .long(options::REFERENCE) .value_name("RFILE") + .value_hint(clap::ValueHint::FilePath) .help("use RFILE's group rather than specifying GROUP values") .takes_value(true) .multiple_occurrences(false), diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index 25a37c372..d4b81ee37 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -157,6 +157,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::REFERENCE) .long("reference") .takes_value(true) + .value_hint(clap::ValueHint::FilePath) .help("use RFILE's mode instead of MODE values"), ) .arg( @@ -170,7 +171,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .required_unless_present(options::MODE) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 3add9df1f..e66e105fb 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -134,6 +134,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::REFERENCE) .help("use RFILE's owner and group rather than specifying OWNER:GROUP values") .value_name("RFILE") + .value_hint(clap::ValueHint::FilePath) .min_values(1), ) .arg( diff --git a/src/uu/chroot/src/chroot.rs b/src/uu/chroot/src/chroot.rs index e54cc3f8f..30cf75644 100644 --- a/src/uu/chroot/src/chroot.rs +++ b/src/uu/chroot/src/chroot.rs @@ -102,6 +102,7 @@ pub fn uu_app<'a>() -> Command<'a> { .infer_long_args(true) .arg( Arg::new(options::NEWROOT) + .value_hint(clap::ValueHint::DirPath) .hide(true) .required(true) .index(1), @@ -139,6 +140,7 @@ pub fn uu_app<'a>() -> Command<'a> { ) .arg( Arg::new(options::COMMAND) + .value_hint(clap::ValueHint::CommandName) .hide(true) .multiple_occurrences(true) .index(2), diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index e901e0820..e9a5c5620 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -150,6 +150,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/comm/src/comm.rs b/src/uu/comm/src/comm.rs index 2207493d3..78ef4e5c2 100644 --- a/src/uu/comm/src/comm.rs +++ b/src/uu/comm/src/comm.rs @@ -173,6 +173,14 @@ pub fn uu_app<'a>() -> Command<'a> { .default_value(options::DELIMITER_DEFAULT) .hide_default_value(true), ) - .arg(Arg::new(options::FILE_1).required(true)) - .arg(Arg::new(options::FILE_2).required(true)) + .arg( + Arg::new(options::FILE_1) + .required(true) + .value_hint(clap::ValueHint::FilePath), + ) + .arg( + Arg::new(options::FILE_2) + .required(true) + .value_hint(clap::ValueHint::FilePath), + ) } diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index 1b47b7828..41466abc8 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -314,6 +314,7 @@ pub fn uu_app<'a>() -> Command<'a> { .conflicts_with(options::NO_TARGET_DIRECTORY) .long(options::TARGET_DIRECTORY) .value_name(options::TARGET_DIRECTORY) + .value_hint(clap::ValueHint::DirPath) .takes_value(true) .validator(|s| { if Path::new(s).is_dir() { @@ -464,7 +465,8 @@ pub fn uu_app<'a>() -> Command<'a> { // END TODO .arg(Arg::new(options::PATHS) - .multiple_occurrences(true)) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath)) } #[uucore::main] diff --git a/src/uu/csplit/src/csplit.rs b/src/uu/csplit/src/csplit.rs index a0b739935..2ef6b34f9 100644 --- a/src/uu/csplit/src/csplit.rs +++ b/src/uu/csplit/src/csplit.rs @@ -797,7 +797,12 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::ELIDE_EMPTY_FILES) .help("remove empty output files"), ) - .arg(Arg::new(options::FILE).hide(true).required(true)) + .arg( + Arg::new(options::FILE) + .hide(true) + .required(true) + .value_hint(clap::ValueHint::FilePath), + ) .arg( Arg::new(options::PATTERN) .hide(true) diff --git a/src/uu/cut/src/cut.rs b/src/uu/cut/src/cut.rs index 2264f4f26..b809b765d 100644 --- a/src/uu/cut/src/cut.rs +++ b/src/uu/cut/src/cut.rs @@ -614,6 +614,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath) ) } diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index 8946768d5..ca18856d1 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -272,6 +272,7 @@ pub fn uu_app<'a>() -> Command<'a> { .short('f') .long(OPT_FILE) .takes_value(true) + .value_hint(clap::ValueHint::FilePath) .help("like --date; once for each line of DATEFILE"), ) .arg( @@ -303,6 +304,7 @@ pub fn uu_app<'a>() -> Command<'a> { .short('r') .long(OPT_REFERENCE) .takes_value(true) + .value_hint(clap::ValueHint::AnyPath) .help("display the last modification time of FILE"), ) .arg( diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index 3f1a54b1c..115da8bcc 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -742,6 +742,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::INFILE) .overrides_with(options::INFILE) .takes_value(true) + .value_hint(clap::ValueHint::FilePath) .require_equals(true) .value_name("FILE") .help("(alternatively if=FILE) specifies the file used for input. When not specified, stdin is used instead") @@ -751,6 +752,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::OUTFILE) .overrides_with(options::OUTFILE) .takes_value(true) + .value_hint(clap::ValueHint::FilePath) .require_equals(true) .value_name("FILE") .help("(alternatively of=FILE) specifies the file used for output. When not specified, stdout is used instead") diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index a11dcf7a0..1f59982b2 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -583,7 +583,11 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .help("limit listing to file systems not of type TYPE"), ) - .arg(Arg::new(OPT_PATHS).multiple_occurrences(true)) + .arg( + Arg::new(OPT_PATHS) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath), + ) } #[cfg(test)] diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index c76dbc0c1..78cf8d802 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -187,6 +187,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) + .value_hint(clap::ValueHint::FilePath) .multiple_occurrences(true), ) } diff --git a/src/uu/dirname/src/dirname.rs b/src/uu/dirname/src/dirname.rs index 030c3981c..ac37e513b 100644 --- a/src/uu/dirname/src/dirname.rs +++ b/src/uu/dirname/src/dirname.rs @@ -88,5 +88,10 @@ pub fn uu_app<'a>() -> Command<'a> { .short('z') .help("separate output with NUL rather than newline"), ) - .arg(Arg::new(options::DIR).hide(true).multiple_occurrences(true)) + .arg( + Arg::new(options::DIR) + .hide(true) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath), + ) } diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index b29a938a4..d358d3e8f 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -884,6 +884,7 @@ pub fn uu_app<'a>() -> Command<'a> { .short('X') .long("exclude-from") .value_name("FILE") + .value_hint(clap::ValueHint::FilePath) .help("exclude files that match any pattern in FILE") .multiple_occurrences(true) @@ -913,6 +914,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) + .value_hint(clap::ValueHint::AnyPath) .multiple_occurrences(true) ) } diff --git a/src/uu/env/src/env.rs b/src/uu/env/src/env.rs index 2ec0ce1c6..a42621dad 100644 --- a/src/uu/env/src/env.rs +++ b/src/uu/env/src/env.rs @@ -144,6 +144,7 @@ pub fn uu_app<'a>() -> Command<'a> { .takes_value(true) .number_of_values(1) .value_name("DIR") + .value_hint(clap::ValueHint::DirPath) .help("change working directory to DIR")) .arg(Arg::new("null") .short('0') @@ -156,6 +157,7 @@ pub fn uu_app<'a>() -> Command<'a> { .takes_value(true) .number_of_values(1) .value_name("PATH") + .value_hint(clap::ValueHint::FilePath) .multiple_occurrences(true) .help("read and set variables from a \".env\"-style configuration file (prior to any \ unset and/or set)")) diff --git a/src/uu/expand/src/expand.rs b/src/uu/expand/src/expand.rs index b9d9309cd..117615162 100644 --- a/src/uu/expand/src/expand.rs +++ b/src/uu/expand/src/expand.rs @@ -207,6 +207,7 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .hide(true) .takes_value(true) + .value_hint(clap::ValueHint::FilePath) ) } diff --git a/src/uu/fmt/src/fmt.rs b/src/uu/fmt/src/fmt.rs index 3cb851674..27afb689f 100644 --- a/src/uu/fmt/src/fmt.rs +++ b/src/uu/fmt/src/fmt.rs @@ -344,6 +344,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(ARG_FILES) .multiple_occurrences(true) - .takes_value(true), + .takes_value(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/fold/src/fold.rs b/src/uu/fold/src/fold.rs index d24d31be9..b2806eb01 100644 --- a/src/uu/fold/src/fold.rs +++ b/src/uu/fold/src/fold.rs @@ -99,7 +99,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/groups/src/groups.rs b/src/uu/groups/src/groups.rs index cd0d05b07..dd2188033 100644 --- a/src/uu/groups/src/groups.rs +++ b/src/uu/groups/src/groups.rs @@ -112,6 +112,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::USERS) .multiple_occurrences(true) .takes_value(true) - .value_name(options::USERS), + .value_name(options::USERS) + .value_hint(clap::ValueHint::Username), ) } diff --git a/src/uu/hashsum/src/hashsum.rs b/src/uu/hashsum/src/hashsum.rs index 244e4b928..872cb5c21 100644 --- a/src/uu/hashsum/src/hashsum.rs +++ b/src/uu/hashsum/src/hashsum.rs @@ -423,6 +423,7 @@ pub fn uu_app_common<'a>() -> Command<'a> { .index(1) .multiple_occurrences(true) .value_name("FILE") + .value_hint(clap::ValueHint::FilePath) .allow_invalid_utf8(true), ) } diff --git a/src/uu/head/src/head.rs b/src/uu/head/src/head.rs index b6d36a4ad..01f08ff93 100644 --- a/src/uu/head/src/head.rs +++ b/src/uu/head/src/head.rs @@ -107,7 +107,11 @@ pub fn uu_app<'a>() -> Command<'a> { .help("line delimiter is NUL, not newline") .overrides_with(options::ZERO_NAME), ) - .arg(Arg::new(options::FILES_NAME).multiple_occurrences(true)) + .arg( + Arg::new(options::FILES_NAME) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), + ) } #[derive(Debug, PartialEq)] diff --git a/src/uu/hostname/src/hostname.rs b/src/uu/hostname/src/hostname.rs index 757caed02..11b0d6cdb 100644 --- a/src/uu/hostname/src/hostname.rs +++ b/src/uu/hostname/src/hostname.rs @@ -105,7 +105,11 @@ pub fn uu_app<'a>() -> Command<'a> { .overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT]) .help("Display the short hostname (the portion before the first dot) if possible"), ) - .arg(Arg::new(OPT_HOST).allow_invalid_utf8(true)) + .arg( + Arg::new(OPT_HOST) + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::Hostname), + ) } fn display_hostname(matches: &ArgMatches) -> UResult<()> { diff --git a/src/uu/id/src/id.rs b/src/uu/id/src/id.rs index cc23ce19f..bb8e261d2 100644 --- a/src/uu/id/src/id.rs +++ b/src/uu/id/src/id.rs @@ -443,7 +443,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::ARG_USERS) .multiple_occurrences(true) .takes_value(true) - .value_name(options::ARG_USERS), + .value_name(options::ARG_USERS) + .value_hint(clap::ValueHint::Username), ) } diff --git a/src/uu/install/src/install.rs b/src/uu/install/src/install.rs index 808898cfb..6750560d2 100644 --- a/src/uu/install/src/install.rs +++ b/src/uu/install/src/install.rs @@ -248,6 +248,7 @@ pub fn uu_app<'a>() -> Command<'a> { .help("set ownership (super-user only)") .value_name("OWNER") .takes_value(true) + .value_hint(clap::ValueHint::Username) ) .arg( Arg::new(OPT_PRESERVE_TIMESTAMPS) @@ -266,6 +267,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(OPT_STRIP_PROGRAM) .help("program used to strip binaries (no action Windows)") .value_name("PROGRAM") + .value_hint(clap::ValueHint::CommandName) ) .arg( backup_control::arguments::suffix() @@ -277,6 +279,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(OPT_TARGET_DIRECTORY) .help("move all SOURCE arguments into DIRECTORY") .value_name("DIRECTORY") + .value_hint(clap::ValueHint::DirPath) ) .arg( // TODO implement flag @@ -307,7 +310,13 @@ pub fn uu_app<'a>() -> Command<'a> { .help("(unimplemented) set security context of files and directories") .value_name("CONTEXT") ) - .arg(Arg::new(ARG_FILES).multiple_occurrences(true).takes_value(true).min_values(1)) + .arg( + Arg::new(ARG_FILES) + .multiple_occurrences(true) + .takes_value(true) + .min_values(1) + .value_hint(clap::ValueHint::AnyPath) + ) } /// Check for unimplemented command line arguments. diff --git a/src/uu/join/src/join.rs b/src/uu/join/src/join.rs index ef19fe328..20a8cbd28 100644 --- a/src/uu/join/src/join.rs +++ b/src/uu/join/src/join.rs @@ -801,12 +801,14 @@ FILENUM is 1 or 2, corresponding to FILE1 or FILE2", Arg::new("file1") .required(true) .value_name("FILE1") + .value_hint(clap::ValueHint::FilePath) .hide(true), ) .arg( Arg::new("file2") .required(true) .value_name("FILE2") + .value_hint(clap::ValueHint::FilePath) .hide(true), ) } diff --git a/src/uu/link/src/link.rs b/src/uu/link/src/link.rs index 3c959af33..1fc0c49ce 100644 --- a/src/uu/link/src/link.rs +++ b/src/uu/link/src/link.rs @@ -46,6 +46,7 @@ pub fn uu_app<'a>() -> Command<'a> { .min_values(2) .max_values(2) .takes_value(true) + .value_hint(clap::ValueHint::AnyPath) .allow_invalid_utf8(true), ) } diff --git a/src/uu/ln/src/ln.rs b/src/uu/ln/src/ln.rs index 088edf219..fdbb32311 100644 --- a/src/uu/ln/src/ln.rs +++ b/src/uu/ln/src/ln.rs @@ -232,6 +232,7 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::TARGET_DIRECTORY) .help("specify the DIRECTORY in which to create the links") .value_name("DIRECTORY") + .value_hint(clap::ValueHint::DirPath) .conflicts_with(options::NO_TARGET_DIRECTORY), ) .arg( @@ -257,6 +258,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(ARG_FILES) .multiple_occurrences(true) .takes_value(true) + .value_hint(clap::ValueHint::AnyPath) .required(true) .min_values(1), ) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 17eec91ec..20d960c51 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -1402,7 +1402,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::PATHS) .multiple_occurrences(true) .takes_value(true) - .allow_invalid_utf8(true), + .value_hint(clap::ValueHint::AnyPath) + .allow_invalid_utf8(true) ) .after_help( "The TIME_STYLE argument can be full-iso, long-iso, iso. \ diff --git a/src/uu/mkdir/src/mkdir.rs b/src/uu/mkdir/src/mkdir.rs index b1d7583d3..6ba58c2bb 100644 --- a/src/uu/mkdir/src/mkdir.rs +++ b/src/uu/mkdir/src/mkdir.rs @@ -137,7 +137,8 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .min_values(1) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::DirPath), ) } diff --git a/src/uu/mkfifo/src/mkfifo.rs b/src/uu/mkfifo/src/mkfifo.rs index 756fd75cf..b14ae8bed 100644 --- a/src/uu/mkfifo/src/mkfifo.rs +++ b/src/uu/mkfifo/src/mkfifo.rs @@ -102,6 +102,7 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FIFO) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/mknod/src/mknod.rs b/src/uu/mknod/src/mknod.rs index 0e7c4be45..fdd57aa01 100644 --- a/src/uu/mknod/src/mknod.rs +++ b/src/uu/mknod/src/mknod.rs @@ -162,7 +162,8 @@ pub fn uu_app<'a>() -> Command<'a> { .value_name("NAME") .help("name of the new file") .required(true) - .index(1), + .index(1) + .value_hint(clap::ValueHint::AnyPath), ) .arg( Arg::new("type") diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index 94def4874..20b95f009 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -202,7 +202,8 @@ pub fn uu_app<'a>() -> Command<'a> { be an absolute name; unlike with -t, TEMPLATE may contain \ slashes, but mktemp creates only the final component", ) - .value_name("DIR"), + .value_name("DIR") + .value_hint(clap::ValueHint::DirPath), ) .arg(Arg::new(OPT_T).short('t').help( "Generate a template (using the supplied prefix and TMPDIR (TMP on windows) if set) \ diff --git a/src/uu/more/src/more.rs b/src/uu/more/src/more.rs index ab94bd435..711d2b214 100644 --- a/src/uu/more/src/more.rs +++ b/src/uu/more/src/more.rs @@ -183,7 +183,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::FILES) .required(false) .multiple_occurrences(true) - .help("Path to the files to be read"), + .help("Path to the files to be read") + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index 1c2390f80..fa8284061 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -156,14 +156,15 @@ pub fn uu_app<'a>() -> Command<'a> { .help("move all SOURCE arguments into DIRECTORY") .takes_value(true) .value_name("DIRECTORY") + .value_hint(clap::ValueHint::DirPath) .conflicts_with(OPT_NO_TARGET_DIRECTORY) .allow_invalid_utf8(true) ) .arg( Arg::new(OPT_NO_TARGET_DIRECTORY) .short('T') - .long(OPT_NO_TARGET_DIRECTORY). - help("treat DEST as a normal file") + .long(OPT_NO_TARGET_DIRECTORY) + .help("treat DEST as a normal file") ) .arg( Arg::new(OPT_UPDATE) @@ -183,6 +184,7 @@ pub fn uu_app<'a>() -> Command<'a> { .min_values(2) .required(true) .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::AnyPath) ) } diff --git a/src/uu/nice/src/nice.rs b/src/uu/nice/src/nice.rs index e78de828b..f0d663bcc 100644 --- a/src/uu/nice/src/nice.rs +++ b/src/uu/nice/src/nice.rs @@ -117,5 +117,9 @@ pub fn uu_app<'a>() -> Command<'a> { .takes_value(true) .allow_hyphen_values(true), ) - .arg(Arg::new(options::COMMAND).multiple_occurrences(true)) + .arg( + Arg::new(options::COMMAND) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::CommandName), + ) } diff --git a/src/uu/nl/src/nl.rs b/src/uu/nl/src/nl.rs index 28cf3fb4d..e6ca7f931 100644 --- a/src/uu/nl/src/nl.rs +++ b/src/uu/nl/src/nl.rs @@ -154,7 +154,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::BODY_NUMBERING) diff --git a/src/uu/nohup/src/nohup.rs b/src/uu/nohup/src/nohup.rs index 0d67ad466..6f605ac4f 100644 --- a/src/uu/nohup/src/nohup.rs +++ b/src/uu/nohup/src/nohup.rs @@ -126,7 +126,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::CMD) .hide(true) .required(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::CommandName), ) .trailing_var_arg(true) .infer_long_args(true) diff --git a/src/uu/od/src/od.rs b/src/uu/od/src/od.rs index 33fac39d3..168213dae 100644 --- a/src/uu/od/src/od.rs +++ b/src/uu/od/src/od.rs @@ -512,7 +512,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILENAME) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/paste/src/paste.rs b/src/uu/paste/src/paste.rs index 2826a19e3..682e66a5d 100644 --- a/src/uu/paste/src/paste.rs +++ b/src/uu/paste/src/paste.rs @@ -71,7 +71,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::FILE) .value_name("FILE") .multiple_occurrences(true) - .default_value("-"), + .default_value("-") + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/pathchk/src/pathchk.rs b/src/uu/pathchk/src/pathchk.rs index 6260590aa..0f21448cf 100644 --- a/src/uu/pathchk/src/pathchk.rs +++ b/src/uu/pathchk/src/pathchk.rs @@ -108,7 +108,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::PATH) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/pinky/src/pinky.rs b/src/uu/pinky/src/pinky.rs index 4a793944f..b5217afe4 100644 --- a/src/uu/pinky/src/pinky.rs +++ b/src/uu/pinky/src/pinky.rs @@ -179,7 +179,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::USER) .takes_value(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::Username), ) .arg( // Redefine the help argument to not include the short flag diff --git a/src/uu/pr/src/pr.rs b/src/uu/pr/src/pr.rs index ca12f0be0..682e9b6d4 100644 --- a/src/uu/pr/src/pr.rs +++ b/src/uu/pr/src/pr.rs @@ -372,6 +372,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::FILES) .multiple_occurrences(true) .multiple_values(true) + .value_hint(clap::ValueHint::FilePath) ) } diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index 2f253b580..9cdad7ccf 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -754,7 +754,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::AUTO_REFERENCE) @@ -826,7 +827,8 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::BREAK_FILE) .help("word break characters in this FILE") .value_name("FILE") - .takes_value(true), + .takes_value(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::IGNORE_CASE) @@ -849,7 +851,8 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::IGNORE_FILE) .help("read ignore word list from FILE") .value_name("FILE") - .takes_value(true), + .takes_value(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::ONLY_FILE) @@ -857,7 +860,8 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::ONLY_FILE) .help("read only word list from this FILE") .value_name("FILE") - .takes_value(true), + .takes_value(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::REFERENCES) diff --git a/src/uu/readlink/src/readlink.rs b/src/uu/readlink/src/readlink.rs index ba1e368f2..10d75e7ef 100644 --- a/src/uu/readlink/src/readlink.rs +++ b/src/uu/readlink/src/readlink.rs @@ -161,7 +161,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(ARG_FILES) .multiple_occurrences(true) - .takes_value(true), + .takes_value(true) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/realpath/src/realpath.rs b/src/uu/realpath/src/realpath.rs index bea89c19e..403e7c456 100644 --- a/src/uu/realpath/src/realpath.rs +++ b/src/uu/realpath/src/realpath.rs @@ -130,7 +130,8 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .required(true) - .min_values(1), + .min_values(1) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/relpath/src/relpath.rs b/src/uu/relpath/src/relpath.rs index 2e45ce927..336e2192d 100644 --- a/src/uu/relpath/src/relpath.rs +++ b/src/uu/relpath/src/relpath.rs @@ -87,6 +87,15 @@ pub fn uu_app<'a>() -> Command<'a> { .arg(Arg::new(options::DIR).short('d').takes_value(true).help( "If any of FROM and TO is not subpath of DIR, output absolute path instead of relative", )) - .arg(Arg::new(options::TO).required(true).takes_value(true)) - .arg(Arg::new(options::FROM).takes_value(true)) + .arg( + Arg::new(options::TO) + .required(true) + .takes_value(true) + .value_hint(clap::ValueHint::AnyPath), + ) + .arg( + Arg::new(options::FROM) + .takes_value(true) + .value_hint(clap::ValueHint::AnyPath), + ) } diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index 0701387d9..4f69c8fb1 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -227,6 +227,7 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .min_values(1) + .value_hint(clap::ValueHint::AnyPath) ) } diff --git a/src/uu/rmdir/src/rmdir.rs b/src/uu/rmdir/src/rmdir.rs index 127b8fcf9..be4e53780 100644 --- a/src/uu/rmdir/src/rmdir.rs +++ b/src/uu/rmdir/src/rmdir.rs @@ -197,6 +197,7 @@ pub fn uu_app<'a>() -> Command<'a> { .takes_value(true) .min_values(1) .required(true) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::DirPath), ) } diff --git a/src/uu/runcon/src/runcon.rs b/src/uu/runcon/src/runcon.rs index 8c20319be..64df4f381 100644 --- a/src/uu/runcon/src/runcon.rs +++ b/src/uu/runcon/src/runcon.rs @@ -156,7 +156,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new("ARG") .multiple_occurrences(true) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::CommandName), ) // Once "ARG" is parsed, everything after that belongs to it. // diff --git a/src/uu/shred/src/shred.rs b/src/uu/shred/src/shred.rs index 05c8d1805..7f1c97c77 100644 --- a/src/uu/shred/src/shred.rs +++ b/src/uu/shred/src/shred.rs @@ -374,7 +374,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/shuf/src/shuf.rs b/src/uu/shuf/src/shuf.rs index 0b62ec84a..6369fc9b5 100644 --- a/src/uu/shuf/src/shuf.rs +++ b/src/uu/shuf/src/shuf.rs @@ -158,14 +158,16 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::OUTPUT) .takes_value(true) .value_name("FILE") - .help("write result to FILE instead of standard output"), + .help("write result to FILE instead of standard output") + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::RANDOM_SOURCE) .long(options::RANDOM_SOURCE) .takes_value(true) .value_name("FILE") - .help("get random bytes from FILE"), + .help("get random bytes from FILE") + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::REPEAT) @@ -179,7 +181,11 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::ZERO_TERMINATED) .help("line delimiter is NUL, not newline"), ) - .arg(Arg::new(options::FILE).takes_value(true)) + .arg( + Arg::new(options::FILE) + .takes_value(true) + .value_hint(clap::ValueHint::FilePath), + ) } fn read_input_file(filename: &str) -> UResult> { diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 141a7dd2c..15becdc6b 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -1397,7 +1397,8 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::OUTPUT) .help("write output to FILENAME instead of stdout") .takes_value(true) - .value_name("FILENAME"), + .value_name("FILENAME") + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::REVERSE) @@ -1461,13 +1462,15 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::TMP_DIR) .help("use DIR for temporaries, not $TMPDIR or /tmp") .takes_value(true) - .value_name("DIR"), + .value_name("DIR") + .value_hint(clap::ValueHint::DirPath), ) .arg( Arg::new(options::COMPRESS_PROG) .long(options::COMPRESS_PROG) .help("compress temporary files with PROG, decompress with PROG -d; PROG has to take input from stdin and output to stdout") - .value_name("PROG"), + .value_name("PROG") + .value_hint(clap::ValueHint::CommandName), ) .arg( Arg::new(options::BATCH_SIZE) @@ -1482,7 +1485,8 @@ pub fn uu_app<'a>() -> Command<'a> { .takes_value(true) .value_name("NUL_FILES") .multiple_occurrences(true) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::DEBUG) @@ -1493,7 +1497,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::FILES) .multiple_occurrences(true) .takes_value(true) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/split/src/split.rs b/src/uu/split/src/split.rs index c90c7a6b2..03905e877 100644 --- a/src/uu/split/src/split.rs +++ b/src/uu/split/src/split.rs @@ -111,9 +111,11 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(OPT_FILTER) .long(OPT_FILTER) .takes_value(true) + .value_name("COMMAND") + .value_hint(clap::ValueHint::CommandName) .help( - "write to shell COMMAND file name is $FILE (Currently not implemented for Windows)", - ), + "write to shell COMMAND; file name is $FILE (Currently not implemented for Windows)", + ), ) .arg( Arg::new(OPT_ELIDE_EMPTY_FILES) @@ -162,7 +164,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(ARG_INPUT) .takes_value(true) .default_value("-") - .index(1), + .index(1) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(ARG_PREFIX) diff --git a/src/uu/stat/src/stat.rs b/src/uu/stat/src/stat.rs index 41c9ae4a9..e261ab813 100644 --- a/src/uu/stat/src/stat.rs +++ b/src/uu/stat/src/stat.rs @@ -1043,6 +1043,7 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .allow_invalid_utf8(true) - .min_values(1), + .min_values(1) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/stdbuf/src/stdbuf.rs b/src/uu/stdbuf/src/stdbuf.rs index 816c86717..e0025d9f1 100644 --- a/src/uu/stdbuf/src/stdbuf.rs +++ b/src/uu/stdbuf/src/stdbuf.rs @@ -232,6 +232,7 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .hide(true) - .required(true), + .required(true) + .value_hint(clap::ValueHint::CommandName), ) } diff --git a/src/uu/sum/src/sum.rs b/src/uu/sum/src/sum.rs index 501635910..9280fcf81 100644 --- a/src/uu/sum/src/sum.rs +++ b/src/uu/sum/src/sum.rs @@ -150,7 +150,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .multiple_occurrences(true) - .hide(true), + .hide(true) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::BSD_COMPATIBLE) diff --git a/src/uu/sync/src/sync.rs b/src/uu/sync/src/sync.rs index 9baf9b182..6f34c11b7 100644 --- a/src/uu/sync/src/sync.rs +++ b/src/uu/sync/src/sync.rs @@ -217,7 +217,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(ARG_FILES) .multiple_occurrences(true) - .takes_value(true), + .takes_value(true) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/tac/src/tac.rs b/src/uu/tac/src/tac.rs index 3151b97e2..62d578ee9 100644 --- a/src/uu/tac/src/tac.rs +++ b/src/uu/tac/src/tac.rs @@ -91,7 +91,8 @@ pub fn uu_app<'a>() -> Command<'a> { .arg( Arg::new(options::FILE) .hide(true) - .multiple_occurrences(true), + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 96b6daf79..8f5a62e61 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -351,7 +351,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::ARG_FILES) .multiple_occurrences(true) .takes_value(true) - .min_values(1), + .min_values(1) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/tee/src/tee.rs b/src/uu/tee/src/tee.rs index d9c2e78f1..7b6b66208 100644 --- a/src/uu/tee/src/tee.rs +++ b/src/uu/tee/src/tee.rs @@ -74,7 +74,11 @@ pub fn uu_app<'a>() -> Command<'a> { .short('i') .help("ignore interrupt signals (ignored on non-Unix platforms)"), ) - .arg(Arg::new(options::FILE).multiple_occurrences(true)) + .arg( + Arg::new(options::FILE) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath), + ) } #[cfg(unix)] diff --git a/src/uu/timeout/src/timeout.rs b/src/uu/timeout/src/timeout.rs index 8374c124c..baafce4df 100644 --- a/src/uu/timeout/src/timeout.rs +++ b/src/uu/timeout/src/timeout.rs @@ -170,6 +170,7 @@ pub fn uu_app<'a>() -> Command<'a> { .index(2) .required(true) .multiple_occurrences(true) + .value_hint(clap::ValueHint::CommandName) ) .trailing_var_arg(true) .infer_long_args(true) diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index f71eb81d0..c250953bc 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -219,7 +219,8 @@ pub fn uu_app<'a>() -> Command<'a> { .long(options::sources::REFERENCE) .help("use this file's times instead of the current time") .value_name("FILE") - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::AnyPath), ) .arg( Arg::new(options::TIME) @@ -238,7 +239,8 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .min_values(1) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::AnyPath), ) .group(ArgGroup::new(options::SOURCES).args(&[ options::sources::CURRENT, diff --git a/src/uu/truncate/src/truncate.rs b/src/uu/truncate/src/truncate.rs index 6c9d8197b..b3110dcc1 100644 --- a/src/uu/truncate/src/truncate.rs +++ b/src/uu/truncate/src/truncate.rs @@ -162,6 +162,7 @@ pub fn uu_app<'a>() -> Command<'a> { .required_unless_present(options::SIZE) .help("base the size of each file on the size of RFILE") .value_name("RFILE") + .value_hint(clap::ValueHint::FilePath) ) .arg( Arg::new(options::SIZE) @@ -176,7 +177,8 @@ pub fn uu_app<'a>() -> Command<'a> { .multiple_occurrences(true) .takes_value(true) .required(true) - .min_values(1)) + .min_values(1) + .value_hint(clap::ValueHint::FilePath)) } /// Truncate the named file to the specified size. diff --git a/src/uu/tsort/src/tsort.rs b/src/uu/tsort/src/tsort.rs index aecd492fe..72b8843e5 100644 --- a/src/uu/tsort/src/tsort.rs +++ b/src/uu/tsort/src/tsort.rs @@ -99,7 +99,12 @@ pub fn uu_app<'a>() -> Command<'a> { .override_usage(format_usage(USAGE)) .about(SUMMARY) .infer_long_args(true) - .arg(Arg::new(options::FILE).default_value("-").hide(true)) + .arg( + Arg::new(options::FILE) + .default_value("-") + .hide(true) + .value_hint(clap::ValueHint::FilePath), + ) } // We use String as a representation of node here diff --git a/src/uu/unexpand/src/unexpand.rs b/src/uu/unexpand/src/unexpand.rs index 70a763f3b..0ebfea613 100644 --- a/src/uu/unexpand/src/unexpand.rs +++ b/src/uu/unexpand/src/unexpand.rs @@ -109,7 +109,12 @@ pub fn uu_app<'a>() -> Command<'a> { .override_usage(format_usage(USAGE)) .about(SUMMARY) .infer_long_args(true) - .arg(Arg::new(options::FILE).hide(true).multiple_occurrences(true)) + .arg( + Arg::new(options::FILE) + .hide(true) + .multiple_occurrences(true) + .value_hint(clap::ValueHint::FilePath) + ) .arg( Arg::new(options::ALL) .short('a') diff --git a/src/uu/uniq/src/uniq.rs b/src/uu/uniq/src/uniq.rs index 32e0783ce..e71c21303 100644 --- a/src/uu/uniq/src/uniq.rs +++ b/src/uu/uniq/src/uniq.rs @@ -392,7 +392,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(ARG_FILES) .multiple_occurrences(true) .takes_value(true) - .max_values(2), + .max_values(2) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/unlink/src/unlink.rs b/src/uu/unlink/src/unlink.rs index fc72b4623..890935f1a 100644 --- a/src/uu/unlink/src/unlink.rs +++ b/src/uu/unlink/src/unlink.rs @@ -36,6 +36,7 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(OPT_PATH) .required(true) .hide(true) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::AnyPath), ) } diff --git a/src/uu/users/src/users.rs b/src/uu/users/src/users.rs index 79fac3b68..b1785d608 100644 --- a/src/uu/users/src/users.rs +++ b/src/uu/users/src/users.rs @@ -64,5 +64,10 @@ pub fn uu_app<'a>() -> Command<'a> { .about(ABOUT) .override_usage(format_usage(USAGE)) .infer_long_args(true) - .arg(Arg::new(ARG_FILES).takes_value(true).max_values(1)) + .arg( + Arg::new(ARG_FILES) + .takes_value(true) + .max_values(1) + .value_hint(clap::ValueHint::FilePath), + ) } diff --git a/src/uu/wc/src/wc.rs b/src/uu/wc/src/wc.rs index 968830c48..ba7c4c1af 100644 --- a/src/uu/wc/src/wc.rs +++ b/src/uu/wc/src/wc.rs @@ -210,7 +210,8 @@ pub fn uu_app<'a>() -> Command<'a> { "read input from the files specified by NUL-terminated names in file F; If F is - then read names from standard input", - ), + ) + .value_hint(clap::ValueHint::FilePath), ) .arg( Arg::new(options::LINES) @@ -234,7 +235,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(ARG_FILES) .multiple_occurrences(true) .takes_value(true) - .allow_invalid_utf8(true), + .allow_invalid_utf8(true) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uu/who/src/who.rs b/src/uu/who/src/who.rs index 47d96a381..6c07039d2 100644 --- a/src/uu/who/src/who.rs +++ b/src/uu/who/src/who.rs @@ -250,7 +250,8 @@ pub fn uu_app<'a>() -> Command<'a> { Arg::new(options::FILE) .takes_value(true) .min_values(1) - .max_values(2), + .max_values(2) + .value_hint(clap::ValueHint::FilePath), ) } diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs index d8e345313..df37e5a69 100644 --- a/src/uucore/src/lib/features/perms.rs +++ b/src/uucore/src/lib/features/perms.rs @@ -456,6 +456,7 @@ pub fn chown_base<'a>( command = command.arg( Arg::new(options::ARG_FILES) .value_name(options::ARG_FILES) + .value_hint(clap::ValueHint::FilePath) .multiple_occurrences(true) .takes_value(true) .required(true) From 996a84cb6f298b9a35f5a5d0ec40f73a8789a205 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 12 May 2022 09:09:10 +0200 Subject: [PATCH 111/111] df: round up values if block size is specified Fixes #3479 --- src/uu/df/src/table.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/uu/df/src/table.rs b/src/uu/df/src/table.rs index a9a37cfeb..fac2ca663 100644 --- a/src/uu/df/src/table.rs +++ b/src/uu/df/src/table.rs @@ -233,7 +233,7 @@ impl<'a> RowFormatter<'a> { SizeFormat::HumanReadable(h) => self.scaled_human_readable(size, h), SizeFormat::StaticBlockSize => { let BlockSize::Bytes(d) = self.options.block_size; - (size / d).to_string() + (size as f64 / d as f64).ceil().to_string() } } } @@ -793,4 +793,28 @@ mod tests { let fmt = RowFormatter::new(&row, &options); assert_eq!(fmt.get_values(), vec!("26%")); } + + #[test] + fn test_row_formatter_with_round_up_byte_values() { + fn get_formatted_values(bytes: u64, bytes_used: u64, bytes_avail: u64) -> Vec { + let options = Options { + block_size: BlockSize::Bytes(1000), + columns: vec![Column::Size, Column::Used, Column::Avail], + ..Default::default() + }; + + let row = Row { + bytes, + bytes_used, + bytes_avail, + ..Default::default() + }; + RowFormatter::new(&row, &options).get_values() + } + + assert_eq!(get_formatted_values(100, 100, 0), vec!("1", "1", "0")); + assert_eq!(get_formatted_values(100, 99, 1), vec!("1", "1", "1")); + assert_eq!(get_formatted_values(1000, 1000, 0), vec!("1", "1", "0")); + assert_eq!(get_formatted_values(1001, 1000, 1), vec!("2", "1", "1")); + } }