From fd38ea4595d6b60c5b40dfccadbbd6ff361c8453 Mon Sep 17 00:00:00 2001 From: oech3 <> Date: Wed, 7 Jan 2026 07:10:31 +0900 Subject: [PATCH 1/2] cksum: Replace hashsum with cksum symlinks --- .github/workflows/CICD.yml | 8 +- .../cspell.dictionaries/jargon.wordlist.txt | 1 - .../workspace.wordlist.txt | 1 - 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 | 132 +- 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 | 420 ------ src/uu/hashsum/src/main.rs | 1 - src/uucore/src/lib/features/checksum/mod.rs | 3 + .../src/lib/features/checksum/validate.rs | 1 - src/uucore/src/lib/lib.rs | 4 +- tests/by-util/test_cksum.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/show-utils.BAT | 4 +- util/show-utils.sh | 4 +- 64 files changed, 125 insertions(+), 1939 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 26620b01291..b27b8f59b53 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 a1bda0e7690..c6a2443f6d7 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 28c468d4f9c..f6fdfec2916 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.toml b/Cargo.toml index 6a5796a46c6..801cc8a806a 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 447e90954f7..fdc405eb2cc 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -99,6 +99,14 @@ fn maybe_sanitize_length( #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { + let binary_name = uucore::util_name(); + // Mimic md5sum, b2sum,... by putting --untagged. clap can't do it yet. + let is_cksum = binary_name.ends_with("cksum"); + let mut args: Vec = args.collect(); + if !is_cksum && !args.is_empty() { + args.insert(1, OsString::from("--untagged")); + } + let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?; let check = matches.get_flag(options::CHECK); @@ -109,13 +117,25 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let strict = matches.get_flag(options::STRICT); let status = matches.get_flag(options::STATUS); - let algo_cli = matches - .get_one::(options::ALGORITHM) - .map(AlgoKind::from_cksum) - .transpose()?; + // 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()?, + }; 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)?; @@ -126,20 +146,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .unwrap() .map(|s| s.as_os_str()); + // https://github.com/clap-rs/clap/issues/4520 bypasses --warn --binary + // clap 5 should fix them... + if !check & (warn || strict || quiet || ignore_missing || status) { + return Err(uucore::error::UUsageError::new( + 1, + "the following required arguments were not provided:\n--check".to_string(), + )); + } if check { // cksum does not support '--check'ing legacy algorithms if algo_cli.is_some_and(AlgoKind::is_legacy) { return Err(ChecksumError::AlgorithmNotSupportedWithCheck.into()); } - let text_flag = matches.get_flag(options::TEXT); - let binary_flag = matches.get_flag(options::BINARY); - let tag = matches.get_flag(options::TAG); - - if tag || binary_flag || text_flag { - return Err(ChecksumError::BinaryTextConflict.into()); - } - // Execute the checksum validation based on the presence of files or the use of stdin let verbose = ChecksumVerbose::new(status, quiet, warn); @@ -153,16 +173,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } // Not --check - // Print hardware debug info if requested - if matches.get_flag(options::DEBUG) { + if is_cksum && matches.get_flag(options::DEBUG) { print_cpu_debug_info(); } // Set the default algorithm to CRC when not '--check'ing. let algo_kind = algo_cli.unwrap_or(AlgoKind::Crc); + // clap can't set default args. So we adjust tag related flags. + // (Should we use shebang wrapper instead?) - let tag = !matches.get_flag(options::UNTAGGED); // Making TAG default at clap blocks --untagged + let tag = !matches.get_flag(options::UNTAGGED); let binary = matches.get_flag(options::BINARY); let algo = SizedAlgoKind::from_unsized(algo_kind, length)?; @@ -186,13 +207,39 @@ 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) - .args_override_self(true) + .args_override_self(true); + 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::DEBUG) + .long(options::DEBUG) + .help(translate!("cksum-help-debug")) + .action(ArgAction::SetTrue), + ); + } + app = app + .arg( + Arg::new(options::UNTAGGED) + .long(options::UNTAGGED) + .help(translate!("cksum-help-untagged")) + .action(ArgAction::SetTrue) + .overrides_with(options::TAG), + ) .arg( Arg::new(options::FILE) .hide(true) @@ -202,21 +249,6 @@ pub fn uu_app() -> Command { .hide_default_value(true) .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) @@ -226,13 +258,6 @@ pub fn uu_app() -> Command { .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) @@ -251,6 +276,9 @@ pub fn uu_app() -> Command { .short('c') .long(options::CHECK) .help(translate!("cksum-help-check")) + .conflicts_with(options::TAG) + .conflicts_with(options::BINARY) + .conflicts_with(options::TEXT) .action(ArgAction::SetTrue), ) .arg( @@ -258,8 +286,6 @@ pub fn uu_app() -> Command { .long(options::BASE64) .help(translate!("cksum-help-base64")) .action(ArgAction::SetTrue) - // Even though this could easily just override an earlier '--raw', - // GNU cksum does not permit these flags to be combined: .conflicts_with(options::RAW), ) .arg( @@ -267,7 +293,6 @@ pub fn uu_app() -> Command { .long(options::TEXT) .short('t') .hide(true) - .overrides_with(options::BINARY) .action(ArgAction::SetTrue) .requires(options::UNTAGGED), ) @@ -317,12 +342,15 @@ pub fn uu_app() -> Command { .short('z') .help(translate!("cksum-help-zero")) .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::DEBUG) - .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), + ); + } + 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 3bc6dcff5b2..00000000000 --- a/src/uu/hashsum/src/hashsum.rs +++ /dev/null @@ -1,420 +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 ignore_missing = matches.get_flag("ignore-missing"); - let warn = matches.get_flag("warn"); - let quiet = matches.get_flag("quiet"); - let strict = matches.get_flag("strict"); - let status = matches.get_flag("status"); - - // clap provides the default value -. So we unwrap() safety. - let files = matches - .get_many::(options::FILE) - .unwrap() - .map(|s| s.as_os_str()); - - 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]) - .requires(options::CHECK), - ) - .arg( - Arg::new(options::STATUS) - .short('s') - .long("status") - .help(translate!("hashsum-help-status")) - .action(ArgAction::SetTrue) - .overrides_with_all([options::QUIET, options::WARN]) - .requires(options::CHECK), - ) - .arg( - Arg::new(options::STRICT) - .long("strict") - .help(translate!("hashsum-help-strict")) - .action(ArgAction::SetTrue) - .requires(options::CHECK), - ) - .arg( - Arg::new("ignore-missing") - .long("ignore-missing") - .help(translate!("hashsum-help-ignore-missing")) - .action(ArgAction::SetTrue) - .requires(options::CHECK), - ) - .arg( - Arg::new(options::WARN) - .short('w') - .long("warn") - .help(translate!("hashsum-help-warn")) - .action(ArgAction::SetTrue) - .overrides_with_all([options::QUIET, options::STATUS]) - .requires(options::CHECK), - ) - .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) - .default_value("-") - .hide_default_value(true) - .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/mod.rs b/src/uucore/src/lib/features/checksum/mod.rs index 7cf7fe129fa..2f3d28b4121 100644 --- a/src/uucore/src/lib/features/checksum/mod.rs +++ b/src/uucore/src/lib/features/checksum/mod.rs @@ -374,6 +374,9 @@ pub enum ChecksumError { #[error("the --raw option is not supported with multiple files")] RawMultipleFiles, + #[error("the --{0} option is meaningful only when verifying checksums")] + CheckOnlyFlag(String), + // --length sanitization errors #[error("--length required for {}", .0.quote())] LengthRequired(String), 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_cksum.rs b/tests/by-util/test_cksum.rs index d1abe3409ba..944015688e9 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -1216,7 +1216,7 @@ fn test_conflicting_options() { .fails_with_code(1) .no_stdout() .stderr_contains( - "cksum: the --binary and --text options are meaningless when verifying checksums", + "cannot be used with", //clap generated message ); scene @@ -1228,7 +1228,7 @@ fn test_conflicting_options() { .fails_with_code(1) .no_stdout() .stderr_contains( - "cksum: the --binary and --text options are meaningless when verifying checksums", + "cannot be used with", //clap generated message ); } diff --git a/tests/by-util/test_hashsum.rs b/tests/by-util/test_hashsum.rs deleted file mode 100644 index 891cb9d4dfd..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 following required arguments were not provided"); //clap generated error -} - -#[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("the following required arguments were not provided"); //clap generated error - scene - .ccmd("md5sum") - .arg("--strict") - .arg(at.subdir.join("in.md5")) - .fails() - .stderr_contains("the following required arguments were not provided"); //clap generated error -} - -#[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 f17c6064d04e4ff950a57e00fba66ea34bb00e4a Mon Sep 17 00:00:00 2001 From: oech3 <> Date: Mon, 12 Jan 2026 13:22:41 +0900 Subject: [PATCH 2/2] Fix translation --- src/uu/cksum/locales/en-US.ftl | 14 +++++++------- src/uu/cksum/locales/fr-FR.ftl | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/uu/cksum/locales/en-US.ftl b/src/uu/cksum/locales/en-US.ftl index 2c29e7f31f4..b7b80008468 100644 --- a/src/uu/cksum/locales/en-US.ftl +++ b/src/uu/cksum/locales/en-US.ftl @@ -1,22 +1,22 @@ cksum-about = Print checksum and size for each file -cksum-usage = cksum (multicall-binary for *sum) [OPTIONS] [FILE]... +cksum-usage = cksum (multicall-binary for {md5,b2,sha*}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: (default if binary name is cksum) + - crc: (equivalent to cksum) - crc32b: (only available through cksum) - - md5: (binary name : md5sum) - - sha1: (binary name : sha1sum) - - sha2: (binary name : sha{"{224,256,384,512}"}sum) + - md5: (equivalent to md5sum) + - sha1: (equivalent to sha1sum) + - sha2: (equivalent to sha{"{224,256,384,512}"}sum) - sha3: (only available through cksum) - - blake2b: (binary name : b2sum) + - blake2b: (equivalent to 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 (default if binary name is cksum) +cksum-help-tag = create a BSD style checksum (default of 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 81cf976cdc1..456f0fe4016 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 ckecksum et la taille de chaque fichier -cksum-usage = cksum (multicall-binary for *sum) [OPTION]... [FICHIER]... +cksum-usage = cksum (multicall-binary for {md5,b2,sha*}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 : (binary name : md5sum) - - sha1 : (binary name : sha1sum) - - sha2: (binary name : sha{"{224,256,384,512}"}sum) + - md5 : (équivalent à md5sum) + - sha1 : (équivalent à sha1sum) + - sha2: (équivalent à sha{"{224,256,384,512}"}sum) - sha3 : (disponible uniquement via cksum) - - blake2b : (binary name : b2sum) + - blake2b : (équivalent à 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 (default if binary name is cksum) +cksum-help-tag = créer une somme de contrôle de style BSD, annuler --untagged (default of 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