blob: 3458f2e059d562935de1425eda8933619a1d6783 [file] [log] [blame]
Eric Andersen2b6ab3c2000-06-13 06:54:53 +00001/* 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.
4 *
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)
8 * any later version.
9 *
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.
14 *
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.
18 */
19
20/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu> */
21/* Hacked to work with BusyBox by Alfred M. Szmidt <ams@trillian.itslinux.org> */
22
Eric Andersen3570a342000-09-25 21:45:58 +000023#include "busybox.h"
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000024#include <stdio.h>
25#include <errno.h>
26#include <ctype.h>
Eric Andersen999bf722000-07-09 06:59:58 +000027#include <getopt.h>
28
Eric Andersene111d692000-12-20 23:19:42 +000029/* For some silly reason, this file uses backwards TRUE and FALSE conventions */
30#undef TRUE
31#undef FALSE
32#define FALSE ((int) 1)
33#define TRUE ((int) 0)
34
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000035//----------------------------------------------------------------------------
36//--------md5.c
37//----------------------------------------------------------------------------
38
39/* md5.c - Functions to compute MD5 message digest of files or memory blocks
40 * according to the definition of MD5 in RFC 1321 from April 1992.
41 * Copyright (C) 1995, 1996 Free Software Foundation, Inc.
42 *
43 * NOTE: The canonical source of this file is maintained with the GNU C
44 * Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
45 *
46 * This program is free software; you can redistribute it and/or modify it
47 * under the terms of the GNU General Public License as published by the
48 * Free Software Foundation; either version 2, or (at your option) any
49 * later version.
50 *
51 * This program is distributed in the hope that it will be useful,
52 * but WITHOUT ANY WARRANTY; without even the implied warranty of
53 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54 * GNU General Public License for more details.
55 *
56 * You should have received a copy of the GNU General Public License
57 * along with this program; if not, write to the Free Software Foundation,
58 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
59 */
60
61/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
62
63#include <sys/types.h>
64#include <stdlib.h>
65#include <string.h>
66#include <endian.h>
67
Eric Andersen3570a342000-09-25 21:45:58 +000068#include "busybox.h"
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000069//----------------------------------------------------------------------------
70//--------md5.h
71//----------------------------------------------------------------------------
72
73/* md5.h - Declaration of functions and data types used for MD5 sum
74 computing library functions.
75 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
76 NOTE: The canonical source of this file is maintained with the GNU C
77 Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
78
79 This program is free software; you can redistribute it and/or modify it
80 under the terms of the GNU General Public License as published by the
81 Free Software Foundation; either version 2, or (at your option) any
82 later version.
83
84 This program is distributed in the hope that it will be useful,
85 but WITHOUT ANY WARRANTY; without even the implied warranty of
86 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87 GNU General Public License for more details.
88
89 You should have received a copy of the GNU General Public License
90 along with this program; if not, write to the Free Software Foundation,
91 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
92
93#ifndef _MD5_H
94#define _MD5_H 1
95
96#include <stdio.h>
97
Pavel Roskin616d13b2000-07-28 19:38:27 +000098#if defined HAVE_LIMITS_H || defined _LIBC
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000099# include <limits.h>
100#endif
101
102/* The following contortions are an attempt to use the C preprocessor
103 to determine an unsigned integral type that is 32 bits wide. An
104 alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
105 doing that would require that the configure script compile and *run*
106 the resulting executable. Locally running cross-compiled executables
107 is usually not possible. */
108
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000109# include <sys/types.h>
110typedef u_int32_t md5_uint32;
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000111
112/* Structure to save state of computation between the single steps. */
113struct md5_ctx
114{
115 md5_uint32 A;
116 md5_uint32 B;
117 md5_uint32 C;
118 md5_uint32 D;
119
120 md5_uint32 total[2];
121 md5_uint32 buflen;
122 char buffer[128];
123};
124
125/*
126 * The following three functions are build up the low level used in
127 * the functions `md5_stream' and `md5_buffer'.
128 */
129
130/* Initialize structure containing state of computation.
131 (RFC 1321, 3.3: Step 3) */
132extern void md5_init_ctx __P ((struct md5_ctx *ctx));
133
134/* Starting with the result of former calls of this function (or the
135 initialization function update the context for the next LEN bytes
136 starting at BUFFER.
137 It is necessary that LEN is a multiple of 64!!! */
138extern void md5_process_block __P ((const void *buffer, size_t len,
139 struct md5_ctx *ctx));
140
141/* Starting with the result of former calls of this function (or the
142 initialization function update the context for the next LEN bytes
143 starting at BUFFER.
144 It is NOT required that LEN is a multiple of 64. */
145extern void md5_process_bytes __P ((const void *buffer, size_t len,
146 struct md5_ctx *ctx));
147
148/* Process the remaining bytes in the buffer and put result from CTX
149 in first 16 bytes following RESBUF. The result is always in little
150 endian byte order, so that a byte-wise output yields to the wanted
151 ASCII representation of the message digest.
152
153 IMPORTANT: On some systems it is required that RESBUF is correctly
154 aligned for a 32 bits value. */
155extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
156
157
158/* Put result from CTX in first 16 bytes following RESBUF. The result is
159 always in little endian byte order, so that a byte-wise output yields
160 to the wanted ASCII representation of the message digest.
161
162 IMPORTANT: On some systems it is required that RESBUF is correctly
163 aligned for a 32 bits value. */
164extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
165
166
167/* Compute MD5 message digest for bytes read from STREAM. The
168 resulting message digest number will be written into the 16 bytes
169 beginning at RESBLOCK. */
170extern int md5_stream __P ((FILE *stream, void *resblock));
171
172/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
173 result is always in little endian byte order, so that a byte-wise
174 output yields to the wanted ASCII representation of the message
175 digest. */
176extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
177
178#endif
179
180//----------------------------------------------------------------------------
181//--------end of md5.h
182//----------------------------------------------------------------------------
183
184#define SWAP(n) (n)
185
186/* This array contains the bytes used to pad the buffer to the next
187 64-byte boundary. (RFC 1321, 3.1: Step 1) */
188static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
189
190/* Initialize structure containing state of computation.
191 (RFC 1321, 3.3: Step 3) */
192void md5_init_ctx(struct md5_ctx *ctx)
193{
194 ctx->A = 0x67452301;
195 ctx->B = 0xefcdab89;
196 ctx->C = 0x98badcfe;
197 ctx->D = 0x10325476;
198
199 ctx->total[0] = ctx->total[1] = 0;
200 ctx->buflen = 0;
201}
202
203/* Put result from CTX in first 16 bytes following RESBUF. The result
204 must be in little endian byte order.
205
206 IMPORTANT: On some systems it is required that RESBUF is correctly
207 aligned for a 32 bits value. */
208void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf)
209{
210 ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
211 ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
212 ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
213 ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
214
215 return resbuf;
216}
217
218/* Process the remaining bytes in the internal buffer and the usual
219 prolog according to the standard and write the result to RESBUF.
220
221 IMPORTANT: On some systems it is required that RESBUF is correctly
222 aligned for a 32 bits value. */
223void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
224{
225 /* Take yet unprocessed bytes into account. */
226 md5_uint32 bytes = ctx->buflen;
227 size_t pad;
228
229 /* Now count remaining bytes. */
230 ctx->total[0] += bytes;
231 if (ctx->total[0] < bytes)
232 ++ctx->total[1];
233
234 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
235 memcpy(&ctx->buffer[bytes], fillbuf, pad);
236
237 /* Put the 64-bit file length in *bits* at the end of the buffer. */
238 *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
239 *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
240 SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29));
241
242 /* Process last bytes. */
243 md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
244
245 return md5_read_ctx(ctx, resbuf);
246}
247
248/* Compute MD5 message digest for bytes read from STREAM. The
249 resulting message digest number will be written into the 16 bytes
250 beginning at RESBLOCK. */
251int md5_stream(FILE *stream, void *resblock)
252{
253 /* Important: BLOCKSIZE must be a multiple of 64. */
254#define BLOCKSIZE 4096
255 struct md5_ctx ctx;
256 char buffer[BLOCKSIZE + 72];
257 size_t sum;
258
259 /* Initialize the computation context. */
260 md5_init_ctx(&ctx);
261
262 /* Iterate over full file contents. */
263 while (1) {
264 /* We read the file in blocks of BLOCKSIZE bytes. One call of the
265 computation function processes the whole buffer so that with the
266 next round of the loop another block can be read. */
267 size_t n;
268 sum = 0;
269
270 /* Read block. Take care for partial reads. */
271 do {
272 n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
273
274 sum += n;
275 }
276 while (sum < BLOCKSIZE && n != 0);
277 if (n == 0 && ferror(stream))
278 return 1;
279
280 /* If end of file is reached, end the loop. */
281 if (n == 0)
282 break;
283
284 /* Process buffer with BLOCKSIZE bytes. Note that
285 BLOCKSIZE % 64 == 0
286 */
287 md5_process_block(buffer, BLOCKSIZE, &ctx);
288 }
289
290 /* Add the last bytes if necessary. */
291 if (sum > 0)
292 md5_process_bytes(buffer, sum, &ctx);
293
294 /* Construct result in desired memory. */
295 md5_finish_ctx(&ctx, resblock);
296 return 0;
297}
298
299/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
300 result is always in little endian byte order, so that a byte-wise
301 output yields to the wanted ASCII representation of the message
302 digest. */
303void *md5_buffer(const char *buffer, size_t len, void *resblock)
304{
305 struct md5_ctx ctx;
306
307 /* Initialize the computation context. */
308 md5_init_ctx(&ctx);
309
310 /* Process whole buffer but last len % 64 bytes. */
311 md5_process_bytes(buffer, len, &ctx);
312
313 /* Put result in desired memory area. */
314 return md5_finish_ctx(&ctx, resblock);
315}
316
317void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
318{
319 /* When we already have some bits in our internal buffer concatenate
320 both inputs first. */
321 if (ctx->buflen != 0) {
322 size_t left_over = ctx->buflen;
323 size_t add = 128 - left_over > len ? len : 128 - left_over;
324
325 memcpy(&ctx->buffer[left_over], buffer, add);
326 ctx->buflen += add;
327
328 if (left_over + add > 64) {
329 md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
330 /* The regions in the following copy operation cannot overlap. */
331 memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
332 (left_over + add) & 63);
333 ctx->buflen = (left_over + add) & 63;
334 }
335
336 buffer = (const char *) buffer + add;
337 len -= add;
338 }
339
340 /* Process available complete blocks. */
341 if (len > 64) {
342 md5_process_block(buffer, len & ~63, ctx);
343 buffer = (const char *) buffer + (len & ~63);
344 len &= 63;
345 }
346
347 /* Move remaining bytes in internal buffer. */
348 if (len > 0) {
349 memcpy(ctx->buffer, buffer, len);
350 ctx->buflen = len;
351 }
352}
353
354/* These are the four functions used in the four steps of the MD5 algorithm
355 and defined in the RFC 1321. The first function is a little bit optimized
356 (as found in Colin Plumbs public domain implementation). */
357/* #define FF(b, c, d) ((b & c) | (~b & d)) */
358#define FF(b, c, d) (d ^ (b & (c ^ d)))
359#define FG(b, c, d) FF (d, b, c)
360#define FH(b, c, d) (b ^ c ^ d)
361#define FI(b, c, d) (c ^ (b | ~d))
362
363/* Process LEN bytes of BUFFER, accumulating context into CTX.
364 It is assumed that LEN % 64 == 0. */
365void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ctx)
366{
367 md5_uint32 correct_words[16];
368 const md5_uint32 *words = buffer;
369 size_t nwords = len / sizeof(md5_uint32);
370 const md5_uint32 *endp = words + nwords;
371 md5_uint32 A = ctx->A;
372 md5_uint32 B = ctx->B;
373 md5_uint32 C = ctx->C;
374 md5_uint32 D = ctx->D;
375
376 /* First increment the byte count. RFC 1321 specifies the possible
377 length of the file up to 2^64 bits. Here we only compute the
378 number of bytes. Do a double word increment. */
379 ctx->total[0] += len;
380 if (ctx->total[0] < len)
381 ++ctx->total[1];
382
383 /* Process all bytes in the buffer with 64 bytes in each round of
384 the loop. */
385 while (words < endp) {
386 md5_uint32 *cwp = correct_words;
387 md5_uint32 A_save = A;
388 md5_uint32 B_save = B;
389 md5_uint32 C_save = C;
390 md5_uint32 D_save = D;
391
392 /* First round: using the given function, the context and a constant
393 the next context is computed. Because the algorithms processing
394 unit is a 32-bit word and it is determined to work on words in
395 little endian byte order we perhaps have to change the byte order
396 before the computation. To reduce the work for the next steps
397 we store the swapped words in the array CORRECT_WORDS. */
398
399#define OP(a, b, c, d, s, T) \
400 do \
401 { \
402 a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
403 ++words; \
404 CYCLIC (a, s); \
405 a += b; \
406 } \
407 while (0)
408
409 /* It is unfortunate that C does not provide an operator for
410 cyclic rotation. Hope the C compiler is smart enough. */
411#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
412
413 /* Before we start, one word to the strange constants.
414 They are defined in RFC 1321 as
415
416 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
417 */
418
419 /* Round 1. */
420 OP(A, B, C, D, 7, 0xd76aa478);
421 OP(D, A, B, C, 12, 0xe8c7b756);
422 OP(C, D, A, B, 17, 0x242070db);
423 OP(B, C, D, A, 22, 0xc1bdceee);
424 OP(A, B, C, D, 7, 0xf57c0faf);
425 OP(D, A, B, C, 12, 0x4787c62a);
426 OP(C, D, A, B, 17, 0xa8304613);
427 OP(B, C, D, A, 22, 0xfd469501);
428 OP(A, B, C, D, 7, 0x698098d8);
429 OP(D, A, B, C, 12, 0x8b44f7af);
430 OP(C, D, A, B, 17, 0xffff5bb1);
431 OP(B, C, D, A, 22, 0x895cd7be);
432 OP(A, B, C, D, 7, 0x6b901122);
433 OP(D, A, B, C, 12, 0xfd987193);
434 OP(C, D, A, B, 17, 0xa679438e);
435 OP(B, C, D, A, 22, 0x49b40821);
436
437 /* For the second to fourth round we have the possibly swapped words
438 in CORRECT_WORDS. Redefine the macro to take an additional first
439 argument specifying the function to use. */
440#undef OP
441#define OP(f, a, b, c, d, k, s, T) \
442 do \
443 { \
444 a += f (b, c, d) + correct_words[k] + T; \
445 CYCLIC (a, s); \
446 a += b; \
447 } \
448 while (0)
449
450 /* Round 2. */
451 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
452 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
453 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
454 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
455 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
456 OP(FG, D, A, B, C, 10, 9, 0x02441453);
457 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
458 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
459 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
460 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
461 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
462 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
463 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
464 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
465 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
466 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
467
468 /* Round 3. */
469 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
470 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
471 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
472 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
473 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
474 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
475 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
476 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
477 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
478 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
479 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
480 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
481 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
482 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
483 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
484 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
485
486 /* Round 4. */
487 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
488 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
489 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
490 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
491 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
492 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
493 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
494 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
495 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
496 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
497 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
498 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
499 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
500 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
501 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
502 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
503
504 /* Add the starting values of the context. */
505 A += A_save;
506 B += B_save;
507 C += C_save;
508 D += D_save;
509 }
510
511 /* Put checksum in context given as argument. */
512 ctx->A = A;
513 ctx->B = B;
514 ctx->C = C;
515 ctx->D = D;
516}
517
518//----------------------------------------------------------------------------
519//--------end of md5.c
520//----------------------------------------------------------------------------
521
522#define ISWHITE(c) ((c) == ' ' || (c) == '\t')
523#define IN_CTYPE_DOMAIN(c) 1
524#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
525#define STREQ(a, b) (strcmp ((a), (b)) == 0)
526#define TOLOWER(Ch) tolower (Ch)
527#define OPENOPTS(BINARY) "r"
528
529/* The minimum length of a valid digest line in a file produced
530 by `md5sum FILE' and read by `md5sum -c'. This length does
531 not include any newline character at the end of a line. */
532#define MIN_DIGEST_LINE_LENGTH 35 /* 32 - message digest length
533 2 - blank and binary indicator
534 1 - minimum filename length */
535
536static int have_read_stdin; /* Nonzero if any of the files read were
537 the standard input. */
538
539static int status_only = 0; /* With -c, don't generate any output.
540 The exit code indicates success or failure */
541static int warn = 0; /* With -w, print a message to standard error warning
542 about each improperly formatted MD5 checksum line */
543
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000544static int split_3(char *s,
545 size_t s_len,
546 unsigned char **u,
547 int *binary,
548 char **w)
549{
550 size_t i = 0;
551 int escaped_filename = 0;
552
553 while (ISWHITE(s[i]))
554 ++i;
555
556 /* The line must have at least 35 (36 if the first is a backslash)
557 more characters to contain correct message digest information.
558 Ignore this line if it is too short. */
559 if (!(s_len - i >= MIN_DIGEST_LINE_LENGTH
560 || (s[i] == '\\' && s_len - i >= 1 + MIN_DIGEST_LINE_LENGTH)))
561 return FALSE;
562
563 if (s[i] == '\\') {
564 ++i;
565 escaped_filename = 1;
566 }
567 *u = (unsigned char *) &s[i];
568
569 /* The first field has to be the 32-character hexadecimal
570 representation of the message digest. If it is not followed
571 immediately by a white space it's an error. */
572 i += 32;
573 if (!ISWHITE(s[i]))
574 return FALSE;
575
576 s[i++] = '\0';
577
578 if (s[i] != ' ' && s[i] != '*')
579 return FALSE;
580 *binary = (s[i++] == '*');
581
582 /* All characters between the type indicator and end of line are
583 significant -- that includes leading and trailing white space. */
584 *w = &s[i];
585
586 if (escaped_filename) {
587 /* Translate each `\n' string in the file name to a NEWLINE,
588 and each `\\' string to a backslash. */
589
590 char *dst = &s[i];
591
592 while (i < s_len) {
593 switch (s[i]) {
594 case '\\':
595 if (i == s_len - 1) {
596 /* A valid line does not end with a backslash. */
597 return FALSE;
598 }
599 ++i;
600 switch (s[i++]) {
601 case 'n':
602 *dst++ = '\n';
603 break;
604 case '\\':
605 *dst++ = '\\';
606 break;
607 default:
608 /* Only `\' or `n' may follow a backslash. */
609 return FALSE;
610 }
611 break;
612
613 case '\0':
614 /* The file name may not contain a NUL. */
615 return FALSE;
616 break;
617
618 default:
619 *dst++ = s[i++];
620 break;
621 }
622 }
623 *dst = '\0';
624 }
625 return TRUE;
626}
627
628static int hex_digits(unsigned char const *s)
629{
630 while (*s) {
631 if (!ISXDIGIT(*s))
632 return TRUE;
633 ++s;
634 }
635 return FALSE;
636}
637
638/* An interface to md5_stream. Operate on FILENAME (it may be "-") and
639 put the result in *MD5_RESULT. Return non-zero upon failure, zero
640 to indicate success. */
641static int md5_file(const char *filename,
642 int binary,
643 unsigned char *md5_result)
644{
645 FILE *fp;
646
647 if (STREQ(filename, "-")) {
648 have_read_stdin = 1;
649 fp = stdin;
650 } else {
651 fp = fopen(filename, OPENOPTS(binary));
652 if (fp == NULL) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000653 perror_msg("%s", filename);
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000654 return FALSE;
655 }
656 }
657
658 if (md5_stream(fp, md5_result)) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000659 perror_msg("%s", filename);
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000660
661 if (fp != stdin)
662 fclose(fp);
663 return FALSE;
664 }
665
666 if (fp != stdin && fclose(fp) == EOF) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000667 perror_msg("%s", filename);
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000668 return FALSE;
669 }
670
671 return TRUE;
672}
673
674static int md5_check(const char *checkfile_name)
675{
676 FILE *checkfile_stream;
677 int n_properly_formated_lines = 0;
678 int n_mismatched_checksums = 0;
679 int n_open_or_read_failures = 0;
680 unsigned char md5buffer[16];
681 size_t line_number;
Eric Andersen70da6a62000-12-20 22:59:16 +0000682 char line[BUFSIZ];
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000683
684 if (STREQ(checkfile_name, "-")) {
685 have_read_stdin = 1;
686 checkfile_stream = stdin;
687 } else {
688 checkfile_stream = fopen(checkfile_name, "r");
689 if (checkfile_stream == NULL) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000690 perror_msg("%s", checkfile_name);
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000691 return FALSE;
692 }
693 }
694
695 line_number = 0;
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000696
697 do {
698 char *filename;
699 int binary;
700 unsigned char *md5num;
701 int line_length;
702
703 ++line_number;
704
Eric Andersen70da6a62000-12-20 22:59:16 +0000705 fgets(line, BUFSIZ-1, checkfile_stream);
706 line_length = strlen(line);
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000707
Eric Andersene111d692000-12-20 23:19:42 +0000708 if (line_length <= 0 || line==NULL)
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000709 break;
710
711 /* Ignore comment lines, which begin with a '#' character. */
712 if (line[0] == '#')
713 continue;
714
715 /* Remove any trailing newline. */
716 if (line[line_length - 1] == '\n')
717 line[--line_length] = '\0';
718
719 if (split_3(line, line_length, &md5num, &binary, &filename)
720 || !hex_digits(md5num)) {
721 if (warn) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000722 error_msg("%s: %lu: improperly formatted MD5 checksum line\n",
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000723 checkfile_name, (unsigned long) line_number);
724 }
725 } else {
726 static const char bin2hex[] = {
727 '0', '1', '2', '3',
728 '4', '5', '6', '7',
729 '8', '9', 'a', 'b',
730 'c', 'd', 'e', 'f'
731 };
732
733 ++n_properly_formated_lines;
734
735 if (md5_file(filename, binary, md5buffer)) {
736 ++n_open_or_read_failures;
737 if (!status_only) {
738 printf("%s: FAILED open or read\n", filename);
739 fflush(stdout);
740 }
741 } else {
742 size_t cnt;
743 /* Compare generated binary number with text representation
744 in check file. Ignore case of hex digits. */
745 for (cnt = 0; cnt < 16; ++cnt) {
746 if (TOLOWER(md5num[2 * cnt])
747 != bin2hex[md5buffer[cnt] >> 4]
748 || (TOLOWER(md5num[2 * cnt + 1])
749 != (bin2hex[md5buffer[cnt] & 0xf])))
750 break;
751 }
752 if (cnt != 16)
753 ++n_mismatched_checksums;
754
755 if (!status_only) {
756 printf("%s: %s\n", filename,
757 (cnt != 16 ? "FAILED" : "OK"));
758 fflush(stdout);
759 }
760 }
761 }
762 }
763
764 while (!feof(checkfile_stream) && !ferror(checkfile_stream));
765
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000766 if (ferror(checkfile_stream)) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000767 error_msg("%s: read error\n", checkfile_name); /* */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000768 return FALSE;
769 }
770
771 if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000772 perror_msg("md5sum: %s", checkfile_name);
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000773 return FALSE;
774 }
775
776 if (n_properly_formated_lines == 0) {
777 /* Warn if no tests are found. */
Mark Whitleyf57c9442000-12-07 19:56:48 +0000778 error_msg("%s: no properly formatted MD5 checksum lines found\n",
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000779 checkfile_name);
780 return FALSE;
781 } else {
782 if (!status_only) {
783 int n_computed_checkums = (n_properly_formated_lines
784 - n_open_or_read_failures);
785
786 if (n_open_or_read_failures > 0) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000787 error_msg("WARNING: %d of %d listed files could not be read\n",
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000788 n_open_or_read_failures, n_properly_formated_lines);
789 return FALSE;
790 }
791
792 if (n_mismatched_checksums > 0) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000793 error_msg("WARNING: %d of %d computed checksums did NOT match\n",
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000794 n_mismatched_checksums, n_computed_checkums);
795 return FALSE;
796 }
797 }
798 }
799
800 return ((n_properly_formated_lines > 0 && n_mismatched_checksums == 0
801 && n_open_or_read_failures == 0) ? 0 : 1);
802}
803
804int md5sum_main(int argc,
805 char **argv)
806{
807 unsigned char md5buffer[16];
808 int do_check = 0;
809 int opt;
810 char **string = NULL;
811 size_t n_strings = 0;
812 size_t err = 0;
813 int file_type_specified = 0;
814 int binary = 0;
815
816 while ((opt = getopt(argc, argv, "g:bcstw")) != -1) {
817 switch (opt) {
818 case 'g': { /* read a string */
819 if (string == NULL)
820 string = (char **) xmalloc ((argc - 1) * sizeof (char *));
821
822 if (optarg == NULL)
823 optarg = "";
824 string[n_strings++] = optarg;
825 break;
826 }
827
828 case 'b': /* read files in binary mode */
829 file_type_specified = 1;
830 binary = 1;
831 break;
832
833 case 'c': /* check MD5 sums against given list */
834 do_check = 1;
835 break;
836
837 case 's': /* don't output anything, status code shows success */
838 status_only = 1;
839 warn = 0;
840 break;
841
842 case 't': /* read files in text mode (default) */
843 file_type_specified = 1;
844 binary = 0;
845 break;
846
847 case 'w': /* warn about improperly formated MD5 checksum lines */
848 status_only = 0;
849 warn = 1;
850 break;
851
852 default:
853 usage(md5sum_usage);
854 }
855 }
856
857 if (file_type_specified && do_check) {
Eric Andersene111d692000-12-20 23:19:42 +0000858 error_msg_and_die("the -b and -t options are meaningless when verifying checksums\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000859 }
860
861 if (n_strings > 0 && do_check) {
Eric Andersene111d692000-12-20 23:19:42 +0000862 error_msg_and_die("the -g and -c options are mutually exclusive\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000863 }
864
865 if (status_only && !do_check) {
Eric Andersene111d692000-12-20 23:19:42 +0000866 error_msg_and_die("the -s option is meaningful only when verifying checksums\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000867 }
868
869 if (warn && !do_check) {
Eric Andersene111d692000-12-20 23:19:42 +0000870 error_msg_and_die("the -w option is meaningful only when verifying checksums\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000871 }
872
873 if (n_strings > 0) {
874 size_t i;
875
876 if (optind < argc) {
Eric Andersene111d692000-12-20 23:19:42 +0000877 error_msg_and_die("no files may be specified when using -g\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000878 }
879 for (i = 0; i < n_strings; ++i) {
880 size_t cnt;
881 md5_buffer (string[i], strlen (string[i]), md5buffer);
882
883 for (cnt = 0; cnt < 16; ++cnt)
884 printf ("%02x", md5buffer[cnt]);
885
886 printf (" \"%s\"\n", string[i]);
887 }
888 } else if (do_check) {
889 if (optind + 1 < argc) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000890 error_msg("only one argument may be specified when using -c\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000891 }
892
893 err = md5_check ((optind == argc) ? "-" : argv[optind]);
894 } else {
895 if (optind == argc)
896 argv[argc++] = "-";
897
898 for (; optind < argc; ++optind) {
899 int fail;
900 char *file = argv[optind];
901
902 fail = md5_file (file, binary, md5buffer);
903 err |= fail;
904 if (!fail) {
905 size_t i;
906 /* Output a leading backslash if the file name contains
907 a newline or backslash. */
908 if (strchr (file, '\n') || strchr (file, '\\'))
909 putchar ('\\');
910
911 for (i = 0; i < 16; ++i)
912 printf ("%02x", md5buffer[i]);
913
914 putchar (' ');
915 if (binary)
916 putchar ('*');
917 else
918 putchar (' ');
919
920 /* Translate each NEWLINE byte to the string, "\\n",
921 and each backslash to "\\\\". */
922 for (i = 0; i < strlen (file); ++i) {
923 switch (file[i]) {
924 case '\n':
925 fputs ("\\n", stdout);
926 break;
927
928 case '\\':
929 fputs ("\\\\", stdout);
930 break;
931
932 default:
933 putchar (file[i]);
934 break;
935 }
936 }
937 putchar ('\n');
938 }
939 }
940 }
941
942 if (fclose (stdout) == EOF) {
Eric Andersene111d692000-12-20 23:19:42 +0000943 error_msg_and_die("write error\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000944 }
945
946 if (have_read_stdin && fclose (stdin) == EOF) {
Eric Andersene111d692000-12-20 23:19:42 +0000947 error_msg_and_die("standard input\n");
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000948 }
949
Matt Kraai3e856ce2000-12-01 02:55:13 +0000950 if (err == 0)
951 return EXIT_SUCCESS;
952 else
953 return EXIT_FAILURE;
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000954}