From a32a4cb149beceb45890d5aec7b4ee60e3f2320f Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 31 Jan 2019 22:09:38 +0100 Subject: [PATCH] Cleanup: unify input file processing code Signed-off-by: David Oberhollenzer --- Makefile.am | 2 +- include/input_file.h | 10 +++- main/cmd/pack/desc.c | 68 +++++----------------- main/cmd/pack/filelist.c | 105 ++++++++++++++++++++++++---------- main/cmd/pack/filelist_read.c | 73 ----------------------- main/cmd/pack/pack.h | 6 +- main/input_file.c | 49 +++++++++++++++- 7 files changed, 148 insertions(+), 165 deletions(-) delete mode 100644 main/cmd/pack/filelist_read.c diff --git a/Makefile.am b/Makefile.am index 098d87c..8c1ff8d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ EXTRA_DIST = autogen.sh ##### commands ##### # pack command -pkg_SOURCES += main/cmd/pack/filelist.c main/cmd/pack/filelist_read.c +pkg_SOURCES += main/cmd/pack/filelist.c pkg_SOURCES += main/cmd/pack/write_toc.c main/cmd/pack/write_files.c pkg_SOURCES += main/cmd/pack/pack.h main/cmd/pack/pack.c pkg_SOURCES += main/cmd/pack/desc.c main/cmd/pack/write_hdr.c diff --git a/include/input_file.h b/include/input_file.h index dbd1bd2..3225772 100644 --- a/include/input_file.h +++ b/include/input_file.h @@ -10,10 +10,18 @@ typedef struct { size_t linenum; } input_file_t; -int prefetch_line(input_file_t *f); +typedef struct { + const char *name; + int (*handle)(input_file_t *f, void *obj); +} keyword_handler_t; void cleanup_file(input_file_t *f); int open_file(input_file_t *f, const char *filename); +int process_file(input_file_t *f, const keyword_handler_t *handlers, + size_t count, void *obj); + +void input_file_complain(const input_file_t *f, const char *msg); + #endif /* INPUT_FILE_H */ diff --git a/main/cmd/pack/desc.c b/main/cmd/pack/desc.c index f73d8ce..97bbaaa 100644 --- a/main/cmd/pack/desc.c +++ b/main/cmd/pack/desc.c @@ -1,8 +1,9 @@ #include "pack.h" -static int handle_requires(input_file_t *f, pkg_desc_t *desc) +static int handle_requires(input_file_t *f, void *obj) { char *ptr = f->line, *end; + pkg_desc_t *desc = obj; dependency_t *dep; size_t len; @@ -18,15 +19,13 @@ static int handle_requires(input_file_t *f, pkg_desc_t *desc) break; if (len > 0xFF) { - fprintf(stderr, "%s: %zu: dependency name too long\n", - f->filename, f->linenum); + input_file_complain(f, "dependency name too long"); return -1; } dep = calloc(1, sizeof(*dep) + len + 1); if (dep == NULL) { - fprintf(stderr, "%s: %zu: out of memory\n", - f->filename, f->linenum); + input_file_complain(f, "out of memory"); return -1; } @@ -41,27 +40,25 @@ static int handle_requires(input_file_t *f, pkg_desc_t *desc) return 0; } -static int handle_name(input_file_t *f, pkg_desc_t *desc) +static int handle_name(input_file_t *f, void *obj) { + pkg_desc_t *desc = obj; + if (desc->name != NULL) { - fprintf(stderr, "%s: %zu: name redefined\n", - f->filename, f->linenum); + input_file_complain(f, "name redefined"); return -1; } desc->name = strdup(f->line); if (desc->name == NULL) { - fputs("out of memory\n", stderr); + input_file_complain(f, "out of memory"); return -1; } return 0; } -static const struct { - const char *name; - int (*handle)(input_file_t *f, pkg_desc_t *desc); -} line_hooks[] = { +static const keyword_handler_t line_hooks[] = { { "requires", handle_requires }, { "name", handle_name }, }; @@ -71,58 +68,19 @@ static const struct { int desc_read(const char *path, pkg_desc_t *desc) { input_file_t f; - size_t i, len; - char *ptr; - int ret; memset(desc, 0, sizeof(*desc)); if (open_file(&f, path)) return -1; - for (;;) { - ret = prefetch_line(&f); - if (ret < 0) - goto fail; - if (ret > 0) - break; - - ptr = f.line; - - for (i = 0; i < NUM_LINE_HOOKS; ++i) { - len = strlen(line_hooks[i].name); - - if (strncmp(ptr, line_hooks[i].name, len) != 0) - continue; - if (!isspace(ptr[len]) && ptr[len] != '\0') - continue; - for (ptr += len; isspace(*ptr); ++ptr) - ; - memmove(f.line, ptr, strlen(ptr) + 1); - break; - } - - if (i == NUM_LINE_HOOKS) { - fprintf(stderr, "%s: %zu: unknown description field\n", - f.filename, f.linenum); - goto fail; - } - - ret = line_hooks[i].handle(&f, desc); - if (ret) - goto fail; - } - - if (desc->name == NULL) { - fprintf(stderr, "%s: no name given in package description\n", - f.filename); + if (process_file(&f, line_hooks, NUM_LINE_HOOKS, desc)) { + cleanup_file(&f); + return -1; } cleanup_file(&f); return 0; -fail: - cleanup_file(&f); - return -1; } void desc_free(pkg_desc_t *desc) diff --git a/main/cmd/pack/filelist.c b/main/cmd/pack/filelist.c index 5d63548..d9dc737 100644 --- a/main/cmd/pack/filelist.c +++ b/main/cmd/pack/filelist.c @@ -7,14 +7,9 @@ static char *skipspace(char *str) return str; } -static void complain(const input_file_t *f, const char *msg) -{ - fprintf(stderr, "%s: %zu: %s\n", f->filename, f->linenum, msg); -} - static void oom(input_file_t *f) { - complain(f, "out of memory"); + input_file_complain(f, "out of memory"); } static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) @@ -34,7 +29,7 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) ; if (!isspace(line[i])) { - complain(f, "expected space after file name"); + input_file_complain(f, "expected space after file name"); goto fail; } @@ -46,17 +41,17 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) memcpy(ent->name, line, i); if (canonicalize_name(ent->name)) { - complain(f, "invalid file name"); + input_file_complain(f, "invalid file name"); goto fail; } if (ent->name[0] == '\0') { - complain(f, "refusing to add entry for '/'"); + input_file_complain(f, "refusing to add entry for '/'"); goto fail; } if (strlen(ent->name) > 0xFFFF) { - complain(f, "name too long"); + input_file_complain(f, "name too long"); goto fail; } @@ -64,20 +59,20 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) /* mode */ if (!isdigit(*line)) { - complain(f, "expected numeric mode after file name"); + input_file_complain(f, "expected numeric mode after file name"); goto fail; } while (isdigit(*line)) { if (*line > '7') { - complain(f, "mode must be octal number"); + input_file_complain(f, "mode must be octal number"); goto fail; } ent->mode = (ent->mode << 3) | (*(line++) - '0'); } if (!isspace(*line)) { - complain(f, "expected space after file mode"); + input_file_complain(f, "expected space after file mode"); goto fail; } @@ -87,7 +82,7 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) /* uid */ if (!isdigit(*line)) { - complain(f, "expected numeric UID after mode"); + input_file_complain(f, "expected numeric UID after mode"); goto fail; } @@ -95,7 +90,7 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) ent->uid = (ent->uid * 10) + (*(line++) - '0'); if (!isspace(*line)) { - complain(f, "expected space after UID"); + input_file_complain(f, "expected space after UID"); goto fail; } @@ -103,7 +98,7 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) /* gid */ if (!isdigit(*line)) { - complain(f, "expected numeric GID after UID"); + input_file_complain(f, "expected numeric GID after UID"); goto fail; } @@ -121,17 +116,26 @@ fail: return NULL; } -image_entry_t *filelist_mkdir(input_file_t *f) +int filelist_mkdir(input_file_t *f, void *obj) { - return filelist_mkentry(f, S_IFDIR); -} - -image_entry_t *filelist_mkslink(input_file_t *f) -{ - image_entry_t *ent = filelist_mkentry(f, S_IFLNK); + image_entry_t *ent = filelist_mkentry(f, S_IFDIR); + image_entry_t **listptr = obj; if (ent == NULL) - return NULL; + return -1; + + ent->next = *listptr; + *listptr = ent; + return 0; +} + +int filelist_mkslink(input_file_t *f, void *obj) +{ + image_entry_t *ent = filelist_mkentry(f, S_IFLNK); + image_entry_t **listptr = obj; + + if (ent == NULL) + return -1; ent->data.symlink.target = strdup(f->line); if (ent->data.symlink.target == NULL) { @@ -140,23 +144,26 @@ image_entry_t *filelist_mkslink(input_file_t *f) } if (strlen(ent->data.symlink.target) > 0xFFFF) { - complain(f, "symlink target too long"); + input_file_complain(f, "symlink target too long"); goto fail; } - return ent; + ent->next = *listptr; + *listptr = ent; + return 0; fail: image_entry_free(ent); - return NULL; + return -1; } -image_entry_t *filelist_mkfile(input_file_t *f) +int filelist_mkfile(input_file_t *f, void *obj) { image_entry_t *ent = filelist_mkentry(f, S_IFREG); + image_entry_t **listptr = obj; struct stat sb; if (ent == NULL) - return NULL; + return -1; ent->data.file.location = strdup(f->line); if (ent->data.file.location == NULL) { @@ -171,13 +178,49 @@ image_entry_t *filelist_mkfile(input_file_t *f) if (sizeof(off_t) > sizeof(uint64_t) && sb.st_size > (off_t)(~((uint64_t)0))) { - complain(f, "input file is too big"); + input_file_complain(f, "input file is too big"); goto fail; } ent->data.file.size = sb.st_size; - return ent; + + ent->next = *listptr; + *listptr = ent; + return 0; fail: image_entry_free(ent); + return -1; +} + +static const keyword_handler_t line_hooks[] = { + { "file", filelist_mkfile }, + { "dir", filelist_mkdir }, + { "slink", filelist_mkslink }, +}; + +#define NUM_LINE_HOOKS (sizeof(line_hooks) / sizeof(line_hooks[0])) + +image_entry_t *filelist_read(const char *filename) +{ + image_entry_t *list = NULL; + input_file_t f; + + if (open_file(&f, filename)) + return NULL; + + if (process_file(&f, line_hooks, NUM_LINE_HOOKS, &list)) + goto fail; + + if (list == NULL) { + fprintf(stderr, "%s: does not contain any entries\n", + f.filename); + goto fail; + } + + cleanup_file(&f); + return list; +fail: + cleanup_file(&f); + image_entry_free_list(list); return NULL; } diff --git a/main/cmd/pack/filelist_read.c b/main/cmd/pack/filelist_read.c deleted file mode 100644 index 350af13..0000000 --- a/main/cmd/pack/filelist_read.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "pack.h" - -static const struct { - const char *name; - image_entry_t *(*handle)(input_file_t *f); -} line_hooks[] = { - { "file", filelist_mkfile }, - { "dir", filelist_mkdir }, - { "slink", filelist_mkslink }, -}; - -#define NUM_LINE_HOOKS (sizeof(line_hooks) / sizeof(line_hooks[0])) - -image_entry_t *filelist_read(const char *filename) -{ - image_entry_t *ent, *list = NULL; - input_file_t f; - size_t i, len; - char *ptr; - int ret; - - if (open_file(&f, filename)) - return NULL; - - for (;;) { - ret = prefetch_line(&f); - if (ret < 0) - goto fail; - if (ret > 0) - break; - - ptr = f.line; - - for (i = 0; i < NUM_LINE_HOOKS; ++i) { - len = strlen(line_hooks[i].name); - - if (strncmp(ptr, line_hooks[i].name, len) != 0) - continue; - if (!isspace(ptr[len]) && ptr[len] != '\0') - continue; - for (ptr += len; isspace(*ptr); ++ptr) - ; - memmove(f.line, ptr, strlen(ptr) + 1); - break; - } - - if (i == NUM_LINE_HOOKS) { - fprintf(stderr, "%s: %zu: unknown entry type\n", - f.filename, f.linenum); - goto fail; - } - - ent = line_hooks[i].handle(&f); - if (ent == NULL) - goto fail; - - ent->next = list; - list = ent; - } - - if (list == NULL) { - fprintf(stderr, "%s: does not contain any entries\n", - f.filename); - goto fail; - } - - cleanup_file(&f); - return list; -fail: - cleanup_file(&f); - image_entry_free_list(list); - return NULL; -} diff --git a/main/cmd/pack/pack.h b/main/cmd/pack/pack.h index 28a5128..8da895a 100644 --- a/main/cmd/pack/pack.h +++ b/main/cmd/pack/pack.h @@ -33,11 +33,11 @@ typedef struct { char *name; } pkg_desc_t; -image_entry_t *filelist_mkdir(input_file_t *f); +int filelist_mkdir(input_file_t *f, void *obj); -image_entry_t *filelist_mkslink(input_file_t *f); +int filelist_mkslink(input_file_t *f, void *obj); -image_entry_t *filelist_mkfile(input_file_t *f); +int filelist_mkfile(input_file_t *f, void *obj); image_entry_t *filelist_read(const char *filename); diff --git a/main/input_file.c b/main/input_file.c index d05a5d5..30cc306 100644 --- a/main/input_file.c +++ b/main/input_file.c @@ -5,7 +5,7 @@ #include "input_file.h" -int prefetch_line(input_file_t *f) +static int prefetch_line(input_file_t *f) { char *line, *ptr; ssize_t ret; @@ -77,3 +77,50 @@ int open_file(input_file_t *f, const char *filename) return 0; } + +void input_file_complain(const input_file_t *f, const char *msg) +{ + fprintf(stderr, "%s: %zu: %s\n", f->filename, f->linenum, msg); +} + +int process_file(input_file_t *f, const keyword_handler_t *handlers, + size_t count, void *obj) +{ + size_t i, len; + char *ptr; + int ret; + + for (;;) { + ret = prefetch_line(f); + if (ret < 0) + return -1; + if (ret > 0) + break; + + ptr = f->line; + + for (i = 0; i < count; ++i) { + len = strlen(handlers[i].name); + + if (strncmp(ptr, handlers[i].name, len) != 0) + continue; + if (!isspace(ptr[len]) && ptr[len] != '\0') + continue; + for (ptr += len; isspace(*ptr); ++ptr) + ; + memmove(f->line, ptr, strlen(ptr) + 1); + break; + } + + if (i == count) { + fprintf(stderr, "%s: %zu: unknown keyword\n", + f->filename, f->linenum); + return -1; + } + + if (handlers[i].handle(f, obj)) + return -1; + } + + return 0; +}