From 8f9ab453cde0f21e42574a2e55d16a6cb7ba866f Mon Sep 17 00:00:00 2001 From: oech3 <> Date: Fri, 2 Jan 2026 15:51:52 +0900 Subject: [PATCH 1/2] cksum: symlink to md5sum,b2sum, and sha*sum --- .github/workflows/CICD.yml | 8 +- .../cspell.dictionaries/jargon.wordlist.txt | 1 - .../workspace.wordlist.txt | 1 - Cargo.lock | 12 - Cargo.toml | 2 - GNUmakefile | 18 +- build.rs | 6 +- docs/compiles_table.csv | 2 +- docs/src/extensions.md | 7 - fuzz/fuzz_targets/fuzz_non_utf8_paths.rs | 7 - src/common/validation.rs | 6 +- src/uu/cksum/locales/en-US.ftl | 16 +- src/uu/cksum/locales/fr-FR.ftl | 14 +- src/uu/cksum/src/cksum.rs | 117 +- src/uu/hashsum/Cargo.toml | 32 - src/uu/hashsum/LICENSE | 1 - src/uu/hashsum/locales/en-US.ftl | 39 - src/uu/hashsum/locales/fr-FR.ftl | 37 - src/uu/hashsum/src/hashsum.rs | 422 ------ src/uu/hashsum/src/main.rs | 1 - .../src/lib/features/checksum/validate.rs | 1 - src/uucore/src/lib/lib.rs | 4 +- tests/by-util/test_hashsum.rs | 1230 ----------------- tests/fixtures/hashsum/b2sum.checkfile | 1 - tests/fixtures/hashsum/b2sum.expected | 1 - tests/fixtures/hashsum/b3sum.checkfile | 1 - tests/fixtures/hashsum/b3sum.expected | 1 - tests/fixtures/hashsum/binary.png | Bin 8055 -> 0 bytes .../fixtures/hashsum/binary.sha256.checkfile | 1 - tests/fixtures/hashsum/binary.sha256.expected | 1 - tests/fixtures/hashsum/input.txt | 1 - tests/fixtures/hashsum/md5.checkfile | 1 - tests/fixtures/hashsum/md5.expected | 1 - tests/fixtures/hashsum/sha1.checkfile | 1 - tests/fixtures/hashsum/sha1.expected | 1 - tests/fixtures/hashsum/sha224.checkfile | 1 - tests/fixtures/hashsum/sha224.expected | 1 - tests/fixtures/hashsum/sha256.checkfile | 1 - tests/fixtures/hashsum/sha256.expected | 1 - tests/fixtures/hashsum/sha384.checkfile | 1 - tests/fixtures/hashsum/sha384.expected | 1 - tests/fixtures/hashsum/sha3_224.checkfile | 1 - tests/fixtures/hashsum/sha3_224.expected | 1 - tests/fixtures/hashsum/sha3_256.checkfile | 1 - tests/fixtures/hashsum/sha3_256.expected | 1 - tests/fixtures/hashsum/sha3_384.checkfile | 1 - tests/fixtures/hashsum/sha3_384.expected | 1 - tests/fixtures/hashsum/sha3_512.checkfile | 1 - tests/fixtures/hashsum/sha3_512.expected | 1 - tests/fixtures/hashsum/sha512.checkfile | 1 - tests/fixtures/hashsum/sha512.expected | 1 - tests/fixtures/hashsum/shake128.checkfile | 1 - tests/fixtures/hashsum/shake128.expected | 1 - tests/fixtures/hashsum/shake256.checkfile | 1 - tests/fixtures/hashsum/shake256.expected | 1 - tests/fixtures/head/zero_terminated.txt | Bin 7605 -> 7209 bytes tests/fixtures/sort/zero-terminated.expected | Bin 907 -> 884 bytes .../sort/zero-terminated.expected.debug | 2 - tests/fixtures/sort/zero-terminated.txt | Bin 907 -> 884 bytes tests/test_localization_and_colors.rs | 27 - tests/tests.rs | 4 - util/build-gnu.sh | 2 +- util/show-utils.BAT | 4 +- util/show-utils.sh | 4 +- 64 files changed, 109 insertions(+), 1949 deletions(-) delete mode 100644 src/uu/hashsum/Cargo.toml delete mode 120000 src/uu/hashsum/LICENSE delete mode 100644 src/uu/hashsum/locales/en-US.ftl delete mode 100644 src/uu/hashsum/locales/fr-FR.ftl delete mode 100644 src/uu/hashsum/src/hashsum.rs delete mode 100644 src/uu/hashsum/src/main.rs delete mode 100644 tests/by-util/test_hashsum.rs delete mode 100644 tests/fixtures/hashsum/b2sum.checkfile delete mode 100644 tests/fixtures/hashsum/b2sum.expected delete mode 100644 tests/fixtures/hashsum/b3sum.checkfile delete mode 100644 tests/fixtures/hashsum/b3sum.expected delete mode 100644 tests/fixtures/hashsum/binary.png delete mode 100644 tests/fixtures/hashsum/binary.sha256.checkfile delete mode 100644 tests/fixtures/hashsum/binary.sha256.expected delete mode 100644 tests/fixtures/hashsum/input.txt delete mode 100644 tests/fixtures/hashsum/md5.checkfile delete mode 100644 tests/fixtures/hashsum/md5.expected delete mode 100644 tests/fixtures/hashsum/sha1.checkfile delete mode 100644 tests/fixtures/hashsum/sha1.expected delete mode 100644 tests/fixtures/hashsum/sha224.checkfile delete mode 100644 tests/fixtures/hashsum/sha224.expected delete mode 100644 tests/fixtures/hashsum/sha256.checkfile delete mode 100644 tests/fixtures/hashsum/sha256.expected delete mode 100644 tests/fixtures/hashsum/sha384.checkfile delete mode 100644 tests/fixtures/hashsum/sha384.expected delete mode 100644 tests/fixtures/hashsum/sha3_224.checkfile delete mode 100644 tests/fixtures/hashsum/sha3_224.expected delete mode 100644 tests/fixtures/hashsum/sha3_256.checkfile delete mode 100644 tests/fixtures/hashsum/sha3_256.expected delete mode 100644 tests/fixtures/hashsum/sha3_384.checkfile delete mode 100644 tests/fixtures/hashsum/sha3_384.expected delete mode 100644 tests/fixtures/hashsum/sha3_512.checkfile delete mode 100644 tests/fixtures/hashsum/sha3_512.expected delete mode 100644 tests/fixtures/hashsum/sha512.checkfile delete mode 100644 tests/fixtures/hashsum/sha512.expected delete mode 100644 tests/fixtures/hashsum/shake128.checkfile delete mode 100644 tests/fixtures/hashsum/shake128.expected delete mode 100644 tests/fixtures/hashsum/shake256.checkfile delete mode 100644 tests/fixtures/hashsum/shake256.expected diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index e6a7fd4509e..f47fd7412fe 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -287,7 +287,7 @@ jobs: mv -T target target.cache fi # Check that we don't cross-build uudoc - # also do not try to generate manpages for part of hashsum + # also do not try to generate manpages for part of cksum make install-manpages PREFIX=/tmp/usr UTILS=true RUSTC_ARCH="--target aarch64-unknown-linux-gnu" # build (host) make build @@ -352,8 +352,8 @@ jobs: set -x DESTDIR=/tmp/ make PROFILE=release MULTICALL=n install # Check that the utils are present - test -f /tmp/usr/local/bin/hashsum - # Check that hashsum symlinks are present + test -f /tmp/usr/local/bin/cksum + # Check that cksum symlinks are present test -h /tmp/usr/local/bin/b2sum test -h /tmp/usr/local/bin/md5sum test -h /tmp/usr/local/bin/sha1sum @@ -366,7 +366,7 @@ jobs: run: | set -x DESTDIR=/tmp/ make PROFILE=release MULTICALL=y LN="ln -svf" install - # Check that relative symlinks of hashsum are present + # Check that relative symlinks of cksum are present [ $(readlink /tmp/usr/local/bin/b2sum) = coreutils ] [ $(readlink /tmp/usr/local/bin/md5sum) = coreutils ] [ $(readlink /tmp/usr/local/bin/sha512sum) = coreutils ] diff --git a/.vscode/cspell.dictionaries/jargon.wordlist.txt b/.vscode/cspell.dictionaries/jargon.wordlist.txt index 9fa0b625aac..512837701aa 100644 --- a/.vscode/cspell.dictionaries/jargon.wordlist.txt +++ b/.vscode/cspell.dictionaries/jargon.wordlist.txt @@ -72,7 +72,6 @@ hardfloat hardlink hardlinks hasher -hashsums hwcaps infile iflag diff --git a/.vscode/cspell.dictionaries/workspace.wordlist.txt b/.vscode/cspell.dictionaries/workspace.wordlist.txt index f9c8d686bff..0e34563e8ee 100644 --- a/.vscode/cspell.dictionaries/workspace.wordlist.txt +++ b/.vscode/cspell.dictionaries/workspace.wordlist.txt @@ -101,7 +101,6 @@ chroot cksum csplit dircolors -hashsum hostid logname mkdir diff --git a/Cargo.lock b/Cargo.lock index e0c8bb88412..6b9821319c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -596,7 +596,6 @@ dependencies = [ "uu_fmt", "uu_fold", "uu_groups", - "uu_hashsum", "uu_head", "uu_hostid", "uu_hostname", @@ -3390,17 +3389,6 @@ dependencies = [ "uucore", ] -[[package]] -name = "uu_hashsum" -version = "0.5.0" -dependencies = [ - "clap", - "codspeed-divan-compat", - "fluent", - "tempfile", - "uucore", -] - [[package]] name = "uu_head" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 6d34d5c1efe..77ddce5bb65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,6 @@ feat_common_core = [ "false", "fmt", "fold", - "hashsum", "head", "join", "link", @@ -456,7 +455,6 @@ false = { optional = true, version = "0.5.0", package = "uu_false", path = "src/ fmt = { optional = true, version = "0.5.0", package = "uu_fmt", path = "src/uu/fmt" } fold = { optional = true, version = "0.5.0", package = "uu_fold", path = "src/uu/fold" } groups = { optional = true, version = "0.5.0", package = "uu_groups", path = "src/uu/groups" } -hashsum = { optional = true, version = "0.5.0", package = "uu_hashsum", path = "src/uu/hashsum" } head = { optional = true, version = "0.5.0", package = "uu_head", path = "src/uu/head" } hostid = { optional = true, version = "0.5.0", package = "uu_hostid", path = "src/uu/hostid" } hostname = { optional = true, version = "0.5.0", package = "uu_hostname", path = "src/uu/hostname" } diff --git a/GNUmakefile b/GNUmakefile index d3430e7e2e5..d73ff1de3f6 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -103,7 +103,6 @@ PROGS := \ false \ fmt \ fold \ - hashsum \ head \ hostname \ join \ @@ -184,7 +183,7 @@ SELINUX_PROGS := \ chcon \ runcon -HASHSUM_PROGS := \ +CKSUM_PROGS := \ b2sum \ md5sum \ sha1sum \ @@ -203,8 +202,8 @@ ifeq ($(SELINUX_ENABLED),1) endif UTILS ?= $(filter-out $(SKIP_UTILS),$(PROGS)) -ifneq ($(filter hashsum,$(UTILS)),hashsum) - HASHSUM_PROGS := +ifneq ($(filter cksum,$(UTILS)),cksum) + CKSUM_PROGS := endif ifneq ($(findstring stdbuf,$(UTILS)),) @@ -236,7 +235,6 @@ TEST_PROGS := \ factor \ false \ fold \ - hashsum \ head \ install \ link \ @@ -386,7 +384,7 @@ build-uudoc: install-manpages: build-uudoc mkdir -p $(DESTDIR)$(DATAROOTDIR)/man/man1 - $(foreach prog, $(INSTALLEES) $(HASHSUM_PROGS), \ + $(foreach prog, $(INSTALLEES) $(CKSUM_PROGS), \ $(BUILDDIR)/uudoc manpage $(prog) > $(DESTDIR)$(DATAROOTDIR)/man/man1/$(PROG_PREFIX)$(prog).1 $(newline) \ ) else @@ -399,7 +397,7 @@ install-completions: build-uudoc mkdir -p $(DESTDIR)$(DATAROOTDIR)/zsh/site-functions mkdir -p $(DESTDIR)$(DATAROOTDIR)/bash-completion/completions mkdir -p $(DESTDIR)$(DATAROOTDIR)/fish/vendor_completions.d - $(foreach prog, $(INSTALLEES) $(HASHSUM_PROGS) , \ + $(foreach prog, $(INSTALLEES) $(CKSUM_PROGS), \ $(BUILDDIR)/uudoc completion $(prog) zsh > $(DESTDIR)$(DATAROOTDIR)/zsh/site-functions/_$(PROG_PREFIX)$(prog) $(newline) \ $(BUILDDIR)/uudoc completion $(prog) bash > $(DESTDIR)$(DATAROOTDIR)/bash-completion/completions/$(PROG_PREFIX)$(prog).bash $(newline) \ $(BUILDDIR)/uudoc completion $(prog) fish > $(DESTDIR)$(DATAROOTDIR)/fish/vendor_completions.d/$(PROG_PREFIX)$(prog).fish $(newline) \ @@ -461,7 +459,7 @@ ifeq (${MULTICALL}, y) $(foreach prog, $(filter-out coreutils, $(INSTALLEES)), \ cd $(INSTALLDIR_BIN) && $(LN) $(PROG_PREFIX)coreutils $(PROG_PREFIX)$(prog) $(newline) \ ) - $(foreach prog, $(HASHSUM_PROGS), \ + $(foreach prog, $(CKSUM_PROGS), \ cd $(INSTALLDIR_BIN) && $(LN) $(PROG_PREFIX)coreutils $(PROG_PREFIX)$(prog) $(newline) \ ) $(if $(findstring test,$(INSTALLEES)), cd $(INSTALLDIR_BIN) && $(LN) $(PROG_PREFIX)coreutils $(PROG_PREFIX)[) @@ -469,8 +467,8 @@ else $(foreach prog, $(INSTALLEES), \ $(INSTALL) -m 755 $(BUILDDIR)/$(prog) $(INSTALLDIR_BIN)/$(PROG_PREFIX)$(prog) $(newline) \ ) - $(foreach prog, $(HASHSUM_PROGS), \ - cd $(INSTALLDIR_BIN) && $(LN) $(PROG_PREFIX)hashsum $(PROG_PREFIX)$(prog) $(newline) \ + $(foreach prog, $(CKSUM_PROGS), \ + cd $(INSTALLDIR_BIN) && $(LN) $(PROG_PREFIX)cksum $(PROG_PREFIX)$(prog) $(newline) \ ) $(if $(findstring test,$(INSTALLEES)), $(INSTALL) -m 755 $(BUILDDIR)/test $(INSTALLDIR_BIN)/$(PROG_PREFIX)[) endif diff --git a/build.rs b/build.rs index 9b35eac5eb4..6334e680fae 100644 --- a/build.rs +++ b/build.rs @@ -75,10 +75,10 @@ pub fn main() { "false" | "true" => { phf_map.entry(krate, format!("(r#{krate}::uumain, r#{krate}::uu_app)")); } - "hashsum" => { - phf_map.entry(krate, format!("({krate}::uumain, {krate}::uu_app_custom)")); + "cksum" => { + phf_map.entry(krate, format!("({krate}::uumain, {krate}::uu_app)")); - let map_value = format!("({krate}::uumain, {krate}::uu_app_common)"); + let map_value = format!("({krate}::uumain, {krate}::uu_app)"); phf_map.entry("md5sum", map_value.clone()); phf_map.entry("sha1sum", map_value.clone()); phf_map.entry("sha224sum", map_value.clone()); diff --git a/docs/compiles_table.csv b/docs/compiles_table.csv index e263067b78d..eb77d2844b0 100644 --- a/docs/compiles_table.csv +++ b/docs/compiles_table.csv @@ -1,4 +1,4 @@ -target,arch,base32,base64,basename,cat,chgrp,chmod,chown,chroot,cksum,comm,cp,csplit,cut,date,df,dircolors,dirname,du,echo,env,expand,expr,factor,false,fmt,fold,groups,hashsum,head,hostid,hostname,id,install,join,kill,link,ln,logname,ls,mkdir,mkfifo,mknod,mktemp,more,mv,nice,nl,nohup,nproc,numfmt,od,paste,pathchk,pinky,printenv,printf,ptx,pwd,readlink,realpath,rm,rmdir,seq,shred,shuf,sleep,sort,split,stat,stdbuf,sum,sync,tac,tail,tee,test,timeout,touch,tr,true,truncate,tsort,tty,uname,unexpand,uniq,unlink,uptime,users,wc,who,whoami,yes,chcon,pr,dir,vdir,dd,basenc,runcon +target,arch,base32,base64,basename,cat,chgrp,chmod,chown,chroot,cksum,comm,cp,csplit,cut,date,df,dircolors,dirname,du,echo,env,expand,expr,factor,false,fmt,fold,groups,head,hostid,hostname,id,install,join,kill,link,ln,logname,ls,mkdir,mkfifo,mknod,mktemp,more,mv,nice,nl,nohup,nproc,numfmt,od,paste,pathchk,pinky,printenv,printf,ptx,pwd,readlink,realpath,rm,rmdir,seq,shred,shuf,sleep,sort,split,stat,stdbuf,sum,sync,tac,tail,tee,test,timeout,touch,tr,true,truncate,tsort,tty,uname,unexpand,uniq,unlink,uptime,users,wc,who,whoami,yes,chcon,pr,dir,vdir,dd,basenc,runcon aarch64-unknown-linux-gnu,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 i686-unknown-linux-gnu,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 powerpc64-unknown-linux-gnu,0,0,0,0,0,0,0,0,0,0,0,101,0,0,0,0,0,0,0,0,0,0,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/docs/src/extensions.md b/docs/src/extensions.md index 80f89e060b5..88dd0d39800 100644 --- a/docs/src/extensions.md +++ b/docs/src/extensions.md @@ -47,13 +47,6 @@ packages. `rm` can display a progress bar when the `-g`/`--progress` flag is set. -## `hashsum` (deprecated) - -This utility does not exist in GNU coreutils. `hashsum` is a utility that -supports computing the checksums with several algorithms. The flags and options -are identical to the `*sum` family of utils (`sha1sum`, `sha256sum`, `b2sum`, -etc.). This utility will be removed in the future and it is advised to use `cksum --untagged` instead. - ## `more` We provide a simple implementation of `more`, which is not part of GNU diff --git a/fuzz/fuzz_targets/fuzz_non_utf8_paths.rs b/fuzz/fuzz_targets/fuzz_non_utf8_paths.rs index ac7480f3230..a9803956306 100644 --- a/fuzz/fuzz_targets/fuzz_non_utf8_paths.rs +++ b/fuzz/fuzz_targets/fuzz_non_utf8_paths.rs @@ -83,7 +83,6 @@ static PATH_PROGRAMS: &[&str] = &[ "vdir", "mkfifo", "mknod", - "hashsum", // File I/O utilities "dd", "sync", @@ -252,12 +251,6 @@ fn test_program_with_non_utf8_path(program: &str, path: &PathBuf) -> CommandResu OsString::from("bs=1"), OsString::from("count=1"), ], - // Hashsum needs algorithm - "hashsum" => vec![ - OsString::from(program), - OsString::from("--md5"), - path_os.to_owned(), - ], // Encoding/decoding programs "base32" | "base64" | "basenc" => vec![OsString::from(program), path_os.to_owned()], "df" => vec![OsString::from(program), path_os.to_owned()], diff --git a/src/common/validation.rs b/src/common/validation.rs index 057e8a9120d..5361a8d774c 100644 --- a/src/common/validation.rs +++ b/src/common/validation.rs @@ -50,9 +50,9 @@ fn get_canonical_util_name(util_name: &str) -> &str { // uu_test aliases - '[' is an alias for test "[" => "test", - // hashsum aliases - all these hash commands are aliases for hashsum + // cksum aliases - all these hash commands are aliases for cksum "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" | "b2sum" => { - "hashsum" + "cksum" } "dir" => "ls", // dir is an alias for ls @@ -98,7 +98,7 @@ mod tests { fn test_get_canonical_util_name() { // Test a few key aliases assert_eq!(get_canonical_util_name("["), "test"); - assert_eq!(get_canonical_util_name("md5sum"), "hashsum"); + assert_eq!(get_canonical_util_name("md5sum"), "cksum"); assert_eq!(get_canonical_util_name("dir"), "ls"); // Test passthrough case diff --git a/src/uu/cksum/locales/en-US.ftl b/src/uu/cksum/locales/en-US.ftl index 834cd77b0ef..2c29e7f31f4 100644 --- a/src/uu/cksum/locales/en-US.ftl +++ b/src/uu/cksum/locales/en-US.ftl @@ -1,22 +1,22 @@ -cksum-about = Print CRC and size for each file -cksum-usage = cksum [OPTIONS] [FILE]... +cksum-about = Print checksum and size for each file +cksum-usage = cksum (multicall-binary for *sum) [OPTIONS] [FILE]... cksum-after-help = DIGEST determines the digest algorithm and default output format: - sysv: (equivalent to sum -s) - bsd: (equivalent to sum -r) - - crc: (equivalent to cksum) + - crc: (default if binary name is cksum) - crc32b: (only available through cksum) - - md5: (equivalent to md5sum) - - sha1: (equivalent to sha1sum) - - sha2: (equivalent to sha{"{224,256,384,512}"}sum) + - md5: (binary name : md5sum) + - sha1: (binary name : sha1sum) + - sha2: (binary name : sha{"{224,256,384,512}"}sum) - sha3: (only available through cksum) - - blake2b: (equivalent to b2sum) + - blake2b: (binary name : b2sum) - sm3: (only available through cksum) # Help messages cksum-help-algorithm = select the digest type to use. See DIGEST below cksum-help-untagged = create a reversed style checksum, without digest type -cksum-help-tag = create a BSD style checksum, undo --untagged (default) +cksum-help-tag = create a BSD style checksum (default if binary name is cksum) cksum-help-length = digest length in bits; must not exceed the max for the blake2 algorithm and must be a multiple of 8 cksum-help-raw = emit a raw binary digest, not hexadecimal cksum-help-strict = exit non-zero for improperly formatted checksum lines diff --git a/src/uu/cksum/locales/fr-FR.ftl b/src/uu/cksum/locales/fr-FR.ftl index 01136f606f9..81cf976cdc1 100644 --- a/src/uu/cksum/locales/fr-FR.ftl +++ b/src/uu/cksum/locales/fr-FR.ftl @@ -1,22 +1,22 @@ -cksum-about = Afficher le CRC et la taille de chaque fichier -cksum-usage = cksum [OPTION]... [FICHIER]... +cksum-about = Afficher le ckecksum et la taille de chaque fichier +cksum-usage = cksum (multicall-binary for *sum) [OPTION]... [FICHIER]... cksum-after-help = DIGEST détermine l'algorithme de condensé et le format de sortie par défaut : - sysv : (équivalent à sum -s) - bsd : (équivalent à sum -r) - crc : (équivalent à cksum) - crc32b : (disponible uniquement via cksum) - - md5 : (équivalent à md5sum) - - sha1 : (équivalent à sha1sum) - - sha2: (équivalent à sha{"{224,256,384,512}"}sum) + - md5 : (binary name : md5sum) + - sha1 : (binary name : sha1sum) + - sha2: (binary name : sha{"{224,256,384,512}"}sum) - sha3 : (disponible uniquement via cksum) - - blake2b : (équivalent à b2sum) + - blake2b : (binary name : b2sum) - sm3 : (disponible uniquement via cksum) # Messages d'aide cksum-help-algorithm = sélectionner le type de condensé à utiliser. Voir DIGEST ci-dessous cksum-help-untagged = créer une somme de contrôle de style inversé, sans type de condensé -cksum-help-tag = créer une somme de contrôle de style BSD, annuler --untagged (par défaut) +cksum-help-tag = créer une somme de contrôle de style BSD (default if binary name is cksum) cksum-help-length = longueur du condensé en bits ; ne doit pas dépasser le maximum pour l'algorithme blake2 et doit être un multiple de 8 cksum-help-raw = émettre un condensé binaire brut, pas hexadécimal cksum-help-strict = sortir avec un code non-zéro pour les lignes de somme de contrôle mal formatées diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 30eabcaac56..d6f6f38b774 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -76,8 +76,9 @@ mod options { /// the untagged case. fn handle_tag_text_binary_flags>( args: impl Iterator, + binary_name: &str, ) -> UResult<(bool, bool)> { - let mut tag = true; + let mut tag = binary_name.ends_with("cksum"); let mut binary = false; let mut text = false; @@ -111,21 +112,18 @@ fn handle_tag_text_binary_flags>( } /// Sanitize the `--length` argument depending on `--algorithm` and `--length`. -fn maybe_sanitize_length( - algo_cli: Option, - input_length: Option<&str>, -) -> UResult> { +fn maybe_sanitize_length(algo_cli: AlgoKind, input_length: Option<&str>) -> UResult> { match (algo_cli, input_length) { // No provided length is not a problem so far. (_, None) => Ok(None), // For SHA2 and SHA3, if a length is provided, ensure it is correct. - (Some(algo @ (AlgoKind::Sha2 | AlgoKind::Sha3)), Some(s_len)) => { + (algo @ (AlgoKind::Sha2 | AlgoKind::Sha3), Some(s_len)) => { sanitize_sha2_sha3_length_str(algo, s_len).map(Some) } // For BLAKE2b, if a length is provided, validate it. - (Some(AlgoKind::Blake2b), Some(len)) => calculate_blake2b_length_str(len), + (AlgoKind::Blake2b, Some(len)) => calculate_blake2b_length_str(len), // For any other provided algorithm, check if length is 0. // Otherwise, this is an error. @@ -136,8 +134,8 @@ fn maybe_sanitize_length( #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { + let binary_name = uucore::util_name(); let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?; - let check = matches.get_flag(options::CHECK); let check_flag = |flag| match (check, matches.get_flag(flag)) { @@ -154,13 +152,28 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let strict = check_flag(options::STRICT)?; let status = check_flag(options::STATUS)?; - let algo_cli = matches - .get_one::(options::ALGORITHM) - .map(AlgoKind::from_cksum) - .transpose()?; + // Set default algo from binary name + let mut algo_cli = match binary_name { + s if s.ends_with("md5sum") => AlgoKind::Md5, + s if s.ends_with("sha1sum") => AlgoKind::Sha1, + s if s.ends_with("sha224sum") => AlgoKind::Sha224, + s if s.ends_with("sha256sum") => AlgoKind::Sha256, + s if s.ends_with("sha384sum") => AlgoKind::Sha384, + s if s.ends_with("sha512sum") => AlgoKind::Sha512, + s if s.ends_with("b2sum") => AlgoKind::Blake2b, + _ => AlgoKind::Crc, + }; + // cksum accepts -a + if binary_name.ends_with("cksum") { + if let Some(algo_str) = matches.get_one::(options::ALGORITHM) { + algo_cli = AlgoKind::from_cksum(algo_str)?; + } + } let input_length = matches - .get_one::(options::LENGTH) + .try_get_one::(options::LENGTH) + .ok() + .flatten() .map(String::as_str); let length = maybe_sanitize_length(algo_cli, input_length)?; @@ -174,7 +187,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if check { // cksum does not support '--check'ing legacy algorithms - if algo_cli.is_some_and(AlgoKind::is_legacy) { + let algo_specified = + !binary_name.ends_with("cksum") || matches.contains_id(options::ALGORITHM); + if algo_specified && algo_cli.is_legacy() { return Err(ChecksumError::AlgorithmNotSupportedWithCheck.into()); } @@ -194,8 +209,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { strict, verbose, }; - - return perform_checksum_validation(files, algo_cli, length, opts); + if algo_specified { + return perform_checksum_validation(files, Some(algo_cli), length, opts); + } + return perform_checksum_validation(files, None, length, opts); } // Not --check @@ -205,12 +222,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { print_cpu_debug_info(); } - // Set the default algorithm to CRC when not '--check'ing. - let algo_kind = algo_cli.unwrap_or(AlgoKind::Crc); + let (tag, binary) = handle_tag_text_binary_flags(std::env::args_os(), binary_name)?; - let (tag, binary) = handle_tag_text_binary_flags(std::env::args_os())?; - - let algo = SizedAlgoKind::from_unsized(algo_kind, length)?; + let algo = SizedAlgoKind::from_unsized(algo_cli, length)?; let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO)); let opts = ChecksumComputeOptions { @@ -231,9 +245,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } pub fn uu_app() -> Command { - Command::new(uucore::util_name()) + let binary_name = uucore::util_name(); + let mut app = Command::new(binary_name) .version(uucore::crate_version!()) - .help_template(uucore::localized_help_template(uucore::util_name())) + .help_template(uucore::localized_help_template(binary_name)) .about(translate!("cksum-about")) .override_usage(format_usage(&translate!("cksum-usage"))) .infer_long_args(true) @@ -245,34 +260,11 @@ pub fn uu_app() -> Command { .value_parser(ValueParser::os_string()) .value_hint(clap::ValueHint::FilePath), ) - .arg( - Arg::new(options::ALGORITHM) - .long(options::ALGORITHM) - .short('a') - .help(translate!("cksum-help-algorithm")) - .value_name("ALGORITHM") - .value_parser(SUPPORTED_ALGORITHMS), - ) - .arg( - Arg::new(options::UNTAGGED) - .long(options::UNTAGGED) - .help(translate!("cksum-help-untagged")) - .action(ArgAction::SetTrue) - .overrides_with(options::TAG), - ) .arg( Arg::new(options::TAG) .long(options::TAG) .help(translate!("cksum-help-tag")) - .action(ArgAction::SetTrue) - .overrides_with(options::UNTAGGED), - ) - .arg( - Arg::new(options::LENGTH) - .long(options::LENGTH) - .short('l') - .help(translate!("cksum-help-length")) - .action(ArgAction::Set), + .action(ArgAction::SetTrue), ) .arg( Arg::new(options::RAW) @@ -358,6 +350,33 @@ pub fn uu_app() -> Command { .long(options::DEBUG) .help(translate!("cksum-help-debug")) .action(ArgAction::SetTrue), - ) - .after_help(translate!("cksum-after-help")) + ); + if binary_name.ends_with("cksum") || binary_name.ends_with("b2sum") { + app = app.arg( + Arg::new(options::LENGTH) + .long(options::LENGTH) + .short('l') + .help(translate!("cksum-help-length")) + .action(ArgAction::Set), + ); + } + if binary_name.ends_with("cksum") { + app = app + .arg( + Arg::new(options::ALGORITHM) + .long(options::ALGORITHM) + .short('a') + .help(translate!("cksum-help-algorithm")) + .value_name("ALGORITHM") + .value_parser(SUPPORTED_ALGORITHMS), + ) + .arg( + Arg::new(options::UNTAGGED) + .long(options::UNTAGGED) + .help(translate!("cksum-help-untagged")) + .action(ArgAction::SetTrue) + .overrides_with(options::TAG), + ); + } + app.after_help(translate!("cksum-after-help")) } diff --git a/src/uu/hashsum/Cargo.toml b/src/uu/hashsum/Cargo.toml deleted file mode 100644 index f77c2c52d84..00000000000 --- a/src/uu/hashsum/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "uu_hashsum" -description = "hashsum ~ (uutils) display or check input digests" -repository = "https://github.com/uutils/coreutils/tree/main/src/uu/hashsum" -version.workspace = true -authors.workspace = true -license.workspace = true -homepage.workspace = true -keywords.workspace = true -categories.workspace = true -edition.workspace = true -readme.workspace = true - -[lints] -workspace = true - -[lib] -path = "src/hashsum.rs" - -[dependencies] -clap = { workspace = true } -uucore = { workspace = true, features = ["checksum", "encoding", "sum"] } -fluent = { workspace = true } - -[[bin]] -name = "hashsum" -path = "src/main.rs" - -[dev-dependencies] -divan = { workspace = true } -tempfile = { workspace = true } -uucore = { workspace = true, features = ["benchmark"] } diff --git a/src/uu/hashsum/LICENSE b/src/uu/hashsum/LICENSE deleted file mode 120000 index 5853aaea53b..00000000000 --- a/src/uu/hashsum/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/src/uu/hashsum/locales/en-US.ftl b/src/uu/hashsum/locales/en-US.ftl deleted file mode 100644 index c0a6a556748..00000000000 --- a/src/uu/hashsum/locales/en-US.ftl +++ /dev/null @@ -1,39 +0,0 @@ -hashsum-about = Compute and check message digests. -hashsum-usage = hashsum -- [OPTIONS]... [FILE]... - -# Utility-specific usage template -hashsum-usage-specific = {$utility_name} [OPTION]... [FILE]... - -# Help messages -hashsum-help-binary-windows = read or check in binary mode (default) -hashsum-help-binary-other = read in binary mode -hashsum-help-text-windows = read or check in text mode -hashsum-help-text-other = read in text mode (default) -hashsum-help-check = read hashsums from the FILEs and check them -hashsum-help-tag = create a BSD-style checksum -hashsum-help-quiet = don't print OK for each successfully verified file -hashsum-help-status = don't output anything, status code shows success -hashsum-help-strict = exit non-zero for improperly formatted checksum lines -hashsum-help-ignore-missing = don't fail or report status for missing files -hashsum-help-warn = warn about improperly formatted checksum lines -hashsum-help-zero = end each output line with NUL, not newline -hashsum-help-length = digest length in bits; must not exceed the max for the blake2 algorithm and must be a multiple of 8 -# Algorithm help messages -hashsum-help-md5 = work with MD5 -hashsum-help-sha1 = work with SHA1 -hashsum-help-sha224 = work with SHA224 -hashsum-help-sha256 = work with SHA256 -hashsum-help-sha384 = work with SHA384 -hashsum-help-sha512 = work with SHA512 -hashsum-help-sha3 = work with SHA3 -hashsum-help-sha3-224 = work with SHA3-224 -hashsum-help-sha3-256 = work with SHA3-256 -hashsum-help-sha3-384 = work with SHA3-384 -hashsum-help-sha3-512 = work with SHA3-512 -hashsum-help-shake128 = work with SHAKE128 using BITS for the output size -hashsum-help-shake256 = work with SHAKE256 using BITS for the output size -hashsum-help-b2sum = work with BLAKE2 -hashsum-help-b3sum = work with BLAKE3 - -# Error messages -hashsum-error-failed-to-read-input = failed to read input diff --git a/src/uu/hashsum/locales/fr-FR.ftl b/src/uu/hashsum/locales/fr-FR.ftl deleted file mode 100644 index 26c61fec9d3..00000000000 --- a/src/uu/hashsum/locales/fr-FR.ftl +++ /dev/null @@ -1,37 +0,0 @@ -hashsum-about = Calculer et vérifier les empreintes de messages. -hashsum-usage = hashsum -- [OPTION]... [FICHIER]... - -# Messages d'aide -hashsum-help-binary-windows = lire ou vérifier en mode binaire (par défaut) -hashsum-help-binary-other = lire en mode binaire -hashsum-help-text-windows = lire ou vérifier en mode texte -hashsum-help-text-other = lire en mode texte (par défaut) -hashsum-help-check = lire les empreintes depuis les FICHIERs et les vérifier -hashsum-help-tag = créer une somme de contrôle de style BSD -hashsum-help-quiet = ne pas afficher OK pour chaque fichier vérifié avec succès -hashsum-help-status = ne rien afficher, le code de statut indique le succès -hashsum-help-strict = sortir avec un code non-zéro pour les lignes de somme de contrôle mal formatées -hashsum-help-ignore-missing = ne pas échouer ou rapporter le statut pour les fichiers manquants -hashsum-help-warn = avertir des lignes de somme de contrôle mal formatées -hashsum-help-zero = terminer chaque ligne de sortie avec NUL, pas de retour à la ligne -hashsum-help-length = longueur de l'empreinte en bits ; ne doit pas dépasser le maximum pour l'algorithme blake2 et doit être un multiple de 8 - -# Messages d'aide des algorithmes -hashsum-help-md5 = travailler avec MD5 -hashsum-help-sha1 = travailler avec SHA1 -hashsum-help-sha224 = travailler avec SHA224 -hashsum-help-sha256 = travailler avec SHA256 -hashsum-help-sha384 = travailler avec SHA384 -hashsum-help-sha512 = travailler avec SHA512 -hashsum-help-sha3 = travailler avec SHA3 -hashsum-help-sha3-224 = travailler avec SHA3-224 -hashsum-help-sha3-256 = travailler avec SHA3-256 -hashsum-help-sha3-384 = travailler avec SHA3-384 -hashsum-help-sha3-512 = travailler avec SHA3-512 -hashsum-help-shake128 = travailler avec SHAKE128 en utilisant BITS pour la taille de sortie -hashsum-help-shake256 = travailler avec SHAKE256 en utilisant BITS pour la taille de sortie -hashsum-help-b2sum = travailler avec BLAKE2 -hashsum-help-b3sum = travailler avec BLAKE3 - -# Messages d'erreur -hashsum-error-failed-to-read-input = échec de la lecture de l'entrée diff --git a/src/uu/hashsum/src/hashsum.rs b/src/uu/hashsum/src/hashsum.rs deleted file mode 100644 index 19e8ad9db04..00000000000 --- a/src/uu/hashsum/src/hashsum.rs +++ /dev/null @@ -1,422 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -// spell-checker:ignore (ToDO) algo, algoname, bitlen, regexes, nread - -use std::ffi::{OsStr, OsString}; -use std::iter; -use std::path::Path; - -use clap::builder::ValueParser; -use clap::{Arg, ArgAction, ArgMatches, Command}; - -use uucore::checksum::compute::{ - ChecksumComputeOptions, figure_out_output_format, perform_checksum_computation, -}; -use uucore::checksum::validate::{ - ChecksumValidateOptions, ChecksumVerbose, perform_checksum_validation, -}; -use uucore::checksum::{ - AlgoKind, ChecksumError, SizedAlgoKind, calculate_blake2b_length_str, - sanitize_sha2_sha3_length_str, -}; -use uucore::error::UResult; -use uucore::line_ending::LineEnding; -use uucore::{format_usage, translate}; - -const NAME: &str = "hashsum"; - -/// Creates a hasher instance based on the command-line flags. -/// -/// # Arguments -/// -/// * `matches` - A reference to the `ArgMatches` object containing the command-line arguments. -/// -/// # Returns -/// -/// Returns a [`UResult`] of a tuple containing the algorithm name, the hasher instance, and -/// the output length in bits or an Err if multiple hash algorithms are specified or if a -/// required flag is missing. -#[allow(clippy::cognitive_complexity)] -fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<(AlgoKind, Option)> { - let mut alg: Option<(AlgoKind, Option)> = None; - - let mut set_or_err = |new_alg: (AlgoKind, Option)| -> UResult<()> { - if alg.is_some() { - return Err(ChecksumError::CombineMultipleAlgorithms.into()); - } - alg = Some(new_alg); - Ok(()) - }; - - if matches.get_flag("md5") { - set_or_err((AlgoKind::Md5, None))?; - } - if matches.get_flag("sha1") { - set_or_err((AlgoKind::Sha1, None))?; - } - if matches.get_flag("sha224") { - set_or_err((AlgoKind::Sha224, None))?; - } - if matches.get_flag("sha256") { - set_or_err((AlgoKind::Sha256, None))?; - } - if matches.get_flag("sha384") { - set_or_err((AlgoKind::Sha384, None))?; - } - if matches.get_flag("sha512") { - set_or_err((AlgoKind::Sha512, None))?; - } - if matches.get_flag("b2sum") { - set_or_err((AlgoKind::Blake2b, None))?; - } - if matches.get_flag("b3sum") { - set_or_err((AlgoKind::Blake3, None))?; - } - if matches.get_flag("sha3") { - match matches.get_one::(options::LENGTH) { - Some(len) => set_or_err(( - AlgoKind::Sha3, - Some(sanitize_sha2_sha3_length_str(AlgoKind::Sha3, len)?), - ))?, - None => return Err(ChecksumError::LengthRequired("SHA3".into()).into()), - } - } - if matches.get_flag("sha3-224") { - set_or_err((AlgoKind::Sha3, Some(224)))?; - } - if matches.get_flag("sha3-256") { - set_or_err((AlgoKind::Sha3, Some(256)))?; - } - if matches.get_flag("sha3-384") { - set_or_err((AlgoKind::Sha3, Some(384)))?; - } - if matches.get_flag("sha3-512") { - set_or_err((AlgoKind::Sha3, Some(512)))?; - } - if matches.get_flag("shake128") { - set_or_err((AlgoKind::Shake128, Some(128)))?; - } - if matches.get_flag("shake256") { - set_or_err((AlgoKind::Shake256, Some(256)))?; - } - - if alg.is_none() { - return Err(ChecksumError::NeedAlgorithmToHash.into()); - } - - Ok(alg.unwrap()) -} - -#[uucore::main] -pub fn uumain(mut args: impl uucore::Args) -> UResult<()> { - // if there is no program name for some reason, default to "hashsum" - let program = args.next().unwrap_or_else(|| OsString::from(NAME)); - let binary_name = Path::new(&program) - .file_stem() - .unwrap_or_else(|| OsStr::new(NAME)) - .to_string_lossy(); - - let args = iter::once(program.clone()).chain(args); - - // Default binary in Windows, text mode otherwise - let binary_flag_default = cfg!(windows); - - let (command, is_hashsum_bin) = uu_app(&binary_name); - - // FIXME: this should use try_get_matches_from() and crash!(), but at the moment that just - // causes "error: " to be printed twice (once from crash!() and once from clap). With - // the current setup, the name of the utility is not printed, but I think this is at - // least somewhat better from a user's perspective. - let matches = uucore::clap_localization::handle_clap_result(command, args)?; - - let length: Option = if binary_name == "b2sum" { - if let Some(len) = matches.get_one::(options::LENGTH) { - calculate_blake2b_length_str(len)? - } else { - None - } - } else { - None - }; - - let (algo_kind, length) = if is_hashsum_bin { - create_algorithm_from_flags(&matches)? - } else { - (AlgoKind::from_bin_name(&binary_name)?, length) - }; - - let binary = if matches.get_flag("binary") { - true - } else if matches.get_flag("text") { - false - } else { - binary_flag_default - }; - let check = matches.get_flag("check"); - - let check_flag = |flag| match (check, matches.get_flag(flag)) { - (_, false) => Ok(false), - (true, true) => Ok(true), - (false, true) => Err(ChecksumError::CheckOnlyFlag(flag.into())), - }; - - // Each of the following flags are only expected in --check mode. - // If we encounter them otherwise, end with an error. - let ignore_missing = check_flag("ignore-missing")?; - let warn = check_flag("warn")?; - let quiet = check_flag("quiet")?; - let strict = check_flag("strict")?; - let status = check_flag("status")?; - - let files = matches.get_many::(options::FILE).map_or_else( - // No files given, read from stdin. - || Box::new(iter::once(OsStr::new("-"))) as Box>, - // At least one file given, read from them. - |files| Box::new(files.map(OsStr::new)) as Box>, - ); - - if check { - // on Windows, allow --binary/--text to be used with --check - // and keep the behavior of defaulting to binary - #[cfg(not(windows))] - { - let text_flag = matches.get_flag("text"); - let binary_flag = matches.get_flag("binary"); - - if binary_flag || text_flag { - return Err(ChecksumError::BinaryTextConflict.into()); - } - } - - let verbose = ChecksumVerbose::new(status, quiet, warn); - - let opts = ChecksumValidateOptions { - ignore_missing, - strict, - verbose, - }; - - // Execute the checksum validation - return perform_checksum_validation(files, Some(algo_kind), length, opts); - } - - let algo = SizedAlgoKind::from_unsized(algo_kind, length)?; - let line_ending = LineEnding::from_zero_flag(matches.get_flag("zero")); - - let opts = ChecksumComputeOptions { - algo_kind: algo, - output_format: figure_out_output_format( - algo, - matches.get_flag(options::TAG), - binary, - /* raw */ false, - /* base64: */ false, - ), - line_ending, - }; - - // Show the hashsum of the input - perform_checksum_computation(opts, files) -} - -mod options { - //pub const ALGORITHM: &str = "algorithm"; - pub const FILE: &str = "file"; - //pub const UNTAGGED: &str = "untagged"; - pub const TAG: &str = "tag"; - pub const LENGTH: &str = "length"; - //pub const RAW: &str = "raw"; - //pub const BASE64: &str = "base64"; - pub const CHECK: &str = "check"; - pub const STRICT: &str = "strict"; - pub const TEXT: &str = "text"; - pub const BINARY: &str = "binary"; - pub const STATUS: &str = "status"; - pub const WARN: &str = "warn"; - pub const QUIET: &str = "quiet"; -} - -pub fn uu_app_common() -> Command { - Command::new(uucore::util_name()) - .version(uucore::crate_version!()) - .help_template(uucore::localized_help_template(uucore::util_name())) - .about(translate!("hashsum-about")) - .override_usage(format_usage(&translate!("hashsum-usage"))) - .infer_long_args(true) - .args_override_self(true) - .arg( - Arg::new(options::BINARY) - .short('b') - .long("binary") - .help({ - #[cfg(windows)] - { - translate!("hashsum-help-binary-windows") - } - #[cfg(not(windows))] - { - translate!("hashsum-help-binary-other") - } - }) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::CHECK) - .short('c') - .long("check") - .help(translate!("hashsum-help-check")) - .action(ArgAction::SetTrue) - .conflicts_with("tag"), - ) - .arg( - Arg::new(options::TAG) - .long("tag") - .help(translate!("hashsum-help-tag")) - .action(ArgAction::SetTrue) - .conflicts_with("text"), - ) - .arg( - Arg::new(options::TEXT) - .short('t') - .long("text") - .help({ - #[cfg(windows)] - { - translate!("hashsum-help-text-windows") - } - #[cfg(not(windows))] - { - translate!("hashsum-help-text-other") - } - }) - .conflicts_with("binary") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::QUIET) - .short('q') - .long(options::QUIET) - .help(translate!("hashsum-help-quiet")) - .action(ArgAction::SetTrue) - .overrides_with_all([options::STATUS, options::WARN]), - ) - .arg( - Arg::new(options::STATUS) - .short('s') - .long("status") - .help(translate!("hashsum-help-status")) - .action(ArgAction::SetTrue) - .overrides_with_all([options::QUIET, options::WARN]), - ) - .arg( - Arg::new(options::STRICT) - .long("strict") - .help(translate!("hashsum-help-strict")) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("ignore-missing") - .long("ignore-missing") - .help(translate!("hashsum-help-ignore-missing")) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::WARN) - .short('w') - .long("warn") - .help(translate!("hashsum-help-warn")) - .action(ArgAction::SetTrue) - .overrides_with_all([options::QUIET, options::STATUS]), - ) - .arg( - Arg::new("zero") - .short('z') - .long("zero") - .help(translate!("hashsum-help-zero")) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::FILE) - .index(1) - .action(ArgAction::Append) - .value_name(options::FILE) - .value_hint(clap::ValueHint::FilePath) - .value_parser(ValueParser::os_string()), - ) -} - -pub fn uu_app_length() -> Command { - uu_app_opt_length(uu_app_common()) -} - -fn uu_app_opt_length(command: Command) -> Command { - command.arg( - Arg::new(options::LENGTH) - .long(options::LENGTH) - .short('l') - .help(translate!("hashsum-help-length")) - .overrides_with(options::LENGTH) - .action(ArgAction::Set), - ) -} - -pub fn uu_app_custom() -> Command { - let mut command = uu_app_opt_length(uu_app_common()); - let algorithms = &[ - ("md5", translate!("hashsum-help-md5")), - ("sha1", translate!("hashsum-help-sha1")), - ("sha224", translate!("hashsum-help-sha224")), - ("sha256", translate!("hashsum-help-sha256")), - ("sha384", translate!("hashsum-help-sha384")), - ("sha512", translate!("hashsum-help-sha512")), - ("sha3", translate!("hashsum-help-sha3")), - ("sha3-224", translate!("hashsum-help-sha3-224")), - ("sha3-256", translate!("hashsum-help-sha3-256")), - ("sha3-384", translate!("hashsum-help-sha3-384")), - ("sha3-512", translate!("hashsum-help-sha3-512")), - ("shake128", translate!("hashsum-help-shake128")), - ("shake256", translate!("hashsum-help-shake256")), - ("b2sum", translate!("hashsum-help-b2sum")), - ("b3sum", translate!("hashsum-help-b3sum")), - ]; - - for (name, desc) in algorithms { - command = command.arg( - Arg::new(*name) - .long(name) - .help(desc) - .action(ArgAction::SetTrue), - ); - } - command -} - -/// hashsum is handled differently in build.rs -/// therefore, this is different from other utilities. -fn uu_app(binary_name: &str) -> (Command, bool) { - let (command, is_hashsum_bin) = match binary_name { - // These all support the same options. - "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" => { - (uu_app_common(), false) - } - // b2sum supports the md5sum options plus -l/--length. - "b2sum" => (uu_app_length(), false), - // We're probably just being called as `hashsum`, so give them everything. - _ => (uu_app_custom(), true), - }; - - // If not called as generic hashsum, override the command name and usage - let command = if is_hashsum_bin { - command - } else { - let usage = translate!("hashsum-usage-specific", "utility_name" => binary_name); - command - .help_template(uucore::localized_help_template(binary_name)) - .override_usage(format_usage(&usage)) - }; - - (command, is_hashsum_bin) -} diff --git a/src/uu/hashsum/src/main.rs b/src/uu/hashsum/src/main.rs deleted file mode 100644 index c31d4a9afb9..00000000000 --- a/src/uu/hashsum/src/main.rs +++ /dev/null @@ -1 +0,0 @@ -uucore::bin!(uu_hashsum); diff --git a/src/uucore/src/lib/features/checksum/validate.rs b/src/uucore/src/lib/features/checksum/validate.rs index aa950abac37..a34d6ed77a9 100644 --- a/src/uucore/src/lib/features/checksum/validate.rs +++ b/src/uucore/src/lib/features/checksum/validate.rs @@ -456,7 +456,6 @@ impl LineInfo { /// In case of non-algo-based format, if `cached_line_format` is Some, it must take the priority /// over the detected format. Otherwise, we must set it the the detected format. /// This specific behavior is emphasized by the test - /// `test_hashsum::test_check_md5sum_only_one_space`. fn parse(s: impl AsRef, cached_line_format: &mut Option) -> Option { let line_bytes = os_str_as_bytes(s.as_ref()).ok()?; diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 7931a69205e..69255534cd3 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -172,9 +172,9 @@ pub fn get_canonical_util_name(util_name: &str) -> &str { // uu_test aliases - '[' is an alias for test "[" => "test", - // hashsum aliases - all these hash commands are aliases for hashsum + // cksum aliases - all these hash commands are aliases for cksum "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" | "b2sum" => { - "hashsum" + "cksum" } "dir" => "ls", // dir is an alias for ls diff --git a/tests/by-util/test_hashsum.rs b/tests/by-util/test_hashsum.rs deleted file mode 100644 index 2f1719b0eca..00000000000 --- a/tests/by-util/test_hashsum.rs +++ /dev/null @@ -1,1230 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -use rstest::rstest; - -use uutests::new_ucmd; -use uutests::util::TestScenario; -use uutests::util_name; -// spell-checker:ignore checkfile, testf, ntestf -macro_rules! get_hash( - ($str:expr) => ( - $str.split(' ').collect::>()[0] - ); -); - -macro_rules! test_digest { - ($id:ident, $t:ident) => { - mod $id { - use uutests::util::*; - use uutests::util_name; - static DIGEST_ARG: &'static str = concat!("--", stringify!($t)); - static EXPECTED_FILE: &'static str = concat!(stringify!($id), ".expected"); - static CHECK_FILE: &'static str = concat!(stringify!($id), ".checkfile"); - static INPUT_FILE: &'static str = "input.txt"; - - #[test] - fn test_single_file() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read(EXPECTED_FILE), - get_hash!( - ts.ucmd() - .arg(DIGEST_ARG) - .arg(INPUT_FILE) - .succeeds() - .no_stderr() - .stdout_str() - ) - ); - } - - #[test] - fn test_stdin() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read(EXPECTED_FILE), - get_hash!( - ts.ucmd() - .arg(DIGEST_ARG) - .pipe_in_fixture(INPUT_FILE) - .succeeds() - .no_stderr() - .stdout_str() - ) - ); - } - - #[test] - fn test_check() { - let ts = TestScenario::new(util_name!()); - println!("File content='{}'", ts.fixtures.read(INPUT_FILE)); - println!("Check file='{}'", ts.fixtures.read(CHECK_FILE)); - - ts.ucmd() - .args(&[DIGEST_ARG, "--check", CHECK_FILE]) - .succeeds() - .no_stderr() - .stdout_is("input.txt: OK\n"); - } - - #[test] - fn test_zero() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read(EXPECTED_FILE), - get_hash!( - ts.ucmd() - .arg(DIGEST_ARG) - .arg("--zero") - .arg(INPUT_FILE) - .succeeds() - .no_stderr() - .stdout_str() - ) - ); - } - - #[test] - fn test_missing_file() { - let ts = TestScenario::new(util_name!()); - let at = &ts.fixtures; - - at.write("a", "file1\n"); - at.write("c", "file3\n"); - - ts.ucmd() - .args(&[DIGEST_ARG, "a", "b", "c"]) - .fails() - .stdout_contains("a\n") - .stdout_contains("c\n") - .stderr_contains("b: No such file or directory"); - } - } - }; -} - -macro_rules! test_digest_with_len { - ($id:ident, $t:ident, $size:expr) => { - mod $id { - use uutests::util::*; - use uutests::util_name; - static DIGEST_ARG: &'static str = concat!("--", stringify!($t)); - static LENGTH_ARG: &'static str = concat!("--length=", stringify!($size)); - static EXPECTED_FILE: &'static str = concat!(stringify!($id), ".expected"); - static CHECK_FILE: &'static str = concat!(stringify!($id), ".checkfile"); - static INPUT_FILE: &'static str = "input.txt"; - - #[test] - fn test_single_file() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read(EXPECTED_FILE), - get_hash!( - ts.ucmd() - .arg(DIGEST_ARG) - .arg(LENGTH_ARG) - .arg(INPUT_FILE) - .succeeds() - .no_stderr() - .stdout_str() - ) - ); - } - - #[test] - fn test_stdin() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read(EXPECTED_FILE), - get_hash!( - ts.ucmd() - .arg(DIGEST_ARG) - .arg(LENGTH_ARG) - .pipe_in_fixture(INPUT_FILE) - .succeeds() - .no_stderr() - .stdout_str() - ) - ); - } - - #[test] - fn test_check() { - let ts = TestScenario::new(util_name!()); - println!("File content='{}'", ts.fixtures.read(INPUT_FILE)); - println!("Check file='{}'", ts.fixtures.read(CHECK_FILE)); - - ts.ucmd() - .args(&[DIGEST_ARG, LENGTH_ARG, "--check", CHECK_FILE]) - .succeeds() - .no_stderr() - .stdout_is("input.txt: OK\n"); - } - - #[test] - fn test_zero() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read(EXPECTED_FILE), - get_hash!( - ts.ucmd() - .arg(DIGEST_ARG) - .arg(LENGTH_ARG) - .arg("--zero") - .arg(INPUT_FILE) - .succeeds() - .no_stderr() - .stdout_str() - ) - ); - } - - #[test] - fn test_missing_file() { - let ts = TestScenario::new(util_name!()); - let at = &ts.fixtures; - - at.write("a", "file1\n"); - at.write("c", "file3\n"); - - ts.ucmd() - .args(&[DIGEST_ARG, LENGTH_ARG, "a", "b", "c"]) - .fails() - .stdout_contains("a\n") - .stdout_contains("c\n") - .stderr_contains("b: No such file or directory"); - } - } - }; -} - -test_digest! {md5, md5} -test_digest! {sha1, sha1} -test_digest! {b3sum, b3sum} -test_digest! {shake128, shake128} -test_digest! {shake256, shake256} - -test_digest_with_len! {sha224, sha224, 224} -test_digest_with_len! {sha256, sha256, 256} -test_digest_with_len! {sha384, sha384, 384} -test_digest_with_len! {sha512, sha512, 512} -test_digest_with_len! {sha3_224, sha3, 224} -test_digest_with_len! {sha3_256, sha3, 256} -test_digest_with_len! {sha3_384, sha3, 384} -test_digest_with_len! {sha3_512, sha3, 512} -test_digest_with_len! {b2sum, b2sum, 512} - -#[test] -fn test_check_sha1() { - // To make sure that #3815 doesn't happen again - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - at.write( - "testf.sha1", - "988881adc9fc3655077dc2d4d757d480b5ea0e11 testf\n", - ); - scene - .ccmd("sha1sum") - .arg("-c") - .arg(at.subdir.join("testf.sha1")) - .succeeds() - .stdout_is("testf: OK\n") - .stderr_is(""); -} - -#[test] -fn test_check_md5_ignore_missing() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - at.write( - "testf.sha1", - "14758f1afd44c09b7992073ccf00b43d testf\n14758f1afd44c09b7992073ccf00b43d testf2\n", - ); - scene - .ccmd("md5sum") - .arg("-c") - .arg(at.subdir.join("testf.sha1")) - .fails() - .stdout_contains("testf2: FAILED open or read"); - - scene - .ccmd("md5sum") - .arg("-c") - .arg("--ignore-missing") - .arg(at.subdir.join("testf.sha1")) - .succeeds() - .stdout_is("testf: OK\n") - .stderr_is(""); - - scene - .ccmd("md5sum") - .arg("--ignore-missing") - .arg(at.subdir.join("testf.sha1")) - .fails() - .stderr_contains("the --ignore-missing option is meaningful only when verifying checksums"); -} - -#[test] -fn test_check_b2sum_length_option_0() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - at.write("testf.b2sum", "9e2bf63e933e610efee4a8d6cd4a9387e80860edee97e27db3b37a828d226ab1eb92a9cdd8ca9ca67a753edaf8bd89a0558496f67a30af6f766943839acf0110 testf\n"); - - scene - .ccmd("b2sum") - .arg("--length=0") - .arg("-c") - .arg(at.subdir.join("testf.b2sum")) - .succeeds() - .stdout_only("testf: OK\n"); -} - -#[test] -fn test_check_b2sum_length_duplicate() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - - scene - .ccmd("b2sum") - .arg("--length=123") - .arg("--length=128") - .arg("testf") - .succeeds() - .stdout_contains("d6d45901dec53e65d2b55fb6e2ab67b0"); -} - -#[test] -fn test_check_b2sum_length_option_8() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - at.write("testf.b2sum", "6a testf\n"); - - scene - .ccmd("b2sum") - .arg("--length=8") - .arg("-c") - .arg(at.subdir.join("testf.b2sum")) - .succeeds() - .stdout_only("testf: OK\n"); -} - -#[test] -fn test_invalid_b2sum_length_option_not_multiple_of_8() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - - scene - .ccmd("b2sum") - .arg("--length=9") - .arg(at.subdir.join("testf")) - .fails_with_code(1) - .stderr_contains("b2sum: invalid length: '9'") - .stderr_contains("b2sum: length is not a multiple of 8"); -} - -#[rstest] -#[case("513")] -#[case("1024")] -#[case("18446744073709552000")] -fn test_invalid_b2sum_length_option_too_large(#[case] len: &str) { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - - scene - .ccmd("b2sum") - .arg("--length") - .arg(len) - .arg(at.subdir.join("testf")) - .fails_with_code(1) - .no_stdout() - .stderr_contains(format!("b2sum: invalid length: '{len}'")) - .stderr_contains("b2sum: maximum digest length for 'BLAKE2b' is 512 bits"); -} - -#[test] -fn test_check_b2sum_tag_output() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - - scene - .ccmd("b2sum") - .arg("--length=0") - .arg("--tag") - .arg("f") - .succeeds() - .stdout_only("BLAKE2b (f) = 786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce\n"); - - scene - .ccmd("b2sum") - .arg("--length=128") - .arg("--tag") - .arg("f") - .succeeds() - .stdout_only("BLAKE2b-128 (f) = cae66941d9efbd404e4d88758ea67670\n"); -} - -#[test] -fn test_check_b2sum_verify() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("a", "a\n"); - - scene - .ccmd("b2sum") - .arg("--tag") - .arg("a") - .succeeds() - .stdout_only("BLAKE2b (a) = bedfbb90d858c2d67b7ee8f7523be3d3b54004ef9e4f02f2ad79a1d05bfdfe49b81e3c92ebf99b504102b6bf003fa342587f5b3124c205f55204e8c4b4ce7d7c\n"); - - scene - .ccmd("b2sum") - .arg("--tag") - .arg("-l") - .arg("128") - .arg("a") - .succeeds() - .stdout_only("BLAKE2b-128 (a) = b93e0fc7bb21633c08bba07c5e71dc00\n"); -} - -#[test] -fn test_check_file_not_found_warning() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("testf", "foobar\n"); - at.write( - "testf.sha1", - "988881adc9fc3655077dc2d4d757d480b5ea0e11 testf\n", - ); - at.remove("testf"); - scene - .ccmd("sha1sum") - .arg("-c") - .arg(at.subdir.join("testf.sha1")) - .fails() - .stdout_is("testf: FAILED open or read\n") - .stderr_is("sha1sum: testf: No such file or directory\nsha1sum: WARNING: 1 listed file could not be read\n"); -} - -// Asterisk `*` is a reserved paths character on win32, nor the path can end with a whitespace. -// ref: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions -#[test] -fn test_check_md5sum() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - #[cfg(not(windows))] - { - for f in &["a", " b", "*c", "dd", " "] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "60b725f10c9c85c70d97880dfe8191b3 a\n\ - bf35d7536c785cf06730d5a40301eba2 b\n\ - f5b61709718c1ecf8db1aea8547d4698 *c\n\ - b064a020db8018f18ff5ae367d01b212 dd\n\ - d784fa8b6d98d27699781bd9a7cf19f0 ", - ); - scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5sum") - .succeeds() - .stdout_is("a: OK\n b: OK\n*c: OK\ndd: OK\n : OK\n") - .stderr_is(""); - } - #[cfg(windows)] - { - for f in &["a", " b", "dd"] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "60b725f10c9c85c70d97880dfe8191b3 a\n\ - bf35d7536c785cf06730d5a40301eba2 b\n\ - b064a020db8018f18ff5ae367d01b212 dd", - ); - scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5sum") - .succeeds() - .stdout_is("a: OK\n b: OK\ndd: OK\n") - .stderr_is(""); - } -} - -// GNU also supports one line sep -#[test] -fn test_check_md5sum_only_one_space() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - for f in ["a", " b", "c"] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "60b725f10c9c85c70d97880dfe8191b3 a\n\ - bf35d7536c785cf06730d5a40301eba2 b\n\ - 2cd6ee2c70b0bde53fbe6cac3c8b8bb1 c\n", - ); - scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5sum") - .succeeds() - .stdout_only("a: OK\n b: OK\nc: OK\n"); -} - -#[test] -fn test_check_md5sum_reverse_bsd() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - #[cfg(not(windows))] - { - for f in &["a", " b", "*c", "dd", " "] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "60b725f10c9c85c70d97880dfe8191b3 a\n\ - bf35d7536c785cf06730d5a40301eba2 b\n\ - f5b61709718c1ecf8db1aea8547d4698 *c\n\ - b064a020db8018f18ff5ae367d01b212 dd\n\ - d784fa8b6d98d27699781bd9a7cf19f0 ", - ); - scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5sum") - .succeeds() - .stdout_is("a: OK\n b: OK\n*c: OK\ndd: OK\n : OK\n") - .stderr_is(""); - } - #[cfg(windows)] - { - for f in &["a", " b", "dd"] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "60b725f10c9c85c70d97880dfe8191b3 a\n\ - bf35d7536c785cf06730d5a40301eba2 b\n\ - b064a020db8018f18ff5ae367d01b212 dd", - ); - scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5sum") - .succeeds() - .stdout_is("a: OK\n b: OK\ndd: OK\n") - .stderr_is(""); - } -} - -#[test] -fn test_check_md5sum_mixed_format() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - #[cfg(not(windows))] - { - for f in &[" b", "*c", "dd", " "] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "bf35d7536c785cf06730d5a40301eba2 b\n\ - f5b61709718c1ecf8db1aea8547d4698 *c\n\ - b064a020db8018f18ff5ae367d01b212 dd\n\ - d784fa8b6d98d27699781bd9a7cf19f0 ", - ); - } - #[cfg(windows)] - { - for f in &[" b", "dd"] { - at.write(f, &format!("{f}\n")); - } - at.write( - "check.md5sum", - "bf35d7536c785cf06730d5a40301eba2 b\n\ - b064a020db8018f18ff5ae367d01b212 dd", - ); - } - scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5sum") - .fails_with_code(1); -} - -#[test] -fn test_invalid_arg() { - new_ucmd!().arg("--definitely-invalid").fails_with_code(1); -} - -#[test] -fn test_conflicting_arg() { - new_ucmd!() - .arg("--tag") - .arg("--check") - .arg("--md5") - .fails_with_code(1); - new_ucmd!() - .arg("--tag") - .arg("--text") - .arg("--md5") - .fails_with_code(1); -} - -#[test] -fn test_tag() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("foobar", "foo bar\n"); - scene - .ccmd("sha256sum") - .arg("--tag") - .arg("foobar") - .succeeds() - .stdout_is( - "SHA256 (foobar) = 1f2ec52b774368781bed1d1fb140a92e0eb6348090619c9291f9a5a3c8e8d151\n", - ); -} - -#[test] -#[cfg(not(windows))] -fn test_with_escape_filename() { - let scene = TestScenario::new(util_name!()); - - let at = &scene.fixtures; - let filename = "a\nb"; - at.touch(filename); - let result = scene.ccmd("md5sum").arg("--text").arg(filename).succeeds(); - let stdout = result.stdout_str(); - println!("stdout {stdout}"); - assert!(stdout.starts_with('\\')); - assert!(stdout.trim().ends_with("a\\nb")); -} - -#[test] -#[cfg(not(windows))] -fn test_with_escape_filename_zero_text() { - let scene = TestScenario::new(util_name!()); - - let at = &scene.fixtures; - let filename = "a\nb"; - at.touch(filename); - let result = scene - .ccmd("md5sum") - .arg("--text") - .arg("--zero") - .arg(filename) - .succeeds(); - let stdout = result.stdout_str(); - println!("stdout {stdout}"); - assert!(!stdout.starts_with('\\')); - assert!(stdout.contains("a\nb")); -} - -#[test] -fn test_check_empty_line() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write( - "in.md5", - "d41d8cd98f00b204e9800998ecf8427e f\n\nd41d8cd98f00b204e9800998ecf8427e f\ninvalid\n\n", - ); - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stderr_contains("WARNING: 1 line is improperly formatted"); -} - -#[test] -#[cfg(not(windows))] -fn test_check_with_escape_filename() { - let scene = TestScenario::new(util_name!()); - - let at = &scene.fixtures; - - let filename = "a\nb"; - at.touch(filename); - let result = scene.ccmd("md5sum").arg("--tag").arg(filename).succeeds(); - let stdout = result.stdout_str(); - println!("stdout {stdout}"); - assert!(stdout.starts_with("\\MD5")); - assert!(stdout.contains("a\\nb")); - at.write("check.md5", stdout); - let result = scene - .ccmd("md5sum") - .arg("--strict") - .arg("-c") - .arg("check.md5") - .succeeds(); - result.stdout_is("\\a\\nb: OK\n"); -} - -#[test] -fn test_check_strict_error() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write( - "in.md5", - "ERR\nERR\nd41d8cd98f00b204e9800998ecf8427e f\nERR\n", - ); - scene - .ccmd("md5sum") - .arg("--check") - .arg("--strict") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains("WARNING: 3 lines are improperly formatted"); -} - -#[test] -fn test_check_warn() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write( - "in.md5", - "d41d8cd98f00b204e9800998ecf8427e f\nd41d8cd98f00b204e9800998ecf8427e f\ninvalid\n", - ); - scene - .ccmd("md5sum") - .arg("--check") - .arg("--warn") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stderr_contains("in.md5: 3: improperly formatted MD5 checksum line") - .stderr_contains("WARNING: 1 line is improperly formatted"); - - // with strict, we should fail the execution - scene - .ccmd("md5sum") - .arg("--check") - .arg("--strict") - .arg(at.subdir.join("in.md5")) - .fails(); -} - -#[test] -fn test_check_status() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "MD5(f)= d41d8cd98f00b204e9800998ecf8427f\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg("--status") - .arg(at.subdir.join("in.md5")) - .fails() - .no_output(); -} - -#[test] -fn test_check_status_code() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427f f\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg("--status") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_is("") - .stdout_is(""); -} - -#[test] -fn test_sha1_with_md5sum_should_fail() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("f.sha1", "SHA1 (f) = d41d8cd98f00b204e9800998ecf8427e\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("f.sha1")) - .fails() - .stderr_contains("f.sha1: no properly formatted checksum lines found") - .stderr_does_not_contain("WARNING: 1 line is improperly formatted"); -} - -#[test] -// Disabled on Windows because of the "*" -#[cfg(not(windows))] -fn test_check_one_two_space_star() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("empty"); - - // with one space, the "*" is removed - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427e *empty\n"); - - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stdout_is("empty: OK\n"); - - // with two spaces, the "*" is not removed - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427e *empty\n"); - // First should fail as *empty doesn't exit - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .fails() - .stdout_is("*empty: FAILED open or read\n"); - - at.touch("*empty"); - // Should pass as we have the file - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stdout_is("*empty: OK\n"); -} - -#[test] -// Disabled on Windows because of the "*" -#[cfg(not(windows))] -fn test_check_space_star_or_not() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("a"); - at.touch("*c"); - - // with one space, the "*" is removed - at.write( - "in.md5", - "d41d8cd98f00b204e9800998ecf8427e *c\n - d41d8cd98f00b204e9800998ecf8427e a\n", - ); - - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .fails() - .stdout_contains("c: FAILED") - .stdout_does_not_contain("a: FAILED") - .stderr_contains("WARNING: 1 line is improperly formatted"); - - at.write( - "in.md5", - "d41d8cd98f00b204e9800998ecf8427e a\n - d41d8cd98f00b204e9800998ecf8427e *c\n", - ); - - // First should fail as *empty doesn't exit - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stdout_contains("a: OK") - .stderr_contains("WARNING: 1 line is improperly formatted"); -} - -#[test] -fn test_check_no_backslash_no_space() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "MD5(f)= d41d8cd98f00b204e9800998ecf8427e\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stdout_is("f: OK\n"); -} - -#[test] -fn test_incomplete_format() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "MD5 (\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains("no properly formatted checksum lines found"); -} - -#[test] -fn test_start_error() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "ERR\nd41d8cd98f00b204e9800998ecf8427e f\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg("--strict") - .arg(at.subdir.join("in.md5")) - .fails() - .stdout_is("f: OK\n") - .stderr_contains("WARNING: 1 line is improperly formatted"); -} - -#[test] -fn test_check_check_ignore_no_file() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427f missing\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg("--ignore-missing") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains("in.md5: no file was verified"); -} - -#[test] -fn test_check_directory_error() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.mkdir("d"); - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427f d\n"); - #[cfg(not(windows))] - let err_msg = "md5sum: d: Is a directory\n"; - #[cfg(windows)] - let err_msg = "md5sum: d: Permission denied\n"; - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains(err_msg); -} - -#[test] -#[cfg(not(windows))] -fn test_continue_after_directory_error() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.mkdir("d"); - at.touch("file"); - at.touch("no_read_perms"); - at.set_mode("no_read_perms", 200); - - let (out, err_msg) = ( - "d41d8cd98f00b204e9800998ecf8427e file\n", - [ - "md5sum: d: Is a directory", - "md5sum: dne: No such file or directory", - "md5sum: no_read_perms: Permission denied\n", - ] - .join("\n"), - ); - - scene - .ccmd("md5sum") - .arg("d") - .arg("dne") - .arg("no_read_perms") - .arg("file") - .fails() - .stdout_is(out) - .stderr_is(err_msg); -} - -#[test] -fn test_check_quiet() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427e f\n"); - scene - .ccmd("md5sum") - .arg("--quiet") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .no_output(); - - // incorrect md5 - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427f f\n"); - scene - .ccmd("md5sum") - .arg("--quiet") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .fails() - .stdout_contains("f: FAILED") - .stderr_contains("WARNING: 1 computed checksum did NOT match"); - - scene - .ccmd("md5sum") - .arg("--quiet") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains("md5sum: the --quiet option is meaningful only when verifying checksums"); - scene - .ccmd("md5sum") - .arg("--strict") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains("md5sum: the --strict option is meaningful only when verifying checksums"); -} - -#[test] -fn test_star_to_start() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.touch("f"); - at.write("in.md5", "d41d8cd98f00b204e9800998ecf8427e *f\n"); - scene - .ccmd("md5sum") - .arg("--check") - .arg(at.subdir.join("in.md5")) - .succeeds() - .stdout_only("f: OK\n"); -} - -#[test] -fn test_check_b2sum_strict_check() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - at.touch("f"); - - let checksums = [ - "2e f\n", - "e4a6a0577479b2b4 f\n", - "cae66941d9efbd404e4d88758ea67670 f\n", - "246c0442cd564aced8145b8b60f1370aa7 f\n", - "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8 f\n", - "4ded8c5fc8b12f3273f877ca585a44ad6503249a2b345d6d9c0e67d85bcb700db4178c0303e93b8f4ad758b8e2c9fd8b3d0c28e585f1928334bb77d36782e8 f\n", - "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce f\n", - ]; - - at.write("ck", &checksums.join("")); - - let output = "f: OK\n".to_string().repeat(checksums.len()); - - scene - .ccmd("b2sum") - .arg("-c") - .arg(at.subdir.join("ck")) - .succeeds() - .stdout_only(&output); - - scene - .ccmd("b2sum") - .arg("--strict") - .arg("-c") - .arg(at.subdir.join("ck")) - .succeeds() - .stdout_only(&output); -} - -#[test] -fn test_check_md5_comment_line() { - // A comment in a checksum file shall be discarded unnoticed. - - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("foo", "foo-content\n"); - at.write( - "MD5SUM", - "\ - # This is a comment\n\ - 8411029f3f5b781026a93db636aca721 foo\n\ - # next comment is empty\n#", - ); - - scene - .ccmd("md5sum") - .arg("--check") - .arg("MD5SUM") - .succeeds() - .stdout_contains("foo: OK") - .no_stderr(); -} - -#[test] -fn test_check_md5_comment_only() { - // A file only filled with comments is equivalent to an empty file, - // and therefore produces an error. - - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("foo", "foo-content\n"); - at.write("MD5SUM", "# This is a comment\n"); - - scene - .ccmd("md5sum") - .arg("--check") - .arg("MD5SUM") - .fails() - .stderr_contains("no properly formatted checksum lines found"); -} - -#[test] -fn test_check_md5_comment_leading_space() { - // A file only filled with comments is equivalent to an empty file, - // and therefore produces an error. - - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; - - at.write("foo", "foo-content\n"); - at.write( - "MD5SUM", - " # This is a comment\n\ - 8411029f3f5b781026a93db636aca721 foo\n", - ); - - scene - .ccmd("md5sum") - .arg("--check") - .arg("MD5SUM") - .succeeds() - .stdout_contains("foo: OK") - .stderr_contains("WARNING: 1 line is improperly formatted"); -} - -#[test] -fn test_sha256_binary() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read("binary.sha256.expected"), - get_hash!( - ts.ucmd() - .arg("--sha256") - .arg("binary.png") - .succeeds() - .no_stderr() - .stdout_str() - ) - ); -} - -#[test] -fn test_sha256_stdin_binary() { - let ts = TestScenario::new(util_name!()); - assert_eq!( - ts.fixtures.read("binary.sha256.expected"), - get_hash!( - ts.ucmd() - .arg("--sha256") - .pipe_in_fixture("binary.png") - .succeeds() - .no_stderr() - .stdout_str() - ) - ); -} - -// This test is currently disabled on windows -#[test] -#[cfg_attr(windows, ignore = "Discussion is in #9168")] -fn test_check_sha256_binary() { - new_ucmd!() - .args(&["--sha256", "--check", "binary.sha256.checkfile"]) - .succeeds() - .no_stderr() - .stdout_is("binary.png: OK\n"); -} - -#[test] -fn test_help_shows_correct_utility_name() { - // Test that help output shows the actual utility name instead of "hashsum" - let scene = TestScenario::new(util_name!()); - - // Test md5sum - scene - .ccmd("md5sum") - .arg("--help") - .succeeds() - .stdout_contains("Usage: md5sum") - .stdout_does_not_contain("Usage: hashsum"); - - // Test sha256sum - scene - .ccmd("sha256sum") - .arg("--help") - .succeeds() - .stdout_contains("Usage: sha256sum") - .stdout_does_not_contain("Usage: hashsum"); - - // Test b2sum - scene - .ccmd("b2sum") - .arg("--help") - .succeeds() - .stdout_contains("Usage: b2sum") - .stdout_does_not_contain("Usage: hashsum"); - - // Test that generic hashsum still shows the correct usage - scene - .ccmd("hashsum") - .arg("--help") - .succeeds() - .stdout_contains("Usage: hashsum --"); -} diff --git a/tests/fixtures/hashsum/b2sum.checkfile b/tests/fixtures/hashsum/b2sum.checkfile deleted file mode 100644 index 9d6781cc895..00000000000 --- a/tests/fixtures/hashsum/b2sum.checkfile +++ /dev/null @@ -1 +0,0 @@ -7355dd5276c21cfe0c593b5063b96af3f96a454b33216f58314f44c3ade92e9cd6cec4210a0836246780e9baf927cc50b9a3d7073e8f9bd12780fddbcb930c6d input.txt diff --git a/tests/fixtures/hashsum/b2sum.expected b/tests/fixtures/hashsum/b2sum.expected deleted file mode 100644 index a0dae0db450..00000000000 --- a/tests/fixtures/hashsum/b2sum.expected +++ /dev/null @@ -1 +0,0 @@ -7355dd5276c21cfe0c593b5063b96af3f96a454b33216f58314f44c3ade92e9cd6cec4210a0836246780e9baf927cc50b9a3d7073e8f9bd12780fddbcb930c6d \ No newline at end of file diff --git a/tests/fixtures/hashsum/b3sum.checkfile b/tests/fixtures/hashsum/b3sum.checkfile deleted file mode 100644 index f8d34d0b6f9..00000000000 --- a/tests/fixtures/hashsum/b3sum.checkfile +++ /dev/null @@ -1 +0,0 @@ -a1a55887535397bf461902491c8779188a5dd1f8c3951b3d9cf6ecba194e87b0 input.txt diff --git a/tests/fixtures/hashsum/b3sum.expected b/tests/fixtures/hashsum/b3sum.expected deleted file mode 100644 index a56e54432d0..00000000000 --- a/tests/fixtures/hashsum/b3sum.expected +++ /dev/null @@ -1 +0,0 @@ -a1a55887535397bf461902491c8779188a5dd1f8c3951b3d9cf6ecba194e87b0 \ No newline at end of file diff --git a/tests/fixtures/hashsum/binary.png b/tests/fixtures/hashsum/binary.png deleted file mode 100644 index 6c4161338f200299744af6dff35884ac5c94516b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8055 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 delta 19 acmeyu*3G`bn29a1IHR~Uce4^x5F-FY9tJZ2 diff --git a/tests/fixtures/sort/zero-terminated.expected.debug b/tests/fixtures/sort/zero-terminated.expected.debug index fbef272b02c..1fdc1da8d87 100644 --- a/tests/fixtures/sort/zero-terminated.expected.debug +++ b/tests/fixtures/sort/zero-terminated.expected.debug @@ -46,8 +46,6 @@ _____________________ __________________ ../../fixtures/fold ___________________ -../../fixtures/hashsum -______________________ ../../fixtures/head ___________________ ../../fixtures/join diff --git a/tests/fixtures/sort/zero-terminated.txt b/tests/fixtures/sort/zero-terminated.txt index 5c547c851ce690dcbca6e40f3add8ae835518702..bb2aa200e813fdf65fc69cf6b52969d1c820052c 100644 GIT binary patch delta 12 TcmeBX|H8IGhH , @rem :: default ("Tier 1" cross-platform) utility list -set "default_utils=base32 base64 basename cat cksum comm cp cut date dircolors dirname echo env expand expr factor false fmt fold hashsum head join link ln ls mkdir mktemp more mv nl od paste printenv printf ptx pwd readlink realpath rm rmdir seq shred shuf sleep sort split sum tac tail tee test tr true truncate tsort unexpand uniq wc yes" +set "default_utils=base32 base64 basename cat cksum comm cp cut date dircolors dirname echo env expand expr factor false fmt fold head join link ln ls mkdir mktemp more mv nl od paste printenv printf ptx pwd readlink realpath rm rmdir seq shred shuf sleep sort split sum tac tail tee test tr true truncate tsort unexpand uniq wc yes" set "project_dir=%ME_parent_dir%" cd "%project_dir%" diff --git a/util/show-utils.sh b/util/show-utils.sh index 3cc48794030..719b803f411 100755 --- a/util/show-utils.sh +++ b/util/show-utils.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # spell-checker:ignore (shell) OSTYPE -# spell-checker:ignore (utils) cksum coreutils dircolors hashsum mkdir mktemp printenv printf readlink realpath grealpath rmdir shuf tsort unexpand +# spell-checker:ignore (utils) cksum coreutils dircolors mkdir mktemp printenv printf readlink realpath grealpath rmdir shuf tsort unexpand # spell-checker:ignore (jq) deps startswith # Use GNU version for realpath on *BSD @@ -15,7 +15,7 @@ ME_parent_dir_abs="$("${REALPATH}" -mP -- "${ME_parent_dir}" || "${REALPATH}" -- # refs: , # default ("Tier 1" cross-platform) utility list -default_utils="base32 base64 basename cat cksum comm cp cut date dircolors dirname echo env expand expr factor false fmt fold hashsum head join link ln ls mkdir mktemp more mv nl od paste printenv printf ptx pwd readlink realpath rm rmdir seq shred shuf sleep sort split sum tac tail tee test tr true truncate tsort unexpand uniq wc yes" +default_utils="base32 base64 basename cat cksum comm cp cut date dircolors dirname echo env expand expr factor false fmt fold head join link ln ls mkdir mktemp more mv nl od paste printenv printf ptx pwd readlink realpath rm rmdir seq shred shuf sleep sort split sum tac tail tee test tr true truncate tsort unexpand uniq wc yes" project_main_dir="${ME_parent_dir_abs}" # printf 'project_main_dir="%s"\n' "${project_main_dir}" From 39d9dad10df87c4039bdfc240fb5803a69f160a0 Mon Sep 17 00:00:00 2001 From: oech3 <> Date: Mon, 5 Jan 2026 06:05:17 +0900 Subject: [PATCH 2/2] Fix --- src/uu/cksum/src/cksum.rs | 72 +++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index f936e5b3dee..76a619157b5 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -75,18 +75,21 @@ mod options { /// output format, the second one indicates if we should use the binary flag in /// the untagged case. /// Sanitize the `--length` argument depending on `--algorithm` and `--length`. -fn maybe_sanitize_length(algo_cli: AlgoKind, input_length: Option<&str>) -> UResult> { +fn maybe_sanitize_length( + algo_cli: Option, + input_length: Option<&str>, +) -> UResult> { match (algo_cli, input_length) { // No provided length is not a problem so far. (_, None) => Ok(None), // For SHA2 and SHA3, if a length is provided, ensure it is correct. - (algo @ (AlgoKind::Sha2 | AlgoKind::Sha3), Some(s_len)) => { + (Some(algo @ (AlgoKind::Sha2 | AlgoKind::Sha3)), Some(s_len)) => { sanitize_sha2_sha3_length_str(algo, s_len).map(Some) } // For BLAKE2b, if a length is provided, validate it. - (AlgoKind::Blake2b, Some(len)) => calculate_blake2b_length_str(len), + (Some(AlgoKind::Blake2b), Some(len)) => calculate_blake2b_length_str(len), // For any other provided algorithm, check if length is 0. // Otherwise, this is an error. @@ -99,6 +102,7 @@ fn maybe_sanitize_length(algo_cli: AlgoKind, input_length: Option<&str>) -> URes pub fn uumain(args: impl uucore::Args) -> UResult<()> { let binary_name = uucore::util_name(); let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?; + let check = matches.get_flag(options::CHECK); let ignore_missing = matches.get_flag(options::IGNORE_MISSING); @@ -107,23 +111,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let strict = matches.get_flag(options::STRICT); let status = matches.get_flag(options::STATUS); - // Set default algo from binary name - let mut algo_cli = match binary_name { - s if s.ends_with("md5sum") => AlgoKind::Md5, - s if s.ends_with("sha1sum") => AlgoKind::Sha1, - s if s.ends_with("sha224sum") => AlgoKind::Sha224, - s if s.ends_with("sha256sum") => AlgoKind::Sha256, - s if s.ends_with("sha384sum") => AlgoKind::Sha384, - s if s.ends_with("sha512sum") => AlgoKind::Sha512, - s if s.ends_with("b2sum") => AlgoKind::Blake2b, - _ => AlgoKind::Crc, + // Set default algo from binary name. We still use None to ignore --check legacy algos. + let algo_cli = match binary_name { + s if s.ends_with("md5sum") => Some(AlgoKind::Md5), + s if s.ends_with("sha1sum") => Some(AlgoKind::Sha1), + s if s.ends_with("sha224sum") => Some(AlgoKind::Sha224), + s if s.ends_with("sha256sum") => Some(AlgoKind::Sha256), + s if s.ends_with("sha384sum") => Some(AlgoKind::Sha384), + s if s.ends_with("sha512sum") => Some(AlgoKind::Sha512), + s if s.ends_with("b2sum") => Some(AlgoKind::Blake2b), + _ => matches + .get_one::(options::ALGORITHM) + .map(|s| AlgoKind::from_cksum(s)) + .transpose()?, }; - // cksum accepts -a - if binary_name.ends_with("cksum") { - if let Some(algo_str) = matches.get_one::(options::ALGORITHM) { - algo_cli = AlgoKind::from_cksum(algo_str)?; - } - } let input_length = matches .try_get_one::(options::LENGTH) @@ -142,9 +143,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if check { // cksum does not support '--check'ing legacy algorithms - let algo_specified = - !binary_name.ends_with("cksum") || matches.contains_id(options::ALGORITHM); - if algo_specified && algo_cli.is_legacy() { + if algo_cli.is_some_and(AlgoKind::is_legacy) { return Err(ChecksumError::AlgorithmNotSupportedWithCheck.into()); } @@ -164,10 +163,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { strict, verbose, }; - if algo_specified { - return perform_checksum_validation(files, Some(algo_cli), length, opts); - } - return perform_checksum_validation(files, None, length, opts); + + return perform_checksum_validation(files, algo_cli, length, opts); } // Not --check @@ -177,12 +174,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { print_cpu_debug_info(); } + // Set the default algorithm to CRC when not '--check'ing. + let algo_kind = algo_cli.unwrap_or(AlgoKind::Crc); - let tag = matches.get_flag(options::TAG) || !matches.get_flag(options::UNTAGGED); + // --untagged is cksum specific. So we use this form... + let is_cksum = binary_name.ends_with("cksum"); + // clap cannot overrides_with --binary by --tag unilaterally... + let tag = (!is_cksum && std::env::args().any(|a| a == "--tag" || a == "-t")) + || (is_cksum && !matches.get_flag(options::UNTAGGED)); let binary = matches.get_flag(options::BINARY); let algo = SizedAlgoKind::from_unsized(algo_kind, length)?; - let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO)); let opts = ChecksumComputeOptions { @@ -223,17 +225,9 @@ pub fn uu_app() -> Command { .long(options::TAG) .help(translate!("cksum-help-tag")) .action(ArgAction::SetTrue) - .overrides_with(options::UNTAGGED) .overrides_with(options::BINARY) .overrides_with(options::TEXT), ) - .arg( - Arg::new(options::LENGTH) - .long(options::LENGTH) - .short('l') - .help(translate!("cksum-help-length")) - .action(ArgAction::Set), - ) .arg( Arg::new(options::RAW) .long(options::RAW) @@ -268,16 +262,13 @@ pub fn uu_app() -> Command { .long(options::TEXT) .short('t') .hide(true) - .overrides_with(options::BINARY) - .action(ArgAction::SetTrue) - .requires(options::UNTAGGED), + .action(ArgAction::SetTrue), ) .arg( Arg::new(options::BINARY) .long(options::BINARY) .short('b') .hide(true) - .overrides_with(options::TEXT) .action(ArgAction::SetTrue), ) .arg( @@ -336,6 +327,7 @@ pub fn uu_app() -> Command { } if binary_name.ends_with("cksum") { app = app + .mut_arg(options::TEXT, |a: Arg| a.requires(options::UNTAGGED)) .arg( Arg::new(options::ALGORITHM) .long(options::ALGORITHM)