diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/coreutils.texi | 8 | ||||
-rw-r--r-- | src/md5sum.c | 34 | ||||
-rwxr-xr-x | tests/misc/md5sum.pl | 23 |
4 files changed, 67 insertions, 2 deletions
@@ -17,6 +17,10 @@ GNU coreutils NEWS -*- outline -*- ** New features + md5sum now supports the --ignore-missing option to allow + verifying a subset of files given a larger list of checksums. + This also affects sha1sum, sha224sum, sha256sum, sha384sum and sha512sum. + printf now supports the '%q' format to print arguments in a form that is reusable by most shells, with non-printable characters escaped with the POSIX proposed $'...' syntax. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 0e28f4971..7918aec6a 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -3830,6 +3830,14 @@ 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. +@item --ignore-missing +@opindex --ignore-missing +@cindex verifying MD5 checksums +This option is useful only when verifying checksums. +When verifying checksums, don't fail or report any status +for missing files. This is useful when verifying a subset +of downloaded files given a larger list of checksums. + @item --quiet @opindex --quiet @cindex verifying MD5 checksums diff --git a/src/md5sum.c b/src/md5sum.c index 5d4b958ee..49da8edc4 100644 --- a/src/md5sum.c +++ b/src/md5sum.c @@ -119,6 +119,9 @@ static bool status_only = false; improperly formatted checksum line. */ static bool warn = false; +/* With --check, ignore missing files. */ +static bool ignore_missing = false; + /* With --check, suppress the "OK" printed for each verified file. */ static bool quiet = false; @@ -133,7 +136,8 @@ static int bsd_reversed = -1; non-character as a pseudo short option, starting with CHAR_MAX + 1. */ enum { - STATUS_OPTION = CHAR_MAX + 1, + IGNORE_MISSING_OPTION = CHAR_MAX + 1, + STATUS_OPTION, QUIET_OPTION, STRICT_OPTION, TAG_OPTION @@ -143,6 +147,7 @@ static struct option const long_options[] = { { "binary", no_argument, NULL, 'b' }, { "check", no_argument, NULL, 'c' }, + { "ignore-missing", no_argument, NULL, IGNORE_MISSING_OPTION}, { "quiet", no_argument, NULL, QUIET_OPTION }, { "status", no_argument, NULL, STATUS_OPTION }, { "text", no_argument, NULL, 't' }, @@ -197,7 +202,8 @@ Print or check %s (%d-bit) checksums.\n\ "), stdout); fputs (_("\ \n\ -The following four options are useful only when verifying checksums:\n\ +The following five options are useful only when verifying checksums:\n\ + --ignore-missing don't fail or report status for missing files\n\ --quiet don't print OK for each successfully verified file\n\ --status don't output anything, status code shows success\n\ --strict exit non-zero for improperly formatted checksum lines\n\ @@ -482,6 +488,11 @@ digest_file (const char *filename, int *binary, unsigned char *bin_result) fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r")); if (fp == NULL) { + if (ignore_missing && errno == ENOENT) + { + *bin_result = '\0'; + return true; + } error (0, errno, "%s", quotef (filename)); return false; } @@ -597,6 +608,7 @@ digest_check (const char *checkfile_name) ++n_properly_formatted_lines; + *bin_buffer = '\1'; /* flag set to 0 for ignored missing files. */ ok = digest_file (filename, &binary, bin_buffer); if (!ok) @@ -610,10 +622,17 @@ digest_check (const char *checkfile_name) printf (": %s\n", _("FAILED open or read")); } } + else if (ignore_missing && ! *bin_buffer) + { + /* Treat an empty buffer as meaning a missing file, + which is ignored with --ignore-missing. */ + ; + } else { size_t digest_bin_bytes = digest_hex_bytes / 2; size_t cnt; + /* Compare generated binary number with text representation in check file. Ignore case of hex digits. */ for (cnt = 0; cnt < digest_bin_bytes; ++cnt) @@ -749,6 +768,9 @@ main (int argc, char **argv) warn = true; quiet = false; break; + case IGNORE_MISSING_OPTION: + ignore_missing = true; + break; case QUIET_OPTION: status_only = false; warn = false; @@ -795,6 +817,14 @@ main (int argc, char **argv) usage (EXIT_FAILURE); } + if (ignore_missing && !do_check) + { + error (0, 0, + _("the --ignore-missing option is meaningful only when " + "verifying checksums")); + usage (EXIT_FAILURE); + } + if (status_only && !do_check) { error (0, 0, diff --git a/tests/misc/md5sum.pl b/tests/misc/md5sum.pl index ad1896d53..3a7744bde 100755 --- a/tests/misc/md5sum.pl +++ b/tests/misc/md5sum.pl @@ -25,6 +25,8 @@ my $prog = 'md5sum'; my $degenerate = "d41d8cd98f00b204e9800998ecf8427e"; +my $try_help = "Try 'md5sum --help' for more information.\n"; + my @Tests = ( ['1', {IN=> {f=> ''}}, {OUT=>"$degenerate f\n"}], @@ -120,6 +122,27 @@ my @Tests = ['check-openssl3', '--check', '--status', {IN=> {'f.md5' => "MD5(f)= $degenerate\n"}}, {AUX=> {f=> 'bar'}}, {EXIT=> 1}], + ['check-ignore-missing-1', '--check', '--ignore-missing', + {AUX=> {f=> ''}}, + {IN=> {'f.md5' => "$degenerate f\n". + "$degenerate f.missing\n"}}, + {OUT=>"f: OK\n"}], + ['check-ignore-missing-2', '--check', '--ignore-missing', + {AUX=> {f=> ''}}, + {IN=> {'f.md5' => "$degenerate f\n". + "$degenerate f.missing\n"}}, + {OUT=>"f: OK\n"}], + ['check-ignore-missing-3', '--check', '--quiet', '--ignore-missing', + {AUX=> {f=> ''}}, + {IN=> {'f.md5' => "$degenerate missing/f\n". + "$degenerate f\n"}}, + {OUT=>""}], + ['check-ignore-missing-4', '--ignore-missing', + {IN=> {f=> ''}}, + {ERR=>"md5sum: the --ignore-missing option is ". + "meaningful only when verifying checksums\n". + $try_help}, + {EXIT=> 1}], ['bsd-segv', '--check', {IN=> {'z' => "MD5 ("}}, {EXIT=> 1}, {ERR=> "$prog: z: no properly formatted MD5 checksum lines found\n"}], |