1 /* Compute checksums of files or strings.
2 Copyright (C) 1995-2011 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,
141 static struct option
const long_options
[] =
143 { "binary", no_argument
, NULL
, 'b' },
144 { "check", no_argument
, NULL
, 'c' },
145 { "quiet", no_argument
, NULL
, QUIET_OPTION
},
146 { "status", no_argument
, NULL
, STATUS_OPTION
},
147 { "text", no_argument
, NULL
, 't' },
148 { "warn", no_argument
, NULL
, 'w' },
149 { "strict", no_argument
, NULL
, STRICT_OPTION
},
150 { GETOPT_HELP_OPTION_DECL
},
151 { GETOPT_VERSION_OPTION_DECL
},
158 if (status
!= EXIT_SUCCESS
)
159 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
164 Usage: %s [OPTION]... [FILE]...\n\
165 Print or check %s (%d-bit) checksums.\n\
166 With no FILE, or when FILE is -, read standard input.\n\
174 -b, --binary read in binary mode (default unless reading tty stdin)\n\
178 -b, --binary read in binary mode\n\
181 -c, --check read %s sums from the FILEs and check them\n"),
185 -t, --text read in text mode (default if reading tty stdin)\n\
189 -t, --text read in text mode (default)\n\
193 The following three options are useful only when verifying checksums:\n\
194 --quiet don't print OK for each successfully verified file\n\
195 --status don't output anything, status code shows success\n\
196 -w, --warn warn about improperly formatted checksum lines\n\
200 --strict with --check, exit non-zero for any invalid input\n\
202 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
203 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
206 The sums are computed as described in %s. When checking, the input\n\
207 should be a former output of this program. The default mode is to print\n\
208 a line with checksum, a character indicating input mode (`*' for binary,\n\
209 space for text), and name for each FILE.\n"),
211 emit_ancillary_info ();
217 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
219 /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
220 'sha1' command into two parts: a hexadecimal digest, and the file
221 name. S is modified. Return true if successful. */
224 bsd_split_3 (char *s
, size_t s_len
, unsigned char **hex_digest
,
234 /* Find end of filename. The BSD 'md5' and 'sha1' commands do not escape
235 filenames, so search backwards for the last ')'. */
237 while (i
&& s
[i
] != ')')
245 while (ISWHITE (s
[i
]))
253 while (ISWHITE (s
[i
]))
256 *hex_digest
= (unsigned char *) &s
[i
];
260 /* Split the string S (of length S_LEN) into three parts:
261 a hexadecimal digest, binary flag, and the file name.
262 S is modified. Return true if successful. */
265 split_3 (char *s
, size_t s_len
,
266 unsigned char **hex_digest
, int *binary
, char **file_name
)
268 bool escaped_filename
= false;
269 size_t algo_name_len
;
272 while (ISWHITE (s
[i
]))
275 /* Check for BSD-style checksum line. */
276 algo_name_len
= strlen (DIGEST_TYPE_STRING
);
277 if (STREQ_LEN (s
+ i
, DIGEST_TYPE_STRING
, algo_name_len
))
279 if (s
[i
+ algo_name_len
] == ' ')
281 if (s
[i
+ algo_name_len
] == '(')
284 return bsd_split_3 (s
+ i
+ algo_name_len
+ 1,
285 s_len
- (i
+ algo_name_len
+ 1),
286 hex_digest
, file_name
);
290 /* Ignore this line if it is too short.
291 Each line must have at least `min_digest_line_length - 1' (or one more, if
292 the first is a backslash) more characters to contain correct message digest
294 if (s_len
- i
< min_digest_line_length
+ (s
[i
] == '\\'))
300 escaped_filename
= true;
302 *hex_digest
= (unsigned char *) &s
[i
];
304 /* The first field has to be the n-character hexadecimal
305 representation of the message digest. If it is not followed
306 immediately by a white space it's an error. */
307 i
+= digest_hex_bytes
;
313 /* If "bsd reversed" format detected. */
314 if ((s_len
- i
== 1) || (s
[i
] != ' ' && s
[i
] != '*'))
316 /* Don't allow mixing bsd and standard formats,
317 to minimize security issues with attackers
318 renaming files with leading spaces.
319 This assumes that with bsd format checksums
320 that the first file name does not have
321 a leading ' ' or '*'. */
322 if (bsd_reversed
== 0)
326 else if (bsd_reversed
!= 1)
329 *binary
= (s
[i
++] == '*');
332 /* All characters between the type indicator and end of line are
333 significant -- that includes leading and trailing white space. */
336 if (escaped_filename
)
338 /* Translate each `\n' string in the file name to a NEWLINE,
339 and each `\\' string to a backslash. */
350 /* A valid line does not end with a backslash. */
363 /* Only `\' or `n' may follow a backslash. */
369 /* The file name may not contain a NUL. */
383 /* Return true if S is a NUL-terminated string of DIGEST_HEX_BYTES hex digits.
384 Otherwise, return false. */
385 static bool _GL_ATTRIBUTE_PURE
386 hex_digits (unsigned char const *s
)
389 for (i
= 0; i
< digest_hex_bytes
; i
++)
398 /* An interface to the function, DIGEST_STREAM.
399 Operate on FILENAME (it may be "-").
401 *BINARY indicates whether the file is binary. BINARY < 0 means it
402 depends on whether binary mode makes any difference and the file is
403 a terminal; in that case, clear *BINARY if the file was treated as
404 text because it was a terminal.
406 Put the checksum in *BIN_RESULT, which must be properly aligned.
407 Return true if successful. */
410 digest_file (const char *filename
, int *binary
, unsigned char *bin_result
)
414 bool is_stdin
= STREQ (filename
, "-");
418 have_read_stdin
= true;
420 if (O_BINARY
&& *binary
)
423 *binary
= ! isatty (STDIN_FILENO
);
425 xfreopen (NULL
, "rb", stdin
);
430 fp
= fopen (filename
, (O_BINARY
&& *binary
? "rb" : "r"));
433 error (0, errno
, "%s", filename
);
438 fadvise (fp
, FADVISE_SEQUENTIAL
);
440 err
= DIGEST_STREAM (fp
, bin_result
);
443 error (0, errno
, "%s", filename
);
449 if (!is_stdin
&& fclose (fp
) != 0)
451 error (0, errno
, "%s", filename
);
459 digest_check (const char *checkfile_name
)
461 FILE *checkfile_stream
;
462 uintmax_t n_misformatted_lines
= 0;
463 uintmax_t n_properly_formatted_lines
= 0;
464 uintmax_t n_improperly_formatted_lines
= 0;
465 uintmax_t n_mismatched_checksums
= 0;
466 uintmax_t n_open_or_read_failures
= 0;
467 unsigned char bin_buffer_unaligned
[DIGEST_BIN_BYTES
+ DIGEST_ALIGN
];
468 /* Make sure bin_buffer is properly aligned. */
469 unsigned char *bin_buffer
= ptr_align (bin_buffer_unaligned
, DIGEST_ALIGN
);
470 uintmax_t line_number
;
472 size_t line_chars_allocated
;
473 bool is_stdin
= STREQ (checkfile_name
, "-");
477 have_read_stdin
= true;
478 checkfile_name
= _("standard input");
479 checkfile_stream
= stdin
;
483 checkfile_stream
= fopen (checkfile_name
, "r");
484 if (checkfile_stream
== NULL
)
486 error (0, errno
, "%s", checkfile_name
);
493 line_chars_allocated
= 0;
496 char *filename
IF_LINT ( = NULL
);
498 unsigned char *hex_digest
IF_LINT ( = NULL
);
502 if (line_number
== 0)
503 error (EXIT_FAILURE
, 0, _("%s: too many checksum lines"),
506 line_length
= getline (&line
, &line_chars_allocated
, checkfile_stream
);
507 if (line_length
<= 0)
510 /* Ignore comment lines, which begin with a '#' character. */
514 /* Remove any trailing newline. */
515 if (line
[line_length
- 1] == '\n')
516 line
[--line_length
] = '\0';
518 if (! (split_3 (line
, line_length
, &hex_digest
, &binary
, &filename
)
519 && ! (is_stdin
&& STREQ (filename
, "-"))
520 && hex_digits (hex_digest
)))
522 ++n_misformatted_lines
;
528 ": improperly formatted %s checksum line"),
529 checkfile_name
, line_number
,
533 ++n_improperly_formatted_lines
;
537 static const char bin2hex
[] = { '0', '1', '2', '3',
540 'c', 'd', 'e', 'f' };
543 ++n_properly_formatted_lines
;
545 ok
= digest_file (filename
, &binary
, bin_buffer
);
549 ++n_open_or_read_failures
;
552 printf (_("%s: FAILED open or read\n"), filename
);
557 size_t digest_bin_bytes
= digest_hex_bytes
/ 2;
559 /* Compare generated binary number with text representation
560 in check file. Ignore case of hex digits. */
561 for (cnt
= 0; cnt
< digest_bin_bytes
; ++cnt
)
563 if (tolower (hex_digest
[2 * cnt
])
564 != bin2hex
[bin_buffer
[cnt
] >> 4]
565 || (tolower (hex_digest
[2 * cnt
+ 1])
566 != (bin2hex
[bin_buffer
[cnt
] & 0xf])))
569 if (cnt
!= digest_bin_bytes
)
570 ++n_mismatched_checksums
;
574 if (cnt
!= digest_bin_bytes
)
575 printf ("%s: %s\n", filename
, _("FAILED"));
577 printf ("%s: %s\n", filename
, _("OK"));
582 while (!feof (checkfile_stream
) && !ferror (checkfile_stream
));
586 if (ferror (checkfile_stream
))
588 error (0, 0, _("%s: read error"), checkfile_name
);
592 if (!is_stdin
&& fclose (checkfile_stream
) != 0)
594 error (0, errno
, "%s", checkfile_name
);
598 if (n_properly_formatted_lines
== 0)
600 /* Warn if no tests are found. */
601 error (0, 0, _("%s: no properly formatted %s checksum lines found"),
602 checkfile_name
, DIGEST_TYPE_STRING
);
608 if (n_misformatted_lines
!= 0)
611 ("WARNING: %" PRIuMAX
" line is improperly formatted",
612 "WARNING: %" PRIuMAX
" lines are improperly formatted",
613 select_plural (n_misformatted_lines
))),
614 n_misformatted_lines
);
616 if (n_open_or_read_failures
!= 0)
619 ("WARNING: %" PRIuMAX
" listed file could not be read",
620 "WARNING: %" PRIuMAX
" listed files could not be read",
621 select_plural (n_open_or_read_failures
))),
622 n_open_or_read_failures
);
624 if (n_mismatched_checksums
!= 0)
627 ("WARNING: %" PRIuMAX
" computed checksum did NOT match",
628 "WARNING: %" PRIuMAX
" computed checksums did NOT match",
629 select_plural (n_mismatched_checksums
))),
630 n_mismatched_checksums
);
634 return (n_properly_formatted_lines
!= 0
635 && n_mismatched_checksums
== 0
636 && n_open_or_read_failures
== 0
637 && (!strict
|| n_improperly_formatted_lines
== 0));
641 main (int argc
, char **argv
)
643 unsigned char bin_buffer_unaligned
[DIGEST_BIN_BYTES
+ DIGEST_ALIGN
];
644 /* Make sure bin_buffer is properly aligned. */
645 unsigned char *bin_buffer
= ptr_align (bin_buffer_unaligned
, DIGEST_ALIGN
);
646 bool do_check
= false;
651 /* Setting values of global variables. */
652 initialize_main (&argc
, &argv
);
653 set_program_name (argv
[0]);
654 setlocale (LC_ALL
, "");
655 bindtextdomain (PACKAGE
, LOCALEDIR
);
656 textdomain (PACKAGE
);
658 atexit (close_stdout
);
660 /* Line buffer stdout to ensure lines are written atomically and immediately
661 so that processes running in parallel do not intersperse their output. */
662 setvbuf (stdout
, NULL
, _IOLBF
, 0);
664 while ((opt
= getopt_long (argc
, argv
, "bctw", long_options
, NULL
)) != -1)
694 case_GETOPT_HELP_CHAR
;
695 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
697 usage (EXIT_FAILURE
);
700 min_digest_line_length
= MIN_DIGEST_LINE_LENGTH
;
701 digest_hex_bytes
= DIGEST_HEX_BYTES
;
703 if (0 <= binary
&& do_check
)
705 error (0, 0, _("the --binary and --text options are meaningless when "
706 "verifying checksums"));
707 usage (EXIT_FAILURE
);
710 if (status_only
&& !do_check
)
713 _("the --status option is meaningful only when verifying checksums"));
714 usage (EXIT_FAILURE
);
717 if (warn
&& !do_check
)
720 _("the --warn option is meaningful only when verifying checksums"));
721 usage (EXIT_FAILURE
);
724 if (quiet
&& !do_check
)
727 _("the --quiet option is meaningful only when verifying checksums"));
728 usage (EXIT_FAILURE
);
731 if (strict
& !do_check
)
734 _("the --strict option is meaningful only when verifying checksums"));
735 usage (EXIT_FAILURE
);
738 if (!O_BINARY
&& binary
< 0)
742 argv
[argc
++] = bad_cast ("-");
744 for (; optind
< argc
; ++optind
)
746 char *file
= argv
[optind
];
749 ok
&= digest_check (file
);
752 int file_is_binary
= binary
;
754 if (! digest_file (file
, &file_is_binary
, bin_buffer
))
760 /* Output a leading backslash if the file name contains
761 a newline or backslash. */
762 if (strchr (file
, '\n') || strchr (file
, '\\'))
765 for (i
= 0; i
< (digest_hex_bytes
/ 2); ++i
)
766 printf ("%02x", bin_buffer
[i
]);
774 /* Translate each NEWLINE byte to the string, "\\n",
775 and each backslash to "\\\\". */
776 for (i
= 0; i
< strlen (file
); ++i
)
781 fputs ("\\n", stdout
);
785 fputs ("\\\\", stdout
);
798 if (have_read_stdin
&& fclose (stdin
) == EOF
)
799 error (EXIT_FAILURE
, errno
, _("standard input"));
801 exit (ok
? EXIT_SUCCESS
: EXIT_FAILURE
);