|
|
1.1.1.3 ! root 1: /* ! 2: * md5sum.c - Generate/check MD5 Message Digests ! 3: * ! 4: * Compile and link with md5.c. If you don't have getopt() in your library ! 5: * also include getopt.c. For MSDOS you can also link with the wildcard ! 6: * initialization function (wildargs.obj for Turbo C and setargv.obj for MSC) ! 7: * so that you can use wildcards on the commandline. ! 8: * ! 9: * Make sure that you compile with -DHIGHFIRST if you are on a big-endian ! 10: * system. Here are some examples of correct MD5 sums: ! 11: * ! 12: * % echo "The meeting last week was swell." | md5sum ! 13: * 050f3905211cddf36107ffc361c23e3d ! 14: * ! 15: * % echo 'There is $1500 in the blue box.' | md5sum ! 16: * 05f8cfc03f4e58cbee731aa4a14b3f03 ! 17: * ! 18: * If you get anything else than this, then you've done something wrong. ;) ! 19: * ! 20: * Written March 1993 by Branko Lankester ! 21: * Modified June 1993 by Colin Plumb for altered md5.c. ! 22: */ ! 23: #include <stdlib.h> /* Added RKNOP 960111 */ ! 24: #include <stdio.h> ! 25: #include <string.h> ! 26: #include "md5.h" ! 27: #ifdef AMIGA /* Added RKNOP 960111 */ ! 28: #include "getopt.h" ! 29: #define getopt(a,b,c) pgp_getopt((a),(b),(c)) ! 30: #endif ! 31: ! 32: #ifdef UNIX ! 33: #define FOPRTXT "r" ! 34: #define FOPRBIN "r" ! 35: #else ! 36: #ifdef VMS ! 37: #define FOPRTXT "r","ctx=stm" ! 38: #define FOPRBIN "rb","ctx=stm" ! 39: #else ! 40: #define FOPRTXT "r" ! 41: #define FOPRBIN "rb" ! 42: #endif ! 43: #endif ! 44: ! 45: extern char *optarg; ! 46: extern int optind; ! 47: ! 48: void usage(); ! 49: void print_digest(); ! 50: int mdfile(FILE *fp, unsigned char *digest); ! 51: int do_check(FILE *chkf); ! 52: ! 53: char *progname; ! 54: int verbose = 0; ! 55: int bin_mode = 0; ! 56: ! 57: void ! 58: main(int argc, char **argv) ! 59: { ! 60: int opt, rc = 0; ! 61: int check = 0; ! 62: FILE *fp; ! 63: unsigned char digest[16]; ! 64: ! 65: progname = *argv; ! 66: while ((opt = getopt(argc, argv, "cbvp:h")) != EOF) { ! 67: switch (opt) { ! 68: case 'c': check = 1; break; ! 69: case 'v': verbose = 1; break; ! 70: case 'b': bin_mode = 1; break; ! 71: default: usage(); ! 72: } ! 73: } ! 74: argc -= optind; ! 75: argv += optind; ! 76: if (check) { ! 77: switch (argc) { ! 78: case 0: fp = stdin; break; ! 79: case 1: if ((fp = fopen(*argv, FOPRTXT)) == NULL) { ! 80: perror(*argv); ! 81: exit(2); ! 82: } ! 83: break; ! 84: default: usage(); ! 85: } ! 86: exit(do_check(fp)); ! 87: } ! 88: if (argc == 0) { ! 89: if (mdfile(stdin, digest)) { ! 90: fprintf(stderr, "%s: read error on stdin\n", progname); ! 91: exit(2); ! 92: } ! 93: print_digest(digest); ! 94: printf("\n"); ! 95: exit(0); ! 96: } ! 97: for ( ; argc > 0; --argc, ++argv) { ! 98: if (bin_mode) ! 99: fp = fopen(*argv, FOPRBIN); ! 100: else ! 101: fp = fopen(*argv, FOPRTXT); ! 102: if (fp == NULL) { ! 103: perror(*argv); ! 104: rc = 2; ! 105: continue; ! 106: } ! 107: if (mdfile(fp, digest)) { ! 108: fprintf(stderr, "%s: error reading %s\n", progname, *argv); ! 109: rc = 2; ! 110: } else { ! 111: print_digest(digest); ! 112: printf(" %c%s\n", bin_mode ? '*' : ' ', *argv); ! 113: } ! 114: fclose(fp); ! 115: } ! 116: exit(rc); ! 117: } ! 118: ! 119: void ! 120: usage() ! 121: { ! 122: fprintf(stderr, "usage: md5sum [-bv] [-c [file]] | [file...]\n"); ! 123: fprintf(stderr, "Generates or checks MD5 Message Digests\n"); ! 124: fprintf(stderr, " -c check message digests (default is generate)\n"); ! 125: fprintf(stderr, " -v verbose, print file names when checking\n"); ! 126: fprintf(stderr, " -b read files in binary mode\n"); ! 127: fprintf(stderr, "The input for -c should be the list of message digests and file names\n"); ! 128: fprintf(stderr, "that is printed on stdout by this program when it generates digests.\n"); ! 129: exit(2); ! 130: } ! 131: ! 132: int ! 133: mdfile(FILE *fp, unsigned char *digest) ! 134: { ! 135: unsigned char buf[1024]; ! 136: MD5_CTX ctx; ! 137: int n; ! 138: ! 139: MD5Init(&ctx); ! 140: while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) ! 141: MD5Update(&ctx, buf, n); ! 142: MD5Final(digest, &ctx); ! 143: if (ferror(fp)) ! 144: return -1; ! 145: return 0; ! 146: } ! 147: ! 148: void ! 149: print_digest(unsigned char *p) ! 150: { ! 151: int i; ! 152: ! 153: for (i = 0; i < 16; ++i) ! 154: printf("%02x", *p++); ! 155: } ! 156: ! 157: int ! 158: hex_digit(int c) ! 159: { ! 160: if (c >= '0' && c <= '9') ! 161: return c - '0'; ! 162: if (c >= 'a' && c <= 'f') ! 163: return c - 'a' + 10; ! 164: return -1; ! 165: } ! 166: ! 167: int ! 168: get_md5_line(FILE *fp, unsigned char *digest, char *file) ! 169: { ! 170: char buf[1024]; ! 171: int i, d1, d2, rc; ! 172: char *p = buf; ! 173: ! 174: if (fgets(buf, sizeof(buf), fp) == NULL) ! 175: return -1; ! 176: ! 177: for (i = 0; i < 16; ++i) { ! 178: if ((d1 = hex_digit(*p++)) == -1) ! 179: return 0; ! 180: if ((d2 = hex_digit(*p++)) == -1) ! 181: return 0; ! 182: *digest++ = d1*16 + d2; ! 183: } ! 184: if (*p++ != ' ') ! 185: return 0; ! 186: /* ! 187: * next char is an attribute char, space means text file ! 188: * if it's a '*' the file should be checked in binary mode. ! 189: */ ! 190: if (*p == ' ') ! 191: rc = 1; ! 192: else if (*p == '*') ! 193: rc = 2; ! 194: else { ! 195: fprintf(stderr, "%s: unrecognized line: %s", progname, buf); ! 196: return 0; ! 197: } ! 198: ++p; ! 199: i = strlen(p); ! 200: if (i < 2 || i > 255) ! 201: return 0; ! 202: p[i-1] = '\0'; ! 203: strcpy(file, p); ! 204: return rc; ! 205: } ! 206: ! 207: int ! 208: do_check(FILE *chkf) ! 209: { ! 210: int rc, ex = 0, failed = 0, checked = 0; ! 211: unsigned char chk_digest[16], file_digest[16]; ! 212: char filename[256]; ! 213: FILE *fp; ! 214: int flen = 14; ! 215: ! 216: while ((rc = get_md5_line(chkf, chk_digest, filename)) >= 0) { ! 217: if (rc == 0) /* not an md5 line */ ! 218: continue; ! 219: if (verbose) { ! 220: if (strlen(filename) > flen) ! 221: flen = strlen(filename); ! 222: fprintf(stderr, "%-*s ", flen, filename); ! 223: } ! 224: if (bin_mode || rc == 2) ! 225: fp = fopen(filename, FOPRBIN); ! 226: else ! 227: fp = fopen(filename, FOPRTXT); ! 228: if (fp == NULL) { ! 229: fprintf(stderr, "%s: can't open %s\n", progname, filename); ! 230: ex = 2; ! 231: continue; ! 232: } ! 233: if (mdfile(fp, file_digest)) { ! 234: fprintf(stderr, "%s: error reading %s\n", progname, filename); ! 235: ex = 2; ! 236: fclose(fp); ! 237: continue; ! 238: } ! 239: fclose(fp); ! 240: if (memcmp(chk_digest, file_digest, 16) != 0) { ! 241: if (verbose) ! 242: fprintf(stderr, "FAILED\n"); ! 243: else ! 244: fprintf(stderr, "%s: MD5 check failed for '%s'\n", progname, filename); ! 245: ++failed; ! 246: } else if (verbose) ! 247: fprintf(stderr, "OK\n"); ! 248: ++checked; ! 249: } ! 250: if (verbose && failed) ! 251: fprintf(stderr, "%s: %d of %d file(s) failed MD5 check\n", progname, failed, checked); ! 252: if (!checked) { ! 253: fprintf(stderr, "%s: no files checked\n", progname); ! 254: return 3; ! 255: } ! 256: if (!ex && failed) ! 257: ex = 1; ! 258: return ex; ! 259: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.