diff options
author | Dacav <dacav@fastmail.com> | 2020-08-29 15:21:04 +0200 |
---|---|---|
committer | Dacav <dacav@fastmail.com> | 2020-08-29 15:21:04 +0200 |
commit | 982fee63848b4efbdbfbb74cfc04f01990781cdc (patch) | |
tree | 854806ae7dbf4f9c1e3e68bb0e5717e75769d539 | |
parent | 32dc8587ab24d5832fb3826a631c8c50524a9a25 (diff) | |
download | forg-982fee63848b4efbdbfbb74cfc04f01990781cdc.tar.gz |
sketchy filehash logic
-rw-r--r-- | filehash.c | 49 | ||||
-rw-r--r-- | filehash.h | 9 | ||||
-rw-r--r-- | forg-import.c | 57 |
3 files changed, 99 insertions, 16 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); } diff --git a/filehash.h b/filehash.h index c52f983..0639c25 100644 --- a/filehash.h +++ b/filehash.h @@ -2,8 +2,17 @@ typedef struct filehash_t filehash_t; +typedef enum { + fhs_accepts, + fhs_failure, + fhs_full, + fhs_rejected, +} filehash_state_t; + filehash_t * filehash_new(const char *hash_program, unsigned max_per_invocation); +filehash_state_t filehash_send(filehash_t *, const char *file_name); + void filehash_free(filehash_t *); diff --git a/forg-import.c b/forg-import.c index 30ee7fc..4cfbcb6 100644 --- a/forg-import.c +++ b/forg-import.c @@ -7,13 +7,16 @@ #include <sysexits.h> #include <unistd.h> +#include "filehash.h" +#include "macros.h" + #define optstr "0h:L:r:" typedef struct { - const char *hash; + const char *hash_program; const char *repository; - unsigned hash_max_lines; + unsigned max_per_invocation; char **files; unsigned n_files; char input_sep; @@ -61,9 +64,9 @@ read_opts(int argc, char **argv) int o; const char *prgname; options_t options = { - .hash = "md5sum", + .hash_program = "md5sum", .repository = ".", - .hash_max_lines = 4096, + .max_per_invocation = 4096, .input_sep = '\n', }; @@ -75,10 +78,10 @@ read_opts(int argc, char **argv) options.input_sep = '\0'; break; case 'h': - options.hash = optarg; + options.hash_program = optarg; break; case 'L': - if (str_to_uint(optarg, &options.hash_max_lines)) + if (str_to_uint(optarg, &options.max_per_invocation)) goto fail; break; case 'r': @@ -167,22 +170,52 @@ done: } static int -run(const options_t *opts) +run(const options_t *opts, filehash_t *fh) { + int ret = 0; void *aux = NULL; - const char *file; + const char *file_name; - while (file = iter_files(opts, &aux), file) - warnx("[%s]", file); + while (file_name = iter_files(opts, &aux), file_name) { - return 0; + switch (filehash_send(fh, file_name)) { + case fhs_accepts: + continue; + + case fhs_failure: + warnx("handle failure!"); + ret = 1; + goto exit; + + case fhs_full: + warnx("handle full!"); + filehash_free(fh); + fh = filehash_new(opts->hash_program, opts->max_per_invocation); + break; + + case fhs_rejected: + bug_abort; + + } + + } + +exit: + filehash_free(fh); + return ret; } int main(int argc, char **argv) { options_t opts; + filehash_t *fh; opts = read_opts(argc, argv); - return run(&opts); + + fh = filehash_new(opts.hash_program, opts.max_per_invocation); + if (!fh) + err(1, "filehash_new"); + + return run(&opts, fh); } |