From 94fbe1edef0c4ac9719340b10d0ce5c5e135aa7d Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 19 Sep 2021 11:25:00 +0200 Subject: [PATCH 01/17] `chroot`: quick fix for #2687 * fixes #2687 * change error message to better mimic GNU --- src/uu/chroot/src/chroot.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/uu/chroot/src/chroot.rs b/src/uu/chroot/src/chroot.rs index 40799d009..c78172025 100644 --- a/src/uu/chroot/src/chroot.rs +++ b/src/uu/chroot/src/chroot.rs @@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { // TODO: refactor the args and command matching // See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967 let command: Vec<&str> = match commands.len() { - 1 => { + 0 => { let shell: &str = match user_shell { Err(_) => default_shell, Ok(ref s) => s.as_ref(), @@ -79,10 +79,22 @@ pub fn uumain(args: impl uucore::Args) -> i32 { set_context(newroot, &matches); + assert!(!command.is_empty()); let pstatus = Command::new(command[0]) .args(&command[1..]) .status() - .unwrap_or_else(|e| crash!(1, "Cannot exec: {}", e)); + .unwrap_or_else(|e| { + // TODO: Exit status: + // 125 if chroot itself fails + // 126 if command is found but cannot be invoked + // 127 if command cannot be found + crash!( + 1, + "failed to run command {}: {}", + command[0].to_string().quote(), + e + ) + }); if pstatus.success() { 0 From 8db8d8ac4ec6eea0109fa5c584991e0823025144 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 19 Sep 2021 22:21:29 +0200 Subject: [PATCH 02/17] chroot: add 'test_default_shell` --- tests/by-util/test_chroot.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/by-util/test_chroot.rs b/tests/by-util/test_chroot.rs index 65d821d01..361133ccb 100644 --- a/tests/by-util/test_chroot.rs +++ b/tests/by-util/test_chroot.rs @@ -89,3 +89,24 @@ fn test_preference_of_userspec() { println!("result.stdout = {}", result.stdout_str()); println!("result.stderr = {}", result.stderr_str()); } + +#[test] +fn test_default_shell() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + let dir = "CHROOT_DIR"; + at.mkdir(dir); + + let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string()); + let expected = format!( + "chroot: failed to run command '{}': No such file or directory", + shell + ); + + if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) { + result.stderr_contains(expected); + } else { + print!("TEST SKIPPED"); + } +} From 8c0b7d1314f15bb2caec618073e7a07b0b229505 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 22 Sep 2021 11:59:43 +0200 Subject: [PATCH 03/17] chroot: move logic so it can be triggered by tests * move the command building logic before the `chroot` syscall so it will be reachable by tests that don't have root permissions. --- src/uu/chroot/src/chroot.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/uu/chroot/src/chroot.rs b/src/uu/chroot/src/chroot.rs index c78172025..55097c1bb 100644 --- a/src/uu/chroot/src/chroot.rs +++ b/src/uu/chroot/src/chroot.rs @@ -77,11 +77,15 @@ pub fn uumain(args: impl uucore::Args) -> i32 { _ => commands, }; + assert!(!command.is_empty()); + let chroot_command = command[0]; + let chroot_args = &command[1..]; + + // NOTE: Tests can only trigger code beyond this point if they're invoked with root permissions set_context(newroot, &matches); - assert!(!command.is_empty()); - let pstatus = Command::new(command[0]) - .args(&command[1..]) + let pstatus = Command::new(chroot_command) + .args(chroot_args) .status() .unwrap_or_else(|e| { // TODO: Exit status: From 30c8a4378893d52161b3f9fbea244fdcd54df52a Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 22 Sep 2021 12:03:22 +0200 Subject: [PATCH 04/17] test_chroot: add comments --- tests/by-util/test_chroot.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/by-util/test_chroot.rs b/tests/by-util/test_chroot.rs index 361133ccb..3e5c22679 100644 --- a/tests/by-util/test_chroot.rs +++ b/tests/by-util/test_chroot.rs @@ -15,6 +15,7 @@ fn test_missing_operand() { #[test] fn test_enter_chroot_fails() { + // NOTE: since #2689 this test also ensures that we don't regress #2687 let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("jail"); @@ -92,6 +93,7 @@ fn test_preference_of_userspec() { #[test] fn test_default_shell() { + // NOTE: This test intends to trigger code which can only be reached with root permissions. let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -99,14 +101,15 @@ fn test_default_shell() { at.mkdir(dir); let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string()); - let expected = format!( + let _expected = format!( "chroot: failed to run command '{}': No such file or directory", shell ); - if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) { - result.stderr_contains(expected); - } else { - print!("TEST SKIPPED"); - } + // TODO: [2021-09; jhscheer] uncomment if/when #2692 gets merged + // if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) { + // result.stderr_contains(expected); + // } else { + // print!("TEST SKIPPED"); + // } } From 4ff5fea502a87c7334d5d954d47c1a1def4e48af Mon Sep 17 00:00:00 2001 From: vulppine Date: Fri, 1 Oct 2021 14:58:26 -0700 Subject: [PATCH 05/17] cp: uumain returns UResult, UError for Error --- src/uu/cp/src/cp.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index cd33f9fa6..97a196dc1 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -49,6 +49,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, UError, UResult}; use uucore::fs::{canonicalize, MissingHandling, ResolveMode}; use walkdir::WalkDir; @@ -105,6 +106,12 @@ quick_error! { } } +impl UError for Error { + fn code(&self) -> i32 { + 1 + } +} + /// Continue next iteration of loop if result of expression is error macro_rules! or_continue( ($expr:expr) => (match $expr { @@ -220,7 +227,6 @@ pub struct Options { static ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY."; static LONG_HELP: &str = ""; -static EXIT_OK: i32 = 0; static EXIT_ERR: i32 = 1; fn usage() -> String { @@ -446,7 +452,7 @@ pub fn uu_app() -> App<'static, 'static> { .multiple(true)) } -pub fn uumain(args: impl uucore::Args) -> i32 { +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = usage(); let matches = uu_app() .after_help(&*format!( @@ -457,11 +463,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .usage(&usage[..]) .get_matches_from(args); - let options = crash_if_err!(EXIT_ERR, Options::from_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 1; + set_exit_code(EXIT_ERR); + return Ok(()); } let paths: Vec = matches @@ -469,7 +476,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .map(|v| v.map(ToString::to_string).collect()) .unwrap_or_default(); - let (sources, target) = crash_if_err!(EXIT_ERR, parse_path_args(&paths, &options)); + let (sources, target) = parse_path_args(&paths, &options)?; if let Err(error) = copy(&sources, &target, &options) { match error { @@ -479,10 +486,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { // Else we caught a fatal bubbled-up error, log it to stderr _ => show_error!("{}", error), }; - return EXIT_ERR; + set_exit_code(EXIT_ERR); } - EXIT_OK + Ok(()) } impl ClobberMode { @@ -1124,7 +1131,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu let xattrs = xattr::list(source)?; for attr in xattrs { if let Some(attr_value) = xattr::get(source, attr.clone())? { - crash_if_err!(EXIT_ERR, xattr::set(dest, attr, &attr_value[..])); + xattr::set(dest, attr, &attr_value[..])?; } } } From c64f09dc59897583d5cf7fac856b2daa69cc6089 Mon Sep 17 00:00:00 2001 From: vulppine Date: Fri, 1 Oct 2021 15:18:05 -0700 Subject: [PATCH 06/17] cp: Adds a needed macro, changes a return --- src/uu/cp/src/cp.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index 97a196dc1..b50bca905 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -49,7 +49,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, UError, UResult}; +use uucore::error::{set_exit_code, ExitCode, UError, UResult}; use uucore::fs::{canonicalize, MissingHandling, ResolveMode}; use walkdir::WalkDir; @@ -452,6 +452,7 @@ pub fn uu_app() -> App<'static, 'static> { .multiple(true)) } +#[uucore_procs::gen_uumain] pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = usage(); let matches = uu_app() @@ -467,8 +468,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup { show_usage_error!("options --backup and --no-clobber are mutually exclusive"); - set_exit_code(EXIT_ERR); - return Ok(()); + return Err(ExitCode(EXIT_ERR).into()); } let paths: Vec = matches From 4319248bb650bda453a17e8f2d30d6b922ed700d Mon Sep 17 00:00:00 2001 From: vulppine Date: Fri, 1 Oct 2021 16:45:19 -0700 Subject: [PATCH 07/17] cp: Changes '1' to 'EXIT_ERR' in UError impl --- src/uu/cp/src/cp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index b50bca905..518a2262c 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -108,7 +108,7 @@ quick_error! { impl UError for Error { fn code(&self) -> i32 { - 1 + EXIT_ERR } } From d5caa0d9d88c7d19cee46b0a4137397ffa7c5642 Mon Sep 17 00:00:00 2001 From: vulppine Date: Sat, 2 Oct 2021 08:15:25 -0700 Subject: [PATCH 08/17] seq: Adds hexadecimal integer parsing --- src/uu/seq/src/seq.rs | 76 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/src/uu/seq/src/seq.rs b/src/uu/seq/src/seq.rs index aac8f2280..594796641 100644 --- a/src/uu/seq/src/seq.rs +++ b/src/uu/seq/src/seq.rs @@ -88,30 +88,76 @@ impl FromStr for Number { if s.starts_with('+') { s = &s[1..]; } - - match s.parse::() { - Ok(n) => { - // If `s` is '-0', then `parse()` returns - // `BigInt::zero()`, but we need to return - // `Number::MinusZero` instead. - if n == BigInt::zero() && s.starts_with('-') { - Ok(Number::MinusZero) - } else { - Ok(Number::BigInt(n)) - } + let is_neg = s.starts_with('-'); + let is_hex = { + // GNU 20.11.2 - Parsing of Floats + match s.find("0x") { + Some(i) => (true, i), + None => match s.find("0X") { + Some(i) => (true, i), + None => (false, 0), + }, } - Err(_) => match s.parse::() { - Ok(value) if value.is_nan() => Err(format!( + }; + + match is_hex { + (true, i) => match i <= 1 { + false => Err(format!( + "invalid hexadecimal argument: {}\nTry '{} --help' for more information.", + s.quote(), + uucore::execution_phrase(), + )), + true => match &s.as_bytes()[i + 2] { + b'-' | b'+' => Err(format!( + "invalid hexadecimal argument: {}\nTry '{} --help' for more information.", + s.quote(), + uucore::execution_phrase(), + )), + // TODO: hexadecimal floating point parsing (see #2660) + b'.' => Err(format!( + "NotImplemented: hexadecimal floating point numbers: {}\nTry '{} --help' for more information.", + s.quote(), + uucore::execution_phrase(), + )), + _ => { + let num = BigInt::from_str_radix(&s[i + 2..], 16) + .map_err(|_| format!( + "invalid hexadecimal argument: {}\nTry '{} --help' for more information.", + s.quote(), + uucore::execution_phrase(), + ))?; + match (is_neg, num == BigInt::zero()) { + (true, true) => Ok(Number::MinusZero), + (true, false) => Ok(Number::BigInt(-num)), + (false, _) => Ok(Number::BigInt(num)), + } + } + }, + }, + (false, _) => match s.parse::() { + Ok(n) => { + // If `s` is '-0', then `parse()` returns + // `BigInt::zero()`, but we need to return + // `Number::MinusZero` instead. + if n == BigInt::zero() && is_neg { + Ok(Number::MinusZero) + } else { + Ok(Number::BigInt(n)) + } + } + Err(_) => match s.parse::() { + Ok(value) if value.is_nan() => Err(format!( "invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.", s.quote(), uucore::execution_phrase(), )), - Ok(value) => Ok(Number::F64(value)), - Err(_) => Err(format!( + Ok(value) => Ok(Number::F64(value)), + Err(_) => Err(format!( "invalid floating point argument: {}\nTry '{} --help' for more information.", s.quote(), uucore::execution_phrase(), )), + }, }, } } From aad0682a404814a03d47efb8bcb88c7b14f8bcdb Mon Sep 17 00:00:00 2001 From: vulppine Date: Sat, 2 Oct 2021 08:46:09 -0700 Subject: [PATCH 09/17] seq: Adds testing for hexadecimal integer parsing --- tests/by-util/test_seq.rs | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 27b5f99bc..2d2ea5344 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -1,6 +1,46 @@ use crate::common::util::*; use std::io::Read; +#[test] +fn test_hex_rejects_posneg_after_identifier() { + new_ucmd!() + .args(&["0x-123ABC"]) + .fails() + .no_stdout() + .stderr_contains("invalid hexadecimal argument: '0x-123ABC'") + .stderr_contains("for more information."); + new_ucmd!() + .args(&["0x+123ABC"]) + .fails() + .no_stdout() + .stderr_contains("invalid hexadecimal argument: '0x+123ABC'") + .stderr_contains("for more information."); + new_ucmd!() + .args(&["-0x-123ABC"]) + .fails() + .no_stdout() + .stderr_contains("invalid hexadecimal argument: '-0x-123ABC'") + .stderr_contains("for more information."); + new_ucmd!() + .args(&["-0x+123ABC"]) + .fails() + .no_stdout() + .stderr_contains("invalid hexadecimal argument: '-0x+123ABC'") + .stderr_contains("for more information."); +} + +#[test] +fn test_hex_lowercase_uppercase() { + new_ucmd!() + .args(&["0xa", "0xA"]) + .succeeds() + .stdout_is("10\n"); + new_ucmd!() + .args(&["0Xa", "0XA"]) + .succeeds() + .stdout_is("10\n"); +} + #[test] fn test_rejects_nan() { let ts = TestScenario::new(util_name!()); From 4e1f945e86e99e350f3f3e12db8057d19401acc2 Mon Sep 17 00:00:00 2001 From: vulppine Date: Sun, 3 Oct 2021 09:50:49 -0700 Subject: [PATCH 10/17] seq: Adds testing for large hex numbers --- tests/by-util/test_seq.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 2d2ea5344..7136f5e76 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -2,7 +2,7 @@ use crate::common::util::*; use std::io::Read; #[test] -fn test_hex_rejects_posneg_after_identifier() { +fn test_hex_rejects_sign_after_identifier() { new_ucmd!() .args(&["0x-123ABC"]) .fails() @@ -41,6 +41,19 @@ fn test_hex_lowercase_uppercase() { .stdout_is("10\n"); } +#[test] +fn test_hex_big_number() { + new_ucmd!() + .args(&[ + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "0x100000000000000000000000000000000", + ]) + .succeeds() + .stdout_is( + "340282366920938463463374607431768211455\n340282366920938463463374607431768211456\n", + ); +} + #[test] fn test_rejects_nan() { let ts = TestScenario::new(util_name!()); From 00c9710206a35eaf8c96b6361c2980c14697c784 Mon Sep 17 00:00:00 2001 From: Thomas Queiroz Date: Sun, 3 Oct 2021 23:57:33 -0300 Subject: [PATCH 11/17] uucore_procs+uu: specify uucore::show_error This allows crates to use `#[uucore_procs::gen_uumain]` without `use uucore::show_error` or #[macro_use] extern crate uucore; Removed unecessary usage --- src/uu/arch/src/arch.rs | 3 --- src/uu/base32/src/base32.rs | 3 --- src/uu/base64/src/base64.rs | 3 --- src/uu/basenc/src/basenc.rs | 3 --- src/uu/cat/src/cat.rs | 2 -- src/uu/chgrp/src/chgrp.rs | 2 -- src/uu/chown/src/chown.rs | 2 -- src/uu/df/src/df.rs | 2 -- src/uu/dirname/src/dirname.rs | 3 --- src/uu/echo/src/echo.rs | 3 --- src/uu/expr/src/expr.rs | 3 --- src/uu/false/src/false.rs | 3 --- src/uu/hostid/src/hostid.rs | 3 --- src/uu/hostname/src/hostname.rs | 3 --- src/uu/mktemp/src/mktemp.rs | 3 --- src/uu/pwd/src/pwd.rs | 3 --- src/uu/sleep/src/sleep.rs | 3 --- src/uu/true/src/true.rs | 3 --- src/uu/unlink/src/unlink.rs | 3 --- src/uu/uptime/src/uptime.rs | 2 -- src/uu/whoami/src/whoami.rs | 2 -- src/uu/yes/src/yes.rs | 2 -- src/uucore_procs/src/lib.rs | 2 +- 23 files changed, 1 insertion(+), 60 deletions(-) diff --git a/src/uu/arch/src/arch.rs b/src/uu/arch/src/arch.rs index 478fef6f1..d23a11cc8 100644 --- a/src/uu/arch/src/arch.rs +++ b/src/uu/arch/src/arch.rs @@ -6,9 +6,6 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use platform_info::*; use clap::{crate_version, App}; diff --git a/src/uu/base32/src/base32.rs b/src/uu/base32/src/base32.rs index 0159ef181..f4b4b49de 100644 --- a/src/uu/base32/src/base32.rs +++ b/src/uu/base32/src/base32.rs @@ -5,9 +5,6 @@ // For the full copyright and license information, please view the LICENSE file // that was distributed with this source code. -#[macro_use] -extern crate uucore; - use std::io::{stdin, Read}; use clap::App; diff --git a/src/uu/base64/src/base64.rs b/src/uu/base64/src/base64.rs index ed8b1b461..c041d6d69 100644 --- a/src/uu/base64/src/base64.rs +++ b/src/uu/base64/src/base64.rs @@ -6,9 +6,6 @@ // For the full copyright and license information, please view the LICENSE file // that was distributed with this source code. -#[macro_use] -extern crate uucore; - use uu_base32::base_common; pub use uu_base32::uu_app; diff --git a/src/uu/basenc/src/basenc.rs b/src/uu/basenc/src/basenc.rs index a730d3e0f..e4b24c351 100644 --- a/src/uu/basenc/src/basenc.rs +++ b/src/uu/basenc/src/basenc.rs @@ -8,9 +8,6 @@ //spell-checker:ignore (args) lsbf msbf -#[macro_use] -extern crate uucore; - use clap::{App, Arg}; use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR}; diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index baf8af6d5..308e11bfe 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -12,8 +12,6 @@ #[cfg(unix)] extern crate unix_socket; -#[macro_use] -extern crate uucore; // last synced with: cat (GNU coreutils) 8.13 use clap::{crate_version, App, Arg}; diff --git a/src/uu/chgrp/src/chgrp.rs b/src/uu/chgrp/src/chgrp.rs index 1795ad0d5..c70e5e5c7 100644 --- a/src/uu/chgrp/src/chgrp.rs +++ b/src/uu/chgrp/src/chgrp.rs @@ -7,8 +7,6 @@ // spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting -#[macro_use] -extern crate uucore; use uucore::display::Quotable; pub use uucore::entries; use uucore::error::{FromIo, UResult, USimpleError}; diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 1cd71d3f5..f24c4ec89 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -7,8 +7,6 @@ // spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname -#[macro_use] -extern crate uucore; use uucore::display::Quotable; pub use uucore::entries::{self, Group, Locate, Passwd}; use uucore::perms::{chown_base, options, IfFrom}; diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index 310d3c664..2f703542c 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -6,8 +6,6 @@ // For the full copyright and license information, please view the LICENSE file // that was distributed with this source code. -#[macro_use] -extern crate uucore; use uucore::error::UError; use uucore::error::UResult; #[cfg(unix)] diff --git a/src/uu/dirname/src/dirname.rs b/src/uu/dirname/src/dirname.rs index 601d93ac0..129c9369e 100644 --- a/src/uu/dirname/src/dirname.rs +++ b/src/uu/dirname/src/dirname.rs @@ -5,9 +5,6 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use std::path::Path; use uucore::display::print_verbatim; diff --git a/src/uu/echo/src/echo.rs b/src/uu/echo/src/echo.rs index 601fd8d48..a0e6c0d9c 100644 --- a/src/uu/echo/src/echo.rs +++ b/src/uu/echo/src/echo.rs @@ -6,9 +6,6 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use std::io::{self, Write}; use std::iter::Peekable; diff --git a/src/uu/expr/src/expr.rs b/src/uu/expr/src/expr.rs index eaf329bc5..6e2a8701a 100644 --- a/src/uu/expr/src/expr.rs +++ b/src/uu/expr/src/expr.rs @@ -5,9 +5,6 @@ //* For the full copyright and license information, please view the LICENSE //* file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use uucore::error::{UResult, USimpleError}; use uucore::InvalidEncodingHandling; diff --git a/src/uu/false/src/false.rs b/src/uu/false/src/false.rs index 88ec1af06..783c7fa0d 100644 --- a/src/uu/false/src/false.rs +++ b/src/uu/false/src/false.rs @@ -5,9 +5,6 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use clap::App; use uucore::error::UResult; diff --git a/src/uu/hostid/src/hostid.rs b/src/uu/hostid/src/hostid.rs index 4c9cafa35..309e15990 100644 --- a/src/uu/hostid/src/hostid.rs +++ b/src/uu/hostid/src/hostid.rs @@ -7,9 +7,6 @@ // spell-checker:ignore (ToDO) gethostid -#[macro_use] -extern crate uucore; - use clap::{crate_version, App}; use libc::c_long; use uucore::error::UResult; diff --git a/src/uu/hostname/src/hostname.rs b/src/uu/hostname/src/hostname.rs index 2de6627e8..9c8504027 100644 --- a/src/uu/hostname/src/hostname.rs +++ b/src/uu/hostname/src/hostname.rs @@ -7,9 +7,6 @@ // spell-checker:ignore (ToDO) MAKEWORD addrs hashset -#[macro_use] -extern crate uucore; - use std::collections::hash_set::HashSet; use std::net::ToSocketAddrs; use std::str; diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index 81a3521e9..4318f0ad6 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -8,9 +8,6 @@ // spell-checker:ignore (paths) GPGHome -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use uucore::display::{println_verbatim, Quotable}; use uucore::error::{FromIo, UError, UResult}; diff --git a/src/uu/pwd/src/pwd.rs b/src/uu/pwd/src/pwd.rs index 1138dba8e..8beb65dbd 100644 --- a/src/uu/pwd/src/pwd.rs +++ b/src/uu/pwd/src/pwd.rs @@ -5,9 +5,6 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use std::env; use std::io; diff --git a/src/uu/sleep/src/sleep.rs b/src/uu/sleep/src/sleep.rs index a70a524c4..80e8cd852 100644 --- a/src/uu/sleep/src/sleep.rs +++ b/src/uu/sleep/src/sleep.rs @@ -5,9 +5,6 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use std::thread; use std::time::Duration; diff --git a/src/uu/true/src/true.rs b/src/uu/true/src/true.rs index 6b4a87bf1..b5fbf7c9d 100644 --- a/src/uu/true/src/true.rs +++ b/src/uu/true/src/true.rs @@ -5,9 +5,6 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -#[macro_use] -extern crate uucore; - use clap::App; use uucore::error::UResult; diff --git a/src/uu/unlink/src/unlink.rs b/src/uu/unlink/src/unlink.rs index 1b4e4c998..58bb5442c 100644 --- a/src/uu/unlink/src/unlink.rs +++ b/src/uu/unlink/src/unlink.rs @@ -7,9 +7,6 @@ /* last synced with: unlink (GNU coreutils) 8.21 */ -#[macro_use] -extern crate uucore; - use std::fs::remove_file; use std::path::Path; diff --git a/src/uu/uptime/src/uptime.rs b/src/uu/uptime/src/uptime.rs index f649b96b6..eabcd1abf 100644 --- a/src/uu/uptime/src/uptime.rs +++ b/src/uu/uptime/src/uptime.rs @@ -11,8 +11,6 @@ use chrono::{Local, TimeZone, Utc}; use clap::{crate_version, App, Arg}; -#[macro_use] -extern crate uucore; // import crate time from utmpx pub use uucore::libc; use uucore::libc::time_t; diff --git a/src/uu/whoami/src/whoami.rs b/src/uu/whoami/src/whoami.rs index 830b86e63..0820588ee 100644 --- a/src/uu/whoami/src/whoami.rs +++ b/src/uu/whoami/src/whoami.rs @@ -9,8 +9,6 @@ #[macro_use] extern crate clap; -#[macro_use] -extern crate uucore; use clap::App; diff --git a/src/uu/yes/src/yes.rs b/src/uu/yes/src/yes.rs index 03ae4e415..bbedc0af1 100644 --- a/src/uu/yes/src/yes.rs +++ b/src/uu/yes/src/yes.rs @@ -12,8 +12,6 @@ use std::io::{self, Write}; #[macro_use] extern crate clap; -#[macro_use] -extern crate uucore; use clap::{App, Arg}; use uucore::error::{UResult, USimpleError}; diff --git a/src/uucore_procs/src/lib.rs b/src/uucore_procs/src/lib.rs index 092a4a66c..13b1dae3b 100644 --- a/src/uucore_procs/src/lib.rs +++ b/src/uucore_procs/src/lib.rs @@ -101,7 +101,7 @@ pub fn gen_uumain(_args: TokenStream, stream: TokenStream) -> TokenStream { Err(e) => { let s = format!("{}", e); if s != "" { - show_error!("{}", s); + uucore::show_error!("{}", s); } if e.usage() { eprintln!("Try '{} --help' for more information.", uucore::execution_phrase()); From e2fa6f9412a3f831c687267d9cc4f47ded80b739 Mon Sep 17 00:00:00 2001 From: Thomas Queiroz Date: Mon, 4 Oct 2021 00:04:33 -0300 Subject: [PATCH 12/17] users: use UResult --- src/uu/users/src/users.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/uu/users/src/users.rs b/src/uu/users/src/users.rs index d374df181..d0768d8d1 100644 --- a/src/uu/users/src/users.rs +++ b/src/uu/users/src/users.rs @@ -11,6 +11,7 @@ use std::path::Path; use clap::{crate_version, App, Arg}; +use uucore::error::UResult; use uucore::utmpx::{self, Utmpx}; static ABOUT: &str = "Print the user names of users currently logged in to the current host"; @@ -29,7 +30,8 @@ If FILE is not specified, use {}. /var/log/wtmp as FILE is common.", ) } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = usage(); let after_help = get_long_usage(); @@ -59,7 +61,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { println!("{}", users.join(" ")); } - 0 + Ok(()) } pub fn uu_app() -> App<'static, 'static> { From cddd40b4e1766a32d3f46f010e64dc07c2fb1fad Mon Sep 17 00:00:00 2001 From: vulppine Date: Tue, 5 Oct 2021 18:41:28 -0700 Subject: [PATCH 13/17] seq: Updates hex parse readability, adds hex test --- src/uu/seq/src/seq.rs | 29 +++++++++-------------------- tests/by-util/test_seq.rs | 10 ++++++++++ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/uu/seq/src/seq.rs b/src/uu/seq/src/seq.rs index 594796641..a76a23c4e 100644 --- a/src/uu/seq/src/seq.rs +++ b/src/uu/seq/src/seq.rs @@ -89,25 +89,9 @@ impl FromStr for Number { s = &s[1..]; } let is_neg = s.starts_with('-'); - let is_hex = { - // GNU 20.11.2 - Parsing of Floats - match s.find("0x") { - Some(i) => (true, i), - None => match s.find("0X") { - Some(i) => (true, i), - None => (false, 0), - }, - } - }; - match is_hex { - (true, i) => match i <= 1 { - false => Err(format!( - "invalid hexadecimal argument: {}\nTry '{} --help' for more information.", - s.quote(), - uucore::execution_phrase(), - )), - true => match &s.as_bytes()[i + 2] { + match s.to_lowercase().find("0x") { + Some(i) if i <= 1 => match &s.as_bytes()[i + 2] { b'-' | b'+' => Err(format!( "invalid hexadecimal argument: {}\nTry '{} --help' for more information.", s.quote(), @@ -133,8 +117,13 @@ impl FromStr for Number { } } }, - }, - (false, _) => match s.parse::() { + Some(_) => Err(format!( + "invalid hexadecimal argument: {}\nTry '{} --help' for more information.", + s.quote(), + uucore::execution_phrase(), + )), + + None => match s.parse::() { Ok(n) => { // If `s` is '-0', then `parse()` returns // `BigInt::zero()`, but we need to return diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 7136f5e76..6ed3cb67d 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -54,6 +54,16 @@ fn test_hex_big_number() { ); } +#[test] +fn test_hex_identifier_in_wrong_place() { + new_ucmd!() + .args(&["1234ABCD0x"]) + .fails() + .no_stdout() + .stderr_contains("invalid hexadecimal argument: '1234ABCD0x'") + .stderr_contains("for more information."); +} + #[test] fn test_rejects_nan() { let ts = TestScenario::new(util_name!()); From a9bfd5df0626168dd3bcbba20799182f48e4d19d Mon Sep 17 00:00:00 2001 From: Chad Brewbaker Date: Sat, 9 Oct 2021 23:01:05 -0500 Subject: [PATCH 14/17] Fix need for ssh keys Github now mandates git ssh keys instead of username/password. I modified the download instructions to remove the need for ssh authentication. --- util/build-gnu.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/build-gnu.sh b/util/build-gnu.sh index bbb16981e..eb8293fbe 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -5,12 +5,12 @@ set -e if test ! -d ../gnu; then echo "Could not find ../gnu" - echo "git clone git@github.com:coreutils/coreutils.git gnu" + echo "git clone https://github.com:coreutils/coreutils.git gnu" exit 1 fi if test ! -d ../gnulib; then echo "Could not find ../gnulib" - echo "git clone git@github.com:coreutils/gnulib.git gnulib" + echo "git clone https://github.com/coreutils/gnulib.git gnulib" exit 1 fi From 00de952592d97c1c717dfe769ab4d57473a1743a Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 10 Oct 2021 09:57:39 +0200 Subject: [PATCH 15/17] Fix various 'if_then_panic' clippy warnings --- tests/by-util/test_dd.rs | 8 ++--- tests/by-util/test_od.rs | 21 +++++++----- tests/common/util.rs | 72 ++++++++++++++++------------------------ 3 files changed, 42 insertions(+), 59 deletions(-) diff --git a/tests/by-util/test_dd.rs b/tests/by-util/test_dd.rs index 918be21f3..8340c7059 100644 --- a/tests/by-util/test_dd.rs +++ b/tests/by-util/test_dd.rs @@ -28,9 +28,7 @@ macro_rules! fixture_path { macro_rules! assert_fixture_exists { ($fname:expr) => {{ let fpath = fixture_path!($fname); - if !fpath.exists() { - panic!("Fixture missing: {:?}", fpath); - } + assert!(fpath.exists(), "Fixture missing: {:?}", fpath); }}; } @@ -38,9 +36,7 @@ macro_rules! assert_fixture_exists { macro_rules! assert_fixture_not_exists { ($fname:expr) => {{ let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname)); - if fpath.exists() { - panic!("Fixture present: {:?}", fpath); - } + assert!(!fpath.exists(), "Fixture present: {:?}", fpath); }}; } diff --git a/tests/by-util/test_od.rs b/tests/by-util/test_od.rs index 0fc1d5106..59a4bae60 100644 --- a/tests/by-util/test_od.rs +++ b/tests/by-util/test_od.rs @@ -35,9 +35,10 @@ fn test_file() { { let mut f = File::create(&file).unwrap(); // spell-checker:disable-next-line - if f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err() { - panic!("Test setup failed - could not write file"); - } + assert!( + !f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err(), + "Test setup failed - could not write file" + ); } new_ucmd!() @@ -75,9 +76,10 @@ fn test_2files() { // spell-checker:disable-next-line for &(path, data) in &[(&file1, "abcdefghijklmnop"), (&file2, "qrstuvwxyz\n")] { let mut f = File::create(&path).unwrap(); - if f.write_all(data.as_bytes()).is_err() { - panic!("Test setup failed - could not write file"); - } + assert!( + !f.write_all(data.as_bytes()).is_err(), + "Test setup failed - could not write file" + ); } new_ucmd!() @@ -126,9 +128,10 @@ fn test_from_mixed() { let (data1, data2, data3) = ("abcdefg", "hijklmnop", "qrstuvwxyz\n"); for &(path, data) in &[(&file1, data1), (&file3, data3)] { let mut f = File::create(&path).unwrap(); - if f.write_all(data.as_bytes()).is_err() { - panic!("Test setup failed - could not write file"); - } + assert!( + !f.write_all(data.as_bytes()).is_err(), + "Test setup failed - could not write file" + ); } new_ucmd!() diff --git a/tests/common/util.rs b/tests/common/util.rs index 8e9078e9c..61576a087 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -163,25 +163,23 @@ impl CmdResult { /// asserts that the command resulted in a success (zero) status code pub fn success(&self) -> &CmdResult { - if !self.success { - panic!( - "Command was expected to succeed.\nstdout = {}\n stderr = {}", - self.stdout_str(), - self.stderr_str() - ); - } + assert!( + self.success, + "Command was expected to succeed.\nstdout = {}\n stderr = {}", + self.stdout_str(), + self.stderr_str() + ); self } /// asserts that the command resulted in a failure (non-zero) status code pub fn failure(&self) -> &CmdResult { - if self.success { - panic!( - "Command was expected to fail.\nstdout = {}\n stderr = {}", - self.stdout_str(), - self.stderr_str() - ); - } + assert!( + !self.success, + "Command was expected to fail.\nstdout = {}\n stderr = {}", + self.stdout_str(), + self.stderr_str() + ); self } @@ -197,12 +195,11 @@ impl CmdResult { /// 1. you can not know exactly what stdout will be or /// 2. you know that stdout will also be empty pub fn no_stderr(&self) -> &CmdResult { - if !self.stderr.is_empty() { - panic!( - "Expected stderr to be empty, but it's:\n{}", - self.stderr_str() - ); - } + assert!( + self.stderr.is_empty(), + "Expected stderr to be empty, but it's:\n{}", + self.stderr_str() + ); self } @@ -213,12 +210,11 @@ impl CmdResult { /// 1. you can not know exactly what stderr will be or /// 2. you know that stderr will also be empty pub fn no_stdout(&self) -> &CmdResult { - if !self.stdout.is_empty() { - panic!( - "Expected stdout to be empty, but it's:\n{}", - self.stderr_str() - ); - } + assert!( + self.stdout.is_empty(), + "Expected stdout to be empty, but it's:\n{}", + self.stderr_str() + ); self } @@ -868,9 +864,7 @@ impl UCommand { /// Add a parameter to the invocation. Path arguments are treated relative /// to the test environment directory. pub fn arg>(&mut self, arg: S) -> &mut UCommand { - if self.has_run { - panic!("{}", ALREADY_RUN); - } + assert!(!self.has_run, ALREADY_RUN); self.comm_string.push(' '); self.comm_string .push_str(arg.as_ref().to_str().unwrap_or_default()); @@ -881,9 +875,7 @@ impl UCommand { /// Add multiple parameters to the invocation. Path arguments are treated relative /// to the test environment directory. pub fn args>(&mut self, args: &[S]) -> &mut UCommand { - if self.has_run { - panic!("{}", MULTIPLE_STDIN_MEANINGLESS); - } + assert!(!self.has_run, MULTIPLE_STDIN_MEANINGLESS); let strings = args .iter() .map(|s| s.as_ref().to_os_string()) @@ -901,9 +893,7 @@ impl UCommand { /// provides standard input to feed in to the command when spawned pub fn pipe_in>>(&mut self, input: T) -> &mut UCommand { - if self.bytes_into_stdin.is_some() { - panic!("{}", MULTIPLE_STDIN_MEANINGLESS); - } + assert!(!self.bytes_into_stdin.is_some(), MULTIPLE_STDIN_MEANINGLESS); self.bytes_into_stdin = Some(input.into()); self } @@ -918,9 +908,7 @@ impl UCommand { /// This is typically useful to test non-standard workflows /// like feeding something to a command that does not read it pub fn ignore_stdin_write_error(&mut self) -> &mut UCommand { - if self.bytes_into_stdin.is_none() { - panic!("{}", NO_STDIN_MEANINGLESS); - } + assert!(!self.bytes_into_stdin.is_none(), NO_STDIN_MEANINGLESS); self.ignore_stdin_write_error = true; self } @@ -930,9 +918,7 @@ impl UCommand { K: AsRef, V: AsRef, { - if self.has_run { - panic!("{}", ALREADY_RUN); - } + assert!(!self.has_run, ALREADY_RUN); self.raw.env(key, val); self } @@ -951,9 +937,7 @@ impl UCommand { /// Spawns the command, feeds the stdin if any, and returns the /// child process immediately. pub fn run_no_wait(&mut self) -> Child { - if self.has_run { - panic!("{}", ALREADY_RUN); - } + assert!(!self.has_run, ALREADY_RUN); self.has_run = true; log_info("run", &self.comm_string); let mut child = self From b4864d760eb51230b6b4517e93f76298bcaa0f58 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sun, 10 Oct 2021 11:33:46 +0200 Subject: [PATCH 16/17] pr: fix locking of stdout --- src/uu/pr/src/pr.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/uu/pr/src/pr.rs b/src/uu/pr/src/pr.rs index 45d9480a7..0886a9991 100644 --- a/src/uu/pr/src/pr.rs +++ b/src/uu/pr/src/pr.rs @@ -20,7 +20,7 @@ use quick_error::ResultExt; use regex::Regex; use std::convert::From; use std::fs::{metadata, File}; -use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Stdout, Write}; +use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Write}; #[cfg(unix)] use std::os::unix::fs::FileTypeExt; @@ -1036,15 +1036,16 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul let header = header_content(options, page); let trailer_content = trailer_content(options); - let out = &mut stdout(); - out.lock(); + let out = stdout(); + let mut out = out.lock(); + for x in header { out.write_all(x.as_bytes())?; out.write_all(line_separator)?; } - let lines_written = write_columns(lines, options, out)?; + let lines_written = write_columns(lines, options, &mut out)?; for (index, x) in trailer_content.iter().enumerate() { out.write_all(x.as_bytes())?; @@ -1060,7 +1061,7 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul fn write_columns( lines: &[FileLine], options: &OutputOptions, - out: &mut Stdout, + out: &mut impl Write, ) -> Result { let line_separator = options.content_line_separator.as_bytes(); From 51613c02eca5db5e935232b61b1a353e6f13966b Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 10 Oct 2021 10:10:46 +0200 Subject: [PATCH 17/17] add a word to ignore... --- tests/by-util/test_od.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/by-util/test_od.rs b/tests/by-util/test_od.rs index 59a4bae60..6c167b325 100644 --- a/tests/by-util/test_od.rs +++ b/tests/by-util/test_od.rs @@ -1,3 +1,4 @@ +// spell-checker:ignore abcdefghijklmnopqrstuvwxyz // * This file is part of the uutils coreutils package. // * // * For the full copyright and license information, please view the LICENSE