From fccab8a6910245f6e20c012dae3a200cb9432435 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 31 Jan 2022 13:47:09 +0000 Subject: [PATCH] hashsum: Refactor `uu_app` to isolate non-"GNU Coreutils" options Several binaries have been added to `hashsum` that have never been part of GNU Coreutils: - `sha3*sum` (uutils/coreutils#869) - `shake*sum` (uutils/coreutils#987) - `b3sum` (uutils/coreutils#3108 and uutils/coreutils#3164) In particular, the `--bits` option, and the `--no-names` option added in uutils/coreutils#3361, are not valid for any GNU Coreutils `*sum` binary (as of Coreutils 9.0). This commit refactors the argument parsing so that `--bits` and `--no-names` become invalid options for the binaries intended to match the GNU Coreutils API, instead of being ignored options. It also refactors the custom binary name handling to distinguish between binaries intended to match the GNU Coreutils API, and binaries that don't have that constraint. Part of uutils/coreutils#2930. --- build.rs | 12 +++-- src/uu/hashsum/src/hashsum.rs | 89 +++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/build.rs b/build.rs index 3df8d891d..734dfc350 100644 --- a/build.rs +++ b/build.rs @@ -104,21 +104,25 @@ pub fn main() { ); let map_value = format!("({krate}::uumain, {krate}::uu_app_common)", krate = krate); + let map_value_bits = + format!("({krate}::uumain, {krate}::uu_app_bits)", krate = krate); + let map_value_b3sum = + format!("({krate}::uumain, {krate}::uu_app_b3sum)", krate = krate); phf_map.entry("md5sum", &map_value); phf_map.entry("sha1sum", &map_value); phf_map.entry("sha224sum", &map_value); phf_map.entry("sha256sum", &map_value); phf_map.entry("sha384sum", &map_value); phf_map.entry("sha512sum", &map_value); - phf_map.entry("sha3sum", &map_value); + phf_map.entry("sha3sum", &map_value_bits); phf_map.entry("sha3-224sum", &map_value); phf_map.entry("sha3-256sum", &map_value); phf_map.entry("sha3-384sum", &map_value); phf_map.entry("sha3-512sum", &map_value); - phf_map.entry("shake128sum", &map_value); - phf_map.entry("shake256sum", &map_value); + phf_map.entry("shake128sum", &map_value_bits); + phf_map.entry("shake256sum", &map_value_bits); phf_map.entry("b2sum", &map_value); - phf_map.entry("b3sum", &map_value); + phf_map.entry("b3sum", &map_value_b3sum); tf.write_all( format!( "#[path=\"{dir}/test_{krate}.rs\"]\nmod test_{krate};\n", diff --git a/src/uu/hashsum/src/hashsum.rs b/src/uu/hashsum/src/hashsum.rs index 872cb5c21..5cb37a3b3 100644 --- a/src/uu/hashsum/src/hashsum.rs +++ b/src/uu/hashsum/src/hashsum.rs @@ -54,27 +54,6 @@ struct Options { output_bits: usize, } -fn is_custom_binary(program: &str) -> bool { - matches!( - program, - "md5sum" - | "sha1sum" - | "sha224sum" - | "sha256sum" - | "sha384sum" - | "sha512sum" - | "sha3sum" - | "sha3-224sum" - | "sha3-256sum" - | "sha3-384sum" - | "sha3-512sum" - | "shake128sum" - | "shake256sum" - | "b2sum" - | "b3sum" - ) -} - #[allow(clippy::cognitive_complexity)] fn detect_algo( program: &str, @@ -373,11 +352,6 @@ pub fn uu_app_common<'a>() -> Command<'a> { .long("tag") .help("create a BSD-style checksum"), ) - .arg( - Arg::new("no-names") - .long("no-names") - .help("Omits filenames in the output (option not present in GNU/Coreutils)"), - ) .arg( Arg::new("text") .short('t') @@ -408,16 +382,6 @@ pub fn uu_app_common<'a>() -> Command<'a> { .long("warn") .help("warn about improperly formatted checksum lines"), ) - // Needed for variable-length output sums (e.g. SHAKE) - .arg( - Arg::new("bits") - .long("bits") - .help("set the size of the output (only for SHAKE)") - .takes_value(true) - .value_name("BITS") - // XXX: should we actually use validators? they're not particularly efficient - .validator(is_valid_bit_num), - ) .arg( Arg::new("FILE") .index(1) @@ -428,8 +392,37 @@ pub fn uu_app_common<'a>() -> Command<'a> { ) } +pub fn uu_app_b3sum<'a>() -> Command<'a> { + uu_app_b3sum_opts(uu_app_common()) +} + +fn uu_app_b3sum_opts(command: Command) -> Command { + command.arg( + Arg::new("no-names") + .long("no-names") + .help("Omits filenames in the output (option not present in GNU/Coreutils)"), + ) +} + +pub fn uu_app_bits<'a>() -> Command<'a> { + uu_app_opt_bits(uu_app_common()) +} + +fn uu_app_opt_bits(command: Command) -> Command { + // Needed for variable-length output sums (e.g. SHAKE) + command.arg( + Arg::new("bits") + .long("bits") + .help("set the size of the output (only for SHAKE)") + .takes_value(true) + .value_name("BITS") + // XXX: should we actually use validators? they're not particularly efficient + .validator(is_valid_bit_num), + ) +} + pub fn uu_app_custom<'a>() -> Command<'a> { - let mut command = uu_app_common(); + let mut command = uu_app_b3sum_opts(uu_app_opt_bits(uu_app_common())); let algorithms = &[ ("md5", "work with MD5"), ("sha1", "work with SHA1"), @@ -463,10 +456,24 @@ pub fn uu_app_custom<'a>() -> Command<'a> { // hashsum is handled differently in build.rs, therefore this is not the same // as in other utilities. fn uu_app<'a>(binary_name: &str) -> Command<'a> { - if !is_custom_binary(binary_name) { - uu_app_custom() - } else { - uu_app_common() + match binary_name { + // These all support the same options. + "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" => { + uu_app_common() + } + // b2sum supports the md5sum options plus -l/--length. + "b2sum" => uu_app_common(), // TODO: Implement -l/--length + // These have never been part of GNU Coreutils, but can function with the same + // options as md5sum. + "sha3-224sum" | "sha3-256sum" | "sha3-384sum" | "sha3-512sum" => uu_app_common(), + // These have never been part of GNU Coreutils, and require an additional --bits + // option to specify their output size. + "sha3sum" | "shake128sum" | "shake256sum" => uu_app_bits(), + // b3sum has never been part of GNU Coreutils, and has a --no-names option in + // addition to the b2sum options. + "b3sum" => uu_app_b3sum(), + // We're probably just being called as `hashsum`, so give them everything. + _ => uu_app_custom(), } }