Switch pkg(7) from libyaml to libucl

This commit is contained in:
Baptiste Daroussin 2014-02-23 21:55:07 +00:00
parent 4ca4d6a814
commit 8a7d859ebf
3 changed files with 82 additions and 146 deletions

View File

@ -4,11 +4,11 @@ PROG= pkg
SRCS= pkg.c dns_utils.c config.c SRCS= pkg.c dns_utils.c config.c
MAN= pkg.7 MAN= pkg.7
CFLAGS+=-I${.CURDIR}/../../contrib/libyaml/include CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include
.PATH: ${.CURDIR}/../../contrib/libyaml/include .PATH: ${.CURDIR}/../../contrib/libucl/include
DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH} ${LIBYAML} ${LIBSBUF} ${LIBSSL} \ DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH} ${LIBUCL} ${LIBSBUF} ${LIBSSL} \
${LIBCRYPTO} ${LIBCRYPTO}
LDADD= -larchive -lelf -lfetch -lyaml -lsbuf -lssl -lcrypto LDADD= -larchive -lelf -lfetch -lucl -lsbuf -lssl -lcrypto
USEPRIVATELIB= yaml USEPRIVATELIB= ucl
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$");
#include <assert.h> #include <assert.h>
#include <dirent.h> #include <dirent.h>
#include <yaml.h> #include <ucl.h>
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
@ -509,76 +509,45 @@ boolstr_to_bool(const char *str)
} }
static void static void
config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype) config_parse(ucl_object_t *obj, pkg_conf_file_t conftype)
{ {
yaml_node_item_t *item;
yaml_node_pair_t *pair;
yaml_node_t *key, *val, *item_val;
struct sbuf *buf = sbuf_new_auto(); struct sbuf *buf = sbuf_new_auto();
ucl_object_t *cur, *seq;
ucl_object_iter_t it = NULL, itseq = NULL;
struct config_entry *temp_config; struct config_entry *temp_config;
struct config_value *cv; struct config_value *cv;
const char *key;
int i; int i;
size_t j; size_t j;
pair = node->data.mapping.pairs.start;
/* Temporary config for configs that may be disabled. */ /* Temporary config for configs that may be disabled. */
temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry));
while (pair < node->data.mapping.pairs.top) { while ((cur = ucl_iterate_object(obj, &it, true))) {
key = yaml_document_get_node(doc, pair->key); key = ucl_object_key(cur);
val = yaml_document_get_node(doc, pair->value); if (key == NULL)
/*
* ignoring silently empty keys can be empty lines
* or user mistakes
*/
if (key->data.scalar.length <= 0) {
++pair;
continue; continue;
}
/*
* silently skip on purpose to allow user to leave
* empty lines without complaining
*/
if (val->type == YAML_NO_NODE ||
(val->type == YAML_SCALAR_NODE &&
val->data.scalar.length <= 0)) {
++pair;
continue;
}
sbuf_clear(buf); sbuf_clear(buf);
if (conftype == CONFFILE_PKG) { if (conftype == CONFFILE_PKG) {
for (j = 0; j < strlen(key->data.scalar.value); ++j) for (j = 0; j < strlen(key); ++j)
sbuf_putc(buf, sbuf_putc(buf, key[j]);
toupper(key->data.scalar.value[j]));
sbuf_finish(buf); sbuf_finish(buf);
} else if (conftype == CONFFILE_REPO) { } else if (conftype == CONFFILE_REPO) {
/* The CONFFILE_REPO type is more restrictive. Only if (strcasecmp(key, "url") == 0)
parse known elements. */
if (strcasecmp(key->data.scalar.value, "url") == 0)
sbuf_cpy(buf, "PACKAGESITE"); sbuf_cpy(buf, "PACKAGESITE");
else if (strcasecmp(key->data.scalar.value, else if (strcasecmp(key, "mirror_type") == 0)
"mirror_type") == 0)
sbuf_cpy(buf, "MIRROR_TYPE"); sbuf_cpy(buf, "MIRROR_TYPE");
else if (strcasecmp(key->data.scalar.value, else if (strcasecmp(key, "signature_type") == 0)
"signature_type") == 0)
sbuf_cpy(buf, "SIGNATURE_TYPE"); sbuf_cpy(buf, "SIGNATURE_TYPE");
else if (strcasecmp(key->data.scalar.value, else if (strcasecmp(key, "fingerprints") == 0)
"fingerprints") == 0)
sbuf_cpy(buf, "FINGERPRINTS"); sbuf_cpy(buf, "FINGERPRINTS");
else if (strcasecmp(key->data.scalar.value, else if (strcasecmp(key, "enabled") == 0) {
"enabled") == 0) { if ((cur->type != UCL_BOOLEAN) ||
/* Skip disabled repos. */ !ucl_object_toboolean(cur))
if (!boolstr_to_bool(val->data.scalar.value))
goto cleanup; goto cleanup;
} else { /* Skip unknown entries for future use. */ } else
++pair;
continue; continue;
}
sbuf_finish(buf); sbuf_finish(buf);
} }
@ -588,51 +557,40 @@ config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype)
} }
/* Silently skip unknown keys to be future compatible. */ /* Silently skip unknown keys to be future compatible. */
if (i == CONFIG_SIZE) { if (i == CONFIG_SIZE)
++pair;
continue; continue;
}
/* env has priority over config file */ /* env has priority over config file */
if (c[i].envset) { if (c[i].envset)
++pair;
continue; continue;
}
/* Parse sequence value ["item1", "item2"] */ /* Parse sequence value ["item1", "item2"] */
switch (c[i].type) { switch (c[i].type) {
case PKG_CONFIG_LIST: case PKG_CONFIG_LIST:
if (val->type != YAML_SEQUENCE_NODE) { if (cur->type != UCL_ARRAY) {
fprintf(stderr, "Skipping invalid array " warnx("Skipping invalid array "
"value for %s.\n", c[i].key); "value for %s.\n", c[i].key);
++pair;
continue; continue;
} }
item = val->data.sequence.items.start;
temp_config[i].list = temp_config[i].list =
malloc(sizeof(*temp_config[i].list)); malloc(sizeof(*temp_config[i].list));
STAILQ_INIT(temp_config[i].list); STAILQ_INIT(temp_config[i].list);
while (item < val->data.sequence.items.top) { while ((seq = ucl_iterate_object(cur, &itseq, true))) {
item_val = yaml_document_get_node(doc, *item); if (seq->type != UCL_STRING)
if (item_val->type != YAML_SCALAR_NODE) {
++item;
continue; continue;
}
cv = malloc(sizeof(struct config_value)); cv = malloc(sizeof(struct config_value));
cv->value = cv->value =
strdup(item_val->data.scalar.value); strdup(ucl_object_tostring(seq));
STAILQ_INSERT_TAIL(temp_config[i].list, cv, STAILQ_INSERT_TAIL(temp_config[i].list, cv,
next); next);
++item;
} }
break; break;
default: default:
/* Normal string value. */ /* Normal string value. */
temp_config[i].value = strdup(val->data.scalar.value); temp_config[i].value = strdup(ucl_object_tostring(cur));
break; break;
} }
++pair;
} }
/* Repo is enabled, copy over all settings from temp_config. */ /* Repo is enabled, copy over all settings from temp_config. */
@ -662,27 +620,22 @@ config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype)
* etc... * etc...
*/ */
static void static void
parse_repo_file(yaml_document_t *doc, yaml_node_t *node) parse_repo_file(ucl_object_t *obj)
{ {
yaml_node_pair_t *pair; ucl_object_iter_t it = NULL;
ucl_object_t *cur;
const char *key;
pair = node->data.mapping.pairs.start; while ((cur = ucl_iterate_object(obj, &it, true))) {
while (pair < node->data.mapping.pairs.top) { key = ucl_object_key(cur);
yaml_node_t *key = yaml_document_get_node(doc, pair->key);
yaml_node_t *val = yaml_document_get_node(doc, pair->value);
if (key->data.scalar.length <= 0) { if (key == NULL)
++pair;
continue; continue;
}
if (val->type != YAML_MAPPING_NODE) { if (cur->type != UCL_OBJECT)
++pair;
continue; continue;
}
config_parse(doc, val, CONFFILE_REPO); config_parse(cur, CONFFILE_REPO);
++pair;
} }
} }
@ -690,37 +643,33 @@ parse_repo_file(yaml_document_t *doc, yaml_node_t *node)
static int static int
read_conf_file(const char *confpath, pkg_conf_file_t conftype) read_conf_file(const char *confpath, pkg_conf_file_t conftype)
{ {
FILE *fp; struct ucl_parser *p;
yaml_parser_t parser; ucl_object_t *obj = NULL;
yaml_document_t doc;
yaml_node_t *node;
if ((fp = fopen(confpath, "r")) == NULL) { p = ucl_parser_new(0);
if (!ucl_parser_add_file(p, confpath)) {
if (errno != ENOENT) if (errno != ENOENT)
err(EXIT_FAILURE, "Unable to open configuration " errx(EXIT_FAILURE, "Unable to parse configuration "
"file %s", confpath); "file %s: %s", confpath, ucl_parser_get_error(p));
ucl_parser_free(p);
/* no configuration present */ /* no configuration present */
return (1); return (1);
} }
yaml_parser_initialize(&parser); obj = ucl_parser_get_object(p);
yaml_parser_set_input_file(&parser, fp); if (obj->type != UCL_OBJECT)
yaml_parser_load(&parser, &doc);
node = yaml_document_get_root_node(&doc);
if (node == NULL || node->type != YAML_MAPPING_NODE)
warnx("Invalid configuration format, ignoring the " warnx("Invalid configuration format, ignoring the "
"configuration file %s", confpath); "configuration file %s", confpath);
else { else {
if (conftype == CONFFILE_PKG) if (conftype == CONFFILE_PKG)
config_parse(&doc, node, conftype); config_parse(obj, conftype);
else if (conftype == CONFFILE_REPO) else if (conftype == CONFFILE_REPO)
parse_repo_file(&doc, node); parse_repo_file(obj);
} }
yaml_document_delete(&doc); ucl_object_free(obj);
yaml_parser_delete(&parser); ucl_parser_free(p);
return (0); return (0);
} }

View File

@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <yaml.h> #include <ucl.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
@ -268,38 +268,28 @@ fetch_to_fd(const char *url, char *path)
} }
static struct fingerprint * static struct fingerprint *
parse_fingerprint(yaml_document_t *doc, yaml_node_t *node) parse_fingerprint(ucl_object_t *obj)
{ {
yaml_node_pair_t *pair; ucl_object_t *cur;
yaml_char_t *function, *fp; ucl_object_iter_t it = NULL;
const char *function, *fp, *key;
struct fingerprint *f; struct fingerprint *f;
hash_t fct = HASH_UNKNOWN; hash_t fct = HASH_UNKNOWN;
function = fp = NULL; function = fp = NULL;
pair = node->data.mapping.pairs.start; while ((cur = ucl_iterate_object(obj, &it, true))) {
while (pair < node->data.mapping.pairs.top) { key = ucl_object_key(cur);
yaml_node_t *key = yaml_document_get_node(doc, pair->key); if (cur->type != UCL_STRING)
yaml_node_t *val = yaml_document_get_node(doc, pair->value); continue;
if (strcasecmp(key, "function") == 0) {
if (key->data.scalar.length <= 0) { function = ucl_object_tostring(cur);
++pair;
continue; continue;
} }
if (strcasecmp(key, "fingerprint") == 0) {
if (val->type != YAML_SCALAR_NODE) { fp = ucl_object_tostring(cur);
++pair;
continue; continue;
} }
if (strcasecmp(key->data.scalar.value, "function") == 0)
function = val->data.scalar.value;
else if (strcasecmp(key->data.scalar.value, "fingerprint")
== 0)
fp = val->data.scalar.value;
++pair;
continue;
} }
if (fp == NULL || function == NULL) if (fp == NULL || function == NULL)
@ -309,7 +299,7 @@ parse_fingerprint(yaml_document_t *doc, yaml_node_t *node)
fct = HASH_SHA256; fct = HASH_SHA256;
if (fct == HASH_UNKNOWN) { if (fct == HASH_UNKNOWN) {
fprintf(stderr, "Unsupported hashing function: %s\n", function); warnx("Unsupported hashing function: %s\n", function);
return (NULL); return (NULL);
} }
@ -335,10 +325,8 @@ free_fingerprint_list(struct fingerprint_list* list)
static struct fingerprint * static struct fingerprint *
load_fingerprint(const char *dir, const char *filename) load_fingerprint(const char *dir, const char *filename)
{ {
yaml_parser_t parser; ucl_object_t *obj = NULL;
yaml_document_t doc; struct ucl_parser *p = NULL;
yaml_node_t *node;
FILE *fp;
struct fingerprint *f; struct fingerprint *f;
char path[MAXPATHLEN]; char path[MAXPATHLEN];
@ -346,24 +334,23 @@ load_fingerprint(const char *dir, const char *filename)
snprintf(path, MAXPATHLEN, "%s/%s", dir, filename); snprintf(path, MAXPATHLEN, "%s/%s", dir, filename);
if ((fp = fopen(path, "r")) == NULL) p = ucl_parser_new(0);
if (!ucl_parser_add_file(p, path)) {
warnx("%s: %s", path, ucl_parser_get_error(p));
ucl_parser_free(p);
return (NULL); return (NULL);
}
yaml_parser_initialize(&parser); obj = ucl_parser_get_object(p);
yaml_parser_set_input_file(&parser, fp);
yaml_parser_load(&parser, &doc);
node = yaml_document_get_root_node(&doc); if (obj->type == UCL_OBJECT)
if (node == NULL || node->type != YAML_MAPPING_NODE) f = parse_fingerprint(obj);
goto out;
f = parse_fingerprint(&doc, node); if (f != NULL)
f->name = strdup(filename); f->name = strdup(filename);
out: ucl_object_free(obj);
yaml_document_delete(&doc); ucl_parser_free(p);
yaml_parser_delete(&parser);
fclose(fp);
return (f); return (f);
} }