adding "check option to md5(1) [was: md5(1) and cal(1) on -questions]

jhell jhell at dataix.net
Mon May 17 19:11:14 UTC 2010


On 05/12/2010 04:01, Eitan Adler wrote:
>> D> 2. Why doesn't md5(1) have a "check" option?  Seems to me requiring a
>> D> manual inspection is error-prone at best, and makes scripting
>> D> unecessarily complicated.
> 
> Would something like the attached patch be good?
> It adds a -c option for a string to check against. It prints
> "[failed]" if the string does not match the files md5 unless in -q
> mode.
> It also returns 2 to indicate md5 match failure for use in scripts.
> 

I have reviewed this patch for functionality and my final conclusion is
commit it.

Though I would like to see the same functionality that the GNU GPL'd
version of md5 has with the '-c' option and being able to check every
sum that is listed in a file against a file on disk(c), this version
brings the availability to doing the checking right from md5 and utils
from a script.

I have also edited the manual page portion of the patch to include the
'[-c string]' option in the SYNOPSIS section of the man pages. This
newly generated patch was generated from the root of the source tree.

# cd /path/to/src
# patch </path/to/patch-file
# cd /path/to/src/sbin/md5
# make obj && make depend && make && make install

Additionally. Thanks for your work on this.

Regards,

-- 

 jhell
-------------- next part --------------
Index: sbin/md5/md5.1
===================================================================
--- sbin/md5/md5.1	(revision 208194)
+++ sbin/md5/md5.1	(working copy)
@@ -8,18 +8,22 @@
 .Sh SYNOPSIS
 .Nm md5
 .Op Fl pqrtx
+.Op Fl c Ar string
 .Op Fl s Ar string
 .Op Ar
 .Nm sha1
 .Op Fl pqrtx
+.Op Fl c Ar string
 .Op Fl s Ar string
 .Op Ar
 .Nm sha256
 .Op Fl pqrtx
+.Op Fl c Ar string
 .Op Fl s Ar string
 .Op Ar
 .Nm rmd160
 .Op Fl pqrtx
+.Op Fl c Ar string
 .Op Fl s Ar string
 .Op Ar
 .Sh DESCRIPTION
@@ -73,6 +77,8 @@
 The hexadecimal checksum of each file listed on the command line is printed
 after the options are processed.
 .Bl -tag -width indent
+.It Fl c Ar string
+Compare files to this md5 string
 .It Fl s Ar string
 Print a checksum of the given
 .Ar string .
@@ -101,7 +107,8 @@
 and
 .Nm rmd160
 utilities exit 0 on success,
-and 1 if at least one of the input files could not be read.
+1 if at least one of the input files could not be read,
+and 2 if at least one file does not have the same hash as the -c option.
 .Sh SEE ALSO
 .Xr cksum 1 ,
 .Xr md5 3 ,
Index: sbin/md5/md5.c
===================================================================
--- sbin/md5/md5.c	(revision 208194)
+++ sbin/md5/md5.c	(working copy)
@@ -44,6 +44,8 @@
 int qflag;
 int rflag;
 int sflag;
+unsigned char* checkAgainst;
+int	checksFailed;
 
 typedef void (DIGEST_Init)(void *);
 typedef void (DIGEST_Update)(void *, const unsigned char *, size_t);
@@ -138,8 +140,13 @@
  		digest = 0;
 
 	failed = 0;
-	while ((ch = getopt(argc, argv, "pqrs:tx")) != -1)
+	checkAgainst = NULL;
+	checksFailed = 0;
+	while ((ch = getopt(argc, argv, "c:pqrs:tx")) != -1)
 		switch (ch) {
+		case 'c':
+			checkAgainst = optarg;
+			break;
 		case 'p':
 			MDFilter(&Algorithm[digest], 1);
 			break;
@@ -173,12 +180,19 @@
 				failed++;
 			} else {
 				if (qflag)
-					printf("%s\n", p);
+					printf("%s", p);
 				else if (rflag)
-					printf("%s %s\n", p, *argv);
+					printf("%s %s", p, *argv);
 				else
-					printf("%s (%s) = %s\n",
+					printf("%s (%s) = %s",
 					    Algorithm[digest].name, *argv, p);
+				if (checkAgainst && strcmp(checkAgainst,p))
+				{
+					checksFailed++;
+					if (!qflag)
+						printf("%s","[ Failed ]");
+				}
+				printf("\n");
 			}
 		} while (*++argv);
 	} else if (!sflag && (optind == 1 || qflag || rflag))
@@ -186,6 +200,8 @@
 
 	if (failed != 0)
 		return (1);
+	if (checksFailed != 0)
+		return (2);
 
 	return (0);
 }
@@ -198,12 +214,20 @@
 	size_t len = strlen(string);
 	char buf[HEX_DIGEST_LENGTH];
 
+	alg->Data(string,len,buf);
 	if (qflag)
-		printf("%s\n", alg->Data(string, len, buf));
+		printf("%s", buf);
 	else if (rflag)
-		printf("%s \"%s\"\n", alg->Data(string, len, buf), string);
+		printf("%s \"%s\"", buf, string);
 	else
-		printf("%s (\"%s\") = %s\n", alg->name, string, alg->Data(string, len, buf));
+		printf("%s (\"%s\") = %s", alg->name, string, buf);
+	if (checkAgainst && strcmp(buf,checkAgainst))
+	{
+		checksFailed++;
+		if (!qflag)
+			printf("%s"," [ failed ]");
+	}
+	printf("\n");
 }
 /*
  * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.


More information about the freebsd-hackers mailing list