From 982fee63848b4efbdbfbb74cfc04f01990781cdc Mon Sep 17 00:00:00 2001 From: Dacav Date: Sat, 29 Aug 2020 15:21:04 +0200 Subject: sketchy filehash logic --- filehash.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- filehash.h | 9 +++++++++ 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 #include #include @@ -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 +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 #include +#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); } -- cgit 1.4.1-2-gfad0