1 /* md5sum.c - Compute MD5 checksum of files or strings according to the
2 * definition of MD5 in RFC 1321 from April 1992.
3 * Copyright (C) 1995-1999 Free Software Foundation, Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu> */
21 /* Hacked to work with BusyBox by Alfred M. Szmidt <ams@trillian.itslinux.org> */
29 //----------------------------------------------------------------------------
31 //----------------------------------------------------------------------------
33 /* md5.c - Functions to compute MD5 message digest of files or memory blocks
34 * according to the definition of MD5 in RFC 1321 from April 1992.
35 * Copyright (C) 1995, 1996 Free Software Foundation, Inc.
37 * NOTE: The canonical source of this file is maintained with the GNU C
38 * Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
40 * This program is free software; you can redistribute it and/or modify it
41 * under the terms of the GNU General Public License as published by the
42 * Free Software Foundation; either version 2, or (at your option) any
45 * This program is distributed in the hope that it will be useful,
46 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 * GNU General Public License for more details.
50 * You should have received a copy of the GNU General Public License
51 * along with this program; if not, write to the Free Software Foundation,
52 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
55 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
57 #include <sys/types.h>
63 //----------------------------------------------------------------------------
65 //----------------------------------------------------------------------------
67 /* md5.h - Declaration of functions and data types used for MD5 sum
68 computing library functions.
69 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
70 NOTE: The canonical source of this file is maintained with the GNU C
71 Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
73 This program is free software; you can redistribute it and/or modify it
74 under the terms of the GNU General Public License as published by the
75 Free Software Foundation; either version 2, or (at your option) any
78 This program is distributed in the hope that it will be useful,
79 but WITHOUT ANY WARRANTY; without even the implied warranty of
80 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81 GNU General Public License for more details.
83 You should have received a copy of the GNU General Public License
84 along with this program; if not, write to the Free Software Foundation,
85 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
92 #if defined HAVE_LIMITS_H || defined _LIBC
96 /* The following contortions are an attempt to use the C preprocessor
97 to determine an unsigned integral type that is 32 bits wide. An
98 alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
99 doing that would require that the configure script compile and *run*
100 the resulting executable. Locally running cross-compiled executables
101 is usually not possible. */
103 # include <sys/types.h>
104 typedef u_int32_t md5_uint32;
106 /* Structure to save state of computation between the single steps. */
120 * The following three functions are build up the low level used in
121 * the functions `md5_stream' and `md5_buffer'.
124 /* Initialize structure containing state of computation.
125 (RFC 1321, 3.3: Step 3) */
126 extern void md5_init_ctx __P ((struct md5_ctx *ctx));
128 /* Starting with the result of former calls of this function (or the
129 initialization function update the context for the next LEN bytes
131 It is necessary that LEN is a multiple of 64!!! */
132 extern void md5_process_block __P ((const void *buffer, size_t len,
133 struct md5_ctx *ctx));
135 /* Starting with the result of former calls of this function (or the
136 initialization function update the context for the next LEN bytes
138 It is NOT required that LEN is a multiple of 64. */
139 extern void md5_process_bytes __P ((const void *buffer, size_t len,
140 struct md5_ctx *ctx));
142 /* Process the remaining bytes in the buffer and put result from CTX
143 in first 16 bytes following RESBUF. The result is always in little
144 endian byte order, so that a byte-wise output yields to the wanted
145 ASCII representation of the message digest.
147 IMPORTANT: On some systems it is required that RESBUF is correctly
148 aligned for a 32 bits value. */
149 extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
152 /* Put result from CTX in first 16 bytes following RESBUF. The result is
153 always in little endian byte order, so that a byte-wise output yields
154 to the wanted ASCII representation of the message digest.
156 IMPORTANT: On some systems it is required that RESBUF is correctly
157 aligned for a 32 bits value. */
158 extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
161 /* Compute MD5 message digest for bytes read from STREAM. The
162 resulting message digest number will be written into the 16 bytes
163 beginning at RESBLOCK. */
164 extern int md5_stream __P ((FILE *stream, void *resblock));
166 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
167 result is always in little endian byte order, so that a byte-wise
168 output yields to the wanted ASCII representation of the message
170 extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
174 //----------------------------------------------------------------------------
175 //--------end of md5.h
176 //----------------------------------------------------------------------------
180 /* This array contains the bytes used to pad the buffer to the next
181 64-byte boundary. (RFC 1321, 3.1: Step 1) */
182 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
184 /* Initialize structure containing state of computation.
185 (RFC 1321, 3.3: Step 3) */
186 void md5_init_ctx(struct md5_ctx *ctx)
193 ctx->total[0] = ctx->total[1] = 0;
197 /* Put result from CTX in first 16 bytes following RESBUF. The result
198 must be in little endian byte order.
200 IMPORTANT: On some systems it is required that RESBUF is correctly
201 aligned for a 32 bits value. */
202 void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf)
204 ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
205 ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
206 ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
207 ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
212 /* Process the remaining bytes in the internal buffer and the usual
213 prolog according to the standard and write the result to RESBUF.
215 IMPORTANT: On some systems it is required that RESBUF is correctly
216 aligned for a 32 bits value. */
217 void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
219 /* Take yet unprocessed bytes into account. */
220 md5_uint32 bytes = ctx->buflen;
223 /* Now count remaining bytes. */
224 ctx->total[0] += bytes;
225 if (ctx->total[0] < bytes)
228 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
229 memcpy(&ctx->buffer[bytes], fillbuf, pad);
231 /* Put the 64-bit file length in *bits* at the end of the buffer. */
232 *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
233 *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
234 SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29));
236 /* Process last bytes. */
237 md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
239 return md5_read_ctx(ctx, resbuf);
242 /* Compute MD5 message digest for bytes read from STREAM. The
243 resulting message digest number will be written into the 16 bytes
244 beginning at RESBLOCK. */
245 int md5_stream(FILE *stream, void *resblock)
247 /* Important: BLOCKSIZE must be a multiple of 64. */
248 #define BLOCKSIZE 4096
250 char buffer[BLOCKSIZE + 72];
253 /* Initialize the computation context. */
256 /* Iterate over full file contents. */
258 /* We read the file in blocks of BLOCKSIZE bytes. One call of the
259 computation function processes the whole buffer so that with the
260 next round of the loop another block can be read. */
264 /* Read block. Take care for partial reads. */
266 n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
270 while (sum < BLOCKSIZE && n != 0);
271 if (n == 0 && ferror(stream))
274 /* If end of file is reached, end the loop. */
278 /* Process buffer with BLOCKSIZE bytes. Note that
281 md5_process_block(buffer, BLOCKSIZE, &ctx);
284 /* Add the last bytes if necessary. */
286 md5_process_bytes(buffer, sum, &ctx);
288 /* Construct result in desired memory. */
289 md5_finish_ctx(&ctx, resblock);
293 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
294 result is always in little endian byte order, so that a byte-wise
295 output yields to the wanted ASCII representation of the message
297 void *md5_buffer(const char *buffer, size_t len, void *resblock)
301 /* Initialize the computation context. */
304 /* Process whole buffer but last len % 64 bytes. */
305 md5_process_bytes(buffer, len, &ctx);
307 /* Put result in desired memory area. */
308 return md5_finish_ctx(&ctx, resblock);
311 void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
313 /* When we already have some bits in our internal buffer concatenate
314 both inputs first. */
315 if (ctx->buflen != 0) {
316 size_t left_over = ctx->buflen;
317 size_t add = 128 - left_over > len ? len : 128 - left_over;
319 memcpy(&ctx->buffer[left_over], buffer, add);
322 if (left_over + add > 64) {
323 md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
324 /* The regions in the following copy operation cannot overlap. */
325 memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
326 (left_over + add) & 63);
327 ctx->buflen = (left_over + add) & 63;
330 buffer = (const char *) buffer + add;
334 /* Process available complete blocks. */
336 md5_process_block(buffer, len & ~63, ctx);
337 buffer = (const char *) buffer + (len & ~63);
341 /* Move remaining bytes in internal buffer. */
343 memcpy(ctx->buffer, buffer, len);
348 /* These are the four functions used in the four steps of the MD5 algorithm
349 and defined in the RFC 1321. The first function is a little bit optimized
350 (as found in Colin Plumbs public domain implementation). */
351 /* #define FF(b, c, d) ((b & c) | (~b & d)) */
352 #define FF(b, c, d) (d ^ (b & (c ^ d)))
353 #define FG(b, c, d) FF (d, b, c)
354 #define FH(b, c, d) (b ^ c ^ d)
355 #define FI(b, c, d) (c ^ (b | ~d))
357 /* Process LEN bytes of BUFFER, accumulating context into CTX.
358 It is assumed that LEN % 64 == 0. */
359 void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ctx)
361 md5_uint32 correct_words[16];
362 const md5_uint32 *words = buffer;
363 size_t nwords = len / sizeof(md5_uint32);
364 const md5_uint32 *endp = words + nwords;
365 md5_uint32 A = ctx->A;
366 md5_uint32 B = ctx->B;
367 md5_uint32 C = ctx->C;
368 md5_uint32 D = ctx->D;
370 /* First increment the byte count. RFC 1321 specifies the possible
371 length of the file up to 2^64 bits. Here we only compute the
372 number of bytes. Do a double word increment. */
373 ctx->total[0] += len;
374 if (ctx->total[0] < len)
377 /* Process all bytes in the buffer with 64 bytes in each round of
379 while (words < endp) {
380 md5_uint32 *cwp = correct_words;
381 md5_uint32 A_save = A;
382 md5_uint32 B_save = B;
383 md5_uint32 C_save = C;
384 md5_uint32 D_save = D;
386 /* First round: using the given function, the context and a constant
387 the next context is computed. Because the algorithms processing
388 unit is a 32-bit word and it is determined to work on words in
389 little endian byte order we perhaps have to change the byte order
390 before the computation. To reduce the work for the next steps
391 we store the swapped words in the array CORRECT_WORDS. */
393 #define OP(a, b, c, d, s, T) \
396 a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
403 /* It is unfortunate that C does not provide an operator for
404 cyclic rotation. Hope the C compiler is smart enough. */
405 #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
407 /* Before we start, one word to the strange constants.
408 They are defined in RFC 1321 as
410 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
414 OP(A, B, C, D, 7, 0xd76aa478);
415 OP(D, A, B, C, 12, 0xe8c7b756);
416 OP(C, D, A, B, 17, 0x242070db);
417 OP(B, C, D, A, 22, 0xc1bdceee);
418 OP(A, B, C, D, 7, 0xf57c0faf);
419 OP(D, A, B, C, 12, 0x4787c62a);
420 OP(C, D, A, B, 17, 0xa8304613);
421 OP(B, C, D, A, 22, 0xfd469501);
422 OP(A, B, C, D, 7, 0x698098d8);
423 OP(D, A, B, C, 12, 0x8b44f7af);
424 OP(C, D, A, B, 17, 0xffff5bb1);
425 OP(B, C, D, A, 22, 0x895cd7be);
426 OP(A, B, C, D, 7, 0x6b901122);
427 OP(D, A, B, C, 12, 0xfd987193);
428 OP(C, D, A, B, 17, 0xa679438e);
429 OP(B, C, D, A, 22, 0x49b40821);
431 /* For the second to fourth round we have the possibly swapped words
432 in CORRECT_WORDS. Redefine the macro to take an additional first
433 argument specifying the function to use. */
435 #define OP(f, a, b, c, d, k, s, T) \
438 a += f (b, c, d) + correct_words[k] + T; \
445 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
446 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
447 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
448 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
449 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
450 OP(FG, D, A, B, C, 10, 9, 0x02441453);
451 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
452 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
453 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
454 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
455 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
456 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
457 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
458 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
459 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
460 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
463 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
464 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
465 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
466 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
467 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
468 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
469 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
470 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
471 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
472 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
473 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
474 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
475 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
476 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
477 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
478 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
481 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
482 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
483 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
484 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
485 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
486 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
487 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
488 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
489 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
490 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
491 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
492 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
493 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
494 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
495 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
496 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
498 /* Add the starting values of the context. */
505 /* Put checksum in context given as argument. */
512 //----------------------------------------------------------------------------
513 //--------end of md5.c
514 //----------------------------------------------------------------------------
516 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
517 #define IN_CTYPE_DOMAIN(c) 1
518 #define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
519 #define STREQ(a, b) (strcmp ((a), (b)) == 0)
520 #define TOLOWER(Ch) tolower (Ch)
521 #define OPENOPTS(BINARY) "r"
523 /* The minimum length of a valid digest line in a file produced
524 by `md5sum FILE' and read by `md5sum -c'. This length does
525 not include any newline character at the end of a line. */
526 #define MIN_DIGEST_LINE_LENGTH 35 /* 32 - message digest length
527 2 - blank and binary indicator
528 1 - minimum filename length */
530 static int have_read_stdin; /* Nonzero if any of the files read were
531 the standard input. */
533 static int status_only = 0; /* With -c, don't generate any output.
534 The exit code indicates success or failure */
535 static int warn = 0; /* With -w, print a message to standard error warning
536 about each improperly formatted MD5 checksum line */
538 static int split_3(char *s,
545 int escaped_filename = 0;
547 while (ISWHITE(s[i]))
550 /* The line must have at least 35 (36 if the first is a backslash)
551 more characters to contain correct message digest information.
552 Ignore this line if it is too short. */
553 if (!(s_len - i >= MIN_DIGEST_LINE_LENGTH
554 || (s[i] == '\\' && s_len - i >= 1 + MIN_DIGEST_LINE_LENGTH)))
559 escaped_filename = 1;
561 *u = (unsigned char *) &s[i];
563 /* The first field has to be the 32-character hexadecimal
564 representation of the message digest. If it is not followed
565 immediately by a white space it's an error. */
572 if (s[i] != ' ' && s[i] != '*')
574 *binary = (s[i++] == '*');
576 /* All characters between the type indicator and end of line are
577 significant -- that includes leading and trailing white space. */
580 if (escaped_filename) {
581 /* Translate each `\n' string in the file name to a NEWLINE,
582 and each `\\' string to a backslash. */
589 if (i == s_len - 1) {
590 /* A valid line does not end with a backslash. */
602 /* Only `\' or `n' may follow a backslash. */
608 /* The file name may not contain a NUL. */
622 static int hex_digits(unsigned char const *s)
632 /* An interface to md5_stream. Operate on FILENAME (it may be "-") and
633 put the result in *MD5_RESULT. Return non-zero upon failure, zero
634 to indicate success. */
635 static int md5_file(const char *filename,
637 unsigned char *md5_result)
641 if (STREQ(filename, "-")) {
645 fp = fopen(filename, OPENOPTS(binary));
647 perror_msg("%s", filename);
652 if (md5_stream(fp, md5_result)) {
653 perror_msg("%s", filename);
660 if (fp != stdin && fclose(fp) == EOF) {
661 perror_msg("%s", filename);
668 static int md5_check(const char *checkfile_name)
670 FILE *checkfile_stream;
671 int n_properly_formated_lines = 0;
672 int n_mismatched_checksums = 0;
673 int n_open_or_read_failures = 0;
674 unsigned char md5buffer[16];
678 if (STREQ(checkfile_name, "-")) {
680 checkfile_stream = stdin;
682 checkfile_stream = fopen(checkfile_name, "r");
683 if (checkfile_stream == NULL) {
684 perror_msg("%s", checkfile_name);
694 unsigned char *md5num;
699 fgets(line, BUFSIZ-1, checkfile_stream);
700 line_length = strlen(line);
702 if (line_length <= 0)
705 /* Ignore comment lines, which begin with a '#' character. */
709 /* Remove any trailing newline. */
710 if (line[line_length - 1] == '\n')
711 line[--line_length] = '\0';
713 if (split_3(line, line_length, &md5num, &binary, &filename)
714 || !hex_digits(md5num)) {
716 error_msg("%s: %lu: improperly formatted MD5 checksum line\n",
717 checkfile_name, (unsigned long) line_number);
720 static const char bin2hex[] = {
727 ++n_properly_formated_lines;
729 if (md5_file(filename, binary, md5buffer)) {
730 ++n_open_or_read_failures;
732 printf("%s: FAILED open or read\n", filename);
737 /* Compare generated binary number with text representation
738 in check file. Ignore case of hex digits. */
739 for (cnt = 0; cnt < 16; ++cnt) {
740 if (TOLOWER(md5num[2 * cnt])
741 != bin2hex[md5buffer[cnt] >> 4]
742 || (TOLOWER(md5num[2 * cnt + 1])
743 != (bin2hex[md5buffer[cnt] & 0xf])))
747 ++n_mismatched_checksums;
750 printf("%s: %s\n", filename,
751 (cnt != 16 ? "FAILED" : "OK"));
758 while (!feof(checkfile_stream) && !ferror(checkfile_stream));
763 if (ferror(checkfile_stream)) {
764 error_msg("%s: read error\n", checkfile_name); /* */
768 if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
769 perror_msg("md5sum: %s", checkfile_name);
773 if (n_properly_formated_lines == 0) {
774 /* Warn if no tests are found. */
775 error_msg("%s: no properly formatted MD5 checksum lines found\n",
780 int n_computed_checkums = (n_properly_formated_lines
781 - n_open_or_read_failures);
783 if (n_open_or_read_failures > 0) {
784 error_msg("WARNING: %d of %d listed files could not be read\n",
785 n_open_or_read_failures, n_properly_formated_lines);
789 if (n_mismatched_checksums > 0) {
790 error_msg("WARNING: %d of %d computed checksums did NOT match\n",
791 n_mismatched_checksums, n_computed_checkums);
797 return ((n_properly_formated_lines > 0 && n_mismatched_checksums == 0
798 && n_open_or_read_failures == 0) ? 0 : 1);
801 int md5sum_main(int argc,
804 unsigned char md5buffer[16];
807 char **string = NULL;
808 size_t n_strings = 0;
810 int file_type_specified = 0;
813 while ((opt = getopt(argc, argv, "g:bcstw")) != -1) {
815 case 'g': { /* read a string */
817 string = (char **) xmalloc ((argc - 1) * sizeof (char *));
821 string[n_strings++] = optarg;
825 case 'b': /* read files in binary mode */
826 file_type_specified = 1;
830 case 'c': /* check MD5 sums against given list */
834 case 's': /* don't output anything, status code shows success */
839 case 't': /* read files in text mode (default) */
840 file_type_specified = 1;
844 case 'w': /* warn about improperly formated MD5 checksum lines */
854 if (file_type_specified && do_check) {
855 error_msg("the -b and -t options are meaningless when verifying checksums\n");
859 if (n_strings > 0 && do_check) {
860 error_msg("the -g and -c options are mutually exclusive\n");
864 if (status_only && !do_check) {
865 error_msg("the -s option is meaningful only when verifying checksums\n");
869 if (warn && !do_check) {
870 error_msg("the -w option is meaningful only when verifying checksums\n");
878 error_msg("no files may be specified when using -g\n");
881 for (i = 0; i < n_strings; ++i) {
883 md5_buffer (string[i], strlen (string[i]), md5buffer);
885 for (cnt = 0; cnt < 16; ++cnt)
886 printf ("%02x", md5buffer[cnt]);
888 printf (" \"%s\"\n", string[i]);
890 } else if (do_check) {
891 if (optind + 1 < argc) {
892 error_msg("only one argument may be specified when using -c\n");
895 err = md5_check ((optind == argc) ? "-" : argv[optind]);
900 for (; optind < argc; ++optind) {
902 char *file = argv[optind];
904 fail = md5_file (file, binary, md5buffer);
908 /* Output a leading backslash if the file name contains
909 a newline or backslash. */
910 if (strchr (file, '\n') || strchr (file, '\\'))
913 for (i = 0; i < 16; ++i)
914 printf ("%02x", md5buffer[i]);
922 /* Translate each NEWLINE byte to the string, "\\n",
923 and each backslash to "\\\\". */
924 for (i = 0; i < strlen (file); ++i) {
927 fputs ("\\n", stdout);
931 fputs ("\\\\", stdout);
944 if (fclose (stdout) == EOF) {
945 error_msg("write error\n");
949 if (have_read_stdin && fclose (stdin) == EOF) {
950 error_msg("standard input\n");