From 07290a455e008c37adc233554eff8ad468608161 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 7 Jan 2013 23:27:08 +0000 Subject: [PATCH] Hash utilities: maintain a hash state object, not a bundle of arguments. This makes a number of things a bit cleaner, except that we (currently pointlessly) remember to free up this state object when we're finished with it. --- cc-hash.c | 40 +++++++++++++++++++++------ cc.h | 46 +++++++++++++++++++++++++------ dsig.c | 10 +++++-- hashsum.c | 95 ++++++++++++++++++++++++++++++--------------------------------- 4 files changed, 122 insertions(+), 69 deletions(-) diff --git a/cc-hash.c b/cc-hash.c index b0d8bb2..9e23f79 100644 --- a/cc-hash.c +++ b/cc-hash.c @@ -193,10 +193,34 @@ const gchash *gethash(const char *name) return (gg); } +/* --- @fhash_init@ ---* + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to initialize + * @const gchash *gch@ = hash class to set + * @unsigned f@ initial flags to set + * + * Returns: --- + * + * Use: Initializes an @fhashstate@ structure. + */ + +void fhash_init(fhashstate *fh, const gchash *gch, unsigned f) + { fh->f = f; fh->gch = gch; } + +/* --- @fhash_free@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to free + * + * Returns: --- + * + * Use: Frees an fhash state. + */ + +void fhash_free(fhashstate *fh) { return; } + /* --- @fhash@ --- * * - * Arguments: @const gchash *gch@ = pointer to hash function to use - * @unsigned f@ = flags to set + * Arguments: @fhashstate *fh@ = pointer to fhash state * @const char *file@ = file name to be hashed (null for stdin) * @void *buf@ = pointer to hash output buffer * @@ -205,7 +229,7 @@ const gchash *gethash(const char *name) * Use: Hashes a file. */ -int fhash(const gchash *gch, unsigned f, const char *file, void *buf) +int fhash(fhashstate *fh, const char *file, void *buf) { FILE *fp; char fbuf[1024 * 128]; @@ -216,21 +240,21 @@ int fhash(const gchash *gch, unsigned f, const char *file, void *buf) if (!file || strcmp(file, "-") == 0) fp = stdin; - else if ((fp = fopen(file, f & FHF_BINARY ? "rb" : "r")) == 0) + else if ((fp = fopen(file, fh->f & FHF_BINARY ? "rb" : "r")) == 0) return (-1); - if (f & FHF_PROGRESS) { + if (fh->f & FHF_PROGRESS) { if (fprogress_init(&ff, file, fp)) return (-1); } - h = GH_INIT(gch); + h = GH_INIT(fh->gch); while ((sz = fread(fbuf, 1, sizeof(fbuf), fp)) > 0) { GH_HASH(h, fbuf, sz); - if (f & FHF_PROGRESS) fprogress_update(&ff, sz); + if (fh->f & FHF_PROGRESS) fprogress_update(&ff, sz); } if (ferror(fp)) rc = -1; if (fp != stdin) fclose(fp); - if (f & FHF_PROGRESS) fprogress_done(&ff); + if (fh->f & FHF_PROGRESS) fprogress_done(&ff); GH_DONE(h, buf); GH_DESTROY(h); return (rc); diff --git a/cc.h b/cc.h index c8b0cdf..7d93fa3 100644 --- a/cc.h +++ b/cc.h @@ -326,6 +326,16 @@ extern const encodeops *getencoding(const char */*ename*/); /*----- File hashing ------------------------------------------------------*/ +typedef struct fhashstate { + const gchash *gch; + unsigned f; +} fhashstate; + +#define FHF_BINARY 0x100u +#define FHF_PROGRESS 0x200u + +#define FHF_MASK 0xff00u + /* --- @gethash@ --- * * * Arguments: @const char *name@ = pointer to name string @@ -337,10 +347,34 @@ extern const encodeops *getencoding(const char */*ename*/); extern const gchash *gethash(const char */*name*/); +/* --- @fhash_init@ ---* + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to initialize + * @const gchash *gch@ = hash class to set + * @unsigned f@ initial flags to set + * + * Returns: --- + * + * Use: Initializes an @fhashstate@ structure. + */ + +extern void fhash_init(fhashstate */*fh*/, + const gchash */*gch*/, unsigned /*f*/); + +/* --- @fhash_free@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to free + * + * Returns: --- + * + * Use: Frees an fhash state. + */ + +extern void fhash_free(fhashstate */*fh*/); + /* --- @fhash@ --- * * - * Arguments: @const gchash *gch@ = pointer to hash function to use - * @unsigned f@ = flags to set + * Arguments: @fhashstate *fh@ = pointer to fhash state * @const char *file@ = file name to be hashed (null for stdin) * @void *buf@ = pointer to hash output buffer * @@ -349,13 +383,7 @@ extern const gchash *gethash(const char */*name*/); * Use: Hashes a file. */ -#define FHF_BINARY 256u -#define FHF_PROGRESS 512u - -#define FHF_MASK 384u - -extern int fhash(const gchash */*gch*/, unsigned /*f*/, - const char */*file*/, void */*buf*/); +extern int fhash(fhashstate */*fh*/, const char */*file*/, void */*buf*/); /* --- @hfparse@ --- * * diff --git a/dsig.c b/dsig.c index 5006423..4847ac8 100644 --- a/dsig.c +++ b/dsig.c @@ -467,6 +467,7 @@ static int sign(int argc, char *argv[]) key_file kf; key *k; sig *s; + fhashstate fh; time_t exp = KEXP_EXPIRE; unsigned verb = 0; const char *ifile = 0, *hfile = 0; @@ -662,12 +663,13 @@ static int sign(int argc, char *argv[]) /* --- Read the next filename to hash --- */ + fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY); breset(&b); if (getstring(ifp, &b.d, GSF_FILE | f)) break; b.tag = T_FILE; DENSURE(&b.b, GH_CLASS(s->h)->hashsz); - if (fhash(GH_CLASS(s->h), f | FHF_BINARY, b.d.buf, b.b.buf)) { + if (fhash(&fh, b.d.buf, b.b.buf)) { moan("error reading `%s': %s", b.d.buf, strerror(errno)); f |= f_bogus; } else { @@ -678,6 +680,7 @@ static int sign(int argc, char *argv[]) } bemit(&b, ofp, s->h, f & f_bin); } + fhash_free(&fh); } } @@ -744,6 +747,7 @@ static int verify(int argc, char *argv[]) sig *s; dstr d = DSTR_INIT; const char *err; + fhashstate fh; FILE *fp; block b; int e; @@ -853,6 +857,7 @@ static int verify(int argc, char *argv[]) if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) printf("WARN public key fails check: %s", err); + fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY); for (;;) { switch (e) { case T_COMMENT: @@ -885,7 +890,7 @@ static int verify(int argc, char *argv[]) case T_FILE: DRESET(&d); DENSURE(&d, GH_CLASS(s->h)->hashsz); - if (fhash(GH_CLASS(s->h), f | FHF_BINARY, b.d.buf, d.buf)) { + if (fhash(&fh, b.d.buf, d.buf)) { if (verb > 1) { printf("BAD error reading file `%s': %s\n", b.d.buf, strerror(errno)); @@ -926,6 +931,7 @@ static int verify(int argc, char *argv[]) } } done: + fhash_free(&fh); bdestroy(&b); dstr_destroy(&d); freesig(s); diff --git a/hashsum.c b/hashsum.c index 820cfbd..8419779 100644 --- a/hashsum.c +++ b/hashsum.c @@ -61,8 +61,7 @@ /*----- Guts --------------------------------------------------------------*/ -static int checkhash(const gchash *gch, unsigned f, - const char *file, const encodeops *e) +static int checkhash(fhashstate *fh, const char *file, const encodeops *e) { int rc; hfpctx hfp; @@ -73,17 +72,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 +91,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; @@ -121,28 +120,27 @@ static int checkhash(const gchash *gch, unsigned f, 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 (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); @@ -154,12 +152,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; @@ -168,25 +164,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 -------------------------------------------------------*/ @@ -239,8 +234,7 @@ MAKELISTTAB(listtab, LISTS) int main(int argc, char *argv[]) { - unsigned f = 0; - const gchash *gch = 0; + fhashstate fh; const encodeops *e = &encodingtab[ENC_HEX]; int rc; @@ -248,6 +242,7 @@ int main(int argc, char *argv[]) ego(argv[0]); sub_init(); + fhash_init(&fh, 0, 0); /* --- Choose a hash function from the name --- */ @@ -256,10 +251,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); } @@ -294,7 +289,7 @@ int main(int argc, char *argv[]) switch (i) { case 'h': - help(stdout, gch); + help(stdout, fh.gch); exit(0); case 'V': version(stdout); @@ -305,43 +300,43 @@ 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 '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); } @@ -350,20 +345,20 @@ 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; } } -- 2.11.0