Refactor cryptcheck() to allow multiple list-files and stdin

Previously, it was not possible to use

sha1sum test.c | sha1sum -c

because the program would not differenciate between an empty
argument and a non-specified argument.
Moreover, why not allow this?

sha1sum -c hashlist1 hashlist2

Digging deeper I found that using function pointers and a
modification in the crypt-backend might simplify the program
a lot by passing the argument-list to both cryptmain and
cryptcheck.
Allowing more than one list-file to be specified is also
consistent with what the other implementations support,
so we not only have simpler code, we also do not silently
break if there's a script around passing multiple files to
check.
This commit is contained in:
FRIGN 2015-03-01 22:51:52 +01:00
parent 0226c05105
commit 9b06720f62
6 changed files with 56 additions and 53 deletions

View File

@ -6,7 +6,7 @@ struct crypt_ops {
void *s; void *s;
}; };
int cryptcheck(char *, int, char **, struct crypt_ops *, uint8_t *, size_t); int cryptcheck(int, char **, struct crypt_ops *, uint8_t *, size_t);
int cryptmain(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 *); int cryptsum(struct crypt_ops *, FILE *, const char *, uint8_t *);
void mdprint(const uint8_t *, const char *, size_t); void mdprint(const uint8_t *, const char *, size_t);

View File

@ -37,27 +37,21 @@ mdcheckline(const char *s, uint8_t *md, size_t sz)
return (i == sz) ? 1 : 0; return (i == sz) ? 1 : 0;
} }
int static void
cryptcheck(char *sumfile, int argc, char *argv[], mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz,
struct crypt_ops *ops, uint8_t *md, size_t sz) int *formatsucks, int *noread, int *nonmatch) {
{ FILE *fp;
FILE *cfp, *fp;
char *line = NULL, *file, *p;
int r, nonmatch = 0, formatsucks = 0, noread = 0, ret = 0;
size_t bufsiz = 0; size_t bufsiz = 0;
int r;
char *line = NULL, *file, *p;
if (!sumfile) while (getline(&line, &bufsiz, listfp) != -1) {
cfp = stdin;
else if (!(cfp = fopen(sumfile, "r")))
eprintf("fopen %s:", sumfile);
while (getline(&line, &bufsiz, cfp) != -1) {
if (!(file = strstr(line, " "))) { if (!(file = strstr(line, " "))) {
formatsucks++; (*formatsucks)++;
continue; continue;
} }
if ((file - line) / 2 != sz) { if ((file - line) / 2 != sz) {
formatsucks++; /* checksum length mismatch */ (*formatsucks)++; /* checksum length mismatch */
continue; continue;
} }
*file = '\0'; *file = '\0';
@ -66,7 +60,7 @@ cryptcheck(char *sumfile, int argc, char *argv[],
*p = '\0'; *p = '\0';
if (!(fp = fopen(file, "r"))) { if (!(fp = fopen(file, "r"))) {
weprintf("fopen %s:", file); weprintf("fopen %s:", file);
noread++; (*noread)++;
continue; continue;
} }
cryptsum(ops, fp, file, md); cryptsum(ops, fp, file, md);
@ -75,33 +69,53 @@ cryptcheck(char *sumfile, int argc, char *argv[],
printf("%s: OK\n", file); printf("%s: OK\n", file);
} else if (r == 0) { } else if (r == 0) {
printf("%s: FAILED\n", file); printf("%s: FAILED\n", file);
nonmatch++; (*nonmatch)++;
} else { } else {
formatsucks++; (*formatsucks)++;
} }
fclose(fp); fclose(fp);
} }
if (sumfile)
fclose(cfp);
free(line); free(line);
if (formatsucks > 0) { }
int
cryptcheck(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
{
FILE *fp;
int formatsucks = 0, noread = 0, nonmatch = 0, ret = 0;
if (argc == 0) {
mdchecklist(stdin, ops, md, sz, &formatsucks, &noread, &nonmatch);
} else {
for (; argc > 0; argc--, argv++) {
if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", *argv);
ret = 1;
continue;
}
mdchecklist(fp, ops, md, sz, &formatsucks, &noread, &nonmatch);
fclose(fp);
}
}
if (formatsucks) {
weprintf("%d lines are improperly formatted\n", formatsucks); weprintf("%d lines are improperly formatted\n", formatsucks);
ret = 1; ret = 1;
} }
if (noread > 0) { if (noread) {
weprintf("%d listed file could not be read\n", noread); weprintf("%d listed file could not be read\n", noread);
ret = 1; ret = 1;
} }
if (nonmatch > 0) { if (nonmatch) {
weprintf("%d computed checksums did NOT match\n", nonmatch); weprintf("%d computed checksums did NOT match\n", nonmatch);
ret = 1; ret = 1;
} }
return ret; return ret;
} }
int int
cryptmain(int argc, char *argv[], cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
struct crypt_ops *ops, uint8_t *md, size_t sz)
{ {
FILE *fp; FILE *fp;
int ret = 0; int ret = 0;
@ -110,7 +124,7 @@ cryptmain(int argc, char *argv[],
cryptsum(ops, stdin, "<stdin>", md); cryptsum(ops, stdin, "<stdin>", md);
mdprint(md, "<stdin>", sz); mdprint(md, "<stdin>", sz);
} else { } else {
for (; argc > 0; argc--) { for (; argc > 0; argc--, argv++) {
if (!(fp = fopen(*argv, "r"))) { if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", *argv); weprintf("fopen %s:", *argv);
ret = 1; ret = 1;
@ -121,7 +135,6 @@ cryptmain(int argc, char *argv[],
else else
mdprint(md, *argv, sz); mdprint(md, *argv, sz);
fclose(fp); fclose(fp);
argv++;
} }
} }
return ret; return ret;

View File

@ -24,20 +24,16 @@ usage(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain;
uint8_t md[MD5_DIGEST_LENGTH]; uint8_t md[MD5_DIGEST_LENGTH];
char *checkfile = NULL;
int cflag = 0;
ARGBEGIN { ARGBEGIN {
case 'c': case 'c':
cflag = 1; cryptfunc = cryptcheck;
checkfile = ARGF();
break; break;
default: default:
usage(); usage();
} ARGEND; } ARGEND;
if (cflag) return cryptfunc(argc, argv, &md5_ops, md, sizeof(md));
return cryptcheck(checkfile, argc, argv, &md5_ops, md, sizeof(md));
return cryptmain(argc, argv, &md5_ops, md, sizeof(md));
} }

View File

@ -17,24 +17,22 @@ struct crypt_ops sha1_ops = {
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-c] [file...]\n", argv0); eprintf("usage: %s [-c] [file ...]\n", argv0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain;
uint8_t md[SHA1_DIGEST_LENGTH]; uint8_t md[SHA1_DIGEST_LENGTH];
char *checkfile = NULL;
ARGBEGIN { ARGBEGIN {
case 'c': case 'c':
checkfile = ARGF(); cryptfunc = cryptcheck;
break; break;
default: default:
usage(); usage();
} ARGEND; } ARGEND;
if (checkfile) return cryptfunc(argc, argv, &sha1_ops, md, sizeof(md));
return cryptcheck(checkfile, argc, argv, &sha1_ops, md, sizeof(md));
return cryptmain(argc, argv, &sha1_ops, md, sizeof(md));
} }

View File

@ -17,24 +17,22 @@ struct crypt_ops sha256_ops = {
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-c] [file...]\n", argv0); eprintf("usage: %s [-c] [file ...]\n", argv0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain;
uint8_t md[SHA256_DIGEST_LENGTH]; uint8_t md[SHA256_DIGEST_LENGTH];
char *checkfile = NULL;
ARGBEGIN { ARGBEGIN {
case 'c': case 'c':
checkfile = ARGF(); cryptfunc = cryptcheck;
break; break;
default: default:
usage(); usage();
} ARGEND; } ARGEND;
if (checkfile) return cryptfunc(argc, argv, &sha256_ops, md, sizeof(md));
return cryptcheck(checkfile, argc, argv, &sha256_ops, md, sizeof(md));
return cryptmain(argc, argv, &sha256_ops, md, sizeof(md));
} }

View File

@ -17,24 +17,22 @@ struct crypt_ops sha512_ops = {
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-c] [file...]\n", argv0); eprintf("usage: %s [-c] [file ...]\n", argv0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain;
uint8_t md[SHA512_DIGEST_LENGTH]; uint8_t md[SHA512_DIGEST_LENGTH];
char *checkfile = NULL;
ARGBEGIN { ARGBEGIN {
case 'c': case 'c':
checkfile = ARGF(); cryptfunc = cryptcheck;
break; break;
default: default:
usage(); usage();
} ARGEND; } ARGEND;
if (checkfile) return cryptfunc(argc, argv, &sha512_ops, md, sizeof(md));
return cryptcheck(checkfile, argc, argv, &sha512_ops, md, sizeof(md));
return cryptmain(argc, argv, &sha512_ops, md, sizeof(md));
} }