split: port ‘split -n N /dev/null’ better to macOS
[coreutils.git] / src / digest.c
blob6ee8a485474ba9fe19e72b42905e6844cb0b26fd
1 /* Compute checksums of files or strings.
2 Copyright (C) 1995-2023 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_SUM || HASH_ALGO_CKSUM
31 # include "sum.h"
32 #endif
33 #if HASH_ALGO_CKSUM
34 # include "cksum.h"
35 # include "base64.h"
36 #endif
37 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
38 # include "blake2/b2sum.h"
39 #endif
40 #if HASH_ALGO_MD5 || HASH_ALGO_CKSUM
41 # include "md5.h"
42 #endif
43 #if HASH_ALGO_SHA1 || HASH_ALGO_CKSUM
44 # include "sha1.h"
45 #endif
46 #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224 || HASH_ALGO_CKSUM
47 # include "sha256.h"
48 #endif
49 #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384 || HASH_ALGO_CKSUM
50 # include "sha512.h"
51 #endif
52 #if HASH_ALGO_CKSUM
53 # include "sm3.h"
54 #endif
55 #include "die.h"
56 #include "error.h"
57 #include "fadvise.h"
58 #include "stdio--.h"
59 #include "xbinary-io.h"
61 /* The official name of this program (e.g., no 'g' prefix). */
62 #if HASH_ALGO_SUM
63 # define PROGRAM_NAME "sum"
64 # define DIGEST_TYPE_STRING "BSD"
65 # define DIGEST_STREAM sumfns[sum_algorithm]
66 # define DIGEST_OUT sum_output_fns[sum_algorithm]
67 # define DIGEST_BITS 16
68 # define DIGEST_ALIGN 4
69 #elif HASH_ALGO_CKSUM
70 # define MAX_DIGEST_BITS 512
71 # define MAX_DIGEST_ALIGN 8
72 # define PROGRAM_NAME "cksum"
73 # define DIGEST_TYPE_STRING algorithm_tags[cksum_algorithm]
74 # define DIGEST_STREAM cksumfns[cksum_algorithm]
75 # define DIGEST_OUT cksum_output_fns[cksum_algorithm]
76 # define DIGEST_BITS MAX_DIGEST_BITS
77 # define DIGEST_ALIGN MAX_DIGEST_ALIGN
78 #elif HASH_ALGO_MD5
79 # define PROGRAM_NAME "md5sum"
80 # define DIGEST_TYPE_STRING "MD5"
81 # define DIGEST_STREAM md5_stream
82 # define DIGEST_BITS 128
83 # define DIGEST_REFERENCE "RFC 1321"
84 # define DIGEST_ALIGN 4
85 #elif HASH_ALGO_BLAKE2
86 # define PROGRAM_NAME "b2sum"
87 # define DIGEST_TYPE_STRING "BLAKE2b"
88 # define DIGEST_STREAM blake2b_stream
89 # define DIGEST_BITS 512
90 # define DIGEST_REFERENCE "RFC 7693"
91 # define DIGEST_ALIGN 8
92 #elif HASH_ALGO_SHA1
93 # define PROGRAM_NAME "sha1sum"
94 # define DIGEST_TYPE_STRING "SHA1"
95 # define DIGEST_STREAM sha1_stream
96 # define DIGEST_BITS 160
97 # define DIGEST_REFERENCE "FIPS-180-1"
98 # define DIGEST_ALIGN 4
99 #elif HASH_ALGO_SHA256
100 # define PROGRAM_NAME "sha256sum"
101 # define DIGEST_TYPE_STRING "SHA256"
102 # define DIGEST_STREAM sha256_stream
103 # define DIGEST_BITS 256
104 # define DIGEST_REFERENCE "FIPS-180-2"
105 # define DIGEST_ALIGN 4
106 #elif HASH_ALGO_SHA224
107 # define PROGRAM_NAME "sha224sum"
108 # define DIGEST_TYPE_STRING "SHA224"
109 # define DIGEST_STREAM sha224_stream
110 # define DIGEST_BITS 224
111 # define DIGEST_REFERENCE "RFC 3874"
112 # define DIGEST_ALIGN 4
113 #elif HASH_ALGO_SHA512
114 # define PROGRAM_NAME "sha512sum"
115 # define DIGEST_TYPE_STRING "SHA512"
116 # define DIGEST_STREAM sha512_stream
117 # define DIGEST_BITS 512
118 # define DIGEST_REFERENCE "FIPS-180-2"
119 # define DIGEST_ALIGN 8
120 #elif HASH_ALGO_SHA384
121 # define PROGRAM_NAME "sha384sum"
122 # define DIGEST_TYPE_STRING "SHA384"
123 # define DIGEST_STREAM sha384_stream
124 # define DIGEST_BITS 384
125 # define DIGEST_REFERENCE "FIPS-180-2"
126 # define DIGEST_ALIGN 8
127 #else
128 # error "Can't decide which hash algorithm to compile."
129 #endif
130 #if !HASH_ALGO_SUM && !HASH_ALGO_CKSUM
131 # define DIGEST_OUT output_file
132 #endif
134 #if HASH_ALGO_SUM
135 # define AUTHORS \
136 proper_name ("Kayvan Aghaiepour"), \
137 proper_name ("David MacKenzie")
138 #elif HASH_ALGO_CKSUM
139 # define AUTHORS \
140 proper_name ("Padraig Brady"), \
141 proper_name ("Q. Frank Xia")
142 #elif HASH_ALGO_BLAKE2
143 # define AUTHORS \
144 proper_name ("Padraig Brady"), \
145 proper_name ("Samuel Neves")
146 #else
147 # define AUTHORS \
148 proper_name ("Ulrich Drepper"), \
149 proper_name ("Scott Miller"), \
150 proper_name ("David Madore")
151 #endif
152 #if !HASH_ALGO_BLAKE2 && !HASH_ALGO_CKSUM
153 # define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
154 #endif
155 #define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
157 /* The minimum length of a valid digest line. This length does
158 not include any newline character at the end of a line. */
159 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
160 # define MIN_DIGEST_LINE_LENGTH 3 /* With -l 8. */
161 #else
162 # define MIN_DIGEST_LINE_LENGTH \
163 (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
164 + 1 /* blank */ \
165 + 1 /* minimum filename length */ )
166 #endif
168 #if !HASH_ALGO_SUM
169 static void
170 output_file (char const *file, int binary_file, void const *digest,
171 bool raw, bool tagged, unsigned char delim, bool args,
172 uintmax_t length);
173 #endif
175 /* True if any of the files read were the standard input. */
176 static bool have_read_stdin;
178 /* The minimum length of a valid checksum line for the selected algorithm. */
179 static size_t min_digest_line_length;
181 /* Set to the length of a digest hex string for the selected algorithm. */
182 static size_t digest_hex_bytes;
184 /* With --check, don't generate any output.
185 The exit code indicates success or failure. */
186 static bool status_only = false;
188 /* With --check, print a message to standard error warning about each
189 improperly formatted checksum line. */
190 static bool warn = false;
192 /* With --check, ignore missing files. */
193 static bool ignore_missing = false;
195 /* With --check, suppress the "OK" printed for each verified file. */
196 static bool quiet = false;
198 /* With --check, exit with a non-zero return code if any line is
199 improperly formatted. */
200 static bool strict = false;
202 /* Whether a BSD reversed format checksum is detected. */
203 static int bsd_reversed = -1;
205 /* line delimiter. */
206 static unsigned char digest_delim = '\n';
208 #if HASH_ALGO_CKSUM
209 /* If true, print base64-encoded digests, not hex. */
210 static bool base64_digest = false;
211 #endif
213 /* If true, print binary digests, not hex. */
214 static bool raw_digest = false;
216 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
217 # define BLAKE2B_MAX_LEN BLAKE2B_OUTBYTES
218 static uintmax_t digest_length;
219 #endif /* HASH_ALGO_BLAKE2 */
221 typedef void (*digest_output_fn)(char const *, int, void const *, bool,
222 bool, unsigned char, bool, uintmax_t);
223 #if HASH_ALGO_SUM
224 enum Algorithm
226 bsd,
227 sysv,
230 static enum Algorithm sum_algorithm;
231 static sumfn sumfns[]=
233 bsd_sum_stream,
234 sysv_sum_stream,
236 static digest_output_fn sum_output_fns[]=
238 output_bsd,
239 output_sysv,
241 #endif
243 #if HASH_ALGO_CKSUM
244 static int
245 md5_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
247 return md5_stream (stream, resstream);
249 static int
250 sha1_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
252 return sha1_stream (stream, resstream);
254 static int
255 sha224_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
257 return sha224_stream (stream, resstream);
259 static int
260 sha256_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
262 return sha256_stream (stream, resstream);
264 static int
265 sha384_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
267 return sha384_stream (stream, resstream);
269 static int
270 sha512_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
272 return sha512_stream (stream, resstream);
274 static int
275 blake2b_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
277 return blake2b_stream (stream, resstream, *length);
279 static int
280 sm3_sum_stream (FILE *stream, void *resstream, uintmax_t *length)
282 return sm3_stream (stream, resstream);
285 enum Algorithm
287 bsd,
288 sysv,
289 crc,
290 md5,
291 sha1,
292 sha224,
293 sha256,
294 sha384,
295 sha512,
296 blake2b,
297 sm3,
300 static char const *const algorithm_args[] =
302 "bsd", "sysv", "crc", "md5", "sha1", "sha224",
303 "sha256", "sha384", "sha512", "blake2b", "sm3", NULL
305 static enum Algorithm const algorithm_types[] =
307 bsd, sysv, crc, md5, sha1, sha224,
308 sha256, sha384, sha512, blake2b, sm3,
310 ARGMATCH_VERIFY (algorithm_args, algorithm_types);
312 static char const *const algorithm_tags[] =
314 "BSD", "SYSV", "CRC", "MD5", "SHA1", "SHA224",
315 "SHA256", "SHA384", "SHA512", "BLAKE2b", "SM3", NULL
317 static int const algorithm_bits[] =
319 16, 16, 32, 128, 160, 224,
320 256, 384, 512, 512, 256, 0
323 static_assert (ARRAY_CARDINALITY (algorithm_bits)
324 == ARRAY_CARDINALITY (algorithm_args));
326 static bool algorithm_specified = false;
327 static enum Algorithm cksum_algorithm = crc;
328 static sumfn cksumfns[]=
330 bsd_sum_stream,
331 sysv_sum_stream,
332 crc_sum_stream,
333 md5_sum_stream,
334 sha1_sum_stream,
335 sha224_sum_stream,
336 sha256_sum_stream,
337 sha384_sum_stream,
338 sha512_sum_stream,
339 blake2b_sum_stream,
340 sm3_sum_stream,
342 static digest_output_fn cksum_output_fns[]=
344 output_bsd,
345 output_sysv,
346 output_crc,
347 output_file,
348 output_file,
349 output_file,
350 output_file,
351 output_file,
352 output_file,
353 output_file,
354 output_file,
356 bool cksum_debug;
357 #endif
359 /* For long options that have no equivalent short option, use a
360 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
362 enum
364 IGNORE_MISSING_OPTION = CHAR_MAX + 1,
365 STATUS_OPTION,
366 QUIET_OPTION,
367 STRICT_OPTION,
368 TAG_OPTION,
369 UNTAG_OPTION,
370 DEBUG_PROGRAM_OPTION,
371 RAW_OPTION,
374 static struct option const long_options[] =
376 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
377 { "length", required_argument, NULL, 'l'},
378 #endif
380 #if !HASH_ALGO_SUM
381 { "check", no_argument, NULL, 'c' },
382 { "ignore-missing", no_argument, NULL, IGNORE_MISSING_OPTION},
383 { "quiet", no_argument, NULL, QUIET_OPTION },
384 { "status", no_argument, NULL, STATUS_OPTION },
385 { "warn", no_argument, NULL, 'w' },
386 { "strict", no_argument, NULL, STRICT_OPTION },
387 { "tag", no_argument, NULL, TAG_OPTION },
388 { "zero", no_argument, NULL, 'z' },
390 # if HASH_ALGO_CKSUM
391 { "algorithm", required_argument, NULL, 'a'},
392 { "base64", no_argument, NULL, 'b' },
393 { "debug", no_argument, NULL, DEBUG_PROGRAM_OPTION},
394 { "raw", no_argument, NULL, RAW_OPTION},
395 { "untagged", no_argument, NULL, UNTAG_OPTION },
396 # else
397 { "binary", no_argument, NULL, 'b' },
398 { "text", no_argument, NULL, 't' },
399 # endif
401 #else
402 {"sysv", no_argument, NULL, 's'},
403 #endif
405 { GETOPT_HELP_OPTION_DECL },
406 { GETOPT_VERSION_OPTION_DECL },
407 { NULL, 0, NULL, 0 }
410 void
411 usage (int status)
413 if (status != EXIT_SUCCESS)
414 emit_try_help ();
415 else
417 printf (_("\
418 Usage: %s [OPTION]... [FILE]...\n\
419 "), program_name);
420 #if HASH_ALGO_CKSUM
421 fputs (_("\
422 Print or verify checksums.\n\
423 By default use the 32 bit CRC algorithm.\n\
424 "), stdout);
425 #else
426 printf (_("\
427 Print or check %s (%d-bit) checksums.\n\
429 DIGEST_TYPE_STRING,
430 DIGEST_BITS);
431 #endif
433 emit_stdin_note ();
434 #if HASH_ALGO_SUM
435 fputs (_("\
437 -r use BSD sum algorithm (the default), use 1K blocks\n\
438 -s, --sysv use System V sum algorithm, use 512 bytes blocks\n\
439 "), stdout);
440 #endif
441 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
442 emit_mandatory_arg_note ();
443 #endif
444 #if HASH_ALGO_CKSUM
445 fputs (_("\
446 -a, --algorithm=TYPE select the digest type to use. See DIGEST below.\
448 "), stdout);
449 fputs (_("\
450 -b, --base64 emit base64-encoded digests, not hexadecimal\
452 "), stdout);
453 #endif
454 #if !HASH_ALGO_SUM
455 # if !HASH_ALGO_CKSUM
456 if (O_BINARY)
457 fputs (_("\
458 -b, --binary read in binary mode (default unless reading tty stdin)\
460 "), stdout);
461 else
462 fputs (_("\
463 -b, --binary read in binary mode\n\
464 "), stdout);
465 # endif
466 fputs (_("\
467 -c, --check read checksums from the FILEs and check them\n\
468 "), stdout);
469 # if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
470 fputs (_("\
471 -l, --length=BITS digest length in bits; must not exceed the max for\n\
472 the blake2 algorithm and must be a multiple of 8\n\
473 "), stdout);
474 # endif
475 # if HASH_ALGO_CKSUM
476 fputs (_("\
477 --raw emit a raw binary digest, not hexadecimal\
479 "), stdout);
480 fputs (_("\
481 --tag create a BSD-style checksum (the default)\n\
482 "), stdout);
483 fputs (_("\
484 --untagged create a reversed style checksum, without digest type\n\
485 "), stdout);
486 # else
487 fputs (_("\
488 --tag create a BSD-style checksum\n\
489 "), stdout);
490 # endif
491 # if !HASH_ALGO_CKSUM
492 if (O_BINARY)
493 fputs (_("\
494 -t, --text read in text mode (default if reading tty stdin)\n\
495 "), stdout);
496 else
497 fputs (_("\
498 -t, --text read in text mode (default)\n\
499 "), stdout);
500 # endif
501 fputs (_("\
502 -z, --zero end each output line with NUL, not newline,\n\
503 and disable file name escaping\n\
504 "), stdout);
505 fputs (_("\
507 The following five options are useful only when verifying checksums:\n\
508 --ignore-missing don't fail or report status for missing files\n\
509 --quiet don't print OK for each successfully verified file\n\
510 --status don't output anything, status code shows success\n\
511 --strict exit non-zero for improperly formatted checksum lines\n\
512 -w, --warn warn about improperly formatted checksum lines\n\
514 "), stdout);
515 #endif
516 #if HASH_ALGO_CKSUM
517 fputs (_("\
518 --debug indicate which implementation used\n\
519 "), stdout);
520 #endif
521 fputs (HELP_OPTION_DESCRIPTION, stdout);
522 fputs (VERSION_OPTION_DESCRIPTION, stdout);
523 #if HASH_ALGO_CKSUM
524 fputs (_("\
526 DIGEST determines the digest algorithm and default output format:\n\
527 sysv (equivalent to sum -s)\n\
528 bsd (equivalent to sum -r)\n\
529 crc (equivalent to cksum)\n\
530 md5 (equivalent to md5sum)\n\
531 sha1 (equivalent to sha1sum)\n\
532 sha224 (equivalent to sha224sum)\n\
533 sha256 (equivalent to sha256sum)\n\
534 sha384 (equivalent to sha384sum)\n\
535 sha512 (equivalent to sha512sum)\n\
536 blake2b (equivalent to b2sum)\n\
537 sm3 (only available through cksum)\n\
538 \n"), stdout);
539 #endif
540 #if !HASH_ALGO_SUM && !HASH_ALGO_CKSUM
541 printf (_("\
543 The sums are computed as described in %s.\n"), DIGEST_REFERENCE);
544 fputs (_("\
545 When checking, the input should be a former output of this program.\n\
546 The default mode is to print a line with: checksum, a space,\n\
547 a character indicating input mode ('*' for binary, ' ' for text\n\
548 or where binary is insignificant), and name for each FILE.\n\
550 Note: There is no difference between binary mode and text mode on GNU systems.\
551 \n"), stdout);
552 #endif
553 #if HASH_ALGO_CKSUM
554 fputs (_("\
555 When checking, the input should be a former output of this program,\n\
556 or equivalent standalone program.\
557 \n"), stdout);
558 #endif
559 emit_ancillary_info (PROGRAM_NAME);
562 exit (status);
565 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
567 /* Given a file name, S of length S_LEN, that is not NUL-terminated,
568 modify it in place, performing the equivalent of this sed substitution:
569 's/\\n/\n/g;s/\\r/\r/g;s/\\\\/\\/g' i.e., replacing each "\\n" string
570 with a newline, each "\\r" string with a carriage return,
571 and each "\\\\" with a single backslash, NUL-terminate it and return S.
572 If S is not a valid escaped file name, i.e., if it ends with an odd number
573 of backslashes or if it contains a backslash followed by anything other
574 than "n" or another backslash, return NULL. */
576 static char *
577 filename_unescape (char *s, size_t s_len)
579 char *dst = s;
581 for (size_t i = 0; i < s_len; i++)
583 switch (s[i])
585 case '\\':
586 if (i == s_len - 1)
588 /* File name ends with an unescaped backslash: invalid. */
589 return NULL;
591 ++i;
592 switch (s[i])
594 case 'n':
595 *dst++ = '\n';
596 break;
597 case 'r':
598 *dst++ = '\r';
599 break;
600 case '\\':
601 *dst++ = '\\';
602 break;
603 default:
604 /* Only '\', 'n' or 'r' may follow a backslash. */
605 return NULL;
607 break;
609 case '\0':
610 /* The file name may not contain a NUL. */
611 return NULL;
613 default:
614 *dst++ = s[i];
615 break;
618 if (dst < s + s_len)
619 *dst = '\0';
621 return s;
624 /* Return true if S is a LEN-byte NUL-terminated string of hex or base64
625 digits and has the expected length. Otherwise, return false. */
626 ATTRIBUTE_PURE
627 static bool
628 valid_digits (unsigned char const *s, size_t len)
630 #if HASH_ALGO_CKSUM
631 if (len == BASE64_LENGTH (digest_length / 8))
633 size_t i;
634 for (i = 0; i < len - digest_length % 3; i++)
636 if (!isbase64 (*s))
637 return false;
638 ++s;
640 for ( ; i < len; i++)
642 if (*s != '=')
643 return false;
644 ++s;
647 else
648 #endif
649 if (len == digest_hex_bytes)
651 for (unsigned int i = 0; i < digest_hex_bytes; i++)
653 if (!isxdigit (*s))
654 return false;
655 ++s;
658 else
659 return false;
661 return *s == '\0';
664 /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
665 'sha1' command into two parts: a hexadecimal digest, and the file
666 name. S is modified. Set *D_LEN to the length of the digest string.
667 Return true if successful. */
669 static bool
670 bsd_split_3 (char *s, size_t s_len,
671 unsigned char **digest, size_t *d_len,
672 char **file_name, bool escaped_filename)
674 if (s_len == 0)
675 return false;
677 /* Find end of filename. */
678 size_t i = s_len - 1;
679 while (i && s[i] != ')')
680 i--;
682 if (s[i] != ')')
683 return false;
685 *file_name = s;
687 if (escaped_filename && filename_unescape (s, i) == NULL)
688 return false;
690 s[i++] = '\0';
692 while (ISWHITE (s[i]))
693 i++;
695 if (s[i] != '=')
696 return false;
698 i++;
700 while (ISWHITE (s[i]))
701 i++;
703 *digest = (unsigned char *) &s[i];
705 *d_len = s_len - i;
706 return valid_digits (*digest, *d_len);
709 #if HASH_ALGO_CKSUM
710 /* Return the corresponding Algorithm for the string S,
711 or -1 for no match. */
713 static ptrdiff_t
714 algorithm_from_tag (char *s)
716 /* Limit check size to this length for perf reasons. */
717 static size_t max_tag_len;
718 if (! max_tag_len)
720 char const * const * tag = algorithm_tags;
721 while (*tag)
723 size_t tag_len = strlen (*tag++);
724 max_tag_len = MAX (tag_len, max_tag_len);
728 size_t i = 0;
730 /* Find end of tag */
731 while (i <= max_tag_len && s[i] && ! ISWHITE (s[i])
732 && s[i] != '-' && s[i] != '(')
733 ++i;
735 if (i > max_tag_len)
736 return -1;
738 /* Terminate tag, and lookup. */
739 char sep = s[i];
740 s[i] = '\0';
741 ptrdiff_t algo = argmatch_exact (s, algorithm_tags);
742 s[i] = sep;
744 return algo;
746 #endif
748 /* Split the string S (of length S_LEN) into three parts:
749 a hexadecimal digest, binary flag, and the file name.
750 S is modified. Set *D_LEN to the length of the digest string.
751 Return true if successful. */
753 static bool
754 split_3 (char *s, size_t s_len,
755 unsigned char **digest, size_t *d_len, int *binary, char **file_name)
757 bool escaped_filename = false;
758 size_t algo_name_len;
760 size_t i = 0;
761 while (ISWHITE (s[i]))
762 ++i;
764 if (s[i] == '\\')
766 ++i;
767 escaped_filename = true;
770 /* Check for BSD-style checksum line. */
772 #if HASH_ALGO_CKSUM
773 if (! algorithm_specified)
775 ptrdiff_t algo_tag = algorithm_from_tag (s + i);
776 if (algo_tag >= 0)
778 if (algo_tag <= crc)
779 return false; /* We don't support checking these older formats. */
780 cksum_algorithm = algo_tag;
782 else
783 return false; /* We only support tagged format without -a. */
785 #endif
787 algo_name_len = strlen (DIGEST_TYPE_STRING);
788 if (STREQ_LEN (s + i, DIGEST_TYPE_STRING, algo_name_len))
790 i += algo_name_len;
791 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
792 /* Terminate and match algorithm name. */
793 char const *algo_name = &s[i - algo_name_len];
794 bool length_specified = s[i] == '-';
795 bool openssl_format = s[i] == '('; /* and no length_specified */
796 s[i++] = '\0';
797 if (!STREQ (algo_name, DIGEST_TYPE_STRING))
798 return false;
799 if (openssl_format)
800 s[--i] = '(';
802 # if HASH_ALGO_BLAKE2
803 digest_length = BLAKE2B_MAX_LEN * 8;
804 # else
805 digest_length = algorithm_bits[cksum_algorithm];
806 # endif
807 if (length_specified)
809 uintmax_t length;
810 char *siend;
811 if (! (xstrtoumax (s + i, &siend, 0, &length, NULL) == LONGINT_OK
812 && 0 < length && length <= digest_length
813 && length % 8 == 0))
814 return false;
816 i = siend - s;
817 digest_length = length;
819 digest_hex_bytes = digest_length / 4;
820 #endif
821 if (s[i] == ' ')
822 ++i;
823 if (s[i] == '(')
825 ++i;
826 *binary = 0;
827 return bsd_split_3 (s + i, s_len - i,
828 digest, d_len, file_name, escaped_filename);
830 return false;
833 /* Ignore this line if it is too short.
834 Each line must have at least 'min_digest_line_length - 1' (or one more, if
835 the first is a backslash) more characters to contain correct message digest
836 information. */
837 if (s_len - i < min_digest_line_length + (s[i] == '\\'))
838 return false;
840 *digest = (unsigned char *) &s[i];
842 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
843 /* Auto determine length. */
844 # if HASH_ALGO_CKSUM
845 if (cksum_algorithm == blake2b) {
846 # endif
847 unsigned char const *hp = *digest;
848 digest_hex_bytes = 0;
849 while (isxdigit (*hp++))
850 digest_hex_bytes++;
851 if (digest_hex_bytes < 2 || digest_hex_bytes % 2
852 || BLAKE2B_MAX_LEN * 2 < digest_hex_bytes)
853 return false;
854 digest_length = digest_hex_bytes * 4;
855 # if HASH_ALGO_CKSUM
857 # endif
858 #endif
860 /* This field must be the hexadecimal or base64 representation
861 of the message digest. */
862 while (s[i] && !ISWHITE (s[i]))
863 i++;
865 *d_len = &s[i] - (char *) *digest;
866 s[i++] = '\0';
868 if (! valid_digits (*digest, *d_len))
869 return false;
871 /* If "bsd reversed" format detected. */
872 if ((s_len - i == 1) || (s[i] != ' ' && s[i] != '*'))
874 /* Don't allow mixing bsd and standard formats,
875 to minimize security issues with attackers
876 renaming files with leading spaces.
877 This assumes that with bsd format checksums
878 that the first file name does not have
879 a leading ' ' or '*'. */
880 if (bsd_reversed == 0)
881 return false;
882 bsd_reversed = 1;
884 else if (bsd_reversed != 1)
886 bsd_reversed = 0;
887 *binary = (s[i++] == '*');
890 /* All characters between the type indicator and end of line are
891 significant -- that includes leading and trailing white space. */
892 *file_name = &s[i];
894 if (escaped_filename)
895 return filename_unescape (&s[i], s_len - i) != NULL;
897 return true;
900 /* If ESCAPE is true, then translate each:
901 NEWLINE byte to the string, "\\n",
902 CARRIAGE RETURN byte to the string, "\\r",
903 and each backslash to "\\\\". */
904 static void
905 print_filename (char const *file, bool escape)
907 if (! escape)
909 fputs (file, stdout);
910 return;
913 while (*file)
915 switch (*file)
917 case '\n':
918 fputs ("\\n", stdout);
919 break;
921 case '\r':
922 fputs ("\\r", stdout);
923 break;
925 case '\\':
926 fputs ("\\\\", stdout);
927 break;
929 default:
930 putchar (*file);
931 break;
933 file++;
937 /* An interface to the function, DIGEST_STREAM.
938 Operate on FILENAME (it may be "-").
940 *BINARY indicates whether the file is binary. BINARY < 0 means it
941 depends on whether binary mode makes any difference and the file is
942 a terminal; in that case, clear *BINARY if the file was treated as
943 text because it was a terminal.
945 Put the checksum in *BIN_RESULT, which must be properly aligned.
946 Put true in *MISSING if the file can't be opened due to ENOENT.
947 Return true if successful. */
949 static bool
950 digest_file (char const *filename, int *binary, unsigned char *bin_result,
951 bool *missing, MAYBE_UNUSED uintmax_t *length)
953 FILE *fp;
954 int err;
955 bool is_stdin = STREQ (filename, "-");
957 *missing = false;
959 if (is_stdin)
961 have_read_stdin = true;
962 fp = stdin;
963 if (O_BINARY && *binary)
965 if (*binary < 0)
966 *binary = ! isatty (STDIN_FILENO);
967 if (*binary)
968 xset_binary_mode (STDIN_FILENO, O_BINARY);
971 else
973 fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r"));
974 if (fp == NULL)
976 if (ignore_missing && errno == ENOENT)
978 *missing = true;
979 return true;
981 error (0, errno, "%s", quotef (filename));
982 return false;
986 fadvise (fp, FADVISE_SEQUENTIAL);
988 #if HASH_ALGO_CKSUM
989 if (cksum_algorithm == blake2b)
990 *length = digest_length / 8;
991 err = DIGEST_STREAM (fp, bin_result, length);
992 #elif HASH_ALGO_SUM
993 err = DIGEST_STREAM (fp, bin_result, length);
994 #elif HASH_ALGO_BLAKE2
995 err = DIGEST_STREAM (fp, bin_result, digest_length / 8);
996 #else
997 err = DIGEST_STREAM (fp, bin_result);
998 #endif
999 err = err ? errno : 0;
1000 if (is_stdin)
1001 clearerr (fp);
1002 else if (fclose (fp) != 0 && !err)
1003 err = errno;
1005 if (err)
1007 error (0, err, "%s", quotef (filename));
1008 return false;
1011 return true;
1014 #if !HASH_ALGO_SUM
1015 static void
1016 output_file (char const *file, int binary_file, void const *digest,
1017 bool raw, bool tagged, unsigned char delim, MAYBE_UNUSED bool args,
1018 MAYBE_UNUSED uintmax_t length)
1020 # if HASH_ALGO_CKSUM
1021 if (raw)
1023 fwrite (digest, 1, digest_length / 8, stdout);
1024 return;
1026 # endif
1028 unsigned char const *bin_buffer = digest;
1030 /* Output a leading backslash if the file name contains problematic chars.
1031 Note we escape '\' itself to provide some forward compat to introduce
1032 escaping of other characters. */
1033 bool needs_escape = delim == '\n' && (strchr (file, '\\')
1034 || strchr (file, '\n')
1035 || strchr (file, '\r'));
1036 if (needs_escape)
1037 putchar ('\\');
1039 if (tagged)
1041 fputs (DIGEST_TYPE_STRING, stdout);
1042 # if HASH_ALGO_BLAKE2
1043 if (digest_length < BLAKE2B_MAX_LEN * 8)
1044 printf ("-%"PRIuMAX, digest_length);
1045 # elif HASH_ALGO_CKSUM
1046 if (cksum_algorithm == blake2b)
1048 if (digest_length < BLAKE2B_MAX_LEN * 8)
1049 printf ("-%"PRIuMAX, digest_length);
1051 # endif
1052 fputs (" (", stdout);
1053 print_filename (file, needs_escape);
1054 fputs (") = ", stdout);
1057 # if HASH_ALGO_CKSUM
1058 if (base64_digest)
1060 char b64[BASE64_LENGTH (DIGEST_BIN_BYTES) + 1];
1061 base64_encode ((char const *) bin_buffer, digest_length / 8,
1062 b64, sizeof b64);
1063 fputs (b64, stdout);
1065 else
1066 # endif
1068 for (size_t i = 0; i < (digest_hex_bytes / 2); ++i)
1069 printf ("%02x", bin_buffer[i]);
1072 if (!tagged)
1074 putchar (' ');
1076 # if HASH_ALGO_CKSUM
1077 /* Simplify output as always in binary mode. */
1078 putchar (' ');
1079 # else
1080 putchar (binary_file ? '*' : ' ');
1081 # endif
1083 print_filename (file, needs_escape);
1086 putchar (delim);
1088 #endif
1090 #if HASH_ALGO_CKSUM
1091 /* Return true if B64_DIGEST is the same as the base64 digest of the
1092 DIGEST_LENGTH/8 bytes at BIN_BUFFER. */
1093 static bool
1094 b64_equal (unsigned char const *b64_digest, unsigned char const *bin_buffer)
1096 size_t b64_n_bytes = BASE64_LENGTH (digest_length / 8);
1097 char b64[BASE64_LENGTH (DIGEST_BIN_BYTES) + 1];
1098 base64_encode ((char const *) bin_buffer, digest_length / 8, b64, sizeof b64);
1099 return memcmp (b64_digest, b64, b64_n_bytes + 1) == 0;
1101 #endif
1103 /* Return true if HEX_DIGEST is the same as the hex-encoded digest of the
1104 DIGEST_LENGTH/8 bytes at BIN_BUFFER. */
1105 static bool
1106 hex_equal (unsigned char const *hex_digest, unsigned char const *bin_buffer)
1108 static const char bin2hex[] = { '0', '1', '2', '3',
1109 '4', '5', '6', '7',
1110 '8', '9', 'a', 'b',
1111 'c', 'd', 'e', 'f' };
1112 size_t digest_bin_bytes = digest_hex_bytes / 2;
1114 /* Compare generated binary number with text representation
1115 in check file. Ignore case of hex digits. */
1116 size_t cnt;
1117 for (cnt = 0; cnt < digest_bin_bytes; ++cnt)
1119 if (tolower (hex_digest[2 * cnt])
1120 != bin2hex[bin_buffer[cnt] >> 4]
1121 || (tolower (hex_digest[2 * cnt + 1])
1122 != (bin2hex[bin_buffer[cnt] & 0xf])))
1123 break;
1125 return cnt == digest_bin_bytes;
1128 static bool
1129 digest_check (char const *checkfile_name)
1131 FILE *checkfile_stream;
1132 uintmax_t n_misformatted_lines = 0;
1133 uintmax_t n_mismatched_checksums = 0;
1134 uintmax_t n_open_or_read_failures = 0;
1135 bool properly_formatted_lines = false;
1136 bool matched_checksums = false;
1137 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
1138 /* Make sure bin_buffer is properly aligned. */
1139 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
1140 uintmax_t line_number;
1141 char *line;
1142 size_t line_chars_allocated;
1143 bool is_stdin = STREQ (checkfile_name, "-");
1145 if (is_stdin)
1147 have_read_stdin = true;
1148 checkfile_name = _("standard input");
1149 checkfile_stream = stdin;
1151 else
1153 checkfile_stream = fopen (checkfile_name, "r");
1154 if (checkfile_stream == NULL)
1156 error (0, errno, "%s", quotef (checkfile_name));
1157 return false;
1161 line_number = 0;
1162 line = NULL;
1163 line_chars_allocated = 0;
1166 char *filename;
1167 int binary;
1168 unsigned char *digest;
1169 ssize_t line_length;
1171 ++line_number;
1172 if (line_number == 0)
1173 die (EXIT_FAILURE, 0, _("%s: too many checksum lines"),
1174 quotef (checkfile_name));
1176 line_length = getline (&line, &line_chars_allocated, checkfile_stream);
1177 if (line_length <= 0)
1178 break;
1180 /* Ignore comment lines, which begin with a '#' character. */
1181 if (line[0] == '#')
1182 continue;
1184 /* Remove any trailing newline. */
1185 line_length -= line[line_length - 1] == '\n';
1186 /* Remove any trailing carriage return. */
1187 line_length -= line[line_length - (0 < line_length)] == '\r';
1189 /* Ignore empty lines. */
1190 if (line_length == 0)
1191 continue;
1193 line[line_length] = '\0';
1195 size_t d_len;
1196 if (! (split_3 (line, line_length, &digest, &d_len, &binary, &filename)
1197 && ! (is_stdin && STREQ (filename, "-"))))
1199 ++n_misformatted_lines;
1201 if (warn)
1203 error (0, 0,
1204 _("%s: %" PRIuMAX
1205 ": improperly formatted %s checksum line"),
1206 quotef (checkfile_name), line_number,
1207 DIGEST_TYPE_STRING);
1210 else
1212 bool ok;
1213 bool missing;
1214 /* Only escape in the edge case producing multiple lines,
1215 to ease automatic processing of status output. */
1216 bool needs_escape = ! status_only && strchr (filename, '\n');
1218 properly_formatted_lines = true;
1220 uintmax_t length;
1221 ok = digest_file (filename, &binary, bin_buffer, &missing, &length);
1223 if (!ok)
1225 ++n_open_or_read_failures;
1226 if (!status_only)
1228 if (needs_escape)
1229 putchar ('\\');
1230 print_filename (filename, needs_escape);
1231 printf (": %s\n", _("FAILED open or read"));
1234 else if (ignore_missing && missing)
1236 /* Ignore missing files with --ignore-missing. */
1239 else
1241 bool match = false;
1242 #if HASH_ALGO_CKSUM
1243 if (d_len < digest_hex_bytes)
1244 match = b64_equal (digest, bin_buffer);
1245 else
1246 #endif
1247 if (d_len == digest_hex_bytes)
1248 match = hex_equal (digest, bin_buffer);
1250 if (match)
1251 matched_checksums = true;
1252 else
1253 ++n_mismatched_checksums;
1255 if (!status_only)
1257 if ( ! matched_checksums || ! quiet)
1259 if (needs_escape)
1260 putchar ('\\');
1261 print_filename (filename, needs_escape);
1264 if ( ! matched_checksums)
1265 printf (": %s\n", _("FAILED"));
1266 else if (!quiet)
1267 printf (": %s\n", _("OK"));
1272 while (!feof (checkfile_stream) && !ferror (checkfile_stream));
1274 free (line);
1276 int err = ferror (checkfile_stream) ? 0 : -1;
1277 if (is_stdin)
1278 clearerr (checkfile_stream);
1279 else if (fclose (checkfile_stream) != 0 && err < 0)
1280 err = errno;
1282 if (0 <= err)
1284 error (0, err, err ? "%s" : _("%s: read error"),
1285 quotef (checkfile_name));
1286 return false;
1289 if (! properly_formatted_lines)
1291 /* Warn if no tests are found. */
1292 error (0, 0, _("%s: no properly formatted checksum lines found"),
1293 quotef (checkfile_name));
1295 else
1297 if (!status_only)
1299 if (n_misformatted_lines != 0)
1300 error (0, 0,
1301 (ngettext
1302 ("WARNING: %" PRIuMAX " line is improperly formatted",
1303 "WARNING: %" PRIuMAX " lines are improperly formatted",
1304 select_plural (n_misformatted_lines))),
1305 n_misformatted_lines);
1307 if (n_open_or_read_failures != 0)
1308 error (0, 0,
1309 (ngettext
1310 ("WARNING: %" PRIuMAX " listed file could not be read",
1311 "WARNING: %" PRIuMAX " listed files could not be read",
1312 select_plural (n_open_or_read_failures))),
1313 n_open_or_read_failures);
1315 if (n_mismatched_checksums != 0)
1316 error (0, 0,
1317 (ngettext
1318 ("WARNING: %" PRIuMAX " computed checksum did NOT match",
1319 "WARNING: %" PRIuMAX " computed checksums did NOT match",
1320 select_plural (n_mismatched_checksums))),
1321 n_mismatched_checksums);
1323 if (ignore_missing && ! matched_checksums)
1324 error (0, 0, _("%s: no file was verified"),
1325 quotef (checkfile_name));
1329 return (properly_formatted_lines
1330 && matched_checksums
1331 && n_mismatched_checksums == 0
1332 && n_open_or_read_failures == 0
1333 && (!strict || n_misformatted_lines == 0));
1337 main (int argc, char **argv)
1339 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
1340 /* Make sure bin_buffer is properly aligned. */
1341 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
1342 bool do_check = false;
1343 int opt;
1344 bool ok = true;
1345 #if HASH_ALGO_CKSUM
1346 int binary = 1;
1347 bool prefix_tag = true;
1348 #else
1349 int binary = -1;
1350 bool prefix_tag = false;
1351 #endif
1353 /* Setting values of global variables. */
1354 initialize_main (&argc, &argv);
1355 set_program_name (argv[0]);
1356 setlocale (LC_ALL, "");
1357 bindtextdomain (PACKAGE, LOCALEDIR);
1358 textdomain (PACKAGE);
1360 atexit (close_stdout);
1362 /* Line buffer stdout to ensure lines are written atomically and immediately
1363 so that processes running in parallel do not intersperse their output. */
1364 setvbuf (stdout, NULL, _IOLBF, 0);
1366 #if HASH_ALGO_SUM
1367 char const *short_opts = "rs";
1368 #elif HASH_ALGO_CKSUM
1369 char const *short_opts = "a:l:bctwz";
1370 char const *digest_length_str = "";
1371 #elif HASH_ALGO_BLAKE2
1372 char const *short_opts = "l:bctwz";
1373 char const *digest_length_str = "";
1374 #else
1375 char const *short_opts = "bctwz";
1376 #endif
1378 while ((opt = getopt_long (argc, argv, short_opts, long_options, NULL)) != -1)
1379 switch (opt)
1381 #if HASH_ALGO_CKSUM
1382 case 'a':
1383 cksum_algorithm = XARGMATCH_EXACT ("--algorithm", optarg,
1384 algorithm_args, algorithm_types);
1385 algorithm_specified = true;
1386 break;
1388 case DEBUG_PROGRAM_OPTION:
1389 cksum_debug = true;
1390 break;
1391 #endif
1392 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
1393 case 'l':
1394 digest_length = xdectoumax (optarg, 0, UINTMAX_MAX, "",
1395 _("invalid length"), 0);
1396 digest_length_str = optarg;
1397 if (digest_length % 8 != 0)
1399 error (0, 0, _("invalid length: %s"), quote (digest_length_str));
1400 die (EXIT_FAILURE, 0, _("length is not a multiple of 8"));
1402 break;
1403 #endif
1404 #if !HASH_ALGO_SUM
1405 case 'c':
1406 do_check = true;
1407 break;
1408 case STATUS_OPTION:
1409 status_only = true;
1410 warn = false;
1411 quiet = false;
1412 break;
1413 # if !HASH_ALGO_CKSUM
1414 case 'b':
1415 binary = 1;
1416 break;
1417 case 't':
1418 binary = 0;
1419 break;
1420 # endif
1421 case 'w':
1422 status_only = false;
1423 warn = true;
1424 quiet = false;
1425 break;
1426 case IGNORE_MISSING_OPTION:
1427 ignore_missing = true;
1428 break;
1429 case QUIET_OPTION:
1430 status_only = false;
1431 warn = false;
1432 quiet = true;
1433 break;
1434 case STRICT_OPTION:
1435 strict = true;
1436 break;
1437 # if HASH_ALGO_CKSUM
1438 case 'b':
1439 base64_digest = true;
1440 break;
1441 case RAW_OPTION:
1442 raw_digest = true;
1443 break;
1444 case UNTAG_OPTION:
1445 prefix_tag = false;
1446 break;
1447 # endif
1448 case TAG_OPTION:
1449 prefix_tag = true;
1450 binary = 1;
1451 break;
1452 case 'z':
1453 digest_delim = '\0';
1454 break;
1455 #endif
1456 #if HASH_ALGO_SUM
1457 case 'r': /* For SysV compatibility. */
1458 sum_algorithm = bsd;
1459 break;
1461 case 's':
1462 sum_algorithm = sysv;
1463 break;
1464 #endif
1465 case_GETOPT_HELP_CHAR;
1466 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1467 default:
1468 usage (EXIT_FAILURE);
1471 min_digest_line_length = MIN_DIGEST_LINE_LENGTH;
1472 #if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
1473 # if HASH_ALGO_CKSUM
1474 if (digest_length && cksum_algorithm != blake2b)
1475 die (EXIT_FAILURE, 0,
1476 _("--length is only supported with --algorithm=blake2b"));
1477 # endif
1478 if (digest_length > BLAKE2B_MAX_LEN * 8)
1480 error (0, 0, _("invalid length: %s"), quote (digest_length_str));
1481 die (EXIT_FAILURE, 0,
1482 _("maximum digest length for %s is %d bits"),
1483 quote (DIGEST_TYPE_STRING),
1484 BLAKE2B_MAX_LEN * 8);
1486 if (digest_length == 0)
1488 # if HASH_ALGO_BLAKE2
1489 digest_length = BLAKE2B_MAX_LEN * 8;
1490 # else
1491 digest_length = algorithm_bits[cksum_algorithm];
1492 # endif
1494 digest_hex_bytes = digest_length / 4;
1495 #else
1496 digest_hex_bytes = DIGEST_HEX_BYTES;
1497 #endif
1499 #if HASH_ALGO_CKSUM
1500 switch (cksum_algorithm)
1502 case bsd:
1503 case sysv:
1504 case crc:
1505 if (do_check && algorithm_specified)
1506 die (EXIT_FAILURE, 0,
1507 _("--check is not supported with --algorithm={bsd,sysv,crc}"));
1508 break;
1509 default:
1510 break;
1513 if (base64_digest && raw_digest)
1515 error (0, 0, _("--base64 and --raw are mutually exclusive"));
1516 usage (EXIT_FAILURE);
1518 #endif
1520 if (prefix_tag && !binary)
1522 /* This could be supported in a backwards compatible way
1523 by prefixing the output line with a space in text mode.
1524 However that's invasive enough that it was agreed to
1525 not support this mode with --tag, as --text use cases
1526 are adequately supported by the default output format. */
1527 error (0, 0, _("--tag does not support --text mode"));
1528 usage (EXIT_FAILURE);
1531 if (digest_delim != '\n' && do_check)
1533 error (0, 0, _("the --zero option is not supported when "
1534 "verifying checksums"));
1535 usage (EXIT_FAILURE);
1537 #if !HASH_ALGO_CKSUM
1538 if (prefix_tag && do_check)
1540 error (0, 0, _("the --tag option is meaningless when "
1541 "verifying checksums"));
1542 usage (EXIT_FAILURE);
1544 #endif
1546 #if !HASH_ALGO_CKSUM
1547 if (0 <= binary && do_check)
1549 error (0, 0, _("the --binary and --text options are meaningless when "
1550 "verifying checksums"));
1551 usage (EXIT_FAILURE);
1553 #endif
1555 if (ignore_missing && !do_check)
1557 error (0, 0,
1558 _("the --ignore-missing option is meaningful only when "
1559 "verifying checksums"));
1560 usage (EXIT_FAILURE);
1563 if (status_only && !do_check)
1565 error (0, 0,
1566 _("the --status option is meaningful only when verifying checksums"));
1567 usage (EXIT_FAILURE);
1570 if (warn && !do_check)
1572 error (0, 0,
1573 _("the --warn option is meaningful only when verifying checksums"));
1574 usage (EXIT_FAILURE);
1577 if (quiet && !do_check)
1579 error (0, 0,
1580 _("the --quiet option is meaningful only when verifying checksums"));
1581 usage (EXIT_FAILURE);
1584 if (strict & !do_check)
1586 error (0, 0,
1587 _("the --strict option is meaningful only when verifying checksums"));
1588 usage (EXIT_FAILURE);
1591 if (!O_BINARY && binary < 0)
1592 binary = 0;
1594 char **operand_lim = argv + argc;
1595 if (optind == argc)
1596 *operand_lim++ = bad_cast ("-");
1597 else if (1 < argc - optind && raw_digest)
1599 die (EXIT_FAILURE, 0,
1600 _("the --raw option is not supported with multiple files"));
1603 for (char **operandp = argv + optind; operandp < operand_lim; operandp++)
1605 char *file = *operandp;
1606 if (do_check)
1607 ok &= digest_check (file);
1608 else
1610 int binary_file = binary;
1611 bool missing;
1612 uintmax_t length;
1614 if (! digest_file (file, &binary_file, bin_buffer, &missing, &length))
1615 ok = false;
1616 else
1618 DIGEST_OUT (file, binary_file, bin_buffer, raw_digest, prefix_tag,
1619 digest_delim, optind != argc, length);
1624 if (have_read_stdin && fclose (stdin) == EOF)
1625 die (EXIT_FAILURE, errno, _("standard input"));
1627 return ok ? EXIT_SUCCESS : EXIT_FAILURE;