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>. */
22 #include <sys/types.h>
32 #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
35 #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
43 /* The official name of this program (e.g., no 'g' prefix). */
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
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
87 # error "Can't decide which hash algorithm to compile."
90 #define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
91 #define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
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 */ \
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. */
136 STATUS_OPTION
= CHAR_MAX
+ 1,
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
},
160 if (status
!= EXIT_SUCCESS
)
165 Usage: %s [OPTION]... [FILE]...\n\
166 Print or check %s (%d-bit) checksums.\n\
177 -b, --binary read in binary mode (default unless reading tty stdin)\n\
182 -b, --binary read in binary mode\n\
185 -c, --check read %s sums from the FILEs and check them\n"),
188 --tag create a BSD-style checksum\n\
192 -t, --text read in text mode (default if reading tty stdin)\n\
196 -t, --text read in text mode (default)\n\
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\
207 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
208 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
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"),
216 emit_ancillary_info (PROGRAM_NAME
);
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. */
233 filename_unescape (char *s
, size_t s_len
)
237 for (size_t i
= 0; i
< s_len
; i
++)
244 /* File name ends with an unescaped backslash: invalid. */
257 /* Only '\' or 'n' may follow a backslash. */
263 /* The file name may not contain a NUL. */
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. */
282 bsd_split_3 (char *s
, size_t s_len
, unsigned char **hex_digest
,
283 char **file_name
, bool escaped_filename
)
290 /* Find end of filename. */
292 while (i
&& s
[i
] != ')')
300 if (escaped_filename
&& filename_unescape (s
, i
) == NULL
)
305 while (ISWHITE (s
[i
]))
313 while (ISWHITE (s
[i
]))
316 *hex_digest
= (unsigned char *) &s
[i
];
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. */
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
;
332 while (ISWHITE (s
[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
] == ' ')
348 if (s
[i
+ algo_name_len
] == '(')
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
361 if (s_len
- i
< min_digest_line_length
+ (s
[i
] == '\\'))
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
;
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)
388 else if (bsd_reversed
!= 1)
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. */
398 if (escaped_filename
)
399 return filename_unescape (&s
[i
], s_len
- i
) != NULL
;
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
)
410 for (i
= 0; i
< digest_hex_bytes
; i
++)
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. */
431 digest_file (const char *filename
, int *binary
, unsigned char *bin_result
)
435 bool is_stdin
= STREQ (filename
, "-");
439 have_read_stdin
= true;
441 if (O_BINARY
&& *binary
)
444 *binary
= ! isatty (STDIN_FILENO
);
446 xfreopen (NULL
, "rb", stdin
);
451 fp
= fopen (filename
, (O_BINARY
&& *binary
? "rb" : "r"));
454 error (0, errno
, "%s", filename
);
459 fadvise (fp
, FADVISE_SEQUENTIAL
);
461 err
= DIGEST_STREAM (fp
, bin_result
);
464 error (0, errno
, "%s", filename
);
470 if (!is_stdin
&& fclose (fp
) != 0)
472 error (0, errno
, "%s", filename
);
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
;
493 size_t line_chars_allocated
;
494 bool is_stdin
= STREQ (checkfile_name
, "-");
498 have_read_stdin
= true;
499 checkfile_name
= _("standard input");
500 checkfile_stream
= stdin
;
504 checkfile_stream
= fopen (checkfile_name
, "r");
505 if (checkfile_stream
== NULL
)
507 error (0, errno
, "%s", checkfile_name
);
514 line_chars_allocated
= 0;
517 char *filename
IF_LINT ( = NULL
);
519 unsigned char *hex_digest
IF_LINT ( = NULL
);
523 if (line_number
== 0)
524 error (EXIT_FAILURE
, 0, _("%s: too many checksum lines"),
527 line_length
= getline (&line
, &line_chars_allocated
, checkfile_stream
);
528 if (line_length
<= 0)
531 /* Ignore comment lines, which begin with a '#' character. */
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
;
549 ": improperly formatted %s checksum line"),
550 checkfile_name
, line_number
,
554 ++n_improperly_formatted_lines
;
558 static const char bin2hex
[] = { '0', '1', '2', '3',
561 'c', 'd', 'e', 'f' };
564 ++n_properly_formatted_lines
;
566 ok
= digest_file (filename
, &binary
, bin_buffer
);
570 ++n_open_or_read_failures
;
573 printf (_("%s: FAILED open or read\n"), filename
);
578 size_t digest_bin_bytes
= digest_hex_bytes
/ 2;
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])))
590 if (cnt
!= digest_bin_bytes
)
591 ++n_mismatched_checksums
;
595 if (cnt
!= digest_bin_bytes
)
596 printf ("%s: %s\n", filename
, _("FAILED"));
598 printf ("%s: %s\n", filename
, _("OK"));
603 while (!feof (checkfile_stream
) && !ferror (checkfile_stream
));
607 if (ferror (checkfile_stream
))
609 error (0, 0, _("%s: read error"), checkfile_name
);
613 if (!is_stdin
&& fclose (checkfile_stream
) != 0)
615 error (0, errno
, "%s", checkfile_name
);
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
);
629 if (n_misformatted_lines
!= 0)
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)
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)
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 "\\\\". */
664 print_filename (char const *file
, bool escape
)
668 fputs (file
, stdout
);
677 fputs ("\\n", stdout
);
681 fputs ("\\\\", stdout
);
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;
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)
751 case_GETOPT_HELP_CHAR
;
752 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
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
)
788 _("the --status option is meaningful only when verifying checksums"));
789 usage (EXIT_FAILURE
);
792 if (warn
&& !do_check
)
795 _("the --warn option is meaningful only when verifying checksums"));
796 usage (EXIT_FAILURE
);
799 if (quiet
&& !do_check
)
802 _("the --quiet option is meaningful only when verifying checksums"));
803 usage (EXIT_FAILURE
);
806 if (strict
& !do_check
)
809 _("the --strict option is meaningful only when verifying checksums"));
810 usage (EXIT_FAILURE
);
813 if (!O_BINARY
&& binary
< 0)
817 argv
[argc
++] = bad_cast ("-");
819 for (; optind
< argc
; ++optind
)
821 char *file
= argv
[optind
];
824 ok
&= digest_check (file
);
827 int file_is_binary
= binary
;
829 if (! digest_file (file
, &file_is_binary
, bin_buffer
))
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');
847 fputs (DIGEST_TYPE_STRING
, stdout
);
848 fputs (" (", stdout
);
849 print_filename (file
, needs_escape
);
850 fputs (") = ", stdout
);
855 /* Output a leading backslash if the file name contains
856 a newline or backslash. */
857 if (!prefix_tag
&& needs_escape
)
860 for (i
= 0; i
< (digest_hex_bytes
/ 2); ++i
)
861 printf ("%02x", bin_buffer
[i
]);
867 putchar (file_is_binary
? '*' : ' ');
869 print_filename (file
, needs_escape
);
877 if (have_read_stdin
&& fclose (stdin
) == EOF
)
878 error (EXIT_FAILURE
, errno
, _("standard input"));
880 return ok
? EXIT_SUCCESS
: EXIT_FAILURE
;