summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--doc/coreutils.texi8
-rw-r--r--src/md5sum.c34
-rwxr-xr-xtests/misc/md5sum.pl23
4 files changed, 67 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index fc5e92787..9f6bff213 100644
--- a/NEWS
+++ b/NEWS
@@ -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"}],