X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/f377eee1983a7c9f33a9920b3bf16180dca909da..097fb6f2f97575ce17738b4afb3216e9492de2b4:/hashsum.c diff --git a/hashsum.c b/hashsum.c index 23b5d56..8a14a76 100644 --- a/hashsum.c +++ b/hashsum.c @@ -61,8 +61,36 @@ /*----- Guts --------------------------------------------------------------*/ -static int checkhash(const gchash *gch, unsigned f, - const char *file, const encodeops *e) +static int checkjunk(const char *path, const struct stat *st, void *p) +{ + const char *what; + fhashstate *fh = p; + + if (!st) { + if (fh->f & f_verbose) + fprintf(stderr, "JUNK (error %s) %s\n", strerror(errno), path); + else + moan("couldn't stat junk file `%s': %s", path, strerror(errno)); + } else { + what = describefile(st); + if (fh->f & f_verbose) + fprintf(stderr, "JUNK %s %s\n", what, path); + else + moan("found junk %s `%s'", what, path); + } + return (0); +} + +static int warnjunk(const char *path, const struct stat *st, void *p) +{ + if (st) + moan("unexpected %s `%s'", describefile(st), path); + else + moan("couldn't stat unexpected file `%s': %s", path, strerror(errno)); + return (0); +} + +static int checkhash(fhashstate *fh, const char *file, const encodeops *e) { int rc; hfpctx hfp; @@ -73,17 +101,17 @@ static int checkhash(const gchash *gch, unsigned f, if (!file || strcmp(file, "-") == 0) hfp.fp = stdin; - else if ((hfp.fp = fopen(file, f & GSF_RAW ? "r" : "rb")) == 0) { + else if ((hfp.fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) { moan("couldn't open `%s': %s", file, strerror(errno)); return (EXIT_FAILURE); } hfp.dline = &dl; hfp.dfile = &df; - hfp.hbuf = xmalloc(2 * gch->hashsz); - hfp.gch = gch; + hfp.hbuf = xmalloc(2 * fh->gch->hashsz); + hfp.gch = fh->gch; hfp.ee = e; - hfp.f = f; + hfp.f = fh->f; while ((hf = hfparse(&hfp)) != HF_EOF) { switch (hf) { @@ -92,7 +120,7 @@ static int checkhash(const gchash *gch, unsigned f, hfp.hbuf = xmalloc(2 * hfp.gch->hashsz); break; case HF_FILE: - if (fhash(hfp.gch, hfp.f, df.buf, hfp.hbuf + hfp.gch->hashsz)) { + if (fhash(fh, df.buf, hfp.hbuf + hfp.gch->hashsz)) { moan("couldn't read `%s': %s", df.buf, strerror(errno)); rc = EXIT_FAILURE; continue; @@ -113,31 +141,35 @@ static int checkhash(const gchash *gch, unsigned f, } } + if (ferror(hfp.fp)) { + moan("error reading input `%s': %s", + file ? file : "", strerror(errno)); + rc = EXIT_FAILURE; + } dstr_destroy(&dl); dstr_destroy(&df); xfree(hfp.hbuf); - if ((f & f_verbose) && nfail) + if ((fh->f & f_verbose) && nfail) moan("%lu of %lu file(s) failed %s check", nfail, n, hfp.gch->name); else if (!n) moan("no files checked"); - return (0); + return (rc); } -static int dohash(const gchash *gch, unsigned f, - const char *file, const encodeops *e) +static int dohash(fhashstate *fh, const char *file, const encodeops *e) { int rc = 0; - octet *p = xmalloc(gch->hashsz); + octet *p = xmalloc(fh->gch->hashsz); - if (fhash(gch, f, file, p)) { + if (fhash(fh, file, p)) { moan("couldn't read `%s': %s", file ? file : "", strerror(errno)); rc = EXIT_FAILURE; } else { - e->put(p, gch->hashsz, stdout); + e->put(p, fh->gch->hashsz, stdout); if (file) { fputc(' ', stdout); - fputc(f & FHF_BINARY ? '*' : ' ', stdout); - if (f & f_escape) + fputc(fh->f & FHF_BINARY ? '*' : ' ', stdout); + if (fh->f & f_escape) putstring(stdout, file, 0); else fputs(file, stdout); @@ -149,12 +181,10 @@ static int dohash(const gchash *gch, unsigned f, return (rc); } -static int dofile(const gchash *gch, unsigned f, - const char *file, const encodeops *e) - { return (f & f_check ? checkhash : dohash)(gch, f, file, e); } +static int dofile(fhashstate *fh, const char *file, const encodeops *e) + { return (fh->f & f_check ? checkhash : dohash)(fh, file, e); } -static int hashfiles(const gchash *gch, unsigned f, - const char *file, const encodeops *e) +static int hashfiles(fhashstate *fh, const char *file, const encodeops *e) { FILE *fp; dstr d = DSTR_INIT; @@ -163,25 +193,24 @@ static int hashfiles(const gchash *gch, unsigned f, if (!file || strcmp(file, "-") == 0) fp = stdin; - else if ((fp = fopen(file, f & GSF_RAW ? "r" : "rb")) == 0) { + else if ((fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) { moan("couldn't open `%s': %s", file, strerror(errno)); return (EXIT_FAILURE); } for (;;) { DRESET(&d); - if (getstring(fp, &d, GSF_FILE | f)) + if (getstring(fp, &d, GSF_FILE | fh->f)) break; - if ((rrc = dofile(gch, f, d.buf, e)) != 0) + if ((rrc = dofile(fh, d.buf, e)) != 0) rc = rrc; } return (rc); } -static int hashsum(const gchash *gch, unsigned f, - const char *file, const encodeops *e) - { return (f & f_files ? hashfiles : dofile)(gch, f, file, e); } +static int hashsum(fhashstate *fh, const char *file, const encodeops *e) + { return (fh->f & f_files ? hashfiles : dofile)(fh, file, e); } /*----- Main driver -------------------------------------------------------*/ @@ -234,15 +263,15 @@ MAKELISTTAB(listtab, LISTS) int main(int argc, char *argv[]) { - unsigned f = 0; - const gchash *gch = 0; - const encodeops *e = &encodingtab[0]; + fhashstate fh; + const encodeops *e = &encodingtab[ENC_HEX]; int rc; /* --- Initialization --- */ ego(argv[0]); sub_init(); + fhash_init(&fh, 0, 0); /* --- Choose a hash function from the name --- */ @@ -251,10 +280,10 @@ int main(int argc, char *argv[]) size_t len = strlen(q); if (len > 3 && strcmp(q + len - 3, "sum") == 0) { q[len - 3] = 0; - gch = gethash(q); + fh.gch = gethash(q); } - if (!gch) - gch = gethash("md5"); + if (!fh.gch) + fh.gch = gethash("md5"); xfree(q); } @@ -277,19 +306,20 @@ int main(int argc, char *argv[]) { "escape", 0, 0, 'e' }, { "check", 0, 0, 'c' }, + { "junk", 0, 0, 'j' }, { "binary", 0, 0, 'b' }, { "verbose", 0, 0, 'v' }, { "progress", 0, 0, 'p' }, { 0, 0, 0, 0 } }; - int i = mdwopt(argc, argv, "hVu a:E:l f0 ecbvp", opts, 0, 0, 0); + int i = mdwopt(argc, argv, "hVu a:E:l f0 ecjbvp", opts, 0, 0, 0); if (i < 0) break; switch (i) { case 'h': - help(stdout, gch); + help(stdout, fh.gch); exit(0); case 'V': version(stdout); @@ -300,43 +330,46 @@ int main(int argc, char *argv[]) case 'l': exit(displaylists(listtab, argv + optind)); case 'a': - if ((gch = gethash(optarg)) == 0) + if ((fh.gch = gethash(optarg)) == 0) die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); - f |= f_oddhash; + fh.f |= f_oddhash; break; case 'E': if ((e = getencoding(optarg)) == 0) die(EXIT_FAILURE, "unknown encoding `%s'", optarg); - f |= f_oddenc; + fh.f |= f_oddenc; break; case 'f': - f |= f_files; + fh.f |= f_files; break; case '0': - f |= GSF_RAW; + fh.f |= GSF_RAW; break; case 'e': - f |= f_escape; + fh.f |= f_escape; break; case 'c': - f |= f_check; + fh.f |= f_check; + break; + case 'j': + fh.f |= FHF_JUNK; break; case 'b': - f |= FHF_BINARY; + fh.f |= FHF_BINARY; break; case 'v': - f |= f_verbose; + fh.f |= f_verbose; break; case 'p': - f |= FHF_PROGRESS; + fh.f |= FHF_PROGRESS; break; default: - f |= f_bogus; + fh.f |= f_bogus; break; } } - if (f & f_bogus) { + if (fh.f & f_bogus) { usage(stderr); exit(EXIT_FAILURE); } @@ -345,24 +378,33 @@ int main(int argc, char *argv[]) /* --- Generate output --- */ - if (!(f & f_check) && (argc || (f & f_files))) { - if (f & f_oddhash) printf("#hash %s\n", gch->name); - if (f & f_oddenc) printf("#encoding %s\n", e->name); - if (f & f_escape) fputs("#escape\n", stdout); + if (!(fh.f & f_check) && (argc || (fh.f & f_files))) { + if (fh.f & f_oddhash) printf("#hash %s\n", fh.gch->name); + if (fh.f & f_oddenc) printf("#encoding %s\n", e->name); + if (fh.f & f_escape) fputs("#escape\n", stdout); } if (!argc) - rc = hashsum(gch, f, 0, e); + rc = hashsum(&fh, 0, e); else { int i; int rrc; rc = 0; for (i = 0; i < argc; i++) { - if ((rrc = hashsum(gch, f, argv[i], e)) != 0) + if ((rrc = hashsum(&fh, argv[i], e)) != 0) rc = rrc; } } + if (fh.f & FHF_JUNK) { + if (fh.f & f_check) { + if (fhash_junk(&fh, checkjunk, &fh)) rc = EXIT_FAILURE; + } else { + if (fhash_junk(&fh, warnjunk, 0) < 0) rc = EXIT_FAILURE; + } + } + fhash_free(&fh); + return (rc); }