From 6c43f743a3f607f91ee22a53db880fce2df645f0 Mon Sep 17 00:00:00 2001 From: Glenn L McGrath Date: Sun, 8 Jun 2003 13:32:12 +0000 Subject: sha1sum option to compare checksums --- coreutils/Config.in | 7 +++ coreutils/sha1sum.c | 162 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 123 insertions(+), 46 deletions(-) diff --git a/coreutils/Config.in b/coreutils/Config.in index 0d5eff3c9..2bcc48a62 100644 --- a/coreutils/Config.in +++ b/coreutils/Config.in @@ -342,6 +342,13 @@ config CONFIG_SHA1SUM help Compute and check SHA1 message digest +config CONFIG_FEATURE_SHA1SUM_CHECK + bool " Enale -c and -w options" + default n + help + Enabling the -c and -w options allow files to be checked + against pre-calculated hash values. + config CONFIG_SLEEP bool "sleep (single integer arg with no suffix)" default n diff --git a/coreutils/sha1sum.c b/coreutils/sha1sum.c index 1c31e3c55..7071fb6b7 100644 --- a/coreutils/sha1sum.c +++ b/coreutils/sha1sum.c @@ -148,81 +148,151 @@ static char sha1sum_stream(FILE *fd, unsigned int *hashval) return(EXIT_SUCCESS); } -static void print_hash(unsigned int *hash_value, unsigned char hash_length, unsigned char *filename) +#define FLAG_SILENT 1 +#define FLAG_CHECK 2 +#define FLAG_WARN 4 + +static unsigned char *hash_bin_to_hex(unsigned int *hash_value, unsigned char hash_length) { unsigned char x; + unsigned char *hex_value; + hex_value = xmalloc(hash_length * 8); for (x = 0; x < hash_length; x++) { - printf("%08x", hash_value[x]); + sprintf(&hex_value[x * 8], "%08x", hash_value[x]); } - putchar(' '); - putchar(' '); - puts(filename); + return(hex_value); } -#define FLAG_SILENT 1 -#define FLAG_CHECK 2 -#define FLAG_WARN 3 +FILE *wfopen_file_or_stdin(const char *file_ptr) +{ + FILE *stream; -/* This should become a common function used by sha1sum and md5sum, - * it needs extra functionality first - */ + if ((file_ptr[0] == '-') && (file_ptr[1] == '\0')) { + stream = stdin; + } else { + stream = bb_wfopen(file_ptr, "r"); + } + + return(stream); +} + +/* This could become a common function for md5 as well, by using md5_stream */ extern int authenticate(int argc, char **argv, char (*hash_ptr)(FILE *stream, unsigned int *hashval), const unsigned char hash_length) { unsigned int hash_value[hash_length]; - unsigned char flags = 0; - int opt; - int return_value; - - while ((opt = getopt(argc, argv, "sc:w")) != -1) { - switch (opt) { - case 's': /* Dont output anything, status code shows success */ - flags |= FLAG_SILENT; - break; -#if 0 - case 'c': /* Check a list of checksums against stored values */ - break; - case 'w': /* Warn of bad formatting when checking files */ - break; + unsigned int flags; + int return_value = EXIT_SUCCESS; + +#ifdef CONFIG_FEATURE_SHA1SUM_CHECK + flags = bb_getopt_ulflags(argc, argv, "scw"); +#else + flags = bb_getopt_ulflags(argc, argv, "s"); #endif - default: - bb_show_usage(); + +#ifdef CONFIG_FEATURE_SHA1SUM_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++] = "-"; } - return_value = EXIT_SUCCESS; - while (optind < argc) { - FILE *stream; +#ifdef CONFIG_FEATURE_SHA1SUM_CHECK + if (flags & FLAG_CHECK) { + FILE *pre_computed_stream; + int count_total = 0; + int count_failed = 0; unsigned char *file_ptr = argv[optind]; - optind++; + if (optind + 1 != argc) { + bb_error_msg_and_die("only one argument may be specified when using -c"); + } + pre_computed_stream = wfopen_file_or_stdin(file_ptr); + while (!feof(pre_computed_stream) && !ferror(pre_computed_stream)) { + FILE *stream; + char *line; + char *line_ptr; + char *hex_value; - if ((file_ptr[0] == '-') && (file_ptr[1] == '\0')) { - stream = stdin; - } else { - stream = bb_wfopen(file_ptr, "r"); - if (stream == NULL) { - return_value = EXIT_FAILURE; + line = bb_get_chomped_line_from_file(pre_computed_stream); + if (line == NULL) { + break; + } + count_total++; + line_ptr = strchr(line, ' '); + if (line_ptr == NULL) { + if (flags & FLAG_WARN) { + bb_error_msg("Invalid format"); + } + free(line); + continue; + } + *line_ptr = '\0'; + line_ptr++; + if ((flags & FLAG_WARN) && (*line_ptr != ' ')) { + bb_error_msg("Invalid format"); + free(line); continue; } + line_ptr++; + stream = bb_wfopen(line_ptr, "r"); + if (hash_ptr(stream, hash_value) == EXIT_FAILURE) { + return_value = EXIT_FAILURE; + } + if (fclose(stream) == EOF) { + bb_perror_msg("Couldnt close file %s", file_ptr); + } + hex_value = hash_bin_to_hex(hash_value, hash_length); + printf("%s: ", line_ptr); + if (strcmp(hex_value, line) != 0) { + puts("FAILED"); + count_failed++; + } else { + puts("ok"); + } + free(line); } - if (hash_ptr(stream, hash_value) == EXIT_FAILURE) { - return_value = EXIT_FAILURE; + if (count_failed) { + bb_error_msg("WARNING: %d of %d computed checksum did NOT match", count_failed, count_total); } - else if (!flags & FLAG_SILENT) { - print_hash(hash_value, hash_length, file_ptr); + if (bb_fclose_nonstdin(pre_computed_stream) == EOF) { + bb_perror_msg_and_die("Couldnt close file %s", file_ptr); } + } else +#endif + while (optind < argc) { + FILE *stream; + unsigned char *file_ptr = argv[optind]; - if (fclose(stream) == EOF) { - bb_perror_msg("Couldnt close file %s", file_ptr); - return_value = EXIT_FAILURE; - } + optind++; - } + stream = wfopen_file_or_stdin(file_ptr); + if (stream == NULL) { + return_value = EXIT_FAILURE; + continue; + } + if (hash_ptr(stream, hash_value) == EXIT_FAILURE) { + return_value = EXIT_FAILURE; + } + else if (!flags & FLAG_SILENT) { + char *hex_value = hash_bin_to_hex(hash_value, hash_length); + printf("%s %s\n", hex_value, file_ptr); + free(hex_value); + } + + if (bb_fclose_nonstdin(stream) == EOF) { + bb_perror_msg("Couldnt close file %s", file_ptr); + return_value = EXIT_FAILURE; + } + } return(return_value); } -- cgit v1.2.3