1 /* Compute checksums of files or strings.
2 Copyright (C) 1995-2017 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>. */
22 #include <sys/types.h>
27 #include "xdectoint.h"
31 # include "blake2/b2sum.h"
39 #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
42 #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
49 #include "xbinary-io.h"
51 /* The official name of this program (e.g., no 'g' prefix). */
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
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
102 # error "Can't decide which hash algorithm to compile."
107 proper_name ("Padraig Brady"), \
108 proper_name ("Samuel Neves")
111 proper_name ("Ulrich Drepper"), \
112 proper_name ("Scott Miller"), \
113 proper_name ("David Madore")
114 # define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
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. */
122 # define MIN_DIGEST_LINE_LENGTH 3 /* With -l 8. */
124 # define MIN_DIGEST_LINE_LENGTH \
125 (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
127 + 1 /* minimum filename length */ )
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;
161 static char const *const algorithm_in_string
[] =
165 static char const *const algorithm_out_string
[] =
173 verify (ARRAY_CARDINALITY (algorithm_in_string
) == 2);
174 verify (ARRAY_CARDINALITY (algorithm_out_string
) == 2);
176 static enum Algorithm b2_algorithm
;
177 static uintmax_t b2_length
;
178 static blake2fn blake2fns
[]=
182 static uintmax_t blake2_max_len
[]=
186 #endif /* HASH_ALGO_BLAKE2 */
188 /* For long options that have no equivalent short option, use a
189 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
192 IGNORE_MISSING_OPTION
= CHAR_MAX
+ 1,
199 static struct option
const long_options
[] =
202 { "length", required_argument
, NULL
, 'l'},
204 { "binary", no_argument
, NULL
, 'b' },
205 { "check", no_argument
, NULL
, 'c' },
206 { "ignore-missing", no_argument
, NULL
, IGNORE_MISSING_OPTION
},
207 { "quiet", no_argument
, NULL
, QUIET_OPTION
},
208 { "status", no_argument
, NULL
, STATUS_OPTION
},
209 { "text", no_argument
, NULL
, 't' },
210 { "warn", no_argument
, NULL
, 'w' },
211 { "strict", no_argument
, NULL
, STRICT_OPTION
},
212 { "tag", no_argument
, NULL
, TAG_OPTION
},
213 { GETOPT_HELP_OPTION_DECL
},
214 { GETOPT_VERSION_OPTION_DECL
},
221 if (status
!= EXIT_SUCCESS
)
226 Usage: %s [OPTION]... [FILE]...\n\
227 Print or check %s (%d-bit) checksums.\n\
237 -b, --binary read in binary mode (default unless reading tty stdin)\n\
242 -b, --binary read in binary mode\n\
246 -c, --check read %s sums from the FILEs and check them\n"),
250 -l, --length digest length in bits; must not exceed the maximum for\n\
251 the blake2 algorithm and must be a multiple of 8\n\
255 --tag create a BSD-style checksum\n\
259 -t, --text read in text mode (default if reading tty stdin)\n\
263 -t, --text read in text mode (default)\n\
267 The following five options are useful only when verifying checksums:\n\
268 --ignore-missing don't fail or report status for missing files\n\
269 --quiet don't print OK for each successfully verified file\n\
270 --status don't output anything, status code shows success\n\
271 --strict exit non-zero for improperly formatted checksum lines\n\
272 -w, --warn warn about improperly formatted checksum lines\n\
275 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
276 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
279 The sums are computed as described in %s. When checking, the input\n\
280 should be a former output of this program. The default mode is to print a\n\
281 line with checksum, a space, a character indicating input mode ('*' for binary,\
282 \n' ' for text or where binary is insignificant), and name for each FILE.\n"),
284 emit_ancillary_info (PROGRAM_NAME
);
290 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
292 /* Given a file name, S of length S_LEN, that is not NUL-terminated,
293 modify it in place, performing the equivalent of this sed substitution:
294 's/\\n/\n/g;s/\\\\/\\/g' i.e., replacing each "\\n" string with a newline
295 and each "\\\\" with a single backslash, NUL-terminate it and return S.
296 If S is not a valid escaped file name, i.e., if it ends with an odd number
297 of backslashes or if it contains a backslash followed by anything other
298 than "n" or another backslash, return NULL. */
301 filename_unescape (char *s
, size_t s_len
)
305 for (size_t i
= 0; i
< s_len
; i
++)
312 /* File name ends with an unescaped backslash: invalid. */
325 /* Only '\' or 'n' may follow a backslash. */
331 /* The file name may not contain a NUL. */
345 /* Return true if S is a NUL-terminated string of DIGEST_HEX_BYTES hex digits.
346 Otherwise, return false. */
347 static bool _GL_ATTRIBUTE_PURE
348 hex_digits (unsigned char const *s
)
350 for (unsigned int i
= 0; i
< digest_hex_bytes
; i
++)
359 /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
360 'sha1' command into two parts: a hexadecimal digest, and the file
361 name. S is modified. Return true if successful. */
364 bsd_split_3 (char *s
, size_t s_len
, unsigned char **hex_digest
,
365 char **file_name
, bool escaped_filename
)
372 /* Find end of filename. */
374 while (i
&& s
[i
] != ')')
382 if (escaped_filename
&& filename_unescape (s
, i
) == NULL
)
387 while (ISWHITE (s
[i
]))
395 while (ISWHITE (s
[i
]))
398 *hex_digest
= (unsigned char *) &s
[i
];
400 return hex_digits (*hex_digest
);
403 /* Split the string S (of length S_LEN) into three parts:
404 a hexadecimal digest, binary flag, and the file name.
405 S is modified. Return true if successful. */
408 split_3 (char *s
, size_t s_len
,
409 unsigned char **hex_digest
, int *binary
, char **file_name
)
411 bool escaped_filename
= false;
412 size_t algo_name_len
;
415 while (ISWHITE (s
[i
]))
421 escaped_filename
= true;
424 /* Check for BSD-style checksum line. */
426 algo_name_len
= strlen (DIGEST_TYPE_STRING
);
427 if (STREQ_LEN (s
+ i
, DIGEST_TYPE_STRING
, algo_name_len
))
431 /* Terminate and match algorithm name. */
432 char const *algo_name
= &s
[i
- algo_name_len
];
433 /* Skip algorithm variants. */
434 while (s
[i
] && ! ISWHITE (s
[i
]) && s
[i
] != '-' && s
[i
] != '(')
436 bool length_specified
= s
[i
] == '-';
437 bool openssl_format
= s
[i
] == '('; /* and no length_specified */
439 ptrdiff_t algo
= argmatch (algo_name
, algorithm_out_string
, NULL
, 0);
447 if (length_specified
)
449 unsigned long int tmp_ulong
;
450 if (xstrtoul (s
+ i
, NULL
, 0, &tmp_ulong
, NULL
) == LONGINT_OK
451 && 0 < tmp_ulong
&& tmp_ulong
<= blake2_max_len
[b2_algorithm
] * 8
452 && tmp_ulong
% 8 == 0)
453 b2_length
= tmp_ulong
;
457 while (ISDIGIT (s
[i
]))
461 b2_length
= blake2_max_len
[b2_algorithm
] * 8;
463 digest_hex_bytes
= b2_length
/ 4;
471 return bsd_split_3 (s
+ i
, s_len
- i
,
472 hex_digest
, file_name
, escaped_filename
);
477 /* Ignore this line if it is too short.
478 Each line must have at least 'min_digest_line_length - 1' (or one more, if
479 the first is a backslash) more characters to contain correct message digest
481 if (s_len
- i
< min_digest_line_length
+ (s
[i
] == '\\'))
484 *hex_digest
= (unsigned char *) &s
[i
];
487 /* Auto determine length. */
488 unsigned char const *hp
= *hex_digest
;
489 digest_hex_bytes
= 0;
490 while (isxdigit (*hp
++))
492 if (digest_hex_bytes
< 2 || digest_hex_bytes
% 2
493 || blake2_max_len
[b2_algorithm
] * 2 < digest_hex_bytes
)
495 b2_length
= digest_hex_bytes
* 4;
498 /* The first field has to be the n-character hexadecimal
499 representation of the message digest. If it is not followed
500 immediately by a white space it's an error. */
501 i
+= digest_hex_bytes
;
507 if (! hex_digits (*hex_digest
))
510 /* If "bsd reversed" format detected. */
511 if ((s_len
- i
== 1) || (s
[i
] != ' ' && s
[i
] != '*'))
513 /* Don't allow mixing bsd and standard formats,
514 to minimize security issues with attackers
515 renaming files with leading spaces.
516 This assumes that with bsd format checksums
517 that the first file name does not have
518 a leading ' ' or '*'. */
519 if (bsd_reversed
== 0)
523 else if (bsd_reversed
!= 1)
526 *binary
= (s
[i
++] == '*');
529 /* All characters between the type indicator and end of line are
530 significant -- that includes leading and trailing white space. */
533 if (escaped_filename
)
534 return filename_unescape (&s
[i
], s_len
- i
) != NULL
;
539 /* If ESCAPE is true, then translate each NEWLINE byte to the string, "\\n",
540 and each backslash to "\\\\". */
542 print_filename (char const *file
, bool escape
)
546 fputs (file
, stdout
);
555 fputs ("\\n", stdout
);
559 fputs ("\\\\", stdout
);
570 /* An interface to the function, DIGEST_STREAM.
571 Operate on FILENAME (it may be "-").
573 *BINARY indicates whether the file is binary. BINARY < 0 means it
574 depends on whether binary mode makes any difference and the file is
575 a terminal; in that case, clear *BINARY if the file was treated as
576 text because it was a terminal.
578 Put the checksum in *BIN_RESULT, which must be properly aligned.
579 Put true in *MISSING if the file can't be opened due to ENOENT.
580 Return true if successful. */
583 digest_file (const char *filename
, int *binary
, unsigned char *bin_result
,
588 bool is_stdin
= STREQ (filename
, "-");
594 have_read_stdin
= true;
596 if (O_BINARY
&& *binary
)
599 *binary
= ! isatty (STDIN_FILENO
);
601 xset_binary_mode (STDIN_FILENO
, O_BINARY
);
606 fp
= fopen (filename
, (O_BINARY
&& *binary
? "rb" : "r"));
609 if (ignore_missing
&& errno
== ENOENT
)
614 error (0, errno
, "%s", quotef (filename
));
619 fadvise (fp
, FADVISE_SEQUENTIAL
);
622 err
= DIGEST_STREAM (fp
, bin_result
, b2_length
/ 8);
624 err
= DIGEST_STREAM (fp
, bin_result
);
628 error (0, errno
, "%s", quotef (filename
));
634 if (!is_stdin
&& fclose (fp
) != 0)
636 error (0, errno
, "%s", quotef (filename
));
644 digest_check (const char *checkfile_name
)
646 FILE *checkfile_stream
;
647 uintmax_t n_misformatted_lines
= 0;
648 uintmax_t n_improperly_formatted_lines
= 0;
649 uintmax_t n_mismatched_checksums
= 0;
650 uintmax_t n_open_or_read_failures
= 0;
651 bool properly_formatted_lines
= false;
652 bool matched_checksums
= false;
653 unsigned char bin_buffer_unaligned
[DIGEST_BIN_BYTES
+ DIGEST_ALIGN
];
654 /* Make sure bin_buffer is properly aligned. */
655 unsigned char *bin_buffer
= ptr_align (bin_buffer_unaligned
, DIGEST_ALIGN
);
656 uintmax_t line_number
;
658 size_t line_chars_allocated
;
659 bool is_stdin
= STREQ (checkfile_name
, "-");
663 have_read_stdin
= true;
664 checkfile_name
= _("standard input");
665 checkfile_stream
= stdin
;
669 checkfile_stream
= fopen (checkfile_name
, "r");
670 if (checkfile_stream
== NULL
)
672 error (0, errno
, "%s", quotef (checkfile_name
));
679 line_chars_allocated
= 0;
682 char *filename
IF_LINT ( = NULL
);
684 unsigned char *hex_digest
IF_LINT ( = NULL
);
688 if (line_number
== 0)
689 die (EXIT_FAILURE
, 0, _("%s: too many checksum lines"),
690 quotef (checkfile_name
));
692 line_length
= getline (&line
, &line_chars_allocated
, checkfile_stream
);
693 if (line_length
<= 0)
696 /* Ignore comment lines, which begin with a '#' character. */
700 /* Remove any trailing newline. */
701 if (line
[line_length
- 1] == '\n')
702 line
[--line_length
] = '\0';
704 if (! (split_3 (line
, line_length
, &hex_digest
, &binary
, &filename
)
705 && ! (is_stdin
&& STREQ (filename
, "-"))))
707 ++n_misformatted_lines
;
713 ": improperly formatted %s checksum line"),
714 quotef (checkfile_name
), line_number
,
718 ++n_improperly_formatted_lines
;
722 static const char bin2hex
[] = { '0', '1', '2', '3',
725 'c', 'd', 'e', 'f' };
728 /* Only escape in the edge case producing multiple lines,
729 to ease automatic processing of status output. */
730 bool needs_escape
= ! status_only
&& strchr (filename
, '\n');
732 properly_formatted_lines
= true;
734 ok
= digest_file (filename
, &binary
, bin_buffer
, &missing
);
738 ++n_open_or_read_failures
;
743 print_filename (filename
, needs_escape
);
744 printf (": %s\n", _("FAILED open or read"));
747 else if (ignore_missing
&& missing
)
749 /* Ignore missing files with --ignore-missing. */
754 size_t digest_bin_bytes
= digest_hex_bytes
/ 2;
757 /* Compare generated binary number with text representation
758 in check file. Ignore case of hex digits. */
759 for (cnt
= 0; cnt
< digest_bin_bytes
; ++cnt
)
761 if (tolower (hex_digest
[2 * cnt
])
762 != bin2hex
[bin_buffer
[cnt
] >> 4]
763 || (tolower (hex_digest
[2 * cnt
+ 1])
764 != (bin2hex
[bin_buffer
[cnt
] & 0xf])))
767 if (cnt
!= digest_bin_bytes
)
768 ++n_mismatched_checksums
;
770 matched_checksums
= true;
774 if (cnt
!= digest_bin_bytes
|| ! quiet
)
778 print_filename (filename
, needs_escape
);
781 if (cnt
!= digest_bin_bytes
)
782 printf (": %s\n", _("FAILED"));
784 printf (": %s\n", _("OK"));
789 while (!feof (checkfile_stream
) && !ferror (checkfile_stream
));
793 if (ferror (checkfile_stream
))
795 error (0, 0, _("%s: read error"), quotef (checkfile_name
));
799 if (!is_stdin
&& fclose (checkfile_stream
) != 0)
801 error (0, errno
, "%s", quotef (checkfile_name
));
805 if (! properly_formatted_lines
)
807 /* Warn if no tests are found. */
808 error (0, 0, _("%s: no properly formatted %s checksum lines found"),
809 quotef (checkfile_name
), DIGEST_TYPE_STRING
);
815 if (n_misformatted_lines
!= 0)
818 ("WARNING: %" PRIuMAX
" line is improperly formatted",
819 "WARNING: %" PRIuMAX
" lines are improperly formatted",
820 select_plural (n_misformatted_lines
))),
821 n_misformatted_lines
);
823 if (n_open_or_read_failures
!= 0)
826 ("WARNING: %" PRIuMAX
" listed file could not be read",
827 "WARNING: %" PRIuMAX
" listed files could not be read",
828 select_plural (n_open_or_read_failures
))),
829 n_open_or_read_failures
);
831 if (n_mismatched_checksums
!= 0)
834 ("WARNING: %" PRIuMAX
" computed checksum did NOT match",
835 "WARNING: %" PRIuMAX
" computed checksums did NOT match",
836 select_plural (n_mismatched_checksums
))),
837 n_mismatched_checksums
);
839 if (ignore_missing
&& ! matched_checksums
)
840 error (0, 0, _("%s: no file was verified"),
841 quotef (checkfile_name
));
845 return (properly_formatted_lines
847 && n_mismatched_checksums
== 0
848 && n_open_or_read_failures
== 0
849 && (!strict
|| n_improperly_formatted_lines
== 0));
853 main (int argc
, char **argv
)
855 unsigned char bin_buffer_unaligned
[DIGEST_BIN_BYTES
+ DIGEST_ALIGN
];
856 /* Make sure bin_buffer is properly aligned. */
857 unsigned char *bin_buffer
= ptr_align (bin_buffer_unaligned
, DIGEST_ALIGN
);
858 bool do_check
= false;
862 bool prefix_tag
= false;
864 /* Setting values of global variables. */
865 initialize_main (&argc
, &argv
);
866 set_program_name (argv
[0]);
867 setlocale (LC_ALL
, "");
868 bindtextdomain (PACKAGE
, LOCALEDIR
);
869 textdomain (PACKAGE
);
871 atexit (close_stdout
);
873 /* Line buffer stdout to ensure lines are written atomically and immediately
874 so that processes running in parallel do not intersperse their output. */
875 setvbuf (stdout
, NULL
, _IOLBF
, 0);
878 const char* short_opts
= "l:bctw";
879 const char* b2_length_str
= "";
881 const char* short_opts
= "bctw";
884 while ((opt
= getopt_long (argc
, argv
, short_opts
, long_options
, NULL
)) != -1)
889 b2_length
= xdectoumax (optarg
, 0, UINTMAX_MAX
, "",
890 _("invalid length"), 0);
891 b2_length_str
= optarg
;
892 if (b2_length
% 8 != 0)
894 error (0, 0, _("invalid length: %s"), quote (b2_length_str
));
895 die (EXIT_FAILURE
, 0, _("length is not a multiple of 8"));
918 case IGNORE_MISSING_OPTION
:
919 ignore_missing
= true;
933 case_GETOPT_HELP_CHAR
;
934 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
936 usage (EXIT_FAILURE
);
939 min_digest_line_length
= MIN_DIGEST_LINE_LENGTH
;
941 if (b2_length
> blake2_max_len
[b2_algorithm
] * 8)
943 error (0, 0, _("invalid length: %s"), quote (b2_length_str
));
944 die (EXIT_FAILURE
, 0,
945 _("maximum digest length for %s is %"PRIuMAX
" bits"),
946 quote (algorithm_in_string
[b2_algorithm
]),
947 blake2_max_len
[b2_algorithm
] * 8);
949 if (b2_length
== 0 && ! do_check
)
950 b2_length
= blake2_max_len
[b2_algorithm
] * 8;
951 digest_hex_bytes
= b2_length
/ 4;
953 digest_hex_bytes
= DIGEST_HEX_BYTES
;
956 if (prefix_tag
&& !binary
)
958 /* This could be supported in a backwards compatible way
959 by prefixing the output line with a space in text mode.
960 However that's invasive enough that it was agreed to
961 not support this mode with --tag, as --text use cases
962 are adequately supported by the default output format. */
963 error (0, 0, _("--tag does not support --text mode"));
964 usage (EXIT_FAILURE
);
967 if (prefix_tag
&& do_check
)
969 error (0, 0, _("the --tag option is meaningless when "
970 "verifying checksums"));
971 usage (EXIT_FAILURE
);
974 if (0 <= binary
&& do_check
)
976 error (0, 0, _("the --binary and --text options are meaningless when "
977 "verifying checksums"));
978 usage (EXIT_FAILURE
);
981 if (ignore_missing
&& !do_check
)
984 _("the --ignore-missing option is meaningful only when "
985 "verifying checksums"));
986 usage (EXIT_FAILURE
);
989 if (status_only
&& !do_check
)
992 _("the --status option is meaningful only when verifying checksums"));
993 usage (EXIT_FAILURE
);
996 if (warn
&& !do_check
)
999 _("the --warn option is meaningful only when verifying checksums"));
1000 usage (EXIT_FAILURE
);
1003 if (quiet
&& !do_check
)
1006 _("the --quiet option is meaningful only when verifying checksums"));
1007 usage (EXIT_FAILURE
);
1010 if (strict
& !do_check
)
1013 _("the --strict option is meaningful only when verifying checksums"));
1014 usage (EXIT_FAILURE
);
1017 if (!O_BINARY
&& binary
< 0)
1020 char **operand_lim
= argv
+ argc
;
1022 *operand_lim
++ = bad_cast ("-");
1024 for (char **operandp
= argv
+ optind
; operandp
< operand_lim
; operandp
++)
1026 char *file
= *operandp
;
1029 ok
&= digest_check (file
);
1032 int file_is_binary
= binary
;
1035 if (! digest_file (file
, &file_is_binary
, bin_buffer
, &missing
))
1039 /* We don't really need to escape, and hence detect, the '\\'
1040 char, and not doing so should be both forwards and backwards
1041 compatible, since only escaped lines would have a '\\' char at
1042 the start. However just in case users are directly comparing
1043 against old (hashed) outputs, in the presence of files
1044 containing '\\' characters, we decided to not simplify the
1045 output in this case. */
1046 bool needs_escape
= strchr (file
, '\\') || strchr (file
, '\n');
1053 #if HASH_ALGO_BLAKE2
1054 fputs (algorithm_out_string
[b2_algorithm
], stdout
);
1055 if (b2_length
< blake2_max_len
[b2_algorithm
] * 8)
1056 printf ("-%"PRIuMAX
, b2_length
);
1058 fputs (DIGEST_TYPE_STRING
, stdout
);
1060 fputs (" (", stdout
);
1061 print_filename (file
, needs_escape
);
1062 fputs (") = ", stdout
);
1065 /* Output a leading backslash if the file name contains
1066 a newline or backslash. */
1067 if (!prefix_tag
&& needs_escape
)
1070 for (size_t i
= 0; i
< (digest_hex_bytes
/ 2); ++i
)
1071 printf ("%02x", bin_buffer
[i
]);
1077 putchar (file_is_binary
? '*' : ' ');
1079 print_filename (file
, needs_escape
);
1087 if (have_read_stdin
&& fclose (stdin
) == EOF
)
1088 die (EXIT_FAILURE
, errno
, _("standard input"));
1090 return ok
? EXIT_SUCCESS
: EXIT_FAILURE
;