Changes for kernel and Busybox
[tomato.git] / release / src / router / busybox / coreutils / md5_sha1_sum.c
blob2cb6dd43c18a7aca5d5e62a7e09e4c2bc81e63bb
1 /* vi: set sw=4 ts=4: */
2 /*
3 * Copyright (C) 2003 Glenn L. McGrath
4 * Copyright (C) 2003-2004 Erik Andersen
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */
9 //usage:#define md5sum_trivial_usage
10 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..."
11 //usage:#define md5sum_full_usage "\n\n"
12 //usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " MD5 checksums"
13 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n"
14 //usage: "\n -c Check sums against list in FILEs"
15 //usage: "\n -s Don't output anything, status code shows success"
16 //usage: "\n -w Warn about improperly formatted checksum lines"
17 //usage: )
18 //usage:
19 //usage:#define md5sum_example_usage
20 //usage: "$ md5sum < busybox\n"
21 //usage: "6fd11e98b98a58f64ff3398d7b324003\n"
22 //usage: "$ md5sum busybox\n"
23 //usage: "6fd11e98b98a58f64ff3398d7b324003 busybox\n"
24 //usage: "$ md5sum -c -\n"
25 //usage: "6fd11e98b98a58f64ff3398d7b324003 busybox\n"
26 //usage: "busybox: OK\n"
27 //usage: "^D\n"
28 //usage:
29 //usage:#define sha1sum_trivial_usage
30 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..."
31 //usage:#define sha1sum_full_usage "\n\n"
32 //usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums"
33 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n"
34 //usage: "\n -c Check sums against list in FILEs"
35 //usage: "\n -s Don't output anything, status code shows success"
36 //usage: "\n -w Warn about improperly formatted checksum lines"
37 //usage: )
38 //usage:
39 //usage:#define sha256sum_trivial_usage
40 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..."
41 //usage:#define sha256sum_full_usage "\n\n"
42 //usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA256 checksums"
43 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n"
44 //usage: "\n -c Check sums against list in FILEs"
45 //usage: "\n -s Don't output anything, status code shows success"
46 //usage: "\n -w Warn about improperly formatted checksum lines"
47 //usage: )
48 //usage:
49 //usage:#define sha512sum_trivial_usage
50 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..."
51 //usage:#define sha512sum_full_usage "\n\n"
52 //usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA512 checksums"
53 //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n"
54 //usage: "\n -c Check sums against list in FILEs"
55 //usage: "\n -s Don't output anything, status code shows success"
56 //usage: "\n -w Warn about improperly formatted checksum lines"
57 //usage: )
59 #include "libbb.h"
61 /* This is a NOEXEC applet. Be very careful! */
63 enum {
64 /* 4th letter of applet_name is... */
65 HASH_MD5 = 's', /* "md5>s<um" */
66 HASH_SHA1 = '1',
67 HASH_SHA256 = '2',
68 HASH_SHA512 = '5',
71 #define FLAG_SILENT 1
72 #define FLAG_CHECK 2
73 #define FLAG_WARN 4
75 /* This might be useful elsewhere */
76 static unsigned char *hash_bin_to_hex(unsigned char *hash_value,
77 unsigned hash_length)
79 /* xzalloc zero-terminates */
80 char *hex_value = xzalloc((hash_length * 2) + 1);
81 bin2hex(hex_value, (char*)hash_value, hash_length);
82 return (unsigned char *)hex_value;
85 static uint8_t *hash_file(const char *filename)
87 int src_fd, hash_len, count;
88 union _ctx_ {
89 sha512_ctx_t sha512;
90 sha256_ctx_t sha256;
91 sha1_ctx_t sha1;
92 md5_ctx_t md5;
93 } context;
94 uint8_t *hash_value;
95 void FAST_FUNC (*update)(void*, const void*, size_t);
96 void FAST_FUNC (*final)(void*, void*);
97 char hash_algo;
99 src_fd = open_or_warn_stdin(filename);
100 if (src_fd < 0) {
101 return NULL;
104 hash_algo = applet_name[3];
106 /* figure specific hash algorithms */
107 if (ENABLE_MD5SUM && hash_algo == HASH_MD5) {
108 md5_begin(&context.md5);
109 update = (void*)md5_hash;
110 final = (void*)md5_end;
111 hash_len = 16;
112 } else if (ENABLE_SHA1SUM && hash_algo == HASH_SHA1) {
113 sha1_begin(&context.sha1);
114 update = (void*)sha1_hash;
115 final = (void*)sha1_end;
116 hash_len = 20;
117 } else if (ENABLE_SHA256SUM && hash_algo == HASH_SHA256) {
118 sha256_begin(&context.sha256);
119 update = (void*)sha256_hash;
120 final = (void*)sha256_end;
121 hash_len = 32;
122 } else if (ENABLE_SHA512SUM && hash_algo == HASH_SHA512) {
123 sha512_begin(&context.sha512);
124 update = (void*)sha512_hash;
125 final = (void*)sha512_end;
126 hash_len = 64;
127 } else {
128 xfunc_die(); /* can't reach this */
132 RESERVE_CONFIG_UBUFFER(in_buf, 4096);
133 while ((count = safe_read(src_fd, in_buf, 4096)) > 0) {
134 update(&context, in_buf, count);
136 hash_value = NULL;
137 if (count == 0) {
138 final(&context, in_buf);
139 hash_value = hash_bin_to_hex(in_buf, hash_len);
141 RELEASE_CONFIG_BUFFER(in_buf);
144 if (src_fd != STDIN_FILENO) {
145 close(src_fd);
148 return hash_value;
151 int md5_sha1_sum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
152 int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv)
154 int return_value = EXIT_SUCCESS;
155 unsigned flags;
157 if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK) {
158 /* -b "binary", -t "text" are ignored (shaNNNsum compat) */
159 flags = getopt32(argv, "scwbt");
160 argv += optind;
161 //argc -= optind;
162 } else {
163 argv += 1;
164 //argc -= 1;
166 if (!*argv)
167 *--argv = (char*)"-";
169 if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && !(flags & FLAG_CHECK)) {
170 if (flags & FLAG_SILENT) {
171 bb_error_msg_and_die("-%c is meaningful only with -c", 's');
173 if (flags & FLAG_WARN) {
174 bb_error_msg_and_die("-%c is meaningful only with -c", 'w');
178 do {
179 if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && (flags & FLAG_CHECK)) {
180 FILE *pre_computed_stream;
181 char *line;
182 int count_total = 0;
183 int count_failed = 0;
185 pre_computed_stream = xfopen_stdin(*argv);
187 while ((line = xmalloc_fgetline(pre_computed_stream)) != NULL) {
188 uint8_t *hash_value;
189 char *filename_ptr;
191 count_total++;
192 filename_ptr = strstr(line, " ");
193 /* handle format for binary checksums */
194 if (filename_ptr == NULL) {
195 filename_ptr = strstr(line, " *");
197 if (filename_ptr == NULL) {
198 if (flags & FLAG_WARN) {
199 bb_error_msg("invalid format");
201 count_failed++;
202 return_value = EXIT_FAILURE;
203 free(line);
204 continue;
206 *filename_ptr = '\0';
207 filename_ptr += 2;
209 hash_value = hash_file(filename_ptr);
211 if (hash_value && (strcmp((char*)hash_value, line) == 0)) {
212 if (!(flags & FLAG_SILENT))
213 printf("%s: OK\n", filename_ptr);
214 } else {
215 if (!(flags & FLAG_SILENT))
216 printf("%s: FAILED\n", filename_ptr);
217 count_failed++;
218 return_value = EXIT_FAILURE;
220 /* possible free(NULL) */
221 free(hash_value);
222 free(line);
224 if (count_failed && !(flags & FLAG_SILENT)) {
225 bb_error_msg("WARNING: %d of %d computed checksums did NOT match",
226 count_failed, count_total);
228 fclose_if_not_stdin(pre_computed_stream);
229 } else {
230 uint8_t *hash_value = hash_file(*argv);
231 if (hash_value == NULL) {
232 return_value = EXIT_FAILURE;
233 } else {
234 printf("%s %s\n", hash_value, *argv);
235 free(hash_value);
238 } while (*++argv);
240 return return_value;