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> */
24 * June 29, 2001 Manuel Novoa III
26 * Added MD5SUM_SIZE_VS_SPEED configuration option.
28 * Current valid values, with data from my system for comparison, are:
29 * (using uClibc and running on linux-2.4.4.tar.bz2)
30 * user times (sec) text size (386)
31 * 0 (fastest) 1.1 6144
34 * 3 (smallest) 5.1 4912
37 #define MD5SUM_SIZE_VS_SPEED 2
39 /**********************************************************************/
48 #include <sys/types.h>
49 #if defined HAVE_LIMITS_H
54 /* For some silly reason, this file uses backwards TRUE and FALSE conventions */
57 #define FALSE ((int) 1)
58 #define TRUE ((int) 0)
60 //----------------------------------------------------------------------------
62 //----------------------------------------------------------------------------
64 /* md5.c - Functions to compute MD5 message digest of files or memory blocks
65 * according to the definition of MD5 in RFC 1321 from April 1992.
68 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
70 //----------------------------------------------------------------------------
72 //----------------------------------------------------------------------------
74 /* md5.h - Declaration of functions and data types used for MD5 sum
75 computing library functions. */
77 typedef u_int32_t md5_uint32;
79 /* Structure to save state of computation between the single steps. */
92 * The following three functions are build up the low level used in
93 * the functions `md5_stream' and `md5_buffer'.
96 /* Initialize structure containing state of computation.
97 (RFC 1321, 3.3: Step 3) */
98 static void md5_init_ctx __P((struct md5_ctx * ctx));
100 /* Starting with the result of former calls of this function (or the
101 initialization function update the context for the next LEN bytes
103 It is necessary that LEN is a multiple of 64!!! */
104 static void md5_process_block __P((const void *buffer, size_t len,
105 struct md5_ctx * ctx));
107 /* Starting with the result of former calls of this function (or the
108 initialization function update the context for the next LEN bytes
110 It is NOT required that LEN is a multiple of 64. */
111 static void md5_process_bytes __P((const void *buffer, size_t len,
112 struct md5_ctx * ctx));
114 /* Process the remaining bytes in the buffer and put result from CTX
115 in first 16 bytes following RESBUF. The result is always in little
116 endian byte order, so that a byte-wise output yields to the wanted
117 ASCII representation of the message digest.
119 IMPORTANT: On some systems it is required that RESBUF is correctly
120 aligned for a 32 bits value. */
121 static void *md5_finish_ctx __P((struct md5_ctx * ctx, void *resbuf));
126 /* Compute MD5 message digest for bytes read from STREAM. The
127 resulting message digest number will be written into the 16 bytes
128 beginning at RESBLOCK. */
129 static int md5_stream __P((FILE * stream, void *resblock));
131 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
132 result is always in little endian byte order, so that a byte-wise
133 output yields to the wanted ASCII representation of the message
135 static void *md5_buffer __P((const char *buffer, size_t len, void *resblock));
137 //----------------------------------------------------------------------------
138 //--------end of md5.h
139 //----------------------------------------------------------------------------
141 /* Handle endian-ness */
142 #if __BYTE_ORDER == __LITTLE_ENDIAN
145 #define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
150 #if MD5SUM_SIZE_VS_SPEED == 0
151 /* This array contains the bytes used to pad the buffer to the next
152 64-byte boundary. (RFC 1321, 3.1: Step 1) */
153 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
156 /* Initialize structure containing state of computation.
157 (RFC 1321, 3.3: Step 3) */
158 void md5_init_ctx(struct md5_ctx *ctx)
165 ctx->total[0] = ctx->total[1] = 0;
169 /* Process the remaining bytes in the internal buffer and the usual
170 prolog according to the standard and write the result to RESBUF.
172 IMPORTANT: On some systems it is required that RESBUF is correctly
173 aligned for a 32 bits value. */
174 static void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
176 /* Take yet unprocessed bytes into account. */
177 md5_uint32 bytes = ctx->buflen;
180 /* Now count remaining bytes. */
181 ctx->total[0] += bytes;
182 if (ctx->total[0] < bytes)
185 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
186 #if MD5SUM_SIZE_VS_SPEED > 0
187 memset(&ctx->buffer[bytes], 0, pad);
188 ctx->buffer[bytes] = 0x80;
190 memcpy(&ctx->buffer[bytes], fillbuf, pad);
193 /* Put the 64-bit file length in *bits* at the end of the buffer. */
194 *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
195 *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
196 SWAP(((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
198 /* Process last bytes. */
199 md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
201 /* Put result from CTX in first 16 bytes following RESBUF. The result is
202 always in little endian byte order, so that a byte-wise output yields
203 to the wanted ASCII representation of the message digest.
205 IMPORTANT: On some systems it is required that RESBUF is correctly
206 aligned for a 32 bits value. */
207 ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
208 ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
209 ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
210 ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
215 /* Compute MD5 message digest for bytes read from STREAM. The
216 resulting message digest number will be written into the 16 bytes
217 beginning at RESBLOCK. */
218 static int md5_stream(FILE * stream, void *resblock)
220 /* Important: BLOCKSIZE must be a multiple of 64. */
221 static const int BLOCKSIZE = 4096;
223 char buffer[BLOCKSIZE + 72];
226 /* Initialize the computation context. */
229 /* Iterate over full file contents. */
231 /* We read the file in blocks of BLOCKSIZE bytes. One call of the
232 computation function processes the whole buffer so that with the
233 next round of the loop another block can be read. */
238 /* Read block. Take care for partial reads. */
240 n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
244 while (sum < BLOCKSIZE && n != 0);
245 if (n == 0 && ferror(stream))
248 /* If end of file is reached, end the loop. */
252 /* Process buffer with BLOCKSIZE bytes. Note that
255 md5_process_block(buffer, BLOCKSIZE, &ctx);
258 /* Add the last bytes if necessary. */
260 md5_process_bytes(buffer, sum, &ctx);
262 /* Construct result in desired memory. */
263 md5_finish_ctx(&ctx, resblock);
267 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
268 result is always in little endian byte order, so that a byte-wise
269 output yields to the wanted ASCII representation of the message
271 static void *md5_buffer(const char *buffer, size_t len, void *resblock)
275 /* Initialize the computation context. */
278 /* Process whole buffer but last len % 64 bytes. */
279 md5_process_bytes(buffer, len, &ctx);
281 /* Put result in desired memory area. */
282 return md5_finish_ctx(&ctx, resblock);
285 static void md5_process_bytes(const void *buffer, size_t len,
288 /* When we already have some bits in our internal buffer concatenate
289 both inputs first. */
290 if (ctx->buflen != 0) {
291 size_t left_over = ctx->buflen;
292 size_t add = 128 - left_over > len ? len : 128 - left_over;
294 memcpy(&ctx->buffer[left_over], buffer, add);
297 if (left_over + add > 64) {
298 md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
299 /* The regions in the following copy operation cannot overlap. */
300 memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
301 (left_over + add) & 63);
302 ctx->buflen = (left_over + add) & 63;
305 buffer = (const char *) buffer + add;
309 /* Process available complete blocks. */
311 md5_process_block(buffer, len & ~63, ctx);
312 buffer = (const char *) buffer + (len & ~63);
316 /* Move remaining bytes in internal buffer. */
318 memcpy(ctx->buffer, buffer, len);
323 /* These are the four functions used in the four steps of the MD5 algorithm
324 and defined in the RFC 1321. The first function is a little bit optimized
325 (as found in Colin Plumbs public domain implementation). */
326 /* #define FF(b, c, d) ((b & c) | (~b & d)) */
327 #define FF(b, c, d) (d ^ (b & (c ^ d)))
328 #define FG(b, c, d) FF (d, b, c)
329 #define FH(b, c, d) (b ^ c ^ d)
330 #define FI(b, c, d) (c ^ (b | ~d))
332 /* Process LEN bytes of BUFFER, accumulating context into CTX.
333 It is assumed that LEN % 64 == 0. */
334 static void md5_process_block(const void *buffer, size_t len,
337 md5_uint32 correct_words[16];
338 const md5_uint32 *words = buffer;
339 size_t nwords = len / sizeof(md5_uint32);
340 const md5_uint32 *endp = words + nwords;
342 #if MD5SUM_SIZE_VS_SPEED > 0
343 static const md5_uint32 C_array[] = {
345 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
346 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
347 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
348 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
350 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
351 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
352 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
353 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
355 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
356 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
357 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
358 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
360 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
361 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
362 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
363 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
366 static const char P_array[] = {
367 #if MD5SUM_SIZE_VS_SPEED > 1
368 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
370 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
371 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
372 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
375 #if MD5SUM_SIZE_VS_SPEED > 1
376 static const char S_array[] = {
385 md5_uint32 A = ctx->A;
386 md5_uint32 B = ctx->B;
387 md5_uint32 C = ctx->C;
388 md5_uint32 D = ctx->D;
390 /* First increment the byte count. RFC 1321 specifies the possible
391 length of the file up to 2^64 bits. Here we only compute the
392 number of bytes. Do a double word increment. */
393 ctx->total[0] += len;
394 if (ctx->total[0] < len)
397 /* Process all bytes in the buffer with 64 bytes in each round of
399 while (words < endp) {
400 md5_uint32 *cwp = correct_words;
401 md5_uint32 A_save = A;
402 md5_uint32 B_save = B;
403 md5_uint32 C_save = C;
404 md5_uint32 D_save = D;
406 #if MD5SUM_SIZE_VS_SPEED > 1
407 #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
409 const md5_uint32 *pc;
415 for (i = 0; i < 16; i++) {
416 cwp[i] = SWAP(words[i]);
420 #if MD5SUM_SIZE_VS_SPEED > 2
425 for (i = 0; i < 64; i++) {
442 temp += cwp[(int) (*pp++)] + *pc++;
443 CYCLIC(temp, ps[i & 3]);
455 for (i = 0; i < 16; i++) {
456 temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
457 CYCLIC(temp, ps[i & 3]);
466 for (i = 0; i < 16; i++) {
467 temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
468 CYCLIC(temp, ps[i & 3]);
476 for (i = 0; i < 16; i++) {
477 temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
478 CYCLIC(temp, ps[i & 3]);
486 for (i = 0; i < 16; i++) {
487 temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
488 CYCLIC(temp, ps[i & 3]);
498 /* First round: using the given function, the context and a constant
499 the next context is computed. Because the algorithms processing
500 unit is a 32-bit word and it is determined to work on words in
501 little endian byte order we perhaps have to change the byte order
502 before the computation. To reduce the work for the next steps
503 we store the swapped words in the array CORRECT_WORDS. */
505 #define OP(a, b, c, d, s, T) \
508 a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
515 /* It is unfortunate that C does not provide an operator for
516 cyclic rotation. Hope the C compiler is smart enough. */
517 /* gcc 2.95.4 seems to be --aaronl */
518 #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
520 /* Before we start, one word to the strange constants.
521 They are defined in RFC 1321 as
523 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
526 #if MD5SUM_SIZE_VS_SPEED == 1
527 const md5_uint32 *pc;
533 #if MD5SUM_SIZE_VS_SPEED == 1
535 for (i = 0; i < 4; i++) {
536 OP(A, B, C, D, 7, *pc++);
537 OP(D, A, B, C, 12, *pc++);
538 OP(C, D, A, B, 17, *pc++);
539 OP(B, C, D, A, 22, *pc++);
542 OP(A, B, C, D, 7, 0xd76aa478);
543 OP(D, A, B, C, 12, 0xe8c7b756);
544 OP(C, D, A, B, 17, 0x242070db);
545 OP(B, C, D, A, 22, 0xc1bdceee);
546 OP(A, B, C, D, 7, 0xf57c0faf);
547 OP(D, A, B, C, 12, 0x4787c62a);
548 OP(C, D, A, B, 17, 0xa8304613);
549 OP(B, C, D, A, 22, 0xfd469501);
550 OP(A, B, C, D, 7, 0x698098d8);
551 OP(D, A, B, C, 12, 0x8b44f7af);
552 OP(C, D, A, B, 17, 0xffff5bb1);
553 OP(B, C, D, A, 22, 0x895cd7be);
554 OP(A, B, C, D, 7, 0x6b901122);
555 OP(D, A, B, C, 12, 0xfd987193);
556 OP(C, D, A, B, 17, 0xa679438e);
557 OP(B, C, D, A, 22, 0x49b40821);
560 /* For the second to fourth round we have the possibly swapped words
561 in CORRECT_WORDS. Redefine the macro to take an additional first
562 argument specifying the function to use. */
564 #define OP(f, a, b, c, d, k, s, T) \
567 a += f (b, c, d) + correct_words[k] + T; \
574 #if MD5SUM_SIZE_VS_SPEED == 1
576 for (i = 0; i < 4; i++) {
577 OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
578 OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
579 OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
580 OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
583 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
584 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
585 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
586 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
587 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
588 OP(FG, D, A, B, C, 10, 9, 0x02441453);
589 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
590 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
591 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
592 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
593 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
594 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
595 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
596 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
597 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
598 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
602 #if MD5SUM_SIZE_VS_SPEED == 1
603 for (i = 0; i < 4; i++) {
604 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
605 OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
606 OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
607 OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
610 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
611 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
612 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
613 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
614 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
615 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
616 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
617 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
618 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
619 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
620 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
621 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
622 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
623 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
624 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
625 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
629 #if MD5SUM_SIZE_VS_SPEED == 1
630 for (i = 0; i < 4; i++) {
631 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
632 OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
633 OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
634 OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
637 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
638 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
639 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
640 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
641 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
642 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
643 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
644 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
645 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
646 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
647 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
648 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
649 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
650 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
651 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
652 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
656 /* Add the starting values of the context. */
663 /* Put checksum in context given as argument. */
670 //----------------------------------------------------------------------------
671 //--------end of md5.c
672 //----------------------------------------------------------------------------
674 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
675 #define ISXDIGIT(c) (isxdigit (c))
677 /* The minimum length of a valid digest line in a file produced
678 by `md5sum FILE' and read by `md5sum -c'. This length does
679 not include any newline character at the end of a line. */
680 static const int MIN_DIGEST_LINE_LENGTH = 35; /* 32 - message digest length
681 2 - blank and binary indicator
682 1 - minimum filename length */
684 static int have_read_stdin; /* Nonzero if any of the files read were
685 the standard input. */
687 static int status_only = 0; /* With -c, don't generate any output.
688 The exit code indicates success or failure */
689 static int warn = 0; /* With -w, print a message to standard error warning
690 about each improperly formatted MD5 checksum line */
692 static int split_3(char *s, size_t s_len, unsigned char **u, char **w)
695 int escaped_filename = 0;
697 while (ISWHITE(s[i]))
700 /* The line must have at least 35 (36 if the first is a backslash)
701 more characters to contain correct message digest information.
702 Ignore this line if it is too short. */
703 if (!(s_len - i >= MIN_DIGEST_LINE_LENGTH
704 || (s[i] == '\\' && s_len - i >= 1 + MIN_DIGEST_LINE_LENGTH)))
709 escaped_filename = 1;
711 *u = (unsigned char *) &s[i];
713 /* The first field has to be the 32-character hexadecimal
714 representation of the message digest. If it is not followed
715 immediately by a white space it's an error. */
722 if (s[i] != ' ' && s[i] != '*')
725 /* All characters between the type indicator and end of line are
726 significant -- that includes leading and trailing white space. */
729 if (escaped_filename) {
730 /* Translate each `\n' string in the file name to a NEWLINE,
731 and each `\\' string to a backslash. */
738 if (i == s_len - 1) {
739 /* A valid line does not end with a backslash. */
751 /* Only `\' or `n' may follow a backslash. */
757 /* The file name may not contain a NUL. */
771 static inline int hex_digits(unsigned char const *s)
781 /* An interface to md5_stream. Operate on FILENAME (it may be "-") and
782 put the result in *MD5_RESULT. Return non-zero upon failure, zero
783 to indicate success. */
784 static int md5_file(const char *filename, unsigned char *md5_result)
788 if (filename[0] == '-' && filename[1] == '\0') {
792 fp = bb_wfopen(filename, "r");
797 if (md5_stream(fp, md5_result)) {
798 bb_perror_msg("%s", filename);
805 if (fp != stdin && fclose(fp) == EOF) {
806 bb_perror_msg("%s", filename);
813 static int md5_check(const char *checkfile_name)
815 FILE *checkfile_stream;
816 int n_properly_formated_lines = 0;
817 int n_mismatched_checksums = 0;
818 int n_open_or_read_failures = 0;
819 unsigned char md5buffer[16];
823 if (checkfile_name[0] == '-' && checkfile_name[1] == '\0') {
825 checkfile_stream = stdin;
827 checkfile_stream = bb_wfopen(checkfile_name, "r");
828 if (checkfile_stream == NULL)
836 unsigned char *md5num;
841 fgets(line, BUFSIZ - 1, checkfile_stream);
842 line_length = strlen(line);
844 if (line_length <= 0 || line == NULL)
847 /* Ignore comment lines, which begin with a '#' character. */
851 /* Remove any trailing newline. */
852 if (line[line_length - 1] == '\n')
853 line[--line_length] = '\0';
855 if (split_3(line, line_length, &md5num, &filename)
856 || !hex_digits(md5num)) {
859 ("%s: %lu: improperly formatted MD5 checksum line",
860 checkfile_name, (unsigned long) line_number);
863 static const char bin2hex[] = {
870 ++n_properly_formated_lines;
872 if (md5_file(filename, md5buffer)) {
873 ++n_open_or_read_failures;
875 printf("%s: FAILED open or read\n", filename);
881 /* Compare generated binary number with text representation
882 in check file. Ignore case of hex digits. */
883 for (cnt = 0; cnt < 16; ++cnt) {
884 if (tolower(md5num[2 * cnt])
885 != bin2hex[md5buffer[cnt] >> 4]
886 || (tolower(md5num[2 * cnt + 1])
887 != (bin2hex[md5buffer[cnt] & 0xf])))
891 ++n_mismatched_checksums;
894 printf("%s: %s\n", filename,
895 (cnt != 16 ? "FAILED" : "OK"));
902 while (!feof(checkfile_stream) && !ferror(checkfile_stream));
904 if (ferror(checkfile_stream)) {
905 bb_error_msg("%s: read error", checkfile_name);
909 if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
910 bb_perror_msg("md5sum: %s", checkfile_name);
914 if (n_properly_formated_lines == 0) {
915 /* Warn if no tests are found. */
916 bb_error_msg("%s: no properly formatted MD5 checksum lines found",
921 int n_computed_checkums = (n_properly_formated_lines
922 - n_open_or_read_failures);
924 if (n_open_or_read_failures > 0) {
926 ("WARNING: %d of %d listed files could not be read",
927 n_open_or_read_failures, n_properly_formated_lines);
931 if (n_mismatched_checksums > 0) {
933 ("WARNING: %d of %d computed checksums did NOT match",
934 n_mismatched_checksums, n_computed_checkums);
940 return ((n_properly_formated_lines > 0 && n_mismatched_checksums == 0
941 && n_open_or_read_failures == 0) ? 0 : 1);
944 int md5sum_main(int argc, char **argv)
946 unsigned char md5buffer[16];
949 char **string = NULL;
950 size_t n_strings = 0;
952 char file_type_specified = 0;
955 while ((opt = getopt(argc, argv, "g:bcstw")) != -1) {
957 case 'g':{ /* read a string */
959 string = (char **) xmalloc((argc - 1) * sizeof(char *));
961 string[n_strings++] = optarg;
965 case 'b': /* read files in binary mode */
966 file_type_specified = 1;
970 case 'c': /* check MD5 sums against given list */
974 case 's': /* don't output anything, status code shows success */
979 case 't': /* read files in text mode (default) */
980 file_type_specified = 1;
984 case 'w': /* warn about improperly formated MD5 checksum lines */
994 if (file_type_specified && do_check) {
996 ("the -b and -t options are meaningless when verifying checksums");
999 if (n_strings > 0 && do_check) {
1000 bb_error_msg_and_die("the -g and -c options are mutually exclusive");
1003 if (status_only && !do_check) {
1004 bb_error_msg_and_die
1005 ("the -s option is meaningful only when verifying checksums");
1008 if (warn && !do_check) {
1009 bb_error_msg_and_die
1010 ("the -w option is meaningful only when verifying checksums");
1013 if (n_strings > 0) {
1016 if (optind < argc) {
1017 bb_error_msg_and_die("no files may be specified when using -g");
1019 for (i = 0; i < n_strings; ++i) {
1022 md5_buffer(string[i], strlen(string[i]), md5buffer);
1024 for (cnt = 0; cnt < 16; ++cnt)
1025 printf("%02x", md5buffer[cnt]);
1027 printf(" \"%s\"\n", string[i]);
1029 } else if (do_check) {
1030 if (optind + 1 < argc) {
1031 bb_error_msg("only one argument may be specified when using -c");
1034 err = md5_check((optind == argc) ? "-" : argv[optind]);
1039 for (; optind < argc; ++optind) {
1041 char *file = argv[optind];
1043 fail = md5_file(file, md5buffer);
1045 if (!fail && file[0] == '-' && file[1] == '\0') {
1048 for (i = 0; i < 16; ++i)
1049 printf("%02x", md5buffer[i]);
1054 /* Output a leading backslash if the file name contains
1055 a newline or backslash. */
1056 if (strchr(file, '\n') || strchr(file, '\\'))
1059 for (i = 0; i < 16; ++i)
1060 printf("%02x", md5buffer[i]);
1068 /* Translate each NEWLINE byte to the string, "\\n",
1069 and each backslash to "\\\\". */
1070 for (i = 0; i < strlen(file); ++i) {
1073 fputs("\\n", stdout);
1077 fputs("\\\\", stdout);
1090 if (fclose(stdout) == EOF) {
1091 bb_error_msg_and_die("write error");
1094 if (have_read_stdin && fclose(stdin) == EOF) {
1095 bb_error_msg_and_die(bb_msg_standard_input);
1099 return EXIT_SUCCESS;
1101 return EXIT_FAILURE;