doc: remove colon from node name
[coreutils.git] / src / md5sum.c
blobde847ccb2116f5a3f7a922c7076408c31fd46968
1 /* Compute checksums of files or strings.
2 Copyright (C) 1995-2019 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>. */
19 #include <config.h>
21 #include <getopt.h>
22 #include <sys/types.h>
24 #include "system.h"
25 #include "argmatch.h"
26 #include "quote.h"
27 #include "xdectoint.h"
28 #include "xstrtol.h"
30 #if HASH_ALGO_BLAKE2
31 # include "blake2/b2sum.h"
32 #endif
33 #if HASH_ALGO_MD5
34 # include "md5.h"
35 #endif
36 #if HASH_ALGO_SHA1
37 # include "sha1.h"
38 #endif
39 #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
40 # include "sha256.h"
41 #endif
42 #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
43 # include "sha512.h"
44 #endif
45 #include "die.h"
46 #include "error.h"
47 #include "fadvise.h"
48 #include "stdio--.h"
49 #include "xbinary-io.h"
51 /* The official name of this program (e.g., no 'g' prefix). */
52 #if HASH_ALGO_MD5
53 # define PROGRAM_NAME "md5sum"
54 # define DIGEST_TYPE_STRING "MD5"
55 # define DIGEST_STREAM md5_stream
56 # define DIGEST_BITS 128
57 # define DIGEST_REFERENCE "RFC 1321"
58 # define DIGEST_ALIGN 4
59 #elif HASH_ALGO_BLAKE2
60 # define PROGRAM_NAME "b2sum"
61 # define DIGEST_TYPE_STRING "BLAKE2"
62 # define DIGEST_STREAM blake2fns[b2_algorithm]
63 # define DIGEST_BITS 512
64 # define DIGEST_REFERENCE "RFC 7693"
65 # define DIGEST_ALIGN 8
66 #elif HASH_ALGO_SHA1
67 # define PROGRAM_NAME "sha1sum"
68 # define DIGEST_TYPE_STRING "SHA1"
69 # define DIGEST_STREAM sha1_stream
70 # define DIGEST_BITS 160
71 # define DIGEST_REFERENCE "FIPS-180-1"
72 # define DIGEST_ALIGN 4
73 #elif HASH_ALGO_SHA256
74 # define PROGRAM_NAME "sha256sum"
75 # define DIGEST_TYPE_STRING "SHA256"
76 # define DIGEST_STREAM sha256_stream
77 # define DIGEST_BITS 256
78 # define DIGEST_REFERENCE "FIPS-180-2"
79 # define DIGEST_ALIGN 4
80 #elif HASH_ALGO_SHA224
81 # define PROGRAM_NAME "sha224sum"
82 # define DIGEST_TYPE_STRING "SHA224"
83 # define DIGEST_STREAM sha224_stream
84 # define DIGEST_BITS 224
85 # define DIGEST_REFERENCE "RFC 3874"
86 # define DIGEST_ALIGN 4
87 #elif HASH_ALGO_SHA512
88 # define PROGRAM_NAME "sha512sum"
89 # define DIGEST_TYPE_STRING "SHA512"
90 # define DIGEST_STREAM sha512_stream
91 # define DIGEST_BITS 512
92 # define DIGEST_REFERENCE "FIPS-180-2"
93 # define DIGEST_ALIGN 8
94 #elif HASH_ALGO_SHA384
95 # define PROGRAM_NAME "sha384sum"
96 # define DIGEST_TYPE_STRING "SHA384"
97 # define DIGEST_STREAM sha384_stream
98 # define DIGEST_BITS 384
99 # define DIGEST_REFERENCE "FIPS-180-2"
100 # define DIGEST_ALIGN 8
101 #else
102 # error "Can't decide which hash algorithm to compile."
103 #endif
105 #if HASH_ALGO_BLAKE2
106 # define AUTHORS \
107 proper_name ("Padraig Brady"), \
108 proper_name ("Samuel Neves")
109 #else
110 # define AUTHORS \
111 proper_name ("Ulrich Drepper"), \
112 proper_name ("Scott Miller"), \
113 proper_name ("David Madore")
114 # define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
115 #endif
116 #define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
119 /* The minimum length of a valid digest line. This length does
120 not include any newline character at the end of a line. */
121 #if HASH_ALGO_BLAKE2
122 # define MIN_DIGEST_LINE_LENGTH 3 /* With -l 8. */
123 #else
124 # define MIN_DIGEST_LINE_LENGTH \
125 (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
126 + 1 /* blank */ \
127 + 1 /* minimum filename length */ )
128 #endif
130 /* True if any of the files read were the standard input. */
131 static bool have_read_stdin;
133 /* The minimum length of a valid checksum line for the selected algorithm. */
134 static size_t min_digest_line_length;
136 /* Set to the length of a digest hex string for the selected algorithm. */
137 static size_t digest_hex_bytes;
139 /* With --check, don't generate any output.
140 The exit code indicates success or failure. */
141 static bool status_only = false;
143 /* With --check, print a message to standard error warning about each
144 improperly formatted checksum line. */
145 static bool warn = false;
147 /* With --check, ignore missing files. */
148 static bool ignore_missing = false;
150 /* With --check, suppress the "OK" printed for each verified file. */
151 static bool quiet = false;
153 /* With --check, exit with a non-zero return code if any line is
154 improperly formatted. */
155 static bool strict = false;
157 /* Whether a BSD reversed format checksum is detected. */
158 static int bsd_reversed = -1;
160 /* line delimiter. */
161 static unsigned char delim = '\n';
163 #if HASH_ALGO_BLAKE2
164 static char const *const algorithm_in_string[] =
166 "blake2b", NULL
168 static char const *const algorithm_out_string[] =
170 "BLAKE2b", NULL
172 enum Algorithm
174 BLAKE2b
176 verify (ARRAY_CARDINALITY (algorithm_in_string) == 2);
177 verify (ARRAY_CARDINALITY (algorithm_out_string) == 2);
179 static enum Algorithm b2_algorithm;
180 static uintmax_t b2_length;
181 static blake2fn blake2fns[]=
183 blake2b_stream
185 static uintmax_t blake2_max_len[]=
187 BLAKE2B_OUTBYTES
189 #endif /* HASH_ALGO_BLAKE2 */
191 /* For long options that have no equivalent short option, use a
192 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
193 enum
195 IGNORE_MISSING_OPTION = CHAR_MAX + 1,
196 STATUS_OPTION,
197 QUIET_OPTION,
198 STRICT_OPTION,
199 TAG_OPTION
202 static struct option const long_options[] =
204 #if HASH_ALGO_BLAKE2
205 { "length", required_argument, NULL, 'l'},
206 #endif
207 { "binary", no_argument, NULL, 'b' },
208 { "check", no_argument, NULL, 'c' },
209 { "ignore-missing", no_argument, NULL, IGNORE_MISSING_OPTION},
210 { "quiet", no_argument, NULL, QUIET_OPTION },
211 { "status", no_argument, NULL, STATUS_OPTION },
212 { "text", no_argument, NULL, 't' },
213 { "warn", no_argument, NULL, 'w' },
214 { "strict", no_argument, NULL, STRICT_OPTION },
215 { "tag", no_argument, NULL, TAG_OPTION },
216 { "zero", no_argument, NULL, 'z' },
217 { GETOPT_HELP_OPTION_DECL },
218 { GETOPT_VERSION_OPTION_DECL },
219 { NULL, 0, NULL, 0 }
222 void
223 usage (int status)
225 if (status != EXIT_SUCCESS)
226 emit_try_help ();
227 else
229 printf (_("\
230 Usage: %s [OPTION]... [FILE]...\n\
231 Print or check %s (%d-bit) checksums.\n\
233 program_name,
234 DIGEST_TYPE_STRING,
235 DIGEST_BITS);
237 emit_stdin_note ();
238 if (O_BINARY)
239 fputs (_("\
241 -b, --binary read in binary mode (default unless reading tty stdin)\n\
242 "), stdout);
243 else
244 fputs (_("\
246 -b, --binary read in binary mode\n\
247 "), stdout);
249 printf (_("\
250 -c, --check read %s sums from the FILEs and check them\n"),
251 DIGEST_TYPE_STRING);
252 #if HASH_ALGO_BLAKE2
253 fputs (_("\
254 -l, --length digest length in bits; must not exceed the maximum for\n\
255 the blake2 algorithm and must be a multiple of 8\n\
256 "), stdout);
257 #endif
258 fputs (_("\
259 --tag create a BSD-style checksum\n\
260 "), stdout);
261 if (O_BINARY)
262 fputs (_("\
263 -t, --text read in text mode (default if reading tty stdin)\n\
264 "), stdout);
265 else
266 fputs (_("\
267 -t, --text read in text mode (default)\n\
268 "), stdout);
269 fputs (_("\
270 -z, --zero end each output line with NUL, not newline,\n\
271 and disable file name escaping\n\
272 "), stdout);
273 fputs (_("\
275 The following five options are useful only when verifying checksums:\n\
276 --ignore-missing don't fail or report status for missing files\n\
277 --quiet don't print OK for each successfully verified file\n\
278 --status don't output anything, status code shows success\n\
279 --strict exit non-zero for improperly formatted checksum lines\n\
280 -w, --warn warn about improperly formatted checksum lines\n\
282 "), stdout);
283 fputs (HELP_OPTION_DESCRIPTION, stdout);
284 fputs (VERSION_OPTION_DESCRIPTION, stdout);
285 printf (_("\
287 The sums are computed as described in %s. When checking, the input\n\
288 should be a former output of this program. The default mode is to print a\n\
289 line with checksum, a space, a character indicating input mode ('*' for binary,\
290 \n' ' for text or where binary is insignificant), and name for each FILE.\n\
292 Note: There is no difference between binary mode and text mode on GNU systems.\
293 \n"),
294 DIGEST_REFERENCE);
295 emit_ancillary_info (PROGRAM_NAME);
298 exit (status);
301 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
303 /* Given a file name, S of length S_LEN, that is not NUL-terminated,
304 modify it in place, performing the equivalent of this sed substitution:
305 's/\\n/\n/g;s/\\\\/\\/g' i.e., replacing each "\\n" string with a newline
306 and each "\\\\" with a single backslash, NUL-terminate it and return S.
307 If S is not a valid escaped file name, i.e., if it ends with an odd number
308 of backslashes or if it contains a backslash followed by anything other
309 than "n" or another backslash, return NULL. */
311 static char *
312 filename_unescape (char *s, size_t s_len)
314 char *dst = s;
316 for (size_t i = 0; i < s_len; i++)
318 switch (s[i])
320 case '\\':
321 if (i == s_len - 1)
323 /* File name ends with an unescaped backslash: invalid. */
324 return NULL;
326 ++i;
327 switch (s[i])
329 case 'n':
330 *dst++ = '\n';
331 break;
332 case '\\':
333 *dst++ = '\\';
334 break;
335 default:
336 /* Only '\' or 'n' may follow a backslash. */
337 return NULL;
339 break;
341 case '\0':
342 /* The file name may not contain a NUL. */
343 return NULL;
345 default:
346 *dst++ = s[i];
347 break;
350 if (dst < s + s_len)
351 *dst = '\0';
353 return s;
356 /* Return true if S is a NUL-terminated string of DIGEST_HEX_BYTES hex digits.
357 Otherwise, return false. */
358 static bool _GL_ATTRIBUTE_PURE
359 hex_digits (unsigned char const *s)
361 for (unsigned int i = 0; i < digest_hex_bytes; i++)
363 if (!isxdigit (*s))
364 return false;
365 ++s;
367 return *s == '\0';
370 /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
371 'sha1' command into two parts: a hexadecimal digest, and the file
372 name. S is modified. Return true if successful. */
374 static bool
375 bsd_split_3 (char *s, size_t s_len, unsigned char **hex_digest,
376 char **file_name, bool escaped_filename)
378 size_t i;
380 if (s_len == 0)
381 return false;
383 /* Find end of filename. */
384 i = s_len - 1;
385 while (i && s[i] != ')')
386 i--;
388 if (s[i] != ')')
389 return false;
391 *file_name = s;
393 if (escaped_filename && filename_unescape (s, i) == NULL)
394 return false;
396 s[i++] = '\0';
398 while (ISWHITE (s[i]))
399 i++;
401 if (s[i] != '=')
402 return false;
404 i++;
406 while (ISWHITE (s[i]))
407 i++;
409 *hex_digest = (unsigned char *) &s[i];
411 return hex_digits (*hex_digest);
414 /* Split the string S (of length S_LEN) into three parts:
415 a hexadecimal digest, binary flag, and the file name.
416 S is modified. Return true if successful. */
418 static bool
419 split_3 (char *s, size_t s_len,
420 unsigned char **hex_digest, int *binary, char **file_name)
422 bool escaped_filename = false;
423 size_t algo_name_len;
425 size_t i = 0;
426 while (ISWHITE (s[i]))
427 ++i;
429 if (s[i] == '\\')
431 ++i;
432 escaped_filename = true;
435 /* Check for BSD-style checksum line. */
437 algo_name_len = strlen (DIGEST_TYPE_STRING);
438 if (STREQ_LEN (s + i, DIGEST_TYPE_STRING, algo_name_len))
440 i += algo_name_len;
441 #if HASH_ALGO_BLAKE2
442 /* Terminate and match algorithm name. */
443 char const *algo_name = &s[i - algo_name_len];
444 /* Skip algorithm variants. */
445 while (s[i] && ! ISWHITE (s[i]) && s[i] != '-' && s[i] != '(')
446 ++i;
447 bool length_specified = s[i] == '-';
448 bool openssl_format = s[i] == '('; /* and no length_specified */
449 s[i++] = '\0';
450 ptrdiff_t algo = argmatch (algo_name, algorithm_out_string, NULL, 0);
451 if (algo < 0)
452 return false;
453 b2_algorithm = algo;
454 if (openssl_format)
455 s[--i] = '(';
457 b2_length = blake2_max_len[b2_algorithm] * 8;
458 if (length_specified)
460 uintmax_t length;
461 char *siend;
462 if (! (xstrtoumax (s + i, &siend, 0, &length, NULL) == LONGINT_OK
463 && 0 < length && length <= b2_length
464 && length % 8 == 0))
465 return false;
467 i = siend - s;
468 b2_length = length;
471 digest_hex_bytes = b2_length / 4;
472 #endif
473 if (s[i] == ' ')
474 ++i;
475 if (s[i] == '(')
477 ++i;
478 *binary = 0;
479 return bsd_split_3 (s + i, s_len - i,
480 hex_digest, file_name, escaped_filename);
482 return false;
485 /* Ignore this line if it is too short.
486 Each line must have at least 'min_digest_line_length - 1' (or one more, if
487 the first is a backslash) more characters to contain correct message digest
488 information. */
489 if (s_len - i < min_digest_line_length + (s[i] == '\\'))
490 return false;
492 *hex_digest = (unsigned char *) &s[i];
494 #if HASH_ALGO_BLAKE2
495 /* Auto determine length. */
496 unsigned char const *hp = *hex_digest;
497 digest_hex_bytes = 0;
498 while (isxdigit (*hp++))
499 digest_hex_bytes++;
500 if (digest_hex_bytes < 2 || digest_hex_bytes % 2
501 || blake2_max_len[b2_algorithm] * 2 < digest_hex_bytes)
502 return false;
503 b2_length = digest_hex_bytes * 4;
504 #endif
506 /* The first field has to be the n-character hexadecimal
507 representation of the message digest. If it is not followed
508 immediately by a white space it's an error. */
509 i += digest_hex_bytes;
510 if (!ISWHITE (s[i]))
511 return false;
513 s[i++] = '\0';
515 if (! hex_digits (*hex_digest))
516 return false;
518 /* If "bsd reversed" format detected. */
519 if ((s_len - i == 1) || (s[i] != ' ' && s[i] != '*'))
521 /* Don't allow mixing bsd and standard formats,
522 to minimize security issues with attackers
523 renaming files with leading spaces.
524 This assumes that with bsd format checksums
525 that the first file name does not have
526 a leading ' ' or '*'. */
527 if (bsd_reversed == 0)
528 return false;
529 bsd_reversed = 1;
531 else if (bsd_reversed != 1)
533 bsd_reversed = 0;
534 *binary = (s[i++] == '*');
537 /* All characters between the type indicator and end of line are
538 significant -- that includes leading and trailing white space. */
539 *file_name = &s[i];
541 if (escaped_filename)
542 return filename_unescape (&s[i], s_len - i) != NULL;
544 return true;
547 /* If ESCAPE is true, then translate each NEWLINE byte to the string, "\\n",
548 and each backslash to "\\\\". */
549 static void
550 print_filename (char const *file, bool escape)
552 if (! escape)
554 fputs (file, stdout);
555 return;
558 while (*file)
560 switch (*file)
562 case '\n':
563 fputs ("\\n", stdout);
564 break;
566 case '\\':
567 fputs ("\\\\", stdout);
568 break;
570 default:
571 putchar (*file);
572 break;
574 file++;
578 /* An interface to the function, DIGEST_STREAM.
579 Operate on FILENAME (it may be "-").
581 *BINARY indicates whether the file is binary. BINARY < 0 means it
582 depends on whether binary mode makes any difference and the file is
583 a terminal; in that case, clear *BINARY if the file was treated as
584 text because it was a terminal.
586 Put the checksum in *BIN_RESULT, which must be properly aligned.
587 Put true in *MISSING if the file can't be opened due to ENOENT.
588 Return true if successful. */
590 static bool
591 digest_file (const char *filename, int *binary, unsigned char *bin_result,
592 bool *missing)
594 FILE *fp;
595 int err;
596 bool is_stdin = STREQ (filename, "-");
598 *missing = false;
600 if (is_stdin)
602 have_read_stdin = true;
603 fp = stdin;
604 if (O_BINARY && *binary)
606 if (*binary < 0)
607 *binary = ! isatty (STDIN_FILENO);
608 if (*binary)
609 xset_binary_mode (STDIN_FILENO, O_BINARY);
612 else
614 fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r"));
615 if (fp == NULL)
617 if (ignore_missing && errno == ENOENT)
619 *missing = true;
620 return true;
622 error (0, errno, "%s", quotef (filename));
623 return false;
627 fadvise (fp, FADVISE_SEQUENTIAL);
629 #if HASH_ALGO_BLAKE2
630 err = DIGEST_STREAM (fp, bin_result, b2_length / 8);
631 #else
632 err = DIGEST_STREAM (fp, bin_result);
633 #endif
634 if (err)
636 error (0, errno, "%s", quotef (filename));
637 if (fp != stdin)
638 fclose (fp);
639 return false;
642 if (!is_stdin && fclose (fp) != 0)
644 error (0, errno, "%s", quotef (filename));
645 return false;
648 return true;
651 static bool
652 digest_check (const char *checkfile_name)
654 FILE *checkfile_stream;
655 uintmax_t n_misformatted_lines = 0;
656 uintmax_t n_improperly_formatted_lines = 0;
657 uintmax_t n_mismatched_checksums = 0;
658 uintmax_t n_open_or_read_failures = 0;
659 bool properly_formatted_lines = false;
660 bool matched_checksums = false;
661 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
662 /* Make sure bin_buffer is properly aligned. */
663 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
664 uintmax_t line_number;
665 char *line;
666 size_t line_chars_allocated;
667 bool is_stdin = STREQ (checkfile_name, "-");
669 if (is_stdin)
671 have_read_stdin = true;
672 checkfile_name = _("standard input");
673 checkfile_stream = stdin;
675 else
677 checkfile_stream = fopen (checkfile_name, "r");
678 if (checkfile_stream == NULL)
680 error (0, errno, "%s", quotef (checkfile_name));
681 return false;
685 line_number = 0;
686 line = NULL;
687 line_chars_allocated = 0;
690 char *filename IF_LINT ( = NULL);
691 int binary;
692 unsigned char *hex_digest IF_LINT ( = NULL);
693 ssize_t line_length;
695 ++line_number;
696 if (line_number == 0)
697 die (EXIT_FAILURE, 0, _("%s: too many checksum lines"),
698 quotef (checkfile_name));
700 line_length = getline (&line, &line_chars_allocated, checkfile_stream);
701 if (line_length <= 0)
702 break;
704 /* Ignore comment lines, which begin with a '#' character. */
705 if (line[0] == '#')
706 continue;
708 /* Remove any trailing newline. */
709 if (line[line_length - 1] == '\n')
710 line[--line_length] = '\0';
712 if (! (split_3 (line, line_length, &hex_digest, &binary, &filename)
713 && ! (is_stdin && STREQ (filename, "-"))))
715 ++n_misformatted_lines;
717 if (warn)
719 error (0, 0,
720 _("%s: %" PRIuMAX
721 ": improperly formatted %s checksum line"),
722 quotef (checkfile_name), line_number,
723 DIGEST_TYPE_STRING);
726 ++n_improperly_formatted_lines;
728 else
730 static const char bin2hex[] = { '0', '1', '2', '3',
731 '4', '5', '6', '7',
732 '8', '9', 'a', 'b',
733 'c', 'd', 'e', 'f' };
734 bool ok;
735 bool missing;
736 /* Only escape in the edge case producing multiple lines,
737 to ease automatic processing of status output. */
738 bool needs_escape = ! status_only && strchr (filename, '\n');
740 properly_formatted_lines = true;
742 ok = digest_file (filename, &binary, bin_buffer, &missing);
744 if (!ok)
746 ++n_open_or_read_failures;
747 if (!status_only)
749 if (needs_escape)
750 putchar ('\\');
751 print_filename (filename, needs_escape);
752 printf (": %s\n", _("FAILED open or read"));
755 else if (ignore_missing && missing)
757 /* Ignore missing files with --ignore-missing. */
760 else
762 size_t digest_bin_bytes = digest_hex_bytes / 2;
763 size_t cnt;
765 /* Compare generated binary number with text representation
766 in check file. Ignore case of hex digits. */
767 for (cnt = 0; cnt < digest_bin_bytes; ++cnt)
769 if (tolower (hex_digest[2 * cnt])
770 != bin2hex[bin_buffer[cnt] >> 4]
771 || (tolower (hex_digest[2 * cnt + 1])
772 != (bin2hex[bin_buffer[cnt] & 0xf])))
773 break;
775 if (cnt != digest_bin_bytes)
776 ++n_mismatched_checksums;
777 else
778 matched_checksums = true;
780 if (!status_only)
782 if (cnt != digest_bin_bytes || ! quiet)
784 if (needs_escape)
785 putchar ('\\');
786 print_filename (filename, needs_escape);
789 if (cnt != digest_bin_bytes)
790 printf (": %s\n", _("FAILED"));
791 else if (!quiet)
792 printf (": %s\n", _("OK"));
797 while (!feof (checkfile_stream) && !ferror (checkfile_stream));
799 free (line);
801 if (ferror (checkfile_stream))
803 error (0, 0, _("%s: read error"), quotef (checkfile_name));
804 return false;
807 if (!is_stdin && fclose (checkfile_stream) != 0)
809 error (0, errno, "%s", quotef (checkfile_name));
810 return false;
813 if (! properly_formatted_lines)
815 /* Warn if no tests are found. */
816 error (0, 0, _("%s: no properly formatted %s checksum lines found"),
817 quotef (checkfile_name), DIGEST_TYPE_STRING);
819 else
821 if (!status_only)
823 if (n_misformatted_lines != 0)
824 error (0, 0,
825 (ngettext
826 ("WARNING: %" PRIuMAX " line is improperly formatted",
827 "WARNING: %" PRIuMAX " lines are improperly formatted",
828 select_plural (n_misformatted_lines))),
829 n_misformatted_lines);
831 if (n_open_or_read_failures != 0)
832 error (0, 0,
833 (ngettext
834 ("WARNING: %" PRIuMAX " listed file could not be read",
835 "WARNING: %" PRIuMAX " listed files could not be read",
836 select_plural (n_open_or_read_failures))),
837 n_open_or_read_failures);
839 if (n_mismatched_checksums != 0)
840 error (0, 0,
841 (ngettext
842 ("WARNING: %" PRIuMAX " computed checksum did NOT match",
843 "WARNING: %" PRIuMAX " computed checksums did NOT match",
844 select_plural (n_mismatched_checksums))),
845 n_mismatched_checksums);
847 if (ignore_missing && ! matched_checksums)
848 error (0, 0, _("%s: no file was verified"),
849 quotef (checkfile_name));
853 return (properly_formatted_lines
854 && matched_checksums
855 && n_mismatched_checksums == 0
856 && n_open_or_read_failures == 0
857 && (!strict || n_improperly_formatted_lines == 0));
861 main (int argc, char **argv)
863 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
864 /* Make sure bin_buffer is properly aligned. */
865 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
866 bool do_check = false;
867 int opt;
868 bool ok = true;
869 int binary = -1;
870 bool prefix_tag = false;
872 /* Setting values of global variables. */
873 initialize_main (&argc, &argv);
874 set_program_name (argv[0]);
875 setlocale (LC_ALL, "");
876 bindtextdomain (PACKAGE, LOCALEDIR);
877 textdomain (PACKAGE);
879 atexit (close_stdout);
881 /* Line buffer stdout to ensure lines are written atomically and immediately
882 so that processes running in parallel do not intersperse their output. */
883 setvbuf (stdout, NULL, _IOLBF, 0);
885 #if HASH_ALGO_BLAKE2
886 const char* short_opts = "l:bctwz";
887 const char* b2_length_str = "";
888 #else
889 const char* short_opts = "bctwz";
890 #endif
892 while ((opt = getopt_long (argc, argv, short_opts, long_options, NULL)) != -1)
893 switch (opt)
895 #if HASH_ALGO_BLAKE2
896 case 'l':
897 b2_length = xdectoumax (optarg, 0, UINTMAX_MAX, "",
898 _("invalid length"), 0);
899 b2_length_str = optarg;
900 if (b2_length % 8 != 0)
902 error (0, 0, _("invalid length: %s"), quote (b2_length_str));
903 die (EXIT_FAILURE, 0, _("length is not a multiple of 8"));
905 break;
906 #endif
907 case 'b':
908 binary = 1;
909 break;
910 case 'c':
911 do_check = true;
912 break;
913 case STATUS_OPTION:
914 status_only = true;
915 warn = false;
916 quiet = false;
917 break;
918 case 't':
919 binary = 0;
920 break;
921 case 'w':
922 status_only = false;
923 warn = true;
924 quiet = false;
925 break;
926 case IGNORE_MISSING_OPTION:
927 ignore_missing = true;
928 break;
929 case QUIET_OPTION:
930 status_only = false;
931 warn = false;
932 quiet = true;
933 break;
934 case STRICT_OPTION:
935 strict = true;
936 break;
937 case TAG_OPTION:
938 prefix_tag = true;
939 binary = 1;
940 break;
941 case 'z':
942 delim = '\0';
943 break;
944 case_GETOPT_HELP_CHAR;
945 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
946 default:
947 usage (EXIT_FAILURE);
950 min_digest_line_length = MIN_DIGEST_LINE_LENGTH;
951 #if HASH_ALGO_BLAKE2
952 if (b2_length > blake2_max_len[b2_algorithm] * 8)
954 error (0, 0, _("invalid length: %s"), quote (b2_length_str));
955 die (EXIT_FAILURE, 0,
956 _("maximum digest length for %s is %"PRIuMAX" bits"),
957 quote (algorithm_in_string[b2_algorithm]),
958 blake2_max_len[b2_algorithm] * 8);
960 if (b2_length == 0 && ! do_check)
961 b2_length = blake2_max_len[b2_algorithm] * 8;
962 digest_hex_bytes = b2_length / 4;
963 #else
964 digest_hex_bytes = DIGEST_HEX_BYTES;
965 #endif
967 if (prefix_tag && !binary)
969 /* This could be supported in a backwards compatible way
970 by prefixing the output line with a space in text mode.
971 However that's invasive enough that it was agreed to
972 not support this mode with --tag, as --text use cases
973 are adequately supported by the default output format. */
974 error (0, 0, _("--tag does not support --text mode"));
975 usage (EXIT_FAILURE);
978 if (delim != '\n' && do_check)
980 error (0, 0, _("the --zero option is not supported when "
981 "verifying checksums"));
982 usage (EXIT_FAILURE);
985 if (prefix_tag && do_check)
987 error (0, 0, _("the --tag option is meaningless when "
988 "verifying checksums"));
989 usage (EXIT_FAILURE);
992 if (0 <= binary && do_check)
994 error (0, 0, _("the --binary and --text options are meaningless when "
995 "verifying checksums"));
996 usage (EXIT_FAILURE);
999 if (ignore_missing && !do_check)
1001 error (0, 0,
1002 _("the --ignore-missing option is meaningful only when "
1003 "verifying checksums"));
1004 usage (EXIT_FAILURE);
1007 if (status_only && !do_check)
1009 error (0, 0,
1010 _("the --status option is meaningful only when verifying checksums"));
1011 usage (EXIT_FAILURE);
1014 if (warn && !do_check)
1016 error (0, 0,
1017 _("the --warn option is meaningful only when verifying checksums"));
1018 usage (EXIT_FAILURE);
1021 if (quiet && !do_check)
1023 error (0, 0,
1024 _("the --quiet option is meaningful only when verifying checksums"));
1025 usage (EXIT_FAILURE);
1028 if (strict & !do_check)
1030 error (0, 0,
1031 _("the --strict option is meaningful only when verifying checksums"));
1032 usage (EXIT_FAILURE);
1035 if (!O_BINARY && binary < 0)
1036 binary = 0;
1038 char **operand_lim = argv + argc;
1039 if (optind == argc)
1040 *operand_lim++ = bad_cast ("-");
1042 for (char **operandp = argv + optind; operandp < operand_lim; operandp++)
1044 char *file = *operandp;
1046 if (do_check)
1047 ok &= digest_check (file);
1048 else
1050 int file_is_binary = binary;
1051 bool missing;
1053 if (! digest_file (file, &file_is_binary, bin_buffer, &missing))
1054 ok = false;
1055 else
1057 /* We don't really need to escape, and hence detect, the '\\'
1058 char, and not doing so should be both forwards and backwards
1059 compatible, since only escaped lines would have a '\\' char at
1060 the start. However just in case users are directly comparing
1061 against old (hashed) outputs, in the presence of files
1062 containing '\\' characters, we decided to not simplify the
1063 output in this case. */
1064 bool needs_escape = (strchr (file, '\\') || strchr (file, '\n'))
1065 && delim == '\n';
1067 if (prefix_tag)
1069 if (needs_escape)
1070 putchar ('\\');
1072 #if HASH_ALGO_BLAKE2
1073 fputs (algorithm_out_string[b2_algorithm], stdout);
1074 if (b2_length < blake2_max_len[b2_algorithm] * 8)
1075 printf ("-%"PRIuMAX, b2_length);
1076 #else
1077 fputs (DIGEST_TYPE_STRING, stdout);
1078 #endif
1079 fputs (" (", stdout);
1080 print_filename (file, needs_escape);
1081 fputs (") = ", stdout);
1084 /* Output a leading backslash if the file name contains
1085 a newline or backslash. */
1086 if (!prefix_tag && needs_escape)
1087 putchar ('\\');
1089 for (size_t i = 0; i < (digest_hex_bytes / 2); ++i)
1090 printf ("%02x", bin_buffer[i]);
1092 if (!prefix_tag)
1094 putchar (' ');
1096 putchar (file_is_binary ? '*' : ' ');
1098 print_filename (file, needs_escape);
1101 putchar (delim);
1106 if (have_read_stdin && fclose (stdin) == EOF)
1107 die (EXIT_FAILURE, errno, _("standard input"));
1109 return ok ? EXIT_SUCCESS : EXIT_FAILURE;