#include <string.h>
#include <mLib/dstr.h>
+#include <mLib/str.h>
#include <mLib/hex.h>
#include <mLib/base32.h>
/*----- File hashing ------------------------------------------------------*/
+/* --- @gethash@ --- *
+ *
+ * Arguments: @const char *name@ = pointer to name string
+ *
+ * Returns: Pointer to appropriate hash class.
+ *
+ * Use: Chooses a hash function by name.
+ */
+
+const gchash *gethash(const char *name)
+{
+ const gchash *const *g, *gg = 0;
+ size_t sz = strlen(name);
+ for (g = ghashtab; *g; g++) {
+ if (strncmp(name, (*g)->name, sz) == 0) {
+ if ((*g)->name[sz] == 0) {
+ gg = *g;
+ break;
+ } else if (gg)
+ return (0);
+ else
+ gg = *g;
+ }
+ }
+ 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
*
* 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];
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);
}
+/* --- @hfparse@ --- *
+ *
+ * Arguments: @hfpctx *hfp@ = pointer to the context structure
+ *
+ * Returns: A code indicating what happened.
+ *
+ * Use: Parses a line from the input file.
+ */
+
+int hfparse(hfpctx *hfp)
+{
+ char *p, *q;
+ const gchash *gch;
+ const encodeops *ee;
+ dstr *d = hfp->dline;
+ size_t hsz;
+
+ /* --- Fetch the input line and get ready to parse --- */
+
+ DRESET(d);
+ if (dstr_putline(d, hfp->fp) == EOF) return (HF_EOF);
+ p = d->buf;
+
+ /* --- Parse magic comments --- */
+
+ if (*p == '#') {
+ p++;
+ if ((q = str_getword(&p)) == 0) return (HF_BAD);
+ if (strcmp(q, "hash") == 0) {
+ if ((q = str_getword(&p)) == 0) return (HF_BAD);
+ if ((gch = gethash(q)) == 0) return (HF_BAD);
+ hfp->gch = gch;
+ return (HF_HASH);
+ } else if (strcmp(q, "encoding") == 0) {
+ if ((q = str_getword(&p)) == 0) return (HF_BAD);
+ if ((ee = getencoding(q)) == 0) return (HF_BAD);
+ hfp->ee = ee;
+ return (HF_ENC);
+ } else if (strcmp(q, "escape") == 0) {
+ hfp->f |= HFF_ESCAPE;
+ return (HF_ESC);
+ }
+ return (HF_BAD);
+ }
+
+ /* --- Otherwise it's a file line --- */
+
+ q = p;
+ while (*p && *p != ' ') p++;
+ if (!*p) return (HF_BAD);
+ *p++ = 0;
+ hsz = hfp->gch->hashsz;
+ if (hfp->ee->get(q, hfp->hbuf, hsz, 0) < hsz) return (HF_BAD);
+ switch (*p) {
+ case '*': hfp->f |= FHF_BINARY; break;
+ case ' ': hfp->f &= ~FHF_BINARY; break;
+ default: return (HF_BAD);
+ }
+ p++;
+
+ DRESET(hfp->dfile);
+ if (hfp->f & HFF_ESCAPE)
+ getstring(&p, hfp->dfile, GSF_STRING);
+ else {
+ dstr_putm(hfp->dfile, p, d->len - (p - d->buf));
+ dstr_putz(hfp->dfile);
+ }
+
+ return (HF_FILE);
+}
+
/*----- String I/O --------------------------------------------------------*/
/* --- @getstring@ --- *