mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-12-22 18:00:49 +01:00
Add package header with dependency information
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
47e237688b
commit
aab510aa98
7 changed files with 233 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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
113
main/cmd/pack/desc.c
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
40
main/cmd/pack/write_hdr.c
Normal 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);
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue