Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2003 Glenn L. McGrath |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 4 | * Copyright (C) 2003-2004 Erik Andersen |
| 5 | * |
Bernhard Reutner-Fischer | 47ea7b7 | 2005-10-27 14:43:27 +0000 | [diff] [blame] | 6 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 7 | */ |
| 8 | |
Denis Vlasenko | b6adbf1 | 2007-05-26 19:00:18 +0000 | [diff] [blame] | 9 | #include "libbb.h" |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 10 | |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 11 | typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 12 | |
| 13 | #define FLAG_SILENT 1 |
| 14 | #define FLAG_CHECK 2 |
| 15 | #define FLAG_WARN 4 |
| 16 | |
Eric Andersen | aff114c | 2004-04-14 17:51:38 +0000 | [diff] [blame] | 17 | /* This might be useful elsewhere */ |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 18 | static unsigned char *hash_bin_to_hex(unsigned char *hash_value, |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 19 | unsigned hash_length) |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 20 | { |
Denis Vlasenko | 3a34d0c | 2007-01-12 22:10:34 +0000 | [diff] [blame] | 21 | /* xzalloc zero-terminates */ |
| 22 | char *hex_value = xzalloc((hash_length * 2) + 1); |
| 23 | bin2hex(hex_value, (char*)hash_value, hash_length); |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 24 | return hex_value; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 25 | } |
| 26 | |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 27 | static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo) |
Glenn L McGrath | 931ae9d | 2003-11-18 23:56:41 +0000 | [diff] [blame] | 28 | { |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 29 | int src_fd, hash_len, count; |
| 30 | union _ctx_ { |
| 31 | sha1_ctx_t sha1; |
| 32 | md5_ctx_t md5; |
| 33 | } context; |
| 34 | uint8_t *hash_value = NULL; |
| 35 | RESERVE_CONFIG_UBUFFER(in_buf, 4096); |
| 36 | void (*update)(const void*, size_t, void*); |
| 37 | void (*final)(void*, void*); |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 38 | |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 39 | src_fd = open_or_warn_stdin(filename); |
| 40 | if (src_fd < 0) { |
| 41 | return NULL; |
Glenn L McGrath | 931ae9d | 2003-11-18 23:56:41 +0000 | [diff] [blame] | 42 | } |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 43 | |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 44 | /* figure specific hash algorithims */ |
| 45 | if (ENABLE_MD5SUM && hash_algo==HASH_MD5) { |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 46 | md5_begin(&context.md5); |
| 47 | update = (void (*)(const void*, size_t, void*))md5_hash; |
| 48 | final = (void (*)(void*, void*))md5_end; |
| 49 | hash_len = 16; |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 50 | } else if (ENABLE_SHA1SUM && hash_algo==HASH_SHA1) { |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 51 | sha1_begin(&context.sha1); |
| 52 | update = (void (*)(const void*, size_t, void*))sha1_hash; |
| 53 | final = (void (*)(void*, void*))sha1_end; |
| 54 | hash_len = 20; |
| 55 | } else { |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 56 | bb_error_msg_and_die("algorithm not supported"); |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 57 | } |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 58 | |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 59 | while (0 < (count = safe_read(src_fd, in_buf, 4096))) { |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 60 | update(in_buf, count, &context); |
| 61 | } |
| 62 | |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 63 | if (count == 0) { |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 64 | final(in_buf, &context); |
| 65 | hash_value = hash_bin_to_hex(in_buf, hash_len); |
| 66 | } |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 67 | |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 68 | RELEASE_CONFIG_BUFFER(in_buf); |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 69 | |
| 70 | if (src_fd != STDIN_FILENO) { |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 71 | close(src_fd); |
| 72 | } |
Bernhard Reutner-Fischer | eba32f4 | 2006-05-10 07:59:32 +0000 | [diff] [blame] | 73 | |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 74 | return hash_value; |
Glenn L McGrath | 931ae9d | 2003-11-18 23:56:41 +0000 | [diff] [blame] | 75 | } |
| 76 | |
Denis Vlasenko | 9b49a5e | 2007-10-11 10:05:36 +0000 | [diff] [blame] | 77 | int md5_sha1_sum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 78 | int md5_sha1_sum_main(int argc ATTRIBUTE_UNUSED, char **argv) |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 79 | { |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 80 | int return_value = EXIT_SUCCESS; |
Glenn L McGrath | 931ae9d | 2003-11-18 23:56:41 +0000 | [diff] [blame] | 81 | uint8_t *hash_value; |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 82 | unsigned flags; |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 83 | hash_algo_t hash_algo = ENABLE_MD5SUM |
Denis Vlasenko | d166f83 | 2007-07-05 00:12:55 +0000 | [diff] [blame] | 84 | ? (ENABLE_SHA1SUM ? (applet_name[0] == 'm' ? HASH_MD5 : HASH_SHA1) : HASH_MD5) |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 85 | : HASH_SHA1; |
Glenn L McGrath | de3ea9f | 2003-11-18 19:35:06 +0000 | [diff] [blame] | 86 | |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 87 | if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK) |
Denis Vlasenko | fe7cd64 | 2007-08-18 15:32:12 +0000 | [diff] [blame] | 88 | flags = getopt32(argv, "scw"); |
Rob Landley | 7cc6b69 | 2006-07-26 16:10:39 +0000 | [diff] [blame] | 89 | else optind = 1; |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 90 | argv += optind; |
| 91 | //argc -= optind; |
| 92 | if (!*argv) |
| 93 | *--argv = (char*)"-"; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 94 | |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 95 | if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && !(flags & FLAG_CHECK)) { |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 96 | if (flags & FLAG_SILENT) { |
| 97 | bb_error_msg_and_die |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 98 | ("-%c is meaningful only when verifying checksums", 's'); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 99 | } else if (flags & FLAG_WARN) { |
| 100 | bb_error_msg_and_die |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 101 | ("-%c is meaningful only when verifying checksums", 'w'); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 102 | } |
| 103 | } |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 104 | |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 105 | if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && (flags & FLAG_CHECK)) { |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 106 | FILE *pre_computed_stream; |
| 107 | int count_total = 0; |
| 108 | int count_failed = 0; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 109 | char *line; |
| 110 | |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 111 | if (argv[1]) { |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 112 | bb_error_msg_and_die |
| 113 | ("only one argument may be specified when using -c"); |
| 114 | } |
| 115 | |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 116 | pre_computed_stream = xfopen_stdin(argv[0]); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 117 | |
Denis Vlasenko | 8ee649a | 2008-03-26 20:04:27 +0000 | [diff] [blame] | 118 | while ((line = xmalloc_fgetline(pre_computed_stream)) != NULL) { |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 119 | char *filename_ptr; |
| 120 | |
| 121 | count_total++; |
| 122 | filename_ptr = strstr(line, " "); |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 123 | /* handle format for binary checksums */ |
| 124 | if (filename_ptr == NULL) { |
| 125 | filename_ptr = strstr(line, " *"); |
| 126 | } |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 127 | if (filename_ptr == NULL) { |
| 128 | if (flags & FLAG_WARN) { |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 129 | bb_error_msg("invalid format"); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 130 | } |
Bernhard Reutner-Fischer | 47ea7b7 | 2005-10-27 14:43:27 +0000 | [diff] [blame] | 131 | count_failed++; |
| 132 | return_value = EXIT_FAILURE; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 133 | free(line); |
| 134 | continue; |
| 135 | } |
| 136 | *filename_ptr = '\0'; |
| 137 | filename_ptr += 2; |
| 138 | |
| 139 | hash_value = hash_file(filename_ptr, hash_algo); |
| 140 | |
Mike Frysinger | 9e16457 | 2005-06-24 21:37:59 +0000 | [diff] [blame] | 141 | if (hash_value && (strcmp((char*)hash_value, line) == 0)) { |
Glenn L McGrath | 5c069aa | 2003-11-20 05:58:26 +0000 | [diff] [blame] | 142 | if (!(flags & FLAG_SILENT)) |
| 143 | printf("%s: OK\n", filename_ptr); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 144 | } else { |
Glenn L McGrath | 5c069aa | 2003-11-20 05:58:26 +0000 | [diff] [blame] | 145 | if (!(flags & FLAG_SILENT)) |
| 146 | printf("%s: FAILED\n", filename_ptr); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 147 | count_failed++; |
Glenn L McGrath | 6db8c22 | 2004-02-22 02:58:57 +0000 | [diff] [blame] | 148 | return_value = EXIT_FAILURE; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 149 | } |
| 150 | /* possible free(NULL) */ |
| 151 | free(hash_value); |
| 152 | free(line); |
| 153 | } |
Glenn L McGrath | 5c069aa | 2003-11-20 05:58:26 +0000 | [diff] [blame] | 154 | if (count_failed && !(flags & FLAG_SILENT)) { |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 155 | bb_error_msg("WARNING: %d of %d computed checksums did NOT match", |
| 156 | count_failed, count_total); |
| 157 | } |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 158 | /* |
Denis Vlasenko | ddec5af | 2006-10-26 23:25:17 +0000 | [diff] [blame] | 159 | if (fclose_if_not_stdin(pre_computed_stream) == EOF) { |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 160 | bb_perror_msg_and_die("cannot close file %s", file_ptr); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 161 | } |
Denis Vlasenko | 1462192 | 2006-11-23 15:59:12 +0000 | [diff] [blame] | 162 | */ |
Rob Landley | 5cf7c2d | 2006-02-21 06:44:43 +0000 | [diff] [blame] | 163 | } else { |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 164 | do { |
| 165 | hash_value = hash_file(*argv, hash_algo); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 166 | if (hash_value == NULL) { |
Glenn L McGrath | 6db8c22 | 2004-02-22 02:58:57 +0000 | [diff] [blame] | 167 | return_value = EXIT_FAILURE; |
Glenn L McGrath | de3ea9f | 2003-11-18 19:35:06 +0000 | [diff] [blame] | 168 | } else { |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 169 | printf("%s %s\n", hash_value, *argv); |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 170 | free(hash_value); |
| 171 | } |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 172 | } while (*++argv); |
Glenn L McGrath | de3ea9f | 2003-11-18 19:35:06 +0000 | [diff] [blame] | 173 | } |
Denis Vlasenko | 5241766 | 2006-09-28 00:29:00 +0000 | [diff] [blame] | 174 | return return_value; |
Glenn L McGrath | d2a897a | 2003-11-10 04:33:55 +0000 | [diff] [blame] | 175 | } |