From ad6c8e1181a3966e35d68c1c354deb1c73f3e974 Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?= Date: Mon, 6 Sep 2021 15:17:12 +0100 Subject: [PATCH] cksum: add --algorithm option to select digest mode * src/digest.c: Organize HASH_ALGO_CKSUM to be table driven, and amalgamate all digest algorithms. (main): Parse all options if HASH_ALGO_CKSUM, and disallow --tag, --zero, and --check with the traditional bsd, sysv, and crc checksums for now. * src/local.mk: Reorganize to include all digest modules in cksum. * tests/misc/cksum-a.sh: Add a new test. * tests/misc/b2sum.sh: Update to default to checking with cksum, as b2sum's implementation diverges a bit from the others. * tests/local.mk: Reference the new test. * doc/coreutils.texi (cksum invocation): Adjust the summary to identify the new mode, and document the new --algorithm option. * man/cksum.x: Adjust description to be more general. * man/*sum.x: Add [See Also] section referencing cksum(1). * NEWS: Mention the new feature. --- NEWS | 7 +- doc/coreutils.texi | 59 ++++++--- man/b2sum.x | 2 + man/cksum.x | 2 +- man/md5sum.x | 2 + man/sha1sum.x | 2 + man/sha224sum.x | 2 + man/sha256sum.x | 2 + man/sha384sum.x | 2 + man/sha512sum.x | 2 + src/digest.c | 302 +++++++++++++++++++++++++++++++++++------- src/local.mk | 27 ++-- tests/local.mk | 1 + tests/misc/b2sum.sh | 27 ++-- tests/misc/cksum-a.sh | 43 ++++++ 15 files changed, 395 insertions(+), 87 deletions(-) create mode 100755 tests/misc/cksum-a.sh diff --git a/NEWS b/NEWS index d9ab04529a..1db2bd0707 100644 --- a/NEWS +++ b/NEWS @@ -88,6 +88,11 @@ GNU coreutils NEWS -*- outline -*- ** New Features + cksum now supports the -a (--algorithm) option to select any + of the existing sum, md5sum, b2sum, sha*sum implementations etc. + cksum now subsumes all of these programs, and coreutils + will introduce no future standalone checksum utility. + expr and factor now support bignums on all platforms. ls --classify now supports the "always", "auto", or "never" flags, @@ -110,7 +115,7 @@ GNU coreutils NEWS -*- outline -*- cat --show-ends will now show \r\n as ^M$. Previously the \r was taken literally, thus overwriting the first character in the line with '$'. - cksum is now up to 4 times faster by using a slice by 8 algorithm, + cksum [-a crc] is now up to 4 times faster by using a slice by 8 algorithm, and at least 8 times faster where pclmul instructions are supported. A new --debug option will indicate if pclmul is being used. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 960df8a355..0cb478964e 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -3922,44 +3922,71 @@ next section) is preferable in new applications. @node cksum invocation -@section @command{cksum}: Print CRC checksum and byte counts +@section @command{cksum}: Print and verify file checksums @pindex cksum @cindex cyclic redundancy check @cindex CRC checksum +@cindex digest -@command{cksum} computes a cyclic redundancy check (CRC) checksum for each -given @var{file}, or standard input if none are given or for a -@var{file} of @samp{-}. Synopsis: +@command{cksum} by default computes a cyclic redundancy check (CRC) checksum +for each given @var{file}, or standard input if none are given or for a +@var{file} of @samp{-}. + +cksum also supports the @option{-a,--algorithm} option to select the +digest algorithm to use, and this is the preferred interface +to these digests, subsuming the other standalone checksumming utilities. +Synopsis: @example cksum [@var{option}]@dots{} [@var{file}]@dots{} @end example -@command{cksum} prints the CRC checksum for each file along with the number -of bytes in the file, and the file name unless no arguments were given. - -@command{cksum} is typically used to ensure that files -transferred by unreliable means (e.g., netnews) have not been corrupted, +@command{cksum} is typically used to ensure that files have not been corrupted, by comparing the @command{cksum} output for the received files with the @command{cksum} output for the original files (typically given in the distribution). -The CRC algorithm is specified by the POSIX standard. It is not -compatible with the BSD or System V @command{sum} algorithms (see the -previous section); it is more robust. +@command{cksum} by default prints the POSIX standard CRC checksum +for each file along with the number of bytes in the file, +and the file name unless no arguments were given. -The program accepts the following options. Also see @ref{Common options}. +The same usage and options as the @command{b2sum} +command are supported. @xref{b2sum invocation}. +In addition @command{cksum} supports the following options. @table @samp +@item -a +@itemx --algorithm +@opindex -a +@opindex --algorithm +@cindex digest algorithm +Compute checksums using the specified digest algorithm. + +Supported legacy checksums (which are not supported by @option{--check}): +@example +@samp{sysv} equivalent to @command{sum -s} +@samp{bsd} equivalent to @command{sum -r} +@samp{crc} equivalent to @command{cksum} (the default) +@end example + +Supported more modern digest algorithms are: +@example +@samp{md5} equivalent to @command{md5sum} +@samp{sha1} equivalent to @command{sha1sum} +@samp{sha224} equivalent to @command{sha224sum} +@samp{sha256} equivalent to @command{sha256sum} +@samp{sha384} equivalent to @command{sha384sum} +@samp{sha512} equivalent to @command{sha512sum} +@samp{blake2b} equivalent to @command{b2sum} +@end example + @item --debug @opindex --debug Output extra information to stderr, like the checksum implementation being used. @end table -@exitstatus - @node b2sum invocation @section @command{b2sum}: Print or check BLAKE2 digests @@ -4078,6 +4105,8 @@ If any listed file cannot be opened or read, if any valid line has an MD5 checksum inconsistent with the associated file, or if no valid line is found, @command{md5sum} exits with nonzero status. Otherwise, it exits successfully. +Note the @command{cksum} command doesn't support @option{--check} +with the older @samp{sysv}, @samp{bsd}, or @samp{crc} algorithms. @item --ignore-missing @opindex --ignore-missing diff --git a/man/b2sum.x b/man/b2sum.x index 3ba490aeed..5a857ca156 100644 --- a/man/b2sum.x +++ b/man/b2sum.x @@ -2,3 +2,5 @@ b2sum \- compute and check BLAKE2 message digest [DESCRIPTION] .\" Add any additional description here +[SEE ALSO] +cksum(1) diff --git a/man/cksum.x b/man/cksum.x index b70a5c46b8..28f954c53c 100644 --- a/man/cksum.x +++ b/man/cksum.x @@ -1,4 +1,4 @@ [NAME] -cksum \- checksum and count the bytes in a file +cksum \- compute and verify file checksums [DESCRIPTION] .\" Add any additional description here diff --git a/man/md5sum.x b/man/md5sum.x index bdb6cc7653..3f4cc6409a 100644 --- a/man/md5sum.x +++ b/man/md5sum.x @@ -7,3 +7,5 @@ Do not use the MD5 algorithm for security related purposes. Instead, use an SHA\-2 algorithm, implemented in the programs sha224sum(1), sha256sum(1), sha384sum(1), sha512sum(1), or the BLAKE2 algorithm, implemented in b2sum(1) +[SEE ALSO] +cksum(1) diff --git a/man/sha1sum.x b/man/sha1sum.x index ef0852f4d1..8fd824f109 100644 --- a/man/sha1sum.x +++ b/man/sha1sum.x @@ -7,3 +7,5 @@ Do not use the SHA-1 algorithm for security related purposes. Instead, use an SHA\-2 algorithm, implemented in the programs sha224sum(1), sha256sum(1), sha384sum(1), sha512sum(1), or the BLAKE2 algorithm, implemented in b2sum(1) +[SEE ALSO] +cksum(1) diff --git a/man/sha224sum.x b/man/sha224sum.x index 8e010a8f06..38a64d29c5 100644 --- a/man/sha224sum.x +++ b/man/sha224sum.x @@ -2,3 +2,5 @@ sha224sum \- compute and check SHA224 message digest [DESCRIPTION] .\" Add any additional description here +[SEE ALSO] +cksum(1) diff --git a/man/sha256sum.x b/man/sha256sum.x index a6cfa36c32..4ad8b35085 100644 --- a/man/sha256sum.x +++ b/man/sha256sum.x @@ -2,3 +2,5 @@ sha256sum \- compute and check SHA256 message digest [DESCRIPTION] .\" Add any additional description here +[SEE ALSO] +cksum(1) diff --git a/man/sha384sum.x b/man/sha384sum.x index 87a5a0092e..a8c09cd62c 100644 --- a/man/sha384sum.x +++ b/man/sha384sum.x @@ -2,3 +2,5 @@ sha384sum \- compute and check SHA384 message digest [DESCRIPTION] .\" Add any additional description here +[SEE ALSO] +cksum(1) diff --git a/man/sha512sum.x b/man/sha512sum.x index b38b6b4647..308bf51eec 100644 --- a/man/sha512sum.x +++ b/man/sha512sum.x @@ -2,3 +2,5 @@ sha512sum \- compute and check SHA512 message digest [DESCRIPTION] .\" Add any additional description here +[SEE ALSO] +cksum(1) diff --git a/src/digest.c b/src/digest.c index 6a48bfddcb..8039c671e7 100644 --- a/src/digest.c +++ b/src/digest.c @@ -27,25 +27,25 @@ #include "xdectoint.h" #include "xstrtol.h" -#if HASH_ALGO_SUM +#if HASH_ALGO_SUM || HASH_ALGO_CKSUM # include "sum.h" #endif #if HASH_ALGO_CKSUM # include "cksum.h" #endif -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM # include "blake2/b2sum.h" #endif -#if HASH_ALGO_MD5 +#if HASH_ALGO_MD5 || HASH_ALGO_CKSUM # include "md5.h" #endif -#if HASH_ALGO_SHA1 +#if HASH_ALGO_SHA1 || HASH_ALGO_CKSUM # include "sha1.h" #endif -#if HASH_ALGO_SHA256 || HASH_ALGO_SHA224 +#if HASH_ALGO_SHA256 || HASH_ALGO_SHA224 || HASH_ALGO_CKSUM # include "sha256.h" #endif -#if HASH_ALGO_SHA512 || HASH_ALGO_SHA384 +#if HASH_ALGO_SHA512 || HASH_ALGO_SHA384 || HASH_ALGO_CKSUM # include "sha512.h" #endif #include "die.h" @@ -63,12 +63,14 @@ # define DIGEST_BITS 16 # define DIGEST_ALIGN 4 #elif HASH_ALGO_CKSUM +# define MAX_DIGEST_BITS 512 +# define MAX_DIGEST_ALIGN 8 # define PROGRAM_NAME "cksum" -# define DIGEST_TYPE_STRING "CRC" -# define DIGEST_STREAM crc_sum_stream -# define DIGEST_OUT output_crc -# define DIGEST_BITS 32 -# define DIGEST_ALIGN 4 +# define DIGEST_TYPE_STRING algorithm_tags[cksum_algorithm] +# define DIGEST_STREAM cksumfns[cksum_algorithm] +# define DIGEST_OUT cksum_output_fns[cksum_algorithm] +# define DIGEST_BITS MAX_DIGEST_BITS +# define DIGEST_ALIGN MAX_DIGEST_ALIGN #elif HASH_ALGO_MD5 # define PROGRAM_NAME "md5sum" # define DIGEST_TYPE_STRING "MD5" @@ -79,7 +81,7 @@ #elif HASH_ALGO_BLAKE2 # define PROGRAM_NAME "b2sum" # define DIGEST_TYPE_STRING "BLAKE2" -# define DIGEST_STREAM blake2fns[b2_algorithm] +# define DIGEST_STREAM blake2b_stream # define DIGEST_BITS 512 # define DIGEST_REFERENCE "RFC 7693" # define DIGEST_ALIGN 8 @@ -141,15 +143,14 @@ proper_name ("Scott Miller"), \ proper_name ("David Madore") #endif -#if !HASH_ALGO_BLAKE2 +#if !HASH_ALGO_BLAKE2 && !HASH_ALGO_CKSUM # define DIGEST_HEX_BYTES (DIGEST_BITS / 4) #endif #define DIGEST_BIN_BYTES (DIGEST_BITS / 8) - /* The minimum length of a valid digest line. This length does not include any newline character at the end of a line. */ -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM # define MIN_DIGEST_LINE_LENGTH 3 /* With -l 8. */ #else # define MIN_DIGEST_LINE_LENGTH \ @@ -158,6 +159,12 @@ + 1 /* minimum filename length */ ) #endif +#if !HASH_ALGO_SUM +static void +output_file (char const *file, int binary_file, void const *digest, + bool tagged, bool args _GL_UNUSED, uintmax_t length _GL_UNUSED); +#endif + /* True if any of the files read were the standard input. */ static bool have_read_stdin; @@ -191,7 +198,7 @@ static int bsd_reversed = -1; /* line delimiter. */ static unsigned char delim = '\n'; -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM static char const *const algorithm_in_string[] = { "blake2b", NULL @@ -200,19 +207,15 @@ static char const *const algorithm_out_string[] = { "BLAKE2b", NULL }; -enum Algorithm +enum blake2_Algorithm { BLAKE2b }; verify (ARRAY_CARDINALITY (algorithm_in_string) == 2); verify (ARRAY_CARDINALITY (algorithm_out_string) == 2); -static enum Algorithm b2_algorithm; +static enum blake2_Algorithm b2_algorithm; static uintmax_t b2_length; -static blake2fn blake2fns[]= -{ - blake2b_stream -}; static uintmax_t blake2_max_len[]= { BLAKE2B_OUTBYTES @@ -242,6 +245,109 @@ static digest_output_fn sum_output_fns[]= #endif #if HASH_ALGO_CKSUM +static int +md5_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return md5_stream (stream, resstream); +} +static int +sha1_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return sha1_stream (stream, resstream); +} +static int +sha224_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return sha224_stream (stream, resstream); +} +static int +sha256_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return sha256_stream (stream, resstream); +} +static int +sha384_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return sha384_stream (stream, resstream); +} +static int +sha512_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return sha512_stream (stream, resstream); +} +static int +blake2b_sum_stream (FILE *stream, void *resstream, uintmax_t *length) +{ + return blake2b_stream (stream, resstream, *length); +} + +enum Algorithm +{ + bsd, + sysv, + crc, + md5, + sha1, + sha224, + sha256, + sha384, + sha512, + blake2b, +}; + +static char const *const algorithm_args[] = +{ + "bsd", "sysv", "crc", "md5", "sha1", "sha224", + "sha256", "sha384", "sha512", "blake2b", NULL +}; +static enum Algorithm const algorithm_types[] = +{ + bsd, sysv, crc, md5, sha1, sha224, + sha256, sha384, sha512, blake2b, +}; +ARGMATCH_VERIFY (algorithm_args, algorithm_types); + +static char const *const algorithm_tags[] = +{ + "BSD", "SYSV", "CRC", "MD5", "SHA1", "SHA224", + "SHA256", "SHA384", "SHA512", "BLAKE2b", NULL +}; +static int const algorithm_bits[] = +{ + 16, 16, 32, 128, 160, 224, + 256, 384, 512, 512, 0 +}; + +verify (ARRAY_CARDINALITY (algorithm_bits) + == ARRAY_CARDINALITY (algorithm_args)); + +static enum Algorithm cksum_algorithm = crc; +static sumfn cksumfns[]= +{ + bsd_sum_stream, + sysv_sum_stream, + crc_sum_stream, + md5_sum_stream, + sha1_sum_stream, + sha224_sum_stream, + sha256_sum_stream, + sha384_sum_stream, + sha512_sum_stream, + blake2b_sum_stream, +}; +static digest_output_fn cksum_output_fns[]= +{ + output_bsd, + output_sysv, + output_crc, + output_file, + output_file, + output_file, + output_file, + output_file, + output_file, + output_file, +}; bool cksum_debug; #endif @@ -260,10 +366,10 @@ enum static struct option const long_options[] = { -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM { "length", required_argument, NULL, 'l'}, #endif -#if !HASH_AGLO_SUM && !HASH_ALGO_CKSUM +#if !HASH_ALGO_SUM { "binary", no_argument, NULL, 'b' }, { "check", no_argument, NULL, 'c' }, { "ignore-missing", no_argument, NULL, IGNORE_MISSING_OPTION}, @@ -276,6 +382,7 @@ static struct option const long_options[] = { "zero", no_argument, NULL, 'z' }, #endif #if HASH_ALGO_CKSUM + {"algorithm", required_argument, NULL, 'a'}, {"debug", no_argument, NULL, DEBUG_PROGRAM_OPTION}, #endif #if HASH_ALGO_SUM @@ -295,11 +402,19 @@ usage (int status) { printf (_("\ Usage: %s [OPTION]... [FILE]...\n\ +"), program_name); +#if HASH_ALGO_CKSUM + fputs (_("\ +Print or verify checksums.\n\ +By default use the 32 bit CRC algorithm.\n\ +"), stdout); +#else + printf (_("\ Print or check %s (%d-bit) checksums.\n\ "), - program_name, DIGEST_TYPE_STRING, DIGEST_BITS); +#endif emit_stdin_note (); #if HASH_ALGO_SUM @@ -309,22 +424,27 @@ Print or check %s (%d-bit) checksums.\n\ -s, --sysv use System V sum algorithm, use 512 bytes blocks\n\ "), stdout); #endif -#if !HASH_ALGO_SUM && !HASH_ALGO_CKSUM - if (O_BINARY) +#if HASH_ALGO_CKSUM fputs (_("\ \n\ + -a, --algorithm select the digest mode to operate in. See DIGEST below.\ +\n\ +"), stdout); +#endif +#if !HASH_ALGO_SUM + if (O_BINARY) + fputs (_("\ -b, --binary read in binary mode (default unless reading tty stdin)\n\ "), stdout); else fputs (_("\ -\n\ -b, --binary read in binary mode\n\ "), stdout); - printf (_("\ - -c, --check read %s sums from the FILEs and check them\n"), - DIGEST_TYPE_STRING); -# if HASH_ALGO_BLAKE2 + fputs (_("\ + -c, --check read checksums from the FILEs and check them\n\ +"), stdout); +# if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM fputs (_("\ -l, --length digest length in bits; must not exceed the maximum for\n\ the blake2 algorithm and must be a multiple of 8\n\ @@ -363,17 +483,40 @@ The following five options are useful only when verifying checksums:\n\ #endif fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); +#if HASH_ALGO_CKSUM + fputs (_("\ +\n\ +DIGEST determines the digest algorithm and default output format:\n\ + 'sysv' (equivalent to sum -s)\n\ + 'bsd' (equivalent to sum -r)\n\ + 'crc' (equivalent to cksum)\n\ + 'md5' (equivalent to md5sum)\n\ + 'sha1' (equivalent to sha1sum)\n\ + 'sha224' (equivalent to sha224sum)\n\ + 'sha256' (equivalent to sha256sum)\n\ + 'sha384' (equivalent to sha384sum)\n\ + 'sha512' (equivalent to sha512sum)\n\ + 'blake2b' (equivalent to b2sum)\n\ +\n"), stdout); +#endif #if !HASH_ALGO_SUM && !HASH_ALGO_CKSUM printf (_("\ \n\ -The sums are computed as described in %s. When checking, the input\n\ -should be a former output of this program. The default mode is to print a\n\ -line with checksum, a space, a character indicating input mode ('*' for binary,\ -\n' ' for text or where binary is insignificant), and name for each FILE.\n\ +The sums are computed as described in %s.\n"), DIGEST_REFERENCE); + fputs (_("\ +When checking, the input should be a former output of this program.\n\ +The default mode is to print a line with: checksum, a space,\n\ +a character indicating input mode ('*' for binary, ' ' for text\n\ +or where binary is insignificant), and name for each FILE.\n\ \n\ Note: There is no difference between binary mode and text mode on GNU systems.\ -\n"), - DIGEST_REFERENCE); +\n"), stdout); +#endif +#if HASH_ALGO_CKSUM + fputs (_("\ +When checking, the input should be a former output of this program,\n\ +or equivalent standalone program.\ +\n"), stdout); #endif emit_ancillary_info (PROGRAM_NAME); } @@ -521,7 +664,10 @@ split_3 (char *s, size_t s_len, if (STREQ_LEN (s + i, DIGEST_TYPE_STRING, algo_name_len)) { i += algo_name_len; -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM +# if HASH_ALGO_CKSUM + if (cksum_algorithm == blake2b) { +# endif /* Terminate and match algorithm name. */ char const *algo_name = &s[i - algo_name_len]; /* Skip algorithm variants. */ @@ -550,7 +696,9 @@ split_3 (char *s, size_t s_len, i = siend - s; b2_length = length; } - +# if HASH_ALGO_CKSUM + } +# endif digest_hex_bytes = b2_length / 4; #endif if (s[i] == ' ') @@ -574,8 +722,11 @@ split_3 (char *s, size_t s_len, *hex_digest = (unsigned char *) &s[i]; -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM /* Auto determine length. */ +# if HASH_ALGO_CKSUM + if (cksum_algorithm == blake2b) { +# endif unsigned char const *hp = *hex_digest; digest_hex_bytes = 0; while (isxdigit (*hp++)) @@ -584,6 +735,9 @@ split_3 (char *s, size_t s_len, || blake2_max_len[b2_algorithm] * 2 < digest_hex_bytes) return false; b2_length = digest_hex_bytes * 4; +# if HASH_ALGO_CKSUM + } +# endif #endif /* The first field has to be the n-character hexadecimal @@ -709,7 +863,11 @@ digest_file (char const *filename, int *binary, unsigned char *bin_result, fadvise (fp, FADVISE_SEQUENTIAL); -#if HASH_ALGO_SUM || HASH_ALGO_CKSUM +#if HASH_ALGO_CKSUM + if (cksum_algorithm == blake2b) + *length = b2_length / 8; + err = DIGEST_STREAM (fp, bin_result, length); +#elif HASH_ALGO_SUM err = DIGEST_STREAM (fp, bin_result, length); #elif HASH_ALGO_BLAKE2 err = DIGEST_STREAM (fp, bin_result, b2_length / 8); @@ -731,7 +889,7 @@ digest_file (char const *filename, int *binary, unsigned char *bin_result, return true; } -#if !HASH_ALGO_SUM && !HASH_ALGO_CKSUM +#if !HASH_ALGO_SUM static void output_file (char const *file, int binary_file, void const *digest, bool tagged, bool args _GL_UNUSED, uintmax_t length _GL_UNUSED) @@ -758,6 +916,13 @@ output_file (char const *file, int binary_file, void const *digest, printf ("-%"PRIuMAX, b2_length); # else fputs (DIGEST_TYPE_STRING, stdout); +# if HASH_ALGO_CKSUM + if (cksum_algorithm == blake2b) + { + if (b2_length < blake2_max_len[b2_algorithm] * 8) + printf ("-%"PRIuMAX, b2_length); + } +# endif # endif fputs (" (", stdout); print_filename (file, needs_escape); @@ -876,7 +1041,8 @@ digest_check (char const *checkfile_name) properly_formatted_lines = true; - ok = digest_file (filename, &binary, bin_buffer, &missing, NULL); + uintmax_t length; + ok = digest_file (filename, &binary, bin_buffer, &missing, &length); if (!ok) { @@ -1023,7 +1189,8 @@ main (int argc, char **argv) #if HASH_ALGO_SUM const char* short_opts = "rs"; #elif HASH_ALGO_CKSUM - const char* short_opts = ""; + const char* short_opts = "a:l:bctwz"; + const char* b2_length_str = ""; #elif HASH_ALGO_BLAKE2 const char* short_opts = "l:bctwz"; const char* b2_length_str = ""; @@ -1035,11 +1202,16 @@ main (int argc, char **argv) switch (opt) { #if HASH_ALGO_CKSUM + case 'a': + cksum_algorithm = XARGMATCH ("--algorithm", optarg, + algorithm_args, algorithm_types); + break; + case DEBUG_PROGRAM_OPTION: cksum_debug = true; break; #endif -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM case 'l': b2_length = xdectoumax (optarg, 0, UINTMAX_MAX, "", _("invalid length"), 0); @@ -1051,7 +1223,7 @@ main (int argc, char **argv) } break; #endif -#if !HASH_ALGO_SUM && !HASH_ALGO_CKSUM +#if !HASH_ALGO_SUM case 'b': binary = 1; break; @@ -1106,7 +1278,12 @@ main (int argc, char **argv) } min_digest_line_length = MIN_DIGEST_LINE_LENGTH; -#if HASH_ALGO_BLAKE2 +#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM +# if HASH_ALGO_CKSUM + if (b2_length && cksum_algorithm != blake2b) + die (EXIT_FAILURE, 0, + _("--length is only supported with --algorithm=blake2b")); +# endif if (b2_length > blake2_max_len[b2_algorithm] * 8) { error (0, 0, _("invalid length: %s"), quote (b2_length_str)); @@ -1117,11 +1294,40 @@ main (int argc, char **argv) } if (b2_length == 0 && ! do_check) b2_length = blake2_max_len[b2_algorithm] * 8; +# if HASH_ALGO_BLAKE2 digest_hex_bytes = b2_length / 4; +# else + if (cksum_algorithm == blake2b) + digest_hex_bytes = b2_length / 4; + else + digest_hex_bytes = algorithm_bits[cksum_algorithm] / 4; +# endif #else digest_hex_bytes = DIGEST_HEX_BYTES; #endif +#if HASH_ALGO_CKSUM + switch (cksum_algorithm) + { + case bsd: + case sysv: + case crc: + if (delim != '\n') + die (EXIT_FAILURE, 0, + _("--zero is not supported with --algorithm={bsd,sysv,crc}")); + if (prefix_tag) + die (EXIT_FAILURE, 0, + _("--tag is not supported with --algorithm={bsd,sysv,crc}")); + if (do_check) + die (EXIT_FAILURE, 0, + _("--check is not supported with --algorithm={bsd,sysv,crc}")); + break; + default: + break; + } + +#endif + if (prefix_tag && !binary) { /* This could be supported in a backwards compatible way diff --git a/src/local.mk b/src/local.mk index 54303d3052..0c8b65d39a 100644 --- a/src/local.mk +++ b/src/local.mk @@ -304,6 +304,7 @@ src_sha224sum_LDADD += $(LIB_CRYPTO) src_sha256sum_LDADD += $(LIB_CRYPTO) src_sha384sum_LDADD += $(LIB_CRYPTO) src_sha512sum_LDADD += $(LIB_CRYPTO) +src_cksum_LDADD += $(LIB_CRYPTO) # for canon_host src_pinky_LDADD += $(GETADDRINFO_LIB) @@ -355,18 +356,6 @@ src___SOURCES = src/lbracket.c nodist_src_coreutils_SOURCES = src/coreutils.h src_coreutils_SOURCES = src/coreutils.c -src_sum_SOURCES = src/sum.c src/sum.h src/digest.c -src_sum_CPPFLAGS = -DHASH_ALGO_SUM=1 $(AM_CPPFLAGS) - -src_cksum_SOURCES = src/cksum.c src/cksum.h src/crctab.c src/digest.c -src_cksum_CPPFLAGS = -DHASH_ALGO_CKSUM=1 $(AM_CPPFLAGS) -if USE_PCLMUL_CRC32 -noinst_LIBRARIES += src/libcksum_pclmul.a -src_libcksum_pclmul_a_SOURCES = src/cksum_pclmul.c src/cksum.h -cksum_pclmul_ldadd = src/libcksum_pclmul.a -src_cksum_LDADD += $(cksum_pclmul_ldadd) -src_libcksum_pclmul_a_CFLAGS = -mavx -mpclmul $(AM_CFLAGS) -endif src_cp_SOURCES = src/cp.c $(copy_sources) $(selinux_sources) src_dir_SOURCES = src/ls.c src/ls-dir.c src_env_SOURCES = src/env.c src/operand2sig.c @@ -401,6 +390,9 @@ src_arch_SOURCES = src/uname.c src/uname-arch.c src_cut_SOURCES = src/cut.c src/set-fields.c src_numfmt_SOURCES = src/numfmt.c src/set-fields.c +src_sum_SOURCES = src/sum.c src/sum.h src/digest.c +src_sum_CPPFLAGS = -DHASH_ALGO_SUM=1 $(AM_CPPFLAGS) + src_md5sum_SOURCES = src/digest.c src_md5sum_CPPFLAGS = -DHASH_ALGO_MD5=1 $(AM_CPPFLAGS) src_sha1sum_SOURCES = src/digest.c @@ -419,6 +411,17 @@ src_b2sum_SOURCES = src/digest.c \ src/blake2/blake2b-ref.c \ src/blake2/b2sum.c src/blake2/b2sum.h +src_cksum_SOURCES = $(src_b2sum_SOURCES) src/sum.c src/sum.h \ + src/cksum.c src/cksum.h src/crctab.c +src_cksum_CPPFLAGS = -DHASH_ALGO_CKSUM=1 -DHAVE_CONFIG_H $(AM_CPPFLAGS) +if USE_PCLMUL_CRC32 +noinst_LIBRARIES += src/libcksum_pclmul.a +src_libcksum_pclmul_a_SOURCES = src/cksum_pclmul.c src/cksum.h +cksum_pclmul_ldadd = src/libcksum_pclmul.a +src_cksum_LDADD += $(cksum_pclmul_ldadd) +src_libcksum_pclmul_a_CFLAGS = -mavx -mpclmul $(AM_CFLAGS) +endif + src_base64_SOURCES = src/basenc.c src_base64_CPPFLAGS = -DBASE_TYPE=64 $(AM_CPPFLAGS) src_base32_SOURCES = src/basenc.c diff --git a/tests/local.mk b/tests/local.mk index 4a08147dff..3ddd6f1bb8 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -289,6 +289,7 @@ all_tests = \ tests/misc/close-stdout.sh \ tests/misc/chroot-fail.sh \ tests/misc/cksum.sh \ + tests/misc/cksum-a.sh \ tests/misc/comm.pl \ tests/misc/csplit.sh \ tests/misc/csplit-1000.sh \ diff --git a/tests/misc/b2sum.sh b/tests/misc/b2sum.sh index 730516cb8c..c5242bed21 100755 --- a/tests/misc/b2sum.sh +++ b/tests/misc/b2sum.sh @@ -17,38 +17,45 @@ # along with this program. If not, see . . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src -print_ver_ b2sum +print_ver_ cksum + +for prog in 'b2sum' 'cksum -a blake2b'; do +# Also check b2sum if built +[ "$prog" = 'b2sum' ] && { $prog --version || continue; } # Ensure we can --check the --tag format we produce -rm check.b2sum +rm -f check.b2sum || framework_failure_ for i in 'a' ' b' '*c' '44' ' '; do echo "$i" > "$i" for l in 0 128; do - b2sum -l $l --tag "$i" >> check.b2sum + $prog -l $l --tag "$i" >> check.b2sum done done # Note -l is inferred from the tags in the mixed format file -b2sum --strict -c check.b2sum || fail=1 +$prog --strict -c check.b2sum || fail=1 # Also ensure the openssl tagged variant works sed 's/ //; s/ =/=/' < check.b2sum > openssl.b2sum || framework_failure_ -b2sum --strict -c openssl.b2sum || fail=1 +$prog --strict -c openssl.b2sum || fail=1 +rm -f check.vals || framework_failure_ # Ensure we can check non tagged format for l in 0 128; do - b2sum -l $l /dev/null | tee -a check.vals > check.b2sum - b2sum -l $l --strict -c check.b2sum || fail=1 - b2sum --strict -c check.b2sum || fail=1 + $prog -l $l /dev/null | tee -a check.vals > check.b2sum + $prog -l $l --strict -c check.b2sum || fail=1 + $prog --strict -c check.b2sum || fail=1 done # Ensure the checksum values are correct. The reference # check.vals was created with the upstream SSE reference implementation. -b2sum -l 128 check.vals > out || fail=1 +$prog --length=128 check.vals > out || fail=1 printf '%s\n' '796485dd32fe9b754ea5fd6c721271d9 check.vals' > exp compare exp out || fail=1 # This would segfault from coreutils-8.26 to coreutils-8.28 printf '%s\n' 'BLAKE2' 'BLAKE2b' 'BLAKE2-' 'BLAKE2(' 'BLAKE2 (' > crash.check \ || framework_failure_ -returns_ 1 b2sum -c crash.check || fail=1 +returns_ 1 $prog -c crash.check || fail=1 + +done Exit $fail diff --git a/tests/misc/cksum-a.sh b/tests/misc/cksum-a.sh new file mode 100755 index 0000000000..7d95b69a44 --- /dev/null +++ b/tests/misc/cksum-a.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# Validate cksum --algorithm operation + +# Copyright (C) 2021 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ cksum + +printf " +bsd sum -r +sysv sum -s +crc cksum +md5 md5um -t +sha1 sha1sum -t +sha224 sha224sum -t +sha256 sha256sum -t +sha384 sha384sum -t +sha512 sha512sum -t +blake2b b2sum -t +" | while read algo prog; do + $prog < /dev/null >> out || continue + cksum --algorithm=$algo < /dev/null >> out-a || fail=1 +done +compare out out-a || fail=1 + +returns_ 1 cksum -a bsd --tag