commit 04f32f4d9aae63f80f5aa9b771190f47593bf62e
parent 18b6e4016108182834d08f54c15daad3a459da9f
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Sun, 23 Mar 2014 12:18:38 +0100
checksum tools: implement -c
Signed-off-by: Hiltjo Posthuma <hiltjo@codemadness.org>
Diffstat:
6 files changed, 105 insertions(+), 4 deletions(-)
diff --git a/crypt.h b/crypt.h
@@ -6,6 +6,7 @@ struct crypt_ops {
void *s;
};
+int cryptcheck(char *, int, char **, struct crypt_ops *, uint8_t *, size_t);
int cryptmain(int, char **, struct crypt_ops *, uint8_t *, size_t);
int cryptsum(struct crypt_ops *, FILE *, const char *, uint8_t *);
void mdprint(const uint8_t *, const char *, size_t);
diff --git a/md5sum.c b/md5sum.c
@@ -24,13 +24,17 @@ int
main(int argc, char *argv[])
{
uint8_t md[MD5_DIGEST_LENGTH];
+ char *checkfile = NULL;
ARGBEGIN {
case 'c':
- eprintf("not implemented\n");
+ checkfile = EARGF(usage());
+ break;
default:
usage();
} ARGEND;
+ if(checkfile)
+ return cryptcheck(checkfile, argc, argv, &md5_ops, md, sizeof(md));
return cryptmain(argc, argv, &md5_ops, md, sizeof(md));
}
diff --git a/sha1sum.c b/sha1sum.c
@@ -24,13 +24,16 @@ int
main(int argc, char *argv[])
{
uint8_t md[SHA1_DIGEST_LENGTH];
+ char *checkfile = NULL;
ARGBEGIN {
case 'c':
- eprintf("not implemented\n");
+ checkfile = EARGF(usage());
default:
usage();
} ARGEND;
+ if(checkfile)
+ return cryptcheck(checkfile, argc, argv, &sha1_ops, md, sizeof(md));
return cryptmain(argc, argv, &sha1_ops, md, sizeof(md));
}
diff --git a/sha256sum.c b/sha256sum.c
@@ -24,13 +24,16 @@ int
main(int argc, char *argv[])
{
uint8_t md[SHA256_DIGEST_LENGTH];
+ char *checkfile = NULL;
ARGBEGIN {
case 'c':
- eprintf("not implemented\n");
+ checkfile = EARGF(usage());
default:
usage();
} ARGEND;
+ if(checkfile)
+ return cryptcheck(checkfile, argc, argv, &sha256_ops, md, sizeof(md));
return cryptmain(argc, argv, &sha256_ops, md, sizeof(md));
}
diff --git a/sha512sum.c b/sha512sum.c
@@ -24,13 +24,16 @@ int
main(int argc, char *argv[])
{
uint8_t md[SHA512_DIGEST_LENGTH];
+ char *checkfile = NULL;
ARGBEGIN {
case 'c':
- eprintf("not implemented\n");
+ checkfile = EARGF(usage());
default:
usage();
} ARGEND;
+ if(checkfile)
+ return cryptcheck(checkfile, argc, argv, &sha512_ops, md, sizeof(md));
return cryptmain(argc, argv, &sha512_ops, md, sizeof(md));
}
diff --git a/util/crypt.c b/util/crypt.c
@@ -2,9 +2,96 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <string.h>
#include "../util.h"
+#include "../text.h"
#include "../crypt.h"
+static int
+hexdec(int c) {
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ else if(c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if(c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1; /* unknown character */
+}
+
+static int
+mdcheckline(const char *s, uint8_t *md, size_t sz) {
+ size_t i;
+ int b1, b2;
+
+ for(i = 0; i < sz; i++) {
+ if(!*s || (b1 = hexdec(*s++)) < 0)
+ return -1; /* invalid format */
+ if(!*s || (b2 = hexdec(*s++)) < 0)
+ return -1; /* invalid format */
+ if((uint8_t)((b1 << 4) | b2) != md[i])
+ return 0; /* value mismatch */
+ }
+ return (i == sz) ? 1 : 0;
+}
+
+int
+cryptcheck(char *sumfile, int argc, char *argv[],
+ struct crypt_ops *ops, uint8_t *md, size_t sz)
+{
+ FILE *cfp, *fp;
+ char *buf = NULL, *line, *file, *p;
+ int r, nonmatch = 0, formatsucks = 0, noread = 0, ret = EXIT_SUCCESS;
+ size_t bufsiz = 0;
+
+ if(!(cfp = fopen(sumfile, "r")))
+ eprintf("fopen %s:", sumfile);
+
+ while((line = afgets(&buf, &bufsiz, cfp))) {
+ if(!(file = strstr(line, " "))) {
+ formatsucks++;
+ continue;
+ }
+ if((file - line) / 2 != sz) {
+ formatsucks++; /* checksum length mismatch */
+ continue;
+ }
+ *file = '\0';
+ file += 2;
+ for(p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */
+ *p = '\0';
+ if(!(fp = fopen(file, "r"))) {
+ weprintf("fopen %s:", file);
+ noread++;
+ continue;
+ }
+ cryptsum(ops, fp, file, md);
+ r = mdcheckline(line, md, sz);
+ if(r == 1) {
+ printf("%s: OK\n", file);
+ } else if(r == 0) {
+ printf("%s: FAILED\n", file);
+ nonmatch++;
+ } else {
+ formatsucks++;
+ }
+ fclose(fp);
+ }
+ fclose(cfp);
+ if(formatsucks > 0) {
+ weprintf("WARNING: %d lines are improperly formatted\n", formatsucks);
+ ret = EXIT_FAILURE;
+ }
+ if(noread > 0) {
+ weprintf("WARNING: %d listed file could not be read\n", noread);
+ ret = EXIT_FAILURE;
+ }
+ if(nonmatch > 0) {
+ weprintf("WARNING: %d computed checksums did NOT match\n", nonmatch);
+ ret = EXIT_FAILURE;
+ }
+ return ret;
+}
+
int
cryptmain(int argc, char *argv[],
struct crypt_ops *ops, uint8_t *md, size_t sz)