Add package header with dependency information

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
David Oberhollenzer 2019-01-28 20:01:36 +01:00
parent 47e237688b
commit aab510aa98
7 changed files with 233 additions and 11 deletions

View File

@ -25,7 +25,8 @@ EXTRA_DIST = autogen.sh
pkg_SOURCES += main/cmd/pack/filelist.c main/cmd/pack/filelist_read.c pkg_SOURCES += main/cmd/pack/filelist.c main/cmd/pack/filelist_read.c
pkg_SOURCES += main/cmd/pack/write_toc.c main/cmd/pack/write_files.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/pack.h main/cmd/pack/pack.c
pkg_SOURCES += main/cmd/pack/input_file.c pkg_SOURCES += main/cmd/pack/input_file.c main/cmd/pack/desc.c
pkg_SOURCES += main/cmd/pack/write_hdr.c
# dump command # dump command
pkg_SOURCES += main/cmd/dump/dump.c main/cmd/dump/dump.h main/cmd/dump/dump_toc.c pkg_SOURCES += main/cmd/dump/dump.c main/cmd/dump/dump.h main/cmd/dump/dump_toc.c

View File

@ -18,6 +18,10 @@ typedef enum {
PKG_COMPRESSION_LZMA = 2, PKG_COMPRESSION_LZMA = 2,
} PKG_COMPRESSION; } PKG_COMPRESSION;
typedef enum {
PKG_DEPENDENCY_REQUIRES = 0,
} PKG_DEPENDENCY_TYPE;
typedef struct { typedef struct {
uint32_t magic; uint32_t magic;
uint8_t compression; uint8_t compression;
@ -54,4 +58,15 @@ typedef struct {
/* uint8_t data[]; */ /* uint8_t data[]; */
} file_data_t; } file_data_t;
typedef struct {
uint16_t num_depends;
/* pkg_dependency_t depends[]; */
} pkg_header_t;
typedef struct {
uint8_t type;
uint8_t name_length;
/* uint8_t name[]; */
} pkg_dependency_t;
#endif /* PKG_FORMAT_H */ #endif /* PKG_FORMAT_H */

113
main/cmd/pack/desc.c Normal file
View File

@ -0,0 +1,113 @@
#include "pack.h"
static int handle_requires(input_file_t *f, pkg_desc_t *desc)
{
char *ptr = f->line, *end;
dependency_t *dep;
size_t len;
while (*ptr != '\0') {
while (isspace(*ptr))
++ptr;
end = ptr;
while (*end != '\0' && !isspace(*end))
++end;
len = end - ptr;
if (len == 0)
break;
if (len > 0xFF) {
fprintf(stderr, "%s: %zu: dependency name too long\n",
f->filename, f->linenum);
return -1;
}
dep = calloc(1, sizeof(*dep) + len + 1);
if (dep == NULL) {
fprintf(stderr, "%s: %zu: out of memory\n",
f->filename, f->linenum);
return -1;
}
memcpy(dep->name, ptr, len);
dep->type = PKG_DEPENDENCY_REQUIRES;
dep->next = desc->deps;
desc->deps = dep;
ptr = end;
}
return 0;
}
static const struct {
const char *name;
int (*handle)(input_file_t *f, pkg_desc_t *desc);
} line_hooks[] = {
{ "requires", handle_requires },
};
#define NUM_LINE_HOOKS (sizeof(line_hooks) / sizeof(line_hooks[0]))
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;
}
return 0;
fail:
return -1;
}
void desc_free(pkg_desc_t *desc)
{
dependency_t *dep;
while (desc->deps != NULL) {
dep = desc->deps;
desc->deps = dep->next;
free(dep);
}
}

View File

@ -3,12 +3,13 @@
static const struct option long_opts[] = { static const struct option long_opts[] = {
{ "toc-compressor", required_argument, NULL, 't' }, { "toc-compressor", required_argument, NULL, 't' },
{ "file-compressor", required_argument, NULL, 'f' }, { "file-compressor", required_argument, NULL, 'f' },
{ "description", required_argument, NULL, 'd' },
{ "file-list", required_argument, NULL, 'l' }, { "file-list", required_argument, NULL, 'l' },
{ "output", required_argument, NULL, 'o' }, { "output", required_argument, NULL, 'o' },
{ NULL, 0, NULL, 0 }, { NULL, 0, NULL, 0 },
}; };
static const char *short_opts = "t:f:l:o:"; static const char *short_opts = "t:f:l:o:d:";
static compressor_t *get_default_compressor(void) static compressor_t *get_default_compressor(void)
{ {
@ -61,10 +62,11 @@ static int alloc_file_ids(image_entry_t *list)
static int cmd_pack(int argc, char **argv) static int cmd_pack(int argc, char **argv)
{ {
const char *filelist = NULL, *filename = NULL; const char *filelist = NULL, *filename = NULL, *descfile = NULL;
compressor_t *cmp_toc, *cmp_files; compressor_t *cmp_toc, *cmp_files;
image_entry_t *list; image_entry_t *list;
pkg_writer_t *wr; pkg_writer_t *wr;
pkg_desc_t desc;
int i; int i;
cmp_toc = get_default_compressor(); cmp_toc = get_default_compressor();
@ -97,12 +99,21 @@ static int cmd_pack(int argc, char **argv)
case 'o': case 'o':
filename = optarg; filename = optarg;
break; break;
case 'd':
descfile = optarg;
break;
default: default:
tell_read_help(argv[0]); tell_read_help(argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (descfile == NULL) {
fputs("missing argument: package description file\n", stderr);
tell_read_help(argv[0]);
return EXIT_FAILURE;
}
if (filename == NULL) { if (filename == NULL) {
fputs("missing argument: output package file\n", stderr); fputs("missing argument: output package file\n", stderr);
tell_read_help(argv[0]); tell_read_help(argv[0]);
@ -118,9 +129,12 @@ static int cmd_pack(int argc, char **argv)
if (optind < argc) if (optind < argc)
fputs("warning: ignoring extra arguments\n", stderr); fputs("warning: ignoring extra arguments\n", stderr);
if (desc_read(descfile, &desc))
return EXIT_FAILURE;
list = filelist_read(filelist); list = filelist_read(filelist);
if (list == NULL) if (list == NULL)
return EXIT_FAILURE; goto fail_desc;
list = image_entry_sort(list); list = image_entry_sort(list);
@ -131,6 +145,9 @@ static int cmd_pack(int argc, char **argv)
if (wr == NULL) if (wr == NULL)
goto fail_fp; goto fail_fp;
if (write_header_data(wr, &desc))
goto fail;
if (write_toc(wr, list, cmp_toc)) if (write_toc(wr, list, cmp_toc))
goto fail; goto fail;
@ -139,11 +156,14 @@ static int cmd_pack(int argc, char **argv)
pkg_writer_close(wr); pkg_writer_close(wr);
image_entry_free_list(list); image_entry_free_list(list);
desc_free(&desc);
return EXIT_SUCCESS; return EXIT_SUCCESS;
fail: fail:
pkg_writer_close(wr); pkg_writer_close(wr);
fail_fp: fail_fp:
image_entry_free_list(list); image_entry_free_list(list);
fail_desc:
desc_free(&desc);
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -28,6 +28,16 @@ typedef struct {
size_t linenum; size_t linenum;
} input_file_t; } input_file_t;
typedef struct dependency_t {
struct dependency_t *next;
int type;
char name[];
} dependency_t;
typedef struct {
dependency_t *deps;
} pkg_desc_t;
image_entry_t *filelist_mkdir(input_file_t *f); image_entry_t *filelist_mkdir(input_file_t *f);
image_entry_t *filelist_mkslink(input_file_t *f); image_entry_t *filelist_mkslink(input_file_t *f);
@ -46,4 +56,10 @@ void cleanup_file(input_file_t *f);
int open_file(input_file_t *f, const char *filename); int open_file(input_file_t *f, const char *filename);
int desc_read(const char *path, pkg_desc_t *desc);
void desc_free(pkg_desc_t *desc);
int write_header_data(pkg_writer_t *wr, pkg_desc_t *desc);
#endif /* PACK_H */ #endif /* PACK_H */

40
main/cmd/pack/write_hdr.c Normal file
View File

@ -0,0 +1,40 @@
#include "pack.h"
int write_header_data(pkg_writer_t *wr, pkg_desc_t *desc)
{
pkg_dependency_t pkgdep;
size_t dep_count = 0;
dependency_t *dep;
pkg_header_t hdr;
for (dep = desc->deps; dep != NULL; dep = dep->next)
dep_count += 1;
if (dep_count > 0xFFFF) {
fputs("too many package dependencies\n", stderr);
return -1;
}
memset(&hdr, 0, sizeof(hdr));
hdr.num_depends = htole16(dep_count);
if (pkg_writer_write_payload(wr, &hdr, sizeof(hdr)))
return -1;
for (dep = desc->deps; dep != NULL; dep = dep->next) {
memset(&pkgdep, 0, sizeof(pkgdep));
pkgdep.type = dep->type;
pkgdep.name_length = strlen(dep->name);
if (pkg_writer_write_payload(wr, &pkgdep, sizeof(pkgdep)))
return -1;
if (pkg_writer_write_payload(wr, dep->name,
pkgdep.name_length)) {
return -1;
}
}
return pkg_writer_end_record(wr);
}

View File

@ -81,30 +81,47 @@ static int flush_to_file(pkg_writer_t *wr)
pkg_writer_t *pkg_writer_open(const char *path) pkg_writer_t *pkg_writer_open(const char *path)
{ {
pkg_writer_t *wr = calloc(1, sizeof(*wr)); pkg_writer_t *wr = calloc(1, sizeof(*wr));
compressor_t *cmp;
cmp = compressor_by_id(PKG_COMPRESSION_NONE);
if (cmp == NULL) {
fputs("missing built in dummy compessor\n", stderr);
return NULL;
}
if (wr == NULL) { if (wr == NULL) {
fputs("out of memory\n", stderr); fputs("out of memory\n", stderr);
return NULL; return NULL;
} }
wr->stream = cmp->compression_stream(cmp);
if (wr->stream == NULL) {
fputs("error creating compressor stream for package header\n",
stderr);
goto fail;
}
wr->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644); wr->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644);
if (wr->fd == -1) { if (wr->fd == -1) {
perror(path); perror(path);
free(wr); goto fail_stream;
return NULL;
} }
wr->path = path; wr->path = path;
wr->current.magic = PKG_MAGIC_HEADER; wr->current.magic = PKG_MAGIC_HEADER;
wr->current.compression = PKG_COMPRESSION_NONE; wr->current.compression = PKG_COMPRESSION_NONE;
if (write_header(wr)) { if (write_header(wr))
close(wr->fd); goto fail_close;
free(wr);
return NULL;
}
return wr; return wr;
fail_close:
close(wr->fd);
fail_stream:
wr->stream->destroy(wr->stream);
fail:
free(wr);
return NULL;
} }
void pkg_writer_close(pkg_writer_t *wr) void pkg_writer_close(pkg_writer_t *wr)