maint: revert "build: update gnulib submodule to latest"
[coreutils/ericb.git] / src / md5sum.c
blob0a67d289444398461b783e6bfec62a87cd7e535d
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>. */
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
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 },
152 { NULL, 0, NULL, 0 }
155 void
156 usage (int status)
158 if (status != EXIT_SUCCESS)
159 fprintf (stderr, _("Try `%s --help' for more information.\n"),
160 program_name);
161 else
163 printf (_("\
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\
169 program_name,
170 DIGEST_TYPE_STRING,
171 DIGEST_BITS);
172 if (O_BINARY)
173 fputs (_("\
174 -b, --binary read in binary mode (default unless reading tty stdin)\n\
175 "), stdout);
176 else
177 fputs (_("\
178 -b, --binary read in binary mode\n\
179 "), stdout);
180 printf (_("\
181 -c, --check read %s sums from the FILEs and check them\n"),
182 DIGEST_TYPE_STRING);
183 if (O_BINARY)
184 fputs (_("\
185 -t, --text read in text mode (default if reading tty stdin)\n\
186 "), stdout);
187 else
188 fputs (_("\
189 -t, --text read in text mode (default)\n\
190 "), stdout);
191 fputs (_("\
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\
198 "), stdout);
199 fputs (_("\
200 --strict with --check, exit non-zero for any invalid input\n\
201 "), stdout);
202 fputs (HELP_OPTION_DESCRIPTION, stdout);
203 fputs (VERSION_OPTION_DESCRIPTION, stdout);
204 printf (_("\
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"),
210 DIGEST_REFERENCE);
211 emit_ancillary_info ();
214 exit (status);
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. */
223 static bool
224 bsd_split_3 (char *s, size_t s_len, unsigned char **hex_digest,
225 char **file_name)
227 size_t i;
229 if (s_len == 0)
230 return false;
232 *file_name = s;
234 /* Find end of filename. The BSD 'md5' and 'sha1' commands do not escape
235 filenames, so search backwards for the last ')'. */
236 i = s_len - 1;
237 while (i && s[i] != ')')
238 i--;
240 if (s[i] != ')')
241 return false;
243 s[i++] = '\0';
245 while (ISWHITE (s[i]))
246 i++;
248 if (s[i] != '=')
249 return false;
251 i++;
253 while (ISWHITE (s[i]))
254 i++;
256 *hex_digest = (unsigned char *) &s[i];
257 return true;
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. */
264 static bool
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;
271 size_t i = 0;
272 while (ISWHITE (s[i]))
273 ++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] == ' ')
280 ++i;
281 if (s[i + algo_name_len] == '(')
283 *binary = 0;
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
293 information. */
294 if (s_len - i < min_digest_line_length + (s[i] == '\\'))
295 return false;
297 if (s[i] == '\\')
299 ++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;
308 if (!ISWHITE (s[i]))
309 return false;
311 s[i++] = '\0';
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)
323 return false;
324 bsd_reversed = 1;
326 else if (bsd_reversed != 1)
328 bsd_reversed = 0;
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. */
334 *file_name = &s[i];
336 if (escaped_filename)
338 /* Translate each `\n' string in the file name to a NEWLINE,
339 and each `\\' string to a backslash. */
341 char *dst = &s[i];
343 while (i < s_len)
345 switch (s[i])
347 case '\\':
348 if (i == s_len - 1)
350 /* A valid line does not end with a backslash. */
351 return false;
353 ++i;
354 switch (s[i++])
356 case 'n':
357 *dst++ = '\n';
358 break;
359 case '\\':
360 *dst++ = '\\';
361 break;
362 default:
363 /* Only `\' or `n' may follow a backslash. */
364 return false;
366 break;
368 case '\0':
369 /* The file name may not contain a NUL. */
370 return false;
371 break;
373 default:
374 *dst++ = s[i++];
375 break;
378 *dst = '\0';
380 return true;
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)
388 unsigned int i;
389 for (i = 0; i < digest_hex_bytes; i++)
391 if (!isxdigit (*s))
392 return false;
393 ++s;
395 return *s == '\0';
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. */
409 static bool
410 digest_file (const char *filename, int *binary, unsigned char *bin_result)
412 FILE *fp;
413 int err;
414 bool is_stdin = STREQ (filename, "-");
416 if (is_stdin)
418 have_read_stdin = true;
419 fp = stdin;
420 if (O_BINARY && *binary)
422 if (*binary < 0)
423 *binary = ! isatty (STDIN_FILENO);
424 if (*binary)
425 xfreopen (NULL, "rb", stdin);
428 else
430 fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r"));
431 if (fp == NULL)
433 error (0, errno, "%s", filename);
434 return false;
438 fadvise (fp, FADVISE_SEQUENTIAL);
440 err = DIGEST_STREAM (fp, bin_result);
441 if (err)
443 error (0, errno, "%s", filename);
444 if (fp != stdin)
445 fclose (fp);
446 return false;
449 if (!is_stdin && fclose (fp) != 0)
451 error (0, errno, "%s", filename);
452 return false;
455 return true;
458 static bool
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;
471 char *line;
472 size_t line_chars_allocated;
473 bool is_stdin = STREQ (checkfile_name, "-");
475 if (is_stdin)
477 have_read_stdin = true;
478 checkfile_name = _("standard input");
479 checkfile_stream = stdin;
481 else
483 checkfile_stream = fopen (checkfile_name, "r");
484 if (checkfile_stream == NULL)
486 error (0, errno, "%s", checkfile_name);
487 return false;
491 line_number = 0;
492 line = NULL;
493 line_chars_allocated = 0;
496 char *filename IF_LINT ( = NULL);
497 int binary;
498 unsigned char *hex_digest IF_LINT ( = NULL);
499 ssize_t line_length;
501 ++line_number;
502 if (line_number == 0)
503 error (EXIT_FAILURE, 0, _("%s: too many checksum lines"),
504 checkfile_name);
506 line_length = getline (&line, &line_chars_allocated, checkfile_stream);
507 if (line_length <= 0)
508 break;
510 /* Ignore comment lines, which begin with a '#' character. */
511 if (line[0] == '#')
512 continue;
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;
524 if (warn)
526 error (0, 0,
527 _("%s: %" PRIuMAX
528 ": improperly formatted %s checksum line"),
529 checkfile_name, line_number,
530 DIGEST_TYPE_STRING);
533 ++n_improperly_formatted_lines;
535 else
537 static const char bin2hex[] = { '0', '1', '2', '3',
538 '4', '5', '6', '7',
539 '8', '9', 'a', 'b',
540 'c', 'd', 'e', 'f' };
541 bool ok;
543 ++n_properly_formatted_lines;
545 ok = digest_file (filename, &binary, bin_buffer);
547 if (!ok)
549 ++n_open_or_read_failures;
550 if (!status_only)
552 printf (_("%s: FAILED open or read\n"), filename);
555 else
557 size_t digest_bin_bytes = digest_hex_bytes / 2;
558 size_t cnt;
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])))
567 break;
569 if (cnt != digest_bin_bytes)
570 ++n_mismatched_checksums;
572 if (!status_only)
574 if (cnt != digest_bin_bytes)
575 printf ("%s: %s\n", filename, _("FAILED"));
576 else if (!quiet)
577 printf ("%s: %s\n", filename, _("OK"));
582 while (!feof (checkfile_stream) && !ferror (checkfile_stream));
584 free (line);
586 if (ferror (checkfile_stream))
588 error (0, 0, _("%s: read error"), checkfile_name);
589 return false;
592 if (!is_stdin && fclose (checkfile_stream) != 0)
594 error (0, errno, "%s", checkfile_name);
595 return false;
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);
604 else
606 if (!status_only)
608 if (n_misformatted_lines != 0)
609 error (0, 0,
610 (ngettext
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)
617 error (0, 0,
618 (ngettext
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)
625 error (0, 0,
626 (ngettext
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;
647 int opt;
648 bool ok = true;
649 int binary = -1;
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)
665 switch (opt)
667 case 'b':
668 binary = 1;
669 break;
670 case 'c':
671 do_check = true;
672 break;
673 case STATUS_OPTION:
674 status_only = true;
675 warn = false;
676 quiet = false;
677 break;
678 case 't':
679 binary = 0;
680 break;
681 case 'w':
682 status_only = false;
683 warn = true;
684 quiet = false;
685 break;
686 case QUIET_OPTION:
687 status_only = false;
688 warn = false;
689 quiet = true;
690 break;
691 case STRICT_OPTION:
692 strict = true;
693 break;
694 case_GETOPT_HELP_CHAR;
695 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
696 default:
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)
712 error (0, 0,
713 _("the --status option is meaningful only when verifying checksums"));
714 usage (EXIT_FAILURE);
717 if (warn && !do_check)
719 error (0, 0,
720 _("the --warn option is meaningful only when verifying checksums"));
721 usage (EXIT_FAILURE);
724 if (quiet && !do_check)
726 error (0, 0,
727 _("the --quiet option is meaningful only when verifying checksums"));
728 usage (EXIT_FAILURE);
731 if (strict & !do_check)
733 error (0, 0,
734 _("the --strict option is meaningful only when verifying checksums"));
735 usage (EXIT_FAILURE);
738 if (!O_BINARY && binary < 0)
739 binary = 0;
741 if (optind == argc)
742 argv[argc++] = bad_cast ("-");
744 for (; optind < argc; ++optind)
746 char *file = argv[optind];
748 if (do_check)
749 ok &= digest_check (file);
750 else
752 int file_is_binary = binary;
754 if (! digest_file (file, &file_is_binary, bin_buffer))
755 ok = false;
756 else
758 size_t i;
760 /* Output a leading backslash if the file name contains
761 a newline or backslash. */
762 if (strchr (file, '\n') || strchr (file, '\\'))
763 putchar ('\\');
765 for (i = 0; i < (digest_hex_bytes / 2); ++i)
766 printf ("%02x", bin_buffer[i]);
768 putchar (' ');
769 if (file_is_binary)
770 putchar ('*');
771 else
772 putchar (' ');
774 /* Translate each NEWLINE byte to the string, "\\n",
775 and each backslash to "\\\\". */
776 for (i = 0; i < strlen (file); ++i)
778 switch (file[i])
780 case '\n':
781 fputs ("\\n", stdout);
782 break;
784 case '\\':
785 fputs ("\\\\", stdout);
786 break;
788 default:
789 putchar (file[i]);
790 break;
793 putchar ('\n');
798 if (have_read_stdin && fclose (stdin) == EOF)
799 error (EXIT_FAILURE, errno, _("standard input"));
801 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);