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/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/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
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;
typedef enum {
PKG_DEPENDENCY_REQUIRES = 0,
} PKG_DEPENDENCY_TYPE;
typedef struct {
uint32_t magic;
uint8_t compression;
@ -54,4 +58,15 @@ typedef struct {
/* uint8_t data[]; */
} 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 */

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

View File

@ -28,6 +28,16 @@ typedef struct {
size_t linenum;
} 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_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 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 */

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 *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) {
fputs("out of memory\n", stderr);
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);
if (wr->fd == -1) {
perror(path);
free(wr);
return NULL;
goto fail_stream;
}
wr->path = path;
wr->current.magic = PKG_MAGIC_HEADER;
wr->current.compression = PKG_COMPRESSION_NONE;
if (write_header(wr)) {
close(wr->fd);
free(wr);
return NULL;
}
if (write_header(wr))
goto fail_close;
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)