In keeping track of content changes on large numbers of files, I have
found that giving md5sum the ability to take the list of file names to be
processed from a file rather than from the command line argument list is
quite helpful. I include the mods I made to the 2.0 version of the
source to implement this feature.
Please consider them for future releases.
Thanks very much,
/ken dawson
-------------------------------------------------------------------------
--- md5sum.c-orig Sun Jul 30 11:36:19 2000
+++ md5sum.c Sun Jul 30 11:34:14 2000
@@ -88,6 +88,7 @@
{ "string", required_argument, 0, 1 },
{ "text", no_argument, 0, 't' },
{ "warn", no_argument, 0, 'w' },
+ { "file", required_argument, 0, 'f' },
{ GETOPT_HELP_OPTION_DECL },
{ GETOPT_VERSION_OPTION_DECL },
{ NULL, 0, NULL, 0 }
@@ -115,6 +116,11 @@
--status don't output anything, status code shows success\n\
-w, --warn warn about improperly formated MD5 checksum lines\n\
\n\
+The --file option is used to draw the list of files from a file; \"-\"\n\
+indicates the standard input.\n\
+\n\
+ -f file, --file file names of files come from file\n\
+\n\
--help display this help and exit\n\
--version output version information and exit\n\
\n\
@@ -446,6 +452,72 @@
&& n_open_or_read_failures == 0) ? 0 : 1);
}
+char *
+get_next_filename (char *argv[], int argc, int *optindp,
+ const char *name, char **bufp, size_t *buflenp)
+{
+ static int name_file_done;
+
+ if (name != NULL && !name_file_done)
+ {
+ /* take file names from the name file */
+
+ static FILE * name_handle;
+
+ if (name_handle == NULL)
+ {
+ if (STREQ (name, "-"))
+ {
+ name_handle = stdin;
+ have_read_stdin = 1;
+ }
+ else if ((name_handle = fopen(name, "r")) == NULL)
+ {
+ error(0, 0, _("%s: cannot open"), name);
+ name_file_done = 1;
+ }
+ }
+
+ if (!name_file_done)
+ {
+ if (getline(bufp, buflenp, name_handle) <= 0)
+ {
+ if (ferror(name_handle))
+ {
+ error(0, 0, _("%s: read error"), name);
+ (void) fclose(name_handle);
+ name_file_done = 1;
+ }
+ else if (feof(name_handle))
+ {
+ if (!STREQ (name, "-"))
+ {
+ if (fclose(name_handle) < 0)
+ {
+ error(0, 0, _("%s: close failed"), name);
+ }
+ }
+
+ name_file_done = 1;
+ }
+ }
+ else
+ {
+ if ((*bufp)[strlen(*bufp)-1] == '\n')
+ {
+ (*bufp)[strlen(*bufp)-1] = '\0';
+ }
+
+ return(*bufp);
+ }
+ }
+ }
+
+ /* take filenames from argv */
+
+ return((*optindp) >= argc ? NULL : argv[(*optindp)++]);
+}
+
int
main (int argc, char **argv)
{
@@ -456,6 +528,7 @@
size_t n_strings = 0;
size_t err = 0;
int file_type_specified = 0;
+ char *name_file = NULL;
#if O_BINARY
/* Binary is default on MSDOS, so the actual file contents
@@ -472,7 +545,7 @@
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
- while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
+ while ((opt = getopt_long (argc, argv, "bctwf:", long_options, NULL)) != -1)
switch (opt)
{
case 0: /* long option */
@@ -506,6 +579,9 @@
status_only = 0;
warn = 1;
break;
+ case 'f':
+ name_file = optarg;
+ break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -540,6 +616,21 @@
usage (EXIT_FAILURE);
}
+ if (name_file != NULL)
+ {
+ if (do_check)
+ {
+ error(0, 0, _("the --file and --check options are mutually exclusive"));
+ usage(EXIT_FAILURE);
+ }
+
+ if (n_strings > 0)
+ {
+ error(0, 0, _("the --file and --string options are mutually exclusive"));
+ usage(EXIT_FAILURE);
+ }
+ }
+
if (n_strings > 0)
{
size_t i;
@@ -573,13 +664,20 @@
}
else
{
- if (optind == argc)
- argv[argc++] = "-";
+ char * file;
+ char * buffer = NULL;
+ size_t bufferlen = 0;
- for (; optind < argc; ++optind)
+ while ((file = get_next_filename(argv, argc, &optind, name_file,
+ &buffer, &bufferlen)) != NULL)
{
int fail;
- char *file = argv[optind];
+
+ if (STREQ (file, "-") && have_read_stdin)
+ {
+ error (0, 0, _("can only read from stdin once"));
+ continue;
+ }
fail = md5_file (file, binary, md5buffer);
err |= fail;
@@ -623,6 +721,11 @@
putchar ('\n');
}
}
+
+ if (buffer != NULL)
+ {
+ free(buffer);
+ }
}
if (fclose (stdout) == EOF)
@@ -633,3 +736,4 @@
exit (err == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
+