about summary refs log tree commit diff stats
path: root/filehash.c
diff options
context:
space:
mode:
Diffstat (limited to 'filehash.c')
-rw-r--r--filehash.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/filehash.c b/filehash.c
index ace1992..03f75a5 100644
--- a/filehash.c
+++ b/filehash.c
@@ -1,5 +1,6 @@
 #include "filehash.h"
 
+#include <err.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -8,6 +9,7 @@ struct filehash_t
   const char *hash_program;
   const char **argv;
   unsigned max_per_invocation;
+  unsigned next;
 };
 
 filehash_t *
@@ -25,12 +27,14 @@ filehash_new(const char *hash_program, unsigned max_per_invocation)
     .argv = reallocarray(NULL, 1 + max_per_invocation, sizeof(const char *)),
   };
 
-  if (!fh->hash_program)
-    goto fail;
   if (!fh->argv)
     goto fail;
 
-  fh->argv[max_per_invocation] = NULL;
+  for (int i = 0; i <= max_per_invocation; ++i)
+    fh->argv[i] = NULL;
+
+  if (!fh->hash_program)
+    goto fail;
 
   return fh;
 
@@ -39,13 +43,50 @@ fail:
   return NULL;
 }
 
+#include <stdio.h>
+static int run_hash(filehash_t *fh)
+{
+  fputs(fh->hash_program, stderr);
+  for (int i = 0; i < fh->next; ++i) {
+    fputc(' ', stderr);
+    fputs(fh->argv[i], stderr);
+  }
+  fputc('\n', stderr);
+  return 0;
+}
+
+filehash_state_t filehash_send(filehash_t *fh, const char *file_name)
+{
+  if (fh->next >= fh->max_per_invocation)
+    return fhs_rejected;
+
+  const char *copy = strdup(file_name);
+  if (!copy) {
+    warn("strdup");
+    return fhs_failure;
+  }
+
+  fh->argv[fh->next++] = copy;
+  if (fh->next < fh->max_per_invocation)
+    return fhs_accepts;
+
+  if (run_hash(fh) == -1)
+    return fhs_failure;
+
+  return fhs_full;
+}
+
 void
 filehash_free(filehash_t *fh)
 {
   if (!fh)
     return;
 
-  free(fh->argv);
+  if (fh->argv) {
+    for (int i = 0; i <= fh->max_per_invocation; ++i)
+      free((void *)fh->argv[i]);
+    free(fh->argv);
+  }
   free((void *)fh->hash_program);
   free(fh);
 }