mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-11-22 04:49:46 +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/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
|
||||||
|
|
|
@ -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
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[] = {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
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 *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)
|
||||||
|
|
Loading…
Reference in a new issue