diff options
Diffstat (limited to 'coreutils/md5_sha1_sum.c')
-rw-r--r-- | coreutils/md5_sha1_sum.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c new file mode 100644 index 000000000..e8d3a1509 --- /dev/null +++ b/coreutils/md5_sha1_sum.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Copyright (C) 2003 Glenn L. McGrath | ||
4 | * Copyright (C) 2003-2004 Erik Andersen | ||
5 | * | ||
6 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
7 | */ | ||
8 | |||
9 | #include "busybox.h" | ||
10 | |||
11 | typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t; | ||
12 | |||
13 | #define FLAG_SILENT 1 | ||
14 | #define FLAG_CHECK 2 | ||
15 | #define FLAG_WARN 4 | ||
16 | |||
17 | /* This might be useful elsewhere */ | ||
18 | static unsigned char *hash_bin_to_hex(unsigned char *hash_value, | ||
19 | unsigned hash_length) | ||
20 | { | ||
21 | int len = 0; | ||
22 | char *hex_value = xmalloc((hash_length * 2) + 2); | ||
23 | while (hash_length--) { | ||
24 | len += sprintf(hex_value + len, "%02x", *hash_value++); | ||
25 | } | ||
26 | return hex_value; | ||
27 | } | ||
28 | |||
29 | static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo) | ||
30 | { | ||
31 | int src_fd, hash_len, count; | ||
32 | union _ctx_ { | ||
33 | sha1_ctx_t sha1; | ||
34 | md5_ctx_t md5; | ||
35 | } context; | ||
36 | uint8_t *hash_value = NULL; | ||
37 | RESERVE_CONFIG_UBUFFER(in_buf, 4096); | ||
38 | void (*update)(const void*, size_t, void*); | ||
39 | void (*final)(void*, void*); | ||
40 | |||
41 | src_fd = STDIN_FILENO; | ||
42 | if (filename[0] != '-' || filename[1]) { /* not "-" */ | ||
43 | src_fd = open(filename, O_RDONLY); | ||
44 | if (src_fd < 0) { | ||
45 | bb_perror_msg("%s", filename); | ||
46 | return NULL; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | /* figure specific hash algorithims */ | ||
51 | if (ENABLE_MD5SUM && hash_algo==HASH_MD5) { | ||
52 | md5_begin(&context.md5); | ||
53 | update = (void (*)(const void*, size_t, void*))md5_hash; | ||
54 | final = (void (*)(void*, void*))md5_end; | ||
55 | hash_len = 16; | ||
56 | } else if (ENABLE_SHA1SUM && hash_algo==HASH_SHA1) { | ||
57 | sha1_begin(&context.sha1); | ||
58 | update = (void (*)(const void*, size_t, void*))sha1_hash; | ||
59 | final = (void (*)(void*, void*))sha1_end; | ||
60 | hash_len = 20; | ||
61 | } else { | ||
62 | bb_error_msg_and_die("algorithm not supported"); | ||
63 | } | ||
64 | |||
65 | while (0 < (count = safe_read(src_fd, in_buf, 4096))) { | ||
66 | update(in_buf, count, &context); | ||
67 | } | ||
68 | |||
69 | if (count == 0) { | ||
70 | final(in_buf, &context); | ||
71 | hash_value = hash_bin_to_hex(in_buf, hash_len); | ||
72 | } | ||
73 | |||
74 | RELEASE_CONFIG_BUFFER(in_buf); | ||
75 | |||
76 | if (src_fd != STDIN_FILENO) { | ||
77 | close(src_fd); | ||
78 | } | ||
79 | |||
80 | return hash_value; | ||
81 | } | ||
82 | |||
83 | int md5_sha1_sum_main(int argc, char **argv) | ||
84 | { | ||
85 | int return_value = EXIT_SUCCESS; | ||
86 | uint8_t *hash_value; | ||
87 | unsigned flags; | ||
88 | hash_algo_t hash_algo = ENABLE_MD5SUM | ||
89 | ? (ENABLE_SHA1SUM ? (**argv=='m' ? HASH_MD5 : HASH_SHA1) : HASH_MD5) | ||
90 | : HASH_SHA1; | ||
91 | |||
92 | if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK) | ||
93 | flags = getopt32(argc, argv, "scw"); | ||
94 | else optind = 1; | ||
95 | |||
96 | if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && !(flags & FLAG_CHECK)) { | ||
97 | if (flags & FLAG_SILENT) { | ||
98 | bb_error_msg_and_die | ||
99 | ("-%c is meaningful only when verifying checksums", 's'); | ||
100 | } else if (flags & FLAG_WARN) { | ||
101 | bb_error_msg_and_die | ||
102 | ("-%c is meaningful only when verifying checksums", 'w'); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | if (argc == optind) { | ||
107 | argv[argc++] = "-"; | ||
108 | } | ||
109 | |||
110 | if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && (flags & FLAG_CHECK)) { | ||
111 | FILE *pre_computed_stream; | ||
112 | int count_total = 0; | ||
113 | int count_failed = 0; | ||
114 | char *file_ptr = argv[optind]; | ||
115 | char *line; | ||
116 | |||
117 | if (optind + 1 != argc) { | ||
118 | bb_error_msg_and_die | ||
119 | ("only one argument may be specified when using -c"); | ||
120 | } | ||
121 | |||
122 | pre_computed_stream = stdin; | ||
123 | if (file_ptr[0] != '-' || file_ptr[1]) { /* not "-" */ | ||
124 | pre_computed_stream = xfopen(file_ptr, "r"); | ||
125 | } | ||
126 | |||
127 | while ((line = xmalloc_getline(pre_computed_stream)) != NULL) { | ||
128 | char *filename_ptr; | ||
129 | |||
130 | count_total++; | ||
131 | filename_ptr = strstr(line, " "); | ||
132 | /* handle format for binary checksums */ | ||
133 | if (filename_ptr == NULL) { | ||
134 | filename_ptr = strstr(line, " *"); | ||
135 | } | ||
136 | if (filename_ptr == NULL) { | ||
137 | if (flags & FLAG_WARN) { | ||
138 | bb_error_msg("invalid format"); | ||
139 | } | ||
140 | count_failed++; | ||
141 | return_value = EXIT_FAILURE; | ||
142 | free(line); | ||
143 | continue; | ||
144 | } | ||
145 | *filename_ptr = '\0'; | ||
146 | filename_ptr += 2; | ||
147 | |||
148 | hash_value = hash_file(filename_ptr, hash_algo); | ||
149 | |||
150 | if (hash_value && (strcmp((char*)hash_value, line) == 0)) { | ||
151 | if (!(flags & FLAG_SILENT)) | ||
152 | printf("%s: OK\n", filename_ptr); | ||
153 | } else { | ||
154 | if (!(flags & FLAG_SILENT)) | ||
155 | printf("%s: FAILED\n", filename_ptr); | ||
156 | count_failed++; | ||
157 | return_value = EXIT_FAILURE; | ||
158 | } | ||
159 | /* possible free(NULL) */ | ||
160 | free(hash_value); | ||
161 | free(line); | ||
162 | } | ||
163 | if (count_failed && !(flags & FLAG_SILENT)) { | ||
164 | bb_error_msg("WARNING: %d of %d computed checksums did NOT match", | ||
165 | count_failed, count_total); | ||
166 | } | ||
167 | /* | ||
168 | if (fclose_if_not_stdin(pre_computed_stream) == EOF) { | ||
169 | bb_perror_msg_and_die("cannot close file %s", file_ptr); | ||
170 | } | ||
171 | */ | ||
172 | } else { | ||
173 | while (optind < argc) { | ||
174 | char *file_ptr = argv[optind++]; | ||
175 | |||
176 | hash_value = hash_file(file_ptr, hash_algo); | ||
177 | if (hash_value == NULL) { | ||
178 | return_value = EXIT_FAILURE; | ||
179 | } else { | ||
180 | printf("%s %s\n", hash_value, file_ptr); | ||
181 | free(hash_value); | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | return return_value; | ||
186 | } | ||