It would be very helpful to have a "recursive" option in md5sum (or any
other *sum utility, for that matter). That way, an entire directory tree
could be summed into a file in order to do integrity checking (with
the "check" flag) at later dates. For example:
% md5sum -r /home/foo > /home/bar/check.md5
md5sums everything in the /home/foo path so that:
% md5sum -c /home/bar/check.md5
can validate the entire /home/foo tree. I have attached a rough, but
working, patch to md5sum.c to facilitate this option. I hope you find
this suggestion helpful!
-Brian
106a107
> { "recursive", no_argument, 0, 'r'},
132a134
> -r, --recursive check directories recursively\n\
477a480,574
>
> void print_sum(char *file, int recurse, int binary,
> unsigned char bin_buffer[],
> int (*digest_stream)(FILE *, void *),
> int *err) {
> int fail;
> struct stat filestat;
>
> if (lstat(file, &filestat) == -1) {
> fprintf(stderr, "Error checking file: \"%s\"\n", file);
> return;
> } else {
> if (recurse && S_ISDIR(filestat.st_mode)) {
> DIR *dp;
> struct dirent *dentry;
> char *ptr;
> int value = 0;
>
> if ((dp = opendir(file)) != NULL) {
> while ((dentry = readdir(dp)) != NULL) {
> if ((strcmp(dentry->d_name, ".") == 0) ||
> (strcmp(dentry->d_name, "..") == 0))
> continue;
>
> ptr = malloc(strlen(file) + 1 +
> strlen(dentry->d_name) + 1);
>
> if (ptr == NULL) {
> fprintf(stderr, "Out of memory\n");
> exit(1);
> }
>
> sprintf(ptr, "%s/%s", file, dentry->d_name);
>
> print_sum(ptr, recurse, binary, bin_buffer,
> DIGEST_STREAM(algorithm), err);
>
> free(ptr);
> }
>
> closedir(dp);
>
> return;
> } else {
> fprintf(stderr, "Errer opening directory %s", file);
> return;
> }
> } else {
>
> fail = digest_file (file, binary, bin_buffer,
> DIGEST_STREAM (algorithm));
> *err |= fail;
> if (!fail)
> {
> size_t i;
>
> /* Output a leading backslash if the file name contains
> a newline or backslash. */
> if (strchr (file, '\n') || strchr (file, '\\'))
> putchar ('\\');
>
> for (i = 0; i < (digest_hex_bytes / 2); ++i)
> printf ("%02x", bin_buffer[i]);
>
> putchar (' ');
> if (binary)
> putchar ('*');
> else
> putchar (' ');
>
> /* Translate each NEWLINE byte to the string, "\\n",
> and each backslash to "\\\\". */
> for (i = 0; i < strlen (file); ++i)
> {
> switch (file[i])
> {
> case '\n':
> fputs ("\\n", stdout);
> break;
>
> case '\\':
> fputs ("\\\\", stdout);
> break;
>
> default:
> putchar (file[i]);
> break;
> }
> }
> putchar ('\n');
> }
> }
> }
> }
>
487a585
> int recursive = 0;
506c604
< while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
---
> while ((opt = getopt_long (argc, argv, "brctw", long_options, NULL)) != -1)
524a623,625
> case 'r':
> recursive = 1;
> break;
622,663c723,724
< fail = digest_file (file, binary, bin_buffer,
< DIGEST_STREAM (algorithm));
< err |= fail;
< if (!fail)
< {
< size_t i;
<
< /* Output a leading backslash if the file name contains
< a newline or backslash. */
< if (strchr (file, '\n') || strchr (file, '\\'))
< putchar ('\\');
<
< for (i = 0; i < (digest_hex_bytes / 2); ++i)
< printf ("%02x", bin_buffer[i]);
<
< putchar (' ');
< if (binary)
< putchar ('*');
< else
< putchar (' ');
<
< /* Translate each NEWLINE byte to the string, "\\n",
< and each backslash to "\\\\". */
< for (i = 0; i < strlen (file); ++i)
< {
< switch (file[i])
< {
< case '\n':
< fputs ("\\n", stdout);
< break;
<
< case '\\':
< fputs ("\\\\", stdout);
< break;
<
< default:
< putchar (file[i]);
< break;
< }
< }
< putchar ('\n');
< }
---
> print_sum(file, recursive, binary, bin_buffer,
> DIGEST_STREAM(algorithm), &err);