| |
static int pkg_set_deps_from_object(struct pkg *, ucl_object_t *);
|
| |
static int pkg_set_files_from_object(struct pkg *, ucl_object_t *);
|
| |
static int pkg_set_dirs_from_object(struct pkg *, ucl_object_t *);
|
| - |
static int parse_seq(struct pkg *, struct pkg_manifest_parser *, int);
|
| - |
static int parse_map(struct pkg *, struct pkg_manifest_parser *, int);
|
| - |
static int pkg_set_licenselogic_from_scalar(struct pkg *, struct pkg_manifest_parser *, int);
|
| - |
static int pkg_set_size_from_scalar(struct pkg *, struct pkg_manifest_parser *, int);
|
| - |
static int pkg_set_from_scalar(struct pkg *, struct pkg_manifest_parser *, int);
|
| - |
|
| - |
#define EV_SCALAR YAML_SCALAR_EVENT
|
| - |
#define EV_MAP YAML_MAPPING_START_EVENT
|
| - |
#define EV_SEQ YAML_SEQUENCE_START_EVENT
|
| - |
#define EV_NONE YAML_NO_EVENT
|
| - |
|
| - |
static struct mkey {
|
| - |
const char *key;
|
| - |
int type;
|
| - |
yaml_event_type_t valid_type;
|
| - |
int (*parse_data)(struct pkg *, struct pkg_manifest_parser *, int type);
|
| - |
} mkeys[] = {
|
| - |
{ "annotations", PKG_ANNOTATIONS, EV_MAP, parse_map},
|
| - |
{ "arch", PKG_ARCH, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "categories", PKG_CATEGORIES, EV_SEQ, parse_seq},
|
| - |
{ "comment", PKG_COMMENT, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "deps", PKG_DEPS, EV_MAP, parse_map},
|
| - |
{ "desc", PKG_DESC, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "directories", PKG_DIRECTORIES, EV_MAP, parse_map},
|
| - |
{ "dirs", PKG_DIRS, EV_SEQ, parse_seq},
|
| - |
{ "files", PKG_FILES, EV_MAP, parse_map},
|
| - |
{ "flatsize", PKG_FLATSIZE, EV_SCALAR, pkg_set_size_from_scalar},
|
| - |
{ "groups", PKG_GROUPS, EV_SEQ, parse_seq},
|
| - |
{ "groups", PKG_GROUPS, EV_MAP, parse_map},
|
| - |
{ "infos", PKG_INFOS, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "licenselogic", -1, EV_SCALAR, pkg_set_licenselogic_from_scalar},
|
| - |
{ "licenses", PKG_LICENSES, EV_SEQ, parse_seq},
|
| - |
{ "maintainer", PKG_MAINTAINER, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "message", PKG_MESSAGE, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "name", PKG_NAME, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "options", PKG_OPTIONS, EV_MAP, parse_map},
|
| - |
{ "origin", PKG_ORIGIN, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "path", PKG_REPOPATH, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "pkgsize", PKG_PKGSIZE, EV_SCALAR, pkg_set_size_from_scalar},
|
| - |
{ "prefix", PKG_PREFIX, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "scripts", PKG_SCRIPTS, EV_MAP, parse_map},
|
| - |
{ "shlibs_provided", PKG_SHLIBS_PROVIDED, EV_SEQ, parse_seq},
|
| - |
{ "shlibs_required", PKG_SHLIBS_REQUIRED, EV_SEQ, parse_seq},
|
| - |
{ "sum", PKG_CKSUM, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "users", PKG_USERS, EV_SEQ, parse_seq},
|
| - |
{ "users", PKG_USERS, EV_MAP, parse_map},
|
| - |
{ "version", PKG_VERSION, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ "www", PKG_WWW, EV_SCALAR, pkg_set_from_scalar},
|
| - |
{ NULL, -99, EV_NONE, NULL}
|
| - |
};
|
| |
|
| |
/*
|
| |
* Keep sorted
|
| |
UT_hash_handle hh;
|
| |
};
|
| |
|
| - |
struct pmk {
|
| - |
const char *key;
|
| - |
int type;
|
| - |
struct dparser *parser;
|
| - |
UT_hash_handle hh;
|
| - |
};
|
| - |
|
| - |
struct pkg_manifest_parser {
|
| - |
yaml_parser_t parser;
|
| - |
yaml_event_t event;
|
| - |
struct sbuf *buf;
|
| - |
struct pmk *keys;
|
| - |
};
|
| - |
|
| - |
int
|
| - |
pkg_manifest_parser_new(struct pkg_manifest_parser **p)
|
| - |
{
|
| - |
struct pmk *k;
|
| - |
struct dparser *dp;
|
| - |
int i;
|
| - |
|
| - |
if (*p != NULL) {
|
| - |
yaml_parser_delete(&(*p)->parser);
|
| - |
yaml_parser_initialize(&(*p)->parser);
|
| - |
return (EPKG_OK);
|
| - |
}
|
| - |
*p = calloc(1, sizeof(struct pkg_manifest_parser));
|
| - |
if (*p == NULL)
|
| - |
return (EPKG_FATAL);
|
| - |
|
| - |
yaml_parser_initialize(&(*p)->parser);
|
| - |
(*p)->buf = sbuf_new_auto();
|
| - |
|
| - |
for (i = 0; mkeys[i].key != NULL; i++) {
|
| - |
HASH_FIND_STR((*p)->keys, __DECONST(char *, mkeys[i].key), k);
|
| - |
if (k == NULL) {
|
| - |
k = calloc(1, sizeof(struct pmk));
|
| - |
k->key = mkeys[i].key;
|
| - |
k->type = mkeys[i].type;
|
| - |
HASH_ADD_KEYPTR(hh, (*p)->keys, __DECONST(char *, k->key), strlen(k->key), k);
|
| - |
}
|
| - |
HASH_FIND_YAMLEVT(k->parser, &mkeys[i].valid_type, dp);
|
| - |
if (dp != NULL)
|
| - |
continue;
|
| - |
dp = calloc(1, sizeof(struct dparser));
|
| - |
dp->type = mkeys[i].valid_type;
|
| - |
dp->parse_data = mkeys[i].parse_data;
|
| - |
HASH_ADD_YAMLEVT(k->parser, type, dp);
|
| - |
}
|
| - |
|
| - |
return (EPKG_OK);
|
| - |
}
|
| - |
|
| - |
static void
|
| - |
mk_free(struct pmk *key)
|
| - |
{
|
| - |
HASH_FREE(key->parser, dparser, free);
|
| - |
free(key);
|
| - |
}
|
| - |
|
| - |
void
|
| - |
pkg_manifest_parser_free(struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
if (p == NULL)
|
| - |
return;
|
| - |
|
| - |
yaml_parser_delete(&p->parser);
|
| - |
HASH_FREE(p->keys, pmk, mk_free);
|
| - |
}
|
| - |
|
| |
int
|
| |
pkg_manifest_keys_new(struct pkg_manifest_key **key)
|
| |
{
|
| |
}
|
| |
|
| |
static int
|
| - |
pkg_set_from_scalar(struct pkg *pkg, struct pkg_manifest_parser *p, int attr)
|
| - |
{
|
| - |
/* strip the scalar */
|
| - |
while (p->event.data.scalar.length > 0 &&
|
| - |
p->event.data.scalar.value[p->event.data.scalar.length - 1] == '\n') {
|
| - |
p->event.data.scalar.value[p->event.data.scalar.length - 1] = '\0';
|
| - |
p->event.data.scalar.length--;
|
| - |
}
|
| - |
|
| - |
return (urldecode(p->event.data.scalar.value, &pkg->fields[attr]));
|
| - |
}
|
| - |
|
| - |
static int
|
| - |
pkg_set_size_from_scalar(struct pkg *pkg, struct pkg_manifest_parser *p, int attr)
|
| - |
{
|
| - |
int64_t size;
|
| - |
const char *errstr = NULL;
|
| - |
|
| - |
size = strtonum(p->event.data.scalar.value, 0, INT64_MAX, &errstr);
|
| - |
if (errstr) {
|
| - |
pkg_emit_error("Unable to convert %s to int64: %s",
|
| - |
p->event.data.scalar.value, errstr);
|
| - |
return (EPKG_FATAL);
|
| - |
}
|
| - |
|
| - |
return (pkg_set(pkg, attr, size));
|
| - |
}
|
| - |
|
| - |
static int
|
| - |
pkg_set_licenselogic_from_scalar(struct pkg *pkg, struct pkg_manifest_parser *p, __unused int attr)
|
| - |
{
|
| - |
if (!strcmp(p->event.data.scalar.value, "single"))
|
| - |
pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t) LICENSE_SINGLE);
|
| - |
else if (!strcmp(p->event.data.scalar.value, "or") ||
|
| - |
!strcmp(p->event.data.scalar.value, "dual"))
|
| - |
pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t)LICENSE_OR);
|
| - |
else if (!strcmp(p->event.data.scalar.value, "and") ||
|
| - |
!strcmp(p->event.data.scalar.value, "multi"))
|
| - |
pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t)LICENSE_AND);
|
| - |
else {
|
| - |
pkg_emit_error("Unknown license logic: %s",
|
| - |
p->event.data.scalar.value);
|
| - |
return (EPKG_FATAL);
|
| - |
}
|
| - |
|
| - |
return (EPKG_OK);
|
| - |
}
|
| - |
|
| - |
static int
|
| - |
parse_seq(struct pkg * pkg, struct pkg_manifest_parser * p, int attr)
|
| - |
{
|
| - |
for (;;) {
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return (EPKG_FATAL);
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_SEQUENCE_END_EVENT)
|
| - |
break;
|
| - |
|
| - |
switch (attr) {
|
| - |
case PKG_CATEGORIES:
|
| - |
if (p->event.type != YAML_SCALAR_EVENT)
|
| - |
pkg_emit_error("Skipping malformed category");
|
| - |
else
|
| - |
pkg_addcategory(pkg, p->event.data.scalar.value);
|
| - |
break;
|
| - |
case PKG_LICENSES:
|
| - |
if (p->event.type != YAML_SCALAR_EVENT)
|
| - |
pkg_emit_error("Skipping malformed license");
|
| - |
else
|
| - |
pkg_addlicense(pkg, p->event.data.scalar.value);
|
| - |
break;
|
| - |
case PKG_USERS:
|
| - |
if (p->event.type == YAML_SCALAR_EVENT)
|
| - |
pkg_adduser(pkg, p->event.data.scalar.value);
|
| - |
else if (p->event.type == YAML_MAPPING_START_EVENT)
|
| - |
parse_map(pkg, p, attr);
|
| - |
else
|
| - |
pkg_emit_error("Skipping malformed users");
|
| - |
break;
|
| - |
case PKG_GROUPS:
|
| - |
if (p->event.type == YAML_SCALAR_EVENT)
|
| - |
pkg_addgroup(pkg, p->event.data.scalar.value);
|
| - |
else if (p->event.type == YAML_MAPPING_START_EVENT)
|
| - |
parse_map(pkg, p, attr);
|
| - |
else
|
| - |
pkg_emit_error("Skipping malformed groups");
|
| - |
break;
|
| - |
case PKG_DIRS:
|
| - |
if (p->event.type == YAML_SCALAR_EVENT)
|
| - |
pkg_adddir(pkg, p->event.data.scalar.value, 1, false);
|
| - |
else if (p->event.type == YAML_MAPPING_START_EVENT)
|
| - |
parse_map(pkg, p, attr);
|
| - |
else
|
| - |
pkg_emit_error("Skipping malformed dirs");
|
| - |
break;
|
| - |
case PKG_SHLIBS_REQUIRED:
|
| - |
if (p->event.type != YAML_SCALAR_EVENT)
|
| - |
pkg_emit_error("Skipping malformed required shared library");
|
| - |
else
|
| - |
pkg_addshlib_required(pkg, p->event.data.scalar.value);
|
| - |
break;
|
| - |
case PKG_SHLIBS_PROVIDED:
|
| - |
if (p->event.type != YAML_SCALAR_EVENT)
|
| - |
pkg_emit_error("Skipping malformed provided shared library");
|
| - |
else
|
| - |
pkg_addshlib_provided(pkg, p->event.data.scalar.value);
|
| - |
break;
|
| - |
}
|
| - |
}
|
| - |
return (EPKG_OK);
|
| - |
}
|
| - |
|
| - |
static void
|
| - |
parse_dep(struct pkg *pkg, struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
int state = 0;
|
| - |
char *orig = NULL, *vers = NULL;
|
| - |
|
| - |
sbuf_clear(p->buf);
|
| - |
sbuf_cat(p->buf, p->event.data.scalar.value);
|
| - |
sbuf_finish(p->buf);
|
| - |
|
| - |
for (;;) {
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
break;
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_MAPPING_START_EVENT)
|
| - |
continue;
|
| - |
|
| - |
if (p->event.type == YAML_MAPPING_END_EVENT)
|
| - |
break;
|
| - |
|
| - |
if (p->event.type != YAML_SCALAR_EVENT) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
break;
|
| - |
}
|
| - |
|
| - |
if (state == 0) {
|
| - |
if (strcmp(p->event.data.scalar.value, "origin") == 0)
|
| - |
state = 1;
|
| - |
else if (strcmp(p->event.data.scalar.value, "version") == 0)
|
| - |
state = 2;
|
| - |
continue;
|
| - |
}
|
| - |
|
| - |
if (state == 1) {
|
| - |
orig = strdup(p->event.data.scalar.value);
|
| - |
state = 0;
|
| - |
continue;
|
| - |
}
|
| - |
|
| - |
if (state == 2) {
|
| - |
vers = strdup(p->event.data.scalar.value);
|
| - |
state = 0;
|
| - |
continue;
|
| - |
}
|
| - |
}
|
| - |
|
| - |
if (orig != NULL && vers != NULL)
|
| - |
pkg_adddep(pkg, sbuf_data(p->buf), orig, vers, false);
|
| - |
else
|
| - |
pkg_emit_error("Skipping malformed dependency %s", sbuf_data(p->buf));
|
| - |
|
| - |
free(vers);
|
| - |
free(orig);
|
| - |
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
static void
|
| - |
parse_script(struct pkg *pkg, struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
pkg_script script_type;
|
| - |
|
| - |
script_type = script_type_str(p->event.data.scalar.value);
|
| - |
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
if (p->event.type != YAML_SCALAR_EVENT) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
urldecode(p->event.data.scalar.value, &p->buf);;
|
| - |
pkg_addscript(pkg, sbuf_data(p->buf), script_type);
|
| - |
}
|
| - |
|
| - |
static void
|
| - |
parse_file(struct pkg *pkg, struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
urldecode(p->event.data.scalar.value, &p->buf);
|
| - |
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_SCALAR_EVENT) {
|
| - |
pkg_addfile(pkg, sbuf_data(p->buf), p->event.data.scalar.value, false);
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_MAPPING_START_EVENT) {
|
| - |
/* TODO */
|
| - |
}
|
| - |
}
|
| - |
|
| - |
static void
|
| - |
parse_option(struct pkg *pkg, struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
sbuf_clear(p->buf);
|
| - |
sbuf_cat(p->buf, p->event.data.scalar.value);
|
| - |
sbuf_finish(p->buf);
|
| - |
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
if (p->event.type != YAML_SCALAR_EVENT) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
pkg_addoption(pkg, sbuf_data(p->buf), p->event.data.scalar.value);
|
| - |
}
|
| - |
|
| - |
static void
|
| - |
parse_directory(struct pkg *pkg, struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
urldecode(p->event.data.scalar.value, &p->buf);
|
| - |
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_SCALAR_EVENT) {
|
| - |
pkg_adddir(pkg, sbuf_data(p->buf), p->event.data.scalar.value[0] == 'y', false);
|
| - |
return;
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_MAPPING_START_EVENT) {
|
| - |
/* TODO */
|
| - |
}
|
| - |
}
|
| - |
|
| - |
static int
|
| - |
parse_map(struct pkg *pkg, struct pkg_manifest_parser *p, int attr)
|
| - |
{
|
| - |
for (;;) {
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
break;
|
| - |
}
|
| - |
|
| - |
if (p->event.type == YAML_MAPPING_END_EVENT)
|
| - |
break;
|
| - |
|
| - |
if (p->event.type != YAML_SCALAR_EVENT)
|
| - |
continue;
|
| - |
|
| - |
switch (attr) {
|
| - |
case PKG_DEPS:
|
| - |
parse_dep(pkg, p);
|
| - |
break;
|
| - |
case PKG_SCRIPTS:
|
| - |
parse_script(pkg, p);
|
| - |
break;
|
| - |
case PKG_FILES:
|
| - |
parse_file(pkg, p);
|
| - |
break;
|
| - |
case PKG_OPTIONS:
|
| - |
parse_option(pkg, p);
|
| - |
break;
|
| - |
case PKG_DIRECTORIES:
|
| - |
parse_directory(pkg, p);
|
| - |
break;
|
| - |
default:
|
| - |
break;
|
| - |
}
|
| - |
}
|
| - |
|
| - |
return (EPKG_OK);
|
| - |
}
|
| - |
|
| - |
static int
|
| |
pkg_string(struct pkg *pkg, ucl_object_t *obj, int attr)
|
| |
{
|
| |
int ret = EPKG_OK;
|
| |
}
|
| |
|
| |
static int
|
| - |
scan_manifest(struct pkg *pkg, struct pkg_manifest_parser *p)
|
| - |
{
|
| - |
int level = 0;
|
| - |
int rc = EPKG_OK;
|
| - |
struct pmk *selected_key;
|
| - |
struct dparser *dp;
|
| - |
|
| - |
pkg_debug(2, "%s", "Start scanning the manifest");
|
| - |
|
| - |
for (;;) {
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
rc = EPKG_FATAL;
|
| - |
break;
|
| - |
}
|
| - |
pkg_debug(3, "YAML event: %d\n", p->event.type);
|
| - |
if (p->event.type == YAML_STREAM_END_EVENT ||
|
| - |
p->event.type == YAML_DOCUMENT_END_EVENT)
|
| - |
break;
|
| - |
|
| - |
if (level == 0 &&
|
| - |
(p->event.type == YAML_STREAM_START_EVENT ||
|
| - |
p->event.type == YAML_DOCUMENT_START_EVENT))
|
| - |
continue;
|
| - |
|
| - |
if (level == 0 && p->event.type == YAML_MAPPING_START_EVENT) {
|
| - |
level++;
|
| - |
continue;
|
| - |
}
|
| - |
|
| - |
if (level == 0 && p->event.type == YAML_MAPPING_START_EVENT) {
|
| - |
pkg_emit_error("Invalid manifest format: la");
|
| - |
rc = EPKG_FATAL;
|
| - |
break;
|
| - |
}
|
| - |
|
| - |
if (level == 1 ) {
|
| - |
if (p->event.type == YAML_MAPPING_END_EVENT) {
|
| - |
level--;
|
| - |
continue;
|
| - |
}
|
| - |
|
| - |
if (p->event.type != YAML_SCALAR_EVENT) {
|
| - |
pkg_emit_error("Invalid manifest format");
|
| - |
rc = EPKG_FATAL;
|
| - |
break;
|
| - |
}
|
| - |
|
| - |
HASH_FIND_STR(p->keys, p->event.data.scalar.value, selected_key);
|
| - |
if (selected_key != NULL) {
|
| - |
pkg_debug(2, "Found keyword '%s'", p->event.data.scalar.value);
|
| - |
if (!yaml_parser_parse(&p->parser, &p->event)) {
|
| - |
pkg_emit_error("Inavlid manifest format");
|
| - |
rc = EPKG_FATAL;
|
| - |
break;
|
| - |
}
|
| - |
|
| - |
HASH_FIND_YAMLEVT(selected_key->parser, &p->event.type, dp);
|
| - |
if (dp != NULL) {
|
| - |
dp->parse_data(pkg, p , selected_key->type);
|
| - |
} else {
|
| - |
pkg_emit_error("No parser associated with '%s'", p->event.data.scalar.value);
|
| - |
rc = EPKG_FATAL;
|
| - |
break;
|
| - |
}
|
| - |
} else {
|
| - |
pkg_emit_error("Unknown keyword: '%s'", p->event.data.scalar.value);
|
| - |
rc = EPKG_FATAL;
|
| - |
break;
|
| - |
}
|
| - |
}
|
| - |
}
|
| - |
|
| - |
return (rc);
|
| - |
}
|
| - |
|
| - |
static int
|
| |
parse_manifest(struct pkg *pkg, struct pkg_manifest_key *keys, ucl_object_t *obj)
|
| |
{
|
| |
ucl_object_t *sub, *tmp;
|