mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-12-22 18:00:49 +01:00
Cleanup: unify input file processing code
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
6fc871b3ff
commit
a32a4cb149
7 changed files with 148 additions and 165 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue