# HG changeset patch # User Pascal Bellard # Date 1333451564 -7200 # Node ID 188ed036ce843f6b8fd7c28f4ef95c51ab130885 # Parent 297bc4cc89841e1927f41905303ddfbf79fec08e syslinux/md5sum.c32: add a status line diff -r 297bc4cc8984 -r 188ed036ce84 syslinux/stuff/extra/md5sum.c --- a/syslinux/stuff/extra/md5sum.c Mon Apr 02 22:48:21 2012 +0200 +++ b/syslinux/stuff/extra/md5sum.c Tue Apr 03 13:12:44 2012 +0200 @@ -1,12 +1,19 @@ -/* vi: set sw=4 ts=4: */ /* - * Based on busybox code + * Based on busybox code. * - * Utility routines. + * Compute MD5 checksum of strings according to the + * definition of MD5 in RFC 1321 from April 1992. * + * Written by Ulrich Drepper , 1995. + * + * Copyright (C) 1995-1999 Free Software Foundation, Inc. + * Copyright (C) 2001 Manuel Novoa III + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen * Copyright (C) 2010 Denys Vlasenko + * Copyright (C) 2012 Pascal Bellard * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. + * Licensed under GPLv2 or later */ #include @@ -18,16 +25,22 @@ #include #define ALIGN1 -const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; + +static uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ +static uint64_t total64; /* must be directly before hash[] */ +static uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */ /* Emit a string of hex representation of bytes */ -char* bin2hex(char *p, const char *cp, int count) +static char* bin2hex(char *p) { + static const char bb_hexdigits_upcase[] ALIGN1 = "0123456789abcdef"; + int count = 16; + const char *cp = (const char *) hash; while (count) { unsigned char c = *cp++; /* put lowercase hex digits */ - *p++ = 0x20 | bb_hexdigits_upcase[c >> 4]; - *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf]; + *p++ = bb_hexdigits_upcase[c >> 4]; + *p++ = bb_hexdigits_upcase[c & 0xf]; count--; } return p; @@ -39,30 +52,24 @@ return (x << n) | (x >> (32 - n)); } -typedef struct md5_ctx_t { - uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ - uint64_t total64; /* must be directly before hash[] */ - uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */ -} md5_ctx_t; - -static void md5_process_block64(md5_ctx_t *ctx); +static void md5_process_block64(void); /* Feed data through a temporary buffer. * The internal buffer remembers previous data until it has 64 * bytes worth to pass on. */ -static void common64_hash(md5_ctx_t *ctx, const void *buffer, size_t len) +static void common64_hash(const void *buffer, size_t len) { - unsigned bufpos = ctx->total64 & 63; + unsigned bufpos = total64 & 63; - ctx->total64 += len; + total64 += len; while (1) { unsigned remaining = 64 - bufpos; if (remaining > len) remaining = len; /* Copy data into aligned buffer */ - memcpy(ctx->wbuffer + bufpos, buffer, remaining); + memcpy(wbuffer + bufpos, buffer, remaining); len -= remaining; buffer = (const char *)buffer + remaining; bufpos += remaining; @@ -71,51 +78,36 @@ if (bufpos != 0) break; /* Buffer is filled up, process it */ - md5_process_block64(ctx); + md5_process_block64(); /*bufpos = 0; - already is */ } } /* Process the remaining bytes in the buffer */ -static void common64_end(md5_ctx_t *ctx) +static void common64_end(void) { - unsigned bufpos = ctx->total64 & 63; + unsigned bufpos = total64 & 63; /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ - ctx->wbuffer[bufpos++] = 0x80; + wbuffer[bufpos++] = 0x80; /* This loop iterates either once or twice, no more, no less */ while (1) { unsigned remaining = 64 - bufpos; - memset(ctx->wbuffer + bufpos, 0, remaining); + memset(wbuffer + bufpos, 0, remaining); /* Do we have enough space for the length count? */ if (remaining >= 8) { /* Store the 64-bit counter of bits in the buffer */ - uint64_t t = ctx->total64 << 3; + uint64_t t = total64 << 3; /* wbuffer is suitably aligned for this */ - *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; + *(uint64_t *) (&wbuffer[64 - 8]) = t; } - md5_process_block64(ctx); + md5_process_block64(); if (remaining >= 8) break; bufpos = 0; } } - -/* - * Compute MD5 checksum of strings according to the - * definition of MD5 in RFC 1321 from April 1992. - * - * Written by Ulrich Drepper , 1995. - * - * Copyright (C) 1995-1999 Free Software Foundation, Inc. - * Copyright (C) 2001 Manuel Novoa III - * Copyright (C) 2003 Glenn L. McGrath - * Copyright (C) 2003 Erik Andersen - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ - /* These are the four functions used in the four steps of the MD5 algorithm * and defined in the RFC 1321. The first function is a little bit optimized * (as found in Colin Plumbs public domain implementation). @@ -131,7 +123,7 @@ #define FI(b, c, d) (c ^ (b | ~d)) /* Hash a single block, 64 bytes long and 4-byte aligned */ -static void md5_process_block64(md5_ctx_t *ctx) +static void md5_process_block64(void) { /* Before we start, one word to the strange constants. They are defined in RFC 1321 as @@ -165,11 +157,11 @@ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ }; - uint32_t *words = (void*) ctx->wbuffer; - uint32_t A = ctx->hash[0]; - uint32_t B = ctx->hash[1]; - uint32_t C = ctx->hash[2]; - uint32_t D = ctx->hash[3]; + uint32_t *words = (void*) wbuffer; + uint32_t A = hash[0]; + uint32_t B = hash[1]; + uint32_t C = hash[2]; + uint32_t D = hash[3]; static const char S_array[] ALIGN1 = { 7, 12, 17, 22, @@ -214,10 +206,10 @@ B = temp; } /* Add checksum to the starting values */ - ctx->hash[0] += A; - ctx->hash[1] += B; - ctx->hash[2] += C; - ctx->hash[3] += D; + hash[0] += A; + hash[1] += B; + hash[2] += C; + hash[3] += D; } #undef FF @@ -228,34 +220,24 @@ /* Initialize structure containing state of computation. * (RFC 1321, 3.3: Step 3) */ -void md5_begin(md5_ctx_t *ctx) +static void md5_begin(void) { - ctx->hash[0] = 0x67452301; - ctx->hash[1] = 0xefcdab89; - ctx->hash[2] = 0x98badcfe; - ctx->hash[3] = 0x10325476; - ctx->total64 = 0; + hash[0] = 0x67452301; + hash[1] = 0xefcdab89; + hash[2] = 0x98badcfe; + hash[3] = 0x10325476; + total64 = 0; } /* Used also for sha1 and sha256 */ -void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) -{ - common64_hash(ctx, buffer, len); -} +#define md5_hash common64_hash /* Process the remaining bytes in the buffer and put result from CTX * in first 16 bytes following RESBUF. The result is always in little * endian byte order, so that a byte-wise output yields to the wanted * ASCII representation of the message digest. */ -void md5_end(md5_ctx_t *ctx, void *resbuf) -{ - /* MD5 stores total in LE, need to swap on BE arches: */ - common64_end(ctx); - - /* The MD5 result is in little endian byte order */ - memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4); -} +#define md5_end common64_end /* * Copyright (C) 2003 Glenn L. McGrath @@ -264,77 +246,63 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -/* This might be useful elsewhere */ -static unsigned char *hash_bin_to_hex(unsigned char *hash_value, - unsigned hash_length) -{ - static char hex_value[16*2+1]; - bin2hex(hex_value, (char*)hash_value, hash_length); - return (unsigned char *)hex_value; -} - -static char *unrock(const char *name) +static char *unrockridge(const char *name) { static char buffer[256]; - char *out = buffer; - int i, j; - for (i = 0, j = 8; *name && (buffer + 255) > (out + i); name++) { - if (*name == '/') { - out[i++] = *name; - out += i; - i = 0; j = 8; + int i = 0, j = 8; + while (*name && i < 255) { + char c = *name++; + //if (c == '\\') c = '/'; + if (c == '.') { + for (j = i; --j >= 0 && buffer[j] != '/';) + if (buffer[j] == '.') buffer[j] = '_'; + if (i - j > 9) i = j + 9; + j = i + 4; } - else if (*name == '.') { - if (i > 8) i = 8; - for (j = 0; j < i; j++) - if (out[j] == '.') out[j] = '_'; - out[i++] = *name; - j = i + 3; - } + else if (c == '/') j = i + 9; else if (i >= j) continue; - else if ((*name >= 'A' && *name <= 'Z') || *name == '_' || - (*name >= '0' && *name <= '9')) - out[i++] = *name; - else if (*name >= 'a' && *name <= 'z') - out[i++] = *name + 'A' - 'a'; - else out[i++] = '_'; + else if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + else if ((c < 'A' || c > 'Z') && (c < '0' || c > '9')) c = '_'; + buffer[i++] = c; } - out[i] = 0; + buffer[i] = 0; return buffer; } static uint8_t *hash_file(const char *filename) { int src_fd, count; - md5_ctx_t context; - uint8_t *hash_value, in_buf[4096]; + uint8_t in_buf[4096]; + static uint8_t hash_value[16*2+1]; src_fd = open(filename, O_RDONLY); if (src_fd < 0) { - src_fd = open(unrock(filename), O_RDONLY); + src_fd = open(unrockridge(filename), O_RDONLY); } if (src_fd < 0) { return NULL; } - md5_begin(&context); + md5_begin(); while ((count = read(src_fd, in_buf, 4096)) > 0) { - md5_hash(&context, in_buf, count); - } - hash_value = NULL; - if (count == 0) { - md5_end(&context, in_buf); - hash_value = hash_bin_to_hex(in_buf, 16); + md5_hash(in_buf, count); } close(src_fd); + + if (count) + return NULL; + + md5_end(); + bin2hex((char *)hash_value); return hash_value; } int main(int argc, char **argv) { - int return_value = EXIT_SUCCESS; + int files = 0, tested = 0, good = 0; + static char clear_eol[] = " "; (void) argc; /* -c implied */ @@ -342,16 +310,15 @@ do { FILE *fp; - char *line, buffer[256]; + char eol, *line, buffer[256]; fp = fopen(*argv,"r"); if (fp == NULL) - fp = fopen(unrock(*argv),"r"); + fp = fopen(unrockridge(*argv),"r"); while ((line = fgets(buffer,256,fp)) != NULL) { uint8_t *hash_value; char *filename_ptr, *status; int len = strlen(line); -#define BLANK " " if (line[0] < '0') continue; @@ -363,7 +330,6 @@ filename_ptr = strstr(line, " *"); } if (filename_ptr == NULL) { - return_value = EXIT_FAILURE; continue; } *filename_ptr = '\0'; @@ -371,20 +337,24 @@ if (filename_ptr[1] == '/') filename_ptr++; - status = "NOT CHECKED" BLANK "\n"; + files++; + status = "NOT CHECKED"; + eol = '\n'; hash_value = hash_file(filename_ptr); if (hash_value) { - status = "OK" BLANK; - if (strcmp((char*)hash_value, line)) { - return_value = EXIT_FAILURE; - status = "FAILED" BLANK "\n"; + tested++; + status = "BROKEN"; + if (!strcmp((char*)hash_value, line)) { + good++; + status = "OK"; + eol = ' '; } } - printf("\r%s: %s", filename_ptr, status); + printf("\r%s: %s%s%c", filename_ptr, status, clear_eol, eol); } fclose(fp); } while (*++argv); - printf("\r" BLANK "\r"); + printf("\r%d files OK, %d broken, %d not checked.%s\n", + good, tested - good, files - tested, clear_eol); +} - return return_value; -}