diff options
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/Config.in | 19 | ||||
-rw-r--r-- | coreutils/Makefile.in | 4 | ||||
-rw-r--r-- | coreutils/md5_sha1_sum.c | 195 |
3 files changed, 208 insertions, 10 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in index 90f681c04..a388cd9e8 100644 --- a/coreutils/Config.in +++ b/coreutils/Config.in @@ -373,14 +373,6 @@ config CONFIG_SHA1SUM help Compute and check SHA1 message digest -config CONFIG_FEATURE_SHA1SUM_CHECK - bool " Enable -c and -w options" - default n - depends on CONFIG_SHA1SUM - help - Enabling the -c and -w options allows files to be checked - against pre-calculated hash values. - config CONFIG_SLEEP bool "sleep (single integer arg with no suffix)" default n @@ -591,4 +583,15 @@ config CONFIG_FEATURE_HUMAN_READABLE help Allow df, du, and ls to have human readable output. +comment "Common options for md5sum, sha1sum" + depends on CONFIG_MD5SUM || CONFIG_SHA1SUM + +config CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + bool " Enable -c and -w options" + default n + depends on CONFIG_MD5SUM || CONFIG_SHA1SUM + help + Enabling the -c and -w options allows files to be checked + against pre-calculated hash values. + endmenu diff --git a/coreutils/Makefile.in b/coreutils/Makefile.in index b672f08f7..c7ba57e04 100644 --- a/coreutils/Makefile.in +++ b/coreutils/Makefile.in @@ -52,7 +52,7 @@ COREUTILS-$(CONFIG_LENGTH) += length.o COREUTILS-$(CONFIG_LN) += ln.o COREUTILS-$(CONFIG_LOGNAME) += logname.o COREUTILS-$(CONFIG_LS) += ls.o -COREUTILS-$(CONFIG_MD5SUM) += md5sum.o +COREUTILS-$(CONFIG_MD5SUM) += md5_sha1_sum.o COREUTILS-$(CONFIG_MKDIR) += mkdir.o COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o COREUTILS-$(CONFIG_MKNOD) += mknod.o @@ -63,7 +63,7 @@ COREUTILS-$(CONFIG_PWD) += pwd.o COREUTILS-$(CONFIG_REALPATH) += realpath.o COREUTILS-$(CONFIG_RM) += rm.o COREUTILS-$(CONFIG_RMDIR) += rmdir.o -COREUTILS-$(CONFIG_SHA1SUM) += sha1sum.o +COREUTILS-$(CONFIG_SHA1SUM) += md5_sha1_sum.o COREUTILS-$(CONFIG_SLEEP) += sleep.o COREUTILS-$(CONFIG_SORT) += sort.o COREUTILS-$(CONFIG_STTY) += stty.o diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c new file mode 100644 index 000000000..f7c44c850 --- /dev/null +++ b/coreutils/md5_sha1_sum.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "busybox.h" + + +#define FLAG_SILENT 1 +#define FLAG_CHECK 2 +#define FLAG_WARN 4 + +/* This might be usefull elsewhere */ +static unsigned char *hash_bin_to_hex(unsigned char *hash_value, + unsigned char hash_length) +{ + int x, len, max; + unsigned char *hex_value; + + max = (hash_length * 2) + 2; + hex_value = xmalloc(max); + for (x = len = 0; x < hash_length; x++) { + len += snprintf(hex_value + len, max - len, "%02x", hash_value[x]); + } + return (hex_value); +} + +static uint8_t *hash_file(const char *filename, uint8_t hash_algo) +{ + uint8_t *hash_value_bin; + uint8_t *hash_value = NULL; + uint8_t hash_length; + int src_fd; + + if (strcmp(filename, "-") == 0) { + src_fd = fileno(stdin); + } else { + src_fd = open(filename, O_RDONLY); + } + + if (hash_algo == HASH_MD5) { + hash_length = 16; + } else { + hash_length = 20; + } + + hash_value_bin = xmalloc(hash_length); + + if ((src_fd != -1) && (hash_fd(src_fd, -1, hash_algo, hash_value_bin) != -2)) { + hash_value = hash_bin_to_hex(hash_value_bin, hash_length); + } else { + bb_perror_msg("%s", filename); + } + + close(src_fd); + + return(hash_value); +} + +/* This could become a common function for md5 as well, by using md5_stream */ +extern int hash_files(int argc, char **argv, const uint8_t hash_algo) +{ + uint8_t *hash_value; + unsigned int flags; + int return_value = EXIT_SUCCESS; + +#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + flags = bb_getopt_ulflags(argc, argv, "scw"); +#else + flags = bb_getopt_ulflags(argc, argv, "s"); +#endif + +#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + if (!(flags & FLAG_CHECK)) { + if (flags & FLAG_SILENT) { + bb_error_msg_and_die + ("the -s option is meaningful only when verifying checksums"); + } else if (flags & FLAG_WARN) { + bb_error_msg_and_die + ("the -w option is meaningful only when verifying checksums"); + } + } +#endif + + if (argc == optind) { + argv[argc++] = "-"; + } +#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + if (flags & FLAG_CHECK) { + FILE *pre_computed_stream; + int count_total = 0; + int count_failed = 0; + unsigned char *file_ptr = argv[optind]; + char *line; + + if (optind + 1 != argc) { + bb_error_msg_and_die + ("only one argument may be specified when using -c"); + } + + if (strcmp(file_ptr, "-") == 0) { + pre_computed_stream = stdin; + } else { + pre_computed_stream = bb_xfopen(file_ptr, "r"); + } + + while ((line = bb_get_chomped_line_from_file(pre_computed_stream)) != NULL) { + char *filename_ptr; + + count_total++; + filename_ptr = strstr(line, " "); + if (filename_ptr == NULL) { + if (flags & FLAG_WARN) { + bb_error_msg("Invalid format"); + } + free(line); + continue; + } + *filename_ptr = '\0'; + filename_ptr += 2; + + hash_value = hash_file(filename_ptr, hash_algo); + + if (hash_value && (strcmp(hash_value, line) == 0)) { + printf("%s: OK\n", filename_ptr); + } else { + printf("%s: FAILED\n", filename_ptr); + count_failed++; + } + /* possible free(NULL) */ + free(hash_value); + free(line); + } + if (count_failed) { + bb_error_msg("WARNING: %d of %d computed checksums did NOT match", + count_failed, count_total); + } + if (bb_fclose_nonstdin(pre_computed_stream) == EOF) { + bb_perror_msg_and_die("Couldnt close file %s", file_ptr); + } + } else +#endif + while (optind < argc) { + unsigned char *file_ptr = argv[optind]; + + optind++; + + hash_value = hash_file(file_ptr, hash_algo); + if (hash_value == NULL) { + return_value++; + } + else if (!flags & FLAG_SILENT) { + printf("%s %s\n", hash_value, file_ptr); + free(hash_value); + } + } + + return (return_value); +} + +#ifdef CONFIG_MD5SUM +extern int md5sum_main(int argc, char **argv) +{ + return(hash_files(argc, argv, HASH_MD5)); +} +#endif + +#ifdef CONFIG_SHA1SUM +extern int sha1sum_main(int argc, char **argv) +{ + return(hash_files(argc, argv, HASH_SHA1)); +} +#endif |