doc: clarify the operation of wc -L
[coreutils.git] / src / md5sum.c
blobbc2b70927b8523ca5d16af204a79be461db87f6a
1 /* Compute checksums of files or strings.
2 Copyright (C) 1995-2015 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 <http://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"
26 #if HASH_ALGO_MD5
27 # include "md5.h"
28 #endif
29 #if HASH_ALGO_SHA1
30 # include "sha1.h"
31 #endif
32 #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
33 # include "sha256.h"
34 #endif
35 #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
36 # include "sha512.h"
37 #endif
38 #include "error.h"
39 #include "fadvise.h"
40 #include "stdio--.h"
41 #include "xfreopen.h"
43 /* The official name of this program (e.g., no 'g' prefix). */
44 #if HASH_ALGO_MD5
45 # define PROGRAM_NAME "md5sum"
46 # define DIGEST_TYPE_STRING "MD5"
47 # define DIGEST_STREAM md5_stream
48 # define DIGEST_BITS 128
49 # define DIGEST_REFERENCE "RFC 1321"
50 # define DIGEST_ALIGN 4
51 #elif HASH_ALGO_SHA1
52 # define PROGRAM_NAME "sha1sum"
53 # define DIGEST_TYPE_STRING "SHA1"
54 # define DIGEST_STREAM sha1_stream
55 # define DIGEST_BITS 160
56 # define DIGEST_REFERENCE "FIPS-180-1"
57 # define DIGEST_ALIGN 4
58 #elif HASH_ALGO_SHA256
59 # define PROGRAM_NAME "sha256sum"
60 # define DIGEST_TYPE_STRING "SHA256"
61 # define DIGEST_STREAM sha256_stream
62 # define DIGEST_BITS 256
63 # define DIGEST_REFERENCE "FIPS-180-2"
64 # define DIGEST_ALIGN 4
65 #elif HASH_ALGO_SHA224
66 # define PROGRAM_NAME "sha224sum"
67 # define DIGEST_TYPE_STRING "SHA224"
68 # define DIGEST_STREAM sha224_stream
69 # define DIGEST_BITS 224
70 # define DIGEST_REFERENCE "RFC 3874"
71 # define DIGEST_ALIGN 4
72 #elif HASH_ALGO_SHA512
73 # define PROGRAM_NAME "sha512sum"
74 # define DIGEST_TYPE_STRING "SHA512"
75 # define DIGEST_STREAM sha512_stream
76 # define DIGEST_BITS 512
77 # define DIGEST_REFERENCE "FIPS-180-2"
78 # define DIGEST_ALIGN 8
79 #elif HASH_ALGO_SHA384
80 # define PROGRAM_NAME "sha384sum"
81 # define DIGEST_TYPE_STRING "SHA384"
82 # define DIGEST_STREAM sha384_stream
83 # define DIGEST_BITS 384
84 # define DIGEST_REFERENCE "FIPS-180-2"
85 # define DIGEST_ALIGN 8
86 #else
87 # error "Can't decide which hash algorithm to compile."
88 #endif
90 #define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
91 #define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
93 #define AUTHORS \
94 proper_name ("Ulrich Drepper"), \
95 proper_name ("Scott Miller"), \
96 proper_name ("David Madore")
98 /* The minimum length of a valid digest line. This length does
99 not include any newline character at the end of a line. */
100 #define MIN_DIGEST_LINE_LENGTH \
101 (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
102 + 1 /* blank */ \
103 + 1 /* minimum filename length */ )
105 /* True if any of the files read were the standard input. */
106 static bool have_read_stdin;
108 /* The minimum length of a valid checksum line for the selected algorithm. */
109 static size_t min_digest_line_length;
111 /* Set to the length of a digest hex string for the selected algorithm. */
112 static size_t digest_hex_bytes;
114 /* With --check, don't generate any output.
115 The exit code indicates success or failure. */
116 static bool status_only = false;
118 /* With --check, print a message to standard error warning about each
119 improperly formatted checksum line. */
120 static bool warn = false;
122 /* With --check, suppress the "OK" printed for each verified file. */
123 static bool quiet = false;
125 /* With --check, exit with a non-zero return code if any line is
126 improperly formatted. */
127 static bool strict = false;
129 /* Whether a BSD reversed format checksum is detected. */
130 static int bsd_reversed = -1;
132 /* For long options that have no equivalent short option, use a
133 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
134 enum
136 STATUS_OPTION = CHAR_MAX + 1,
137 QUIET_OPTION,
138 STRICT_OPTION,
139 TAG_OPTION
142 static struct option const long_options[] =
144 { "binary", no_argument, NULL, 'b' },
145 { "check", no_argument, NULL, 'c' },
146 { "quiet", no_argument, NULL, QUIET_OPTION },
147 { "status", no_argument, NULL, STATUS_OPTION },
148 { "text", no_argument, NULL, 't' },
149 { "warn", no_argument, NULL, 'w' },
150 { "strict", no_argument, NULL, STRICT_OPTION },
151 { "tag", no_argument, NULL, TAG_OPTION },
152 { GETOPT_HELP_OPTION_DECL },
153 { GETOPT_VERSION_OPTION_DECL },
154 { NULL, 0, NULL, 0 }
157 void
158 usage (int status)
160 if (status != EXIT_SUCCESS)
161 emit_try_help ();
162 else
164 printf (_("\
165 Usage: %s [OPTION]... [FILE]...\n\
166 Print or check %s (%d-bit) checksums.\n\
168 program_name,
169 DIGEST_TYPE_STRING,
170 DIGEST_BITS);
172 emit_stdin_note ();
174 if (O_BINARY)
175 fputs (_("\
177 -b, --binary read in binary mode (default unless reading tty stdin)\n\
178 "), stdout);
179 else
180 fputs (_("\
182 -b, --binary read in binary mode\n\
183 "), stdout);
184 printf (_("\
185 -c, --check read %s sums from the FILEs and check them\n"),
186 DIGEST_TYPE_STRING);
187 fputs (_("\
188 --tag create a BSD-style checksum\n\
189 "), stdout);
190 if (O_BINARY)
191 fputs (_("\
192 -t, --text read in text mode (default if reading tty stdin)\n\
193 "), stdout);
194 else
195 fputs (_("\
196 -t, --text read in text mode (default)\n\
197 "), stdout);
198 fputs (_("\
200 The following four options are useful only when verifying checksums:\n\
201 --quiet don't print OK for each successfully verified file\n\
202 --status don't output anything, status code shows success\n\
203 --strict exit non-zero for improperly formatted checksum lines\n\
204 -w, --warn warn about improperly formatted checksum lines\n\
206 "), stdout);
207 fputs (HELP_OPTION_DESCRIPTION, stdout);
208 fputs (VERSION_OPTION_DESCRIPTION, stdout);
209 printf (_("\
211 The sums are computed as described in %s. When checking, the input\n\
212 should be a former output of this program. The default mode is to print a\n\
213 line with checksum, a space, a character indicating input mode ('*' for binary,\
214 \n' ' for text or where binary is insignificant), and name for each FILE.\n"),
215 DIGEST_REFERENCE);
216 emit_ancillary_info (PROGRAM_NAME);
219 exit (status);
222 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
224 /* Given a file name, S of length S_LEN, that is not NUL-terminated,
225 modify it in place, performing the equivalent of this sed substitution:
226 's/\\n/\n/g;s/\\\\/\\/g' i.e., replacing each "\\n" string with a newline
227 and each "\\\\" with a single backslash, NUL-terminate it and return S.
228 If S is not a valid escaped file name, i.e., if it ends with an odd number
229 of backslashes or if it contains a backslash followed by anything other
230 than "n" or another backslash, return NULL. */
232 static char *
233 filename_unescape (char *s, size_t s_len)
235 char *dst = s;
237 for (size_t i = 0; i < s_len; i++)
239 switch (s[i])
241 case '\\':
242 if (i == s_len - 1)
244 /* File name ends with an unescaped backslash: invalid. */
245 return NULL;
247 ++i;
248 switch (s[i])
250 case 'n':
251 *dst++ = '\n';
252 break;
253 case '\\':
254 *dst++ = '\\';
255 break;
256 default:
257 /* Only '\' or 'n' may follow a backslash. */
258 return NULL;
260 break;
262 case '\0':
263 /* The file name may not contain a NUL. */
264 return NULL;
266 default:
267 *dst++ = s[i];
268 break;
271 if (dst < s + s_len)
272 *dst = '\0';
274 return s;
277 /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
278 'sha1' command into two parts: a hexadecimal digest, and the file
279 name. S is modified. Return true if successful. */
281 static bool
282 bsd_split_3 (char *s, size_t s_len, unsigned char **hex_digest,
283 char **file_name, bool escaped_filename)
285 size_t i;
287 if (s_len == 0)
288 return false;
290 /* Find end of filename. */
291 i = s_len - 1;
292 while (i && s[i] != ')')
293 i--;
295 if (s[i] != ')')
296 return false;
298 *file_name = s;
300 if (escaped_filename && filename_unescape (s, i) == NULL)
301 return false;
303 s[i++] = '\0';
305 while (ISWHITE (s[i]))
306 i++;
308 if (s[i] != '=')
309 return false;
311 i++;
313 while (ISWHITE (s[i]))
314 i++;
316 *hex_digest = (unsigned char *) &s[i];
317 return true;
320 /* Split the string S (of length S_LEN) into three parts:
321 a hexadecimal digest, binary flag, and the file name.
322 S is modified. Return true if successful. */
324 static bool
325 split_3 (char *s, size_t s_len,
326 unsigned char **hex_digest, int *binary, char **file_name)
328 bool escaped_filename = false;
329 size_t algo_name_len;
331 size_t i = 0;
332 while (ISWHITE (s[i]))
333 ++i;
335 if (s[i] == '\\')
337 ++i;
338 escaped_filename = true;
341 /* Check for BSD-style checksum line. */
343 algo_name_len = strlen (DIGEST_TYPE_STRING);
344 if (STREQ_LEN (s + i, DIGEST_TYPE_STRING, algo_name_len))
346 if (s[i + algo_name_len] == ' ')
347 ++i;
348 if (s[i + algo_name_len] == '(')
350 *binary = 0;
351 return bsd_split_3 (s + i + algo_name_len + 1,
352 s_len - (i + algo_name_len + 1),
353 hex_digest, file_name, escaped_filename);
357 /* Ignore this line if it is too short.
358 Each line must have at least 'min_digest_line_length - 1' (or one more, if
359 the first is a backslash) more characters to contain correct message digest
360 information. */
361 if (s_len - i < min_digest_line_length + (s[i] == '\\'))
362 return false;
364 *hex_digest = (unsigned char *) &s[i];
366 /* The first field has to be the n-character hexadecimal
367 representation of the message digest. If it is not followed
368 immediately by a white space it's an error. */
369 i += digest_hex_bytes;
370 if (!ISWHITE (s[i]))
371 return false;
373 s[i++] = '\0';
375 /* If "bsd reversed" format detected. */
376 if ((s_len - i == 1) || (s[i] != ' ' && s[i] != '*'))
378 /* Don't allow mixing bsd and standard formats,
379 to minimize security issues with attackers
380 renaming files with leading spaces.
381 This assumes that with bsd format checksums
382 that the first file name does not have
383 a leading ' ' or '*'. */
384 if (bsd_reversed == 0)
385 return false;
386 bsd_reversed = 1;
388 else if (bsd_reversed != 1)
390 bsd_reversed = 0;
391 *binary = (s[i++] == '*');
394 /* All characters between the type indicator and end of line are
395 significant -- that includes leading and trailing white space. */
396 *file_name = &s[i];
398 if (escaped_filename)
399 return filename_unescape (&s[i], s_len - i) != NULL;
401 return true;
404 /* Return true if S is a NUL-terminated string of DIGEST_HEX_BYTES hex digits.
405 Otherwise, return false. */
406 static bool _GL_ATTRIBUTE_PURE
407 hex_digits (unsigned char const *s)
409 unsigned int i;
410 for (i = 0; i < digest_hex_bytes; i++)
412 if (!isxdigit (*s))
413 return false;
414 ++s;
416 return *s == '\0';
419 /* An interface to the function, DIGEST_STREAM.
420 Operate on FILENAME (it may be "-").
422 *BINARY indicates whether the file is binary. BINARY < 0 means it
423 depends on whether binary mode makes any difference and the file is
424 a terminal; in that case, clear *BINARY if the file was treated as
425 text because it was a terminal.
427 Put the checksum in *BIN_RESULT, which must be properly aligned.
428 Return true if successful. */
430 static bool
431 digest_file (const char *filename, int *binary, unsigned char *bin_result)
433 FILE *fp;
434 int err;
435 bool is_stdin = STREQ (filename, "-");
437 if (is_stdin)
439 have_read_stdin = true;
440 fp = stdin;
441 if (O_BINARY && *binary)
443 if (*binary < 0)
444 *binary = ! isatty (STDIN_FILENO);
445 if (*binary)
446 xfreopen (NULL, "rb", stdin);
449 else
451 fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r"));
452 if (fp == NULL)
454 error (0, errno, "%s", filename);
455 return false;
459 fadvise (fp, FADVISE_SEQUENTIAL);
461 err = DIGEST_STREAM (fp, bin_result);
462 if (err)
464 error (0, errno, "%s", filename);
465 if (fp != stdin)
466 fclose (fp);
467 return false;
470 if (!is_stdin && fclose (fp) != 0)
472 error (0, errno, "%s", filename);
473 return false;
476 return true;
479 static bool
480 digest_check (const char *checkfile_name)
482 FILE *checkfile_stream;
483 uintmax_t n_misformatted_lines = 0;
484 uintmax_t n_properly_formatted_lines = 0;
485 uintmax_t n_improperly_formatted_lines = 0;
486 uintmax_t n_mismatched_checksums = 0;
487 uintmax_t n_open_or_read_failures = 0;
488 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
489 /* Make sure bin_buffer is properly aligned. */
490 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
491 uintmax_t line_number;
492 char *line;
493 size_t line_chars_allocated;
494 bool is_stdin = STREQ (checkfile_name, "-");
496 if (is_stdin)
498 have_read_stdin = true;
499 checkfile_name = _("standard input");
500 checkfile_stream = stdin;
502 else
504 checkfile_stream = fopen (checkfile_name, "r");
505 if (checkfile_stream == NULL)
507 error (0, errno, "%s", checkfile_name);
508 return false;
512 line_number = 0;
513 line = NULL;
514 line_chars_allocated = 0;
517 char *filename IF_LINT ( = NULL);
518 int binary;
519 unsigned char *hex_digest IF_LINT ( = NULL);
520 ssize_t line_length;
522 ++line_number;
523 if (line_number == 0)
524 error (EXIT_FAILURE, 0, _("%s: too many checksum lines"),
525 checkfile_name);
527 line_length = getline (&line, &line_chars_allocated, checkfile_stream);
528 if (line_length <= 0)
529 break;
531 /* Ignore comment lines, which begin with a '#' character. */
532 if (line[0] == '#')
533 continue;
535 /* Remove any trailing newline. */
536 if (line[line_length - 1] == '\n')
537 line[--line_length] = '\0';
539 if (! (split_3 (line, line_length, &hex_digest, &binary, &filename)
540 && ! (is_stdin && STREQ (filename, "-"))
541 && hex_digits (hex_digest)))
543 ++n_misformatted_lines;
545 if (warn)
547 error (0, 0,
548 _("%s: %" PRIuMAX
549 ": improperly formatted %s checksum line"),
550 checkfile_name, line_number,
551 DIGEST_TYPE_STRING);
554 ++n_improperly_formatted_lines;
556 else
558 static const char bin2hex[] = { '0', '1', '2', '3',
559 '4', '5', '6', '7',
560 '8', '9', 'a', 'b',
561 'c', 'd', 'e', 'f' };
562 bool ok;
564 ++n_properly_formatted_lines;
566 ok = digest_file (filename, &binary, bin_buffer);
568 if (!ok)
570 ++n_open_or_read_failures;
571 if (!status_only)
573 printf (_("%s: FAILED open or read\n"), filename);
576 else
578 size_t digest_bin_bytes = digest_hex_bytes / 2;
579 size_t cnt;
580 /* Compare generated binary number with text representation
581 in check file. Ignore case of hex digits. */
582 for (cnt = 0; cnt < digest_bin_bytes; ++cnt)
584 if (tolower (hex_digest[2 * cnt])
585 != bin2hex[bin_buffer[cnt] >> 4]
586 || (tolower (hex_digest[2 * cnt + 1])
587 != (bin2hex[bin_buffer[cnt] & 0xf])))
588 break;
590 if (cnt != digest_bin_bytes)
591 ++n_mismatched_checksums;
593 if (!status_only)
595 if (cnt != digest_bin_bytes)
596 printf ("%s: %s\n", filename, _("FAILED"));
597 else if (!quiet)
598 printf ("%s: %s\n", filename, _("OK"));
603 while (!feof (checkfile_stream) && !ferror (checkfile_stream));
605 free (line);
607 if (ferror (checkfile_stream))
609 error (0, 0, _("%s: read error"), checkfile_name);
610 return false;
613 if (!is_stdin && fclose (checkfile_stream) != 0)
615 error (0, errno, "%s", checkfile_name);
616 return false;
619 if (n_properly_formatted_lines == 0)
621 /* Warn if no tests are found. */
622 error (0, 0, _("%s: no properly formatted %s checksum lines found"),
623 checkfile_name, DIGEST_TYPE_STRING);
625 else
627 if (!status_only)
629 if (n_misformatted_lines != 0)
630 error (0, 0,
631 (ngettext
632 ("WARNING: %" PRIuMAX " line is improperly formatted",
633 "WARNING: %" PRIuMAX " lines are improperly formatted",
634 select_plural (n_misformatted_lines))),
635 n_misformatted_lines);
637 if (n_open_or_read_failures != 0)
638 error (0, 0,
639 (ngettext
640 ("WARNING: %" PRIuMAX " listed file could not be read",
641 "WARNING: %" PRIuMAX " listed files could not be read",
642 select_plural (n_open_or_read_failures))),
643 n_open_or_read_failures);
645 if (n_mismatched_checksums != 0)
646 error (0, 0,
647 (ngettext
648 ("WARNING: %" PRIuMAX " computed checksum did NOT match",
649 "WARNING: %" PRIuMAX " computed checksums did NOT match",
650 select_plural (n_mismatched_checksums))),
651 n_mismatched_checksums);
655 return (n_properly_formatted_lines != 0
656 && n_mismatched_checksums == 0
657 && n_open_or_read_failures == 0
658 && (!strict || n_improperly_formatted_lines == 0));
661 /* If ESCAPE is true, then translate each NEWLINE byte to the string, "\\n",
662 and each backslash to "\\\\". */
663 static void
664 print_filename (char const *file, bool escape)
666 if (! escape)
668 fputs (file, stdout);
669 return;
672 while (*file)
674 switch (*file)
676 case '\n':
677 fputs ("\\n", stdout);
678 break;
680 case '\\':
681 fputs ("\\\\", stdout);
682 break;
684 default:
685 putchar (*file);
686 break;
688 file++;
693 main (int argc, char **argv)
695 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
696 /* Make sure bin_buffer is properly aligned. */
697 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
698 bool do_check = false;
699 int opt;
700 bool ok = true;
701 int binary = -1;
702 bool prefix_tag = false;
704 /* Setting values of global variables. */
705 initialize_main (&argc, &argv);
706 set_program_name (argv[0]);
707 setlocale (LC_ALL, "");
708 bindtextdomain (PACKAGE, LOCALEDIR);
709 textdomain (PACKAGE);
711 atexit (close_stdout);
713 /* Line buffer stdout to ensure lines are written atomically and immediately
714 so that processes running in parallel do not intersperse their output. */
715 setvbuf (stdout, NULL, _IOLBF, 0);
717 while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
718 switch (opt)
720 case 'b':
721 binary = 1;
722 break;
723 case 'c':
724 do_check = true;
725 break;
726 case STATUS_OPTION:
727 status_only = true;
728 warn = false;
729 quiet = false;
730 break;
731 case 't':
732 binary = 0;
733 break;
734 case 'w':
735 status_only = false;
736 warn = true;
737 quiet = false;
738 break;
739 case QUIET_OPTION:
740 status_only = false;
741 warn = false;
742 quiet = true;
743 break;
744 case STRICT_OPTION:
745 strict = true;
746 break;
747 case TAG_OPTION:
748 prefix_tag = true;
749 binary = 1;
750 break;
751 case_GETOPT_HELP_CHAR;
752 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
753 default:
754 usage (EXIT_FAILURE);
757 min_digest_line_length = MIN_DIGEST_LINE_LENGTH;
758 digest_hex_bytes = DIGEST_HEX_BYTES;
760 if (prefix_tag && !binary)
762 /* This could be supported in a backwards compatible way
763 by prefixing the output line with a space in text mode.
764 However that's invasive enough that it was agreed to
765 not support this mode with --tag, as --text use cases
766 are adequately supported by the default output format. */
767 error (0, 0, _("--tag does not support --text mode"));
768 usage (EXIT_FAILURE);
771 if (prefix_tag && do_check)
773 error (0, 0, _("the --tag option is meaningless when "
774 "verifying checksums"));
775 usage (EXIT_FAILURE);
778 if (0 <= binary && do_check)
780 error (0, 0, _("the --binary and --text options are meaningless when "
781 "verifying checksums"));
782 usage (EXIT_FAILURE);
785 if (status_only && !do_check)
787 error (0, 0,
788 _("the --status option is meaningful only when verifying checksums"));
789 usage (EXIT_FAILURE);
792 if (warn && !do_check)
794 error (0, 0,
795 _("the --warn option is meaningful only when verifying checksums"));
796 usage (EXIT_FAILURE);
799 if (quiet && !do_check)
801 error (0, 0,
802 _("the --quiet option is meaningful only when verifying checksums"));
803 usage (EXIT_FAILURE);
806 if (strict & !do_check)
808 error (0, 0,
809 _("the --strict option is meaningful only when verifying checksums"));
810 usage (EXIT_FAILURE);
813 if (!O_BINARY && binary < 0)
814 binary = 0;
816 if (optind == argc)
817 argv[argc++] = bad_cast ("-");
819 for (; optind < argc; ++optind)
821 char *file = argv[optind];
823 if (do_check)
824 ok &= digest_check (file);
825 else
827 int file_is_binary = binary;
829 if (! digest_file (file, &file_is_binary, bin_buffer))
830 ok = false;
831 else
833 /* We don't really need to escape, and hence detect, the '\\'
834 char, and not doing so should be both forwards and backwards
835 compatible, since only escaped lines would have a '\\' char at
836 the start. However just in case users are directly comparing
837 against old (hashed) outputs, in the presence of files
838 containing '\\' characters, we decided to not simplify the
839 output in this case. */
840 bool needs_escape = strchr (file, '\\') || strchr (file, '\n');
842 if (prefix_tag)
844 if (needs_escape)
845 putchar ('\\');
847 fputs (DIGEST_TYPE_STRING, stdout);
848 fputs (" (", stdout);
849 print_filename (file, needs_escape);
850 fputs (") = ", stdout);
853 size_t i;
855 /* Output a leading backslash if the file name contains
856 a newline or backslash. */
857 if (!prefix_tag && needs_escape)
858 putchar ('\\');
860 for (i = 0; i < (digest_hex_bytes / 2); ++i)
861 printf ("%02x", bin_buffer[i]);
863 if (!prefix_tag)
865 putchar (' ');
867 putchar (file_is_binary ? '*' : ' ');
869 print_filename (file, needs_escape);
872 putchar ('\n');
877 if (have_read_stdin && fclose (stdin) == EOF)
878 error (EXIT_FAILURE, errno, _("standard input"));
880 return ok ? EXIT_SUCCESS : EXIT_FAILURE;