diff --git a/external/libucl/include/ucl.h b/external/libucl/include/ucl.h index 8376b8a..a464a00 100644 --- a/external/libucl/include/ucl.h +++ b/external/libucl/include/ucl.h @@ -32,6 +32,12 @@ #include #include +#ifdef _WIN32 +# define UCL_EXTERN __declspec(dllexport) +#else +# define UCL_EXTERN +#endif + /** * @mainpage * This is a reference manual for UCL API. You may find the description of UCL format by following this @@ -200,14 +206,14 @@ typedef struct ucl_object_s { * @param obj CL object * @return zero terminated key */ -char* ucl_copy_key_trash (ucl_object_t *obj); +UCL_EXTERN char* ucl_copy_key_trash (ucl_object_t *obj); /** * Copy and return a string value of an object, returned key is zero-terminated * @param obj CL object * @return zero terminated string representation of object value */ -char* ucl_copy_value_trash (ucl_object_t *obj); +UCL_EXTERN char* ucl_copy_value_trash (ucl_object_t *obj); /** * Creates a new object @@ -253,7 +259,7 @@ ucl_object_typed_new (unsigned int type) * @param flags conversion flags * @return new object */ -ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, +UCL_EXTERN ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; /** @@ -345,7 +351,7 @@ ucl_object_frombool (bool bv) * @param copy_key make an internal copy of key * @return new value of top object */ -ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, +UCL_EXTERN ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; /** @@ -358,10 +364,25 @@ ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, * @param copy_key make an internal copy of key * @return new value of top object */ -ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, +UCL_EXTERN ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; /** + * Delete a object associated with key 'key', old object will be unrefered, + * @param top object + * @param key key associated to the object to remove + * @param keylen length of the key (or 0 for NULL terminated keys) + */ +UCL_EXTERN bool ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen); + +/** + * Delete a object associated with key 'key', old object will be unrefered, + * @param top object + * @param key key associated to the object to remove + */ +UCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top, const char *key); + +/** * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, * try to merge its content * @param top destination object (will be created automatically if top is NULL) @@ -371,7 +392,7 @@ ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, * @param copy_key make an internal copy of key * @return new value of top object */ -ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, +UCL_EXTERN ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; /** @@ -791,7 +812,7 @@ ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) * @param key key to search * @return object matched the specified key or NULL if key is not found */ -ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key); +UCL_EXTERN ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key); /** * Return object identified by a fixed size key in the specified object @@ -800,7 +821,7 @@ ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key); * @param klen length of a key * @return object matched the specified key or NULL if key is not found */ -ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen); +UCL_EXTERN ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen); /** * Returns a key of an object as a NULL terminated string @@ -830,7 +851,7 @@ ucl_object_keyl (ucl_object_t *obj, size_t *len) * Free ucl object * @param obj ucl object to free */ -void ucl_object_free (ucl_object_t *obj); +UCL_EXTERN void ucl_object_free (ucl_object_t *obj); /** * Increase reference count for an object @@ -865,7 +886,7 @@ typedef void* ucl_object_iter_t; * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... * @return the next object or NULL */ -ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); +UCL_EXTERN ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); /** @} */ @@ -894,7 +915,7 @@ struct ucl_parser; * @param pool pool to allocate memory from * @return new parser object */ -struct ucl_parser* ucl_parser_new (int flags); +UCL_EXTERN struct ucl_parser* ucl_parser_new (int flags); /** * Register new handler for a macro @@ -903,7 +924,7 @@ struct ucl_parser* ucl_parser_new (int flags); * @param handler handler (it is called immediately after macro is parsed) * @param ud opaque user data for a handler */ -void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, +UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, ucl_macro_handler handler, void* ud); /** @@ -912,7 +933,7 @@ void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, * @param var variable name * @param value variable value */ -void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, +UCL_EXTERN void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, const char *value); /** @@ -923,7 +944,7 @@ void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, * @param err if *err is NULL it is set to parser error * @return true if chunk has been added and false in case of error */ -bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); +UCL_EXTERN bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); /** * Load and add data from a file @@ -932,7 +953,7 @@ bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, * @param err if *err is NULL it is set to parser error * @return true if chunk has been added and false in case of error */ -bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); +UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); /** * Get a top object for a parser @@ -940,18 +961,18 @@ bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); * @param err if *err is NULL it is set to parser error * @return top parser object or NULL */ -ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); +UCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); /** * Get the error string if failing * @param parser parser object */ -const char *ucl_parser_get_error(struct ucl_parser *parser); +UCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser); /** * Free ucl parser object * @param parser parser object */ -void ucl_parser_free (struct ucl_parser *parser); +UCL_EXTERN void ucl_parser_free (struct ucl_parser *parser); /** * Add new public key to parser for signatures check @@ -961,7 +982,7 @@ void ucl_parser_free (struct ucl_parser *parser); * @param err if *err is NULL it is set to parser error * @return true if a key has been successfully added */ -bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); +UCL_EXTERN bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); /** * Set FILENAME and CURDIR variables in parser @@ -970,7 +991,7 @@ bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t * @param need_expand perform realpath() if this variable is true and filename is not NULL * @return true if variables has been set */ -bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, +UCL_EXTERN bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand); /** @} */ @@ -1005,7 +1026,7 @@ struct ucl_emitter_functions { * #UCL_EMIT_CONFIG then emit config like object * @return dump of an object (must be freed after using) or NULL in case of error */ -unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); +UCL_EXTERN unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); /** * Emit object to a string @@ -1014,7 +1035,7 @@ unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); * #UCL_EMIT_CONFIG then emit config like object * @return dump of an object (must be freed after using) or NULL in case of error */ -bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, +UCL_EXTERN bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, struct ucl_emitter_functions *emitter); /** @} */ diff --git a/external/libucl/src/ucl_internal.h b/external/libucl/src/ucl_internal.h index e2a6d52..49c4aae 100644 --- a/external/libucl/src/ucl_internal.h +++ b/external/libucl/src/ucl_internal.h @@ -25,7 +25,9 @@ #define UCL_INTERNAL_H_ #include +#ifndef _WIN32 #include +#endif #include #include diff --git a/external/libucl/src/ucl_util.c b/external/libucl/src/ucl_util.c index 6ab1d38..34080d4 100644 --- a/external/libucl/src/ucl_util.c +++ b/external/libucl/src/ucl_util.c @@ -35,6 +35,75 @@ #include #endif +#ifdef _WIN32 +#include + +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_READWRITE 3 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_FAILED ((void *) -1) + +static void *mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset) +{ + void *map = NULL; + HANDLE handle = INVALID_HANDLE_VALUE; + + switch (prot) { + default: + case PROT_READ: + { + handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0); + if (!handle) break; + map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length); + CloseHandle(handle); + break; + } + case PROT_WRITE: + { + handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0); + if (!handle) break; + map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length); + CloseHandle(handle); + break; + } + case PROT_READWRITE: + { + handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0); + if (!handle) break; + map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length); + CloseHandle(handle); + break; + } + } + if (map == (void *) NULL) { + return (void *) MAP_FAILED; + } + return (void *) ((char *) map + offset); +} + +static int munmap(void *map,size_t length) +{ + if (!UnmapViewOfFile(map)) { + return(-1); + } + return(0); +} + +static char* realpath(const char *path, char *resolved_path) { + char *p; + char tmp[MAX_PATH + 1]; + strncpy(tmp, path, sizeof(tmp)-1); + p = tmp; + while(*p) { + if (*p == '/') *p = '\\'; + p++; + } + return _fullpath(resolved_path, tmp, MAX_PATH); +} +#endif + /** * @file rcl_util.c * Utilities for rcl parsing @@ -177,7 +246,7 @@ ucl_unescape_json_string (char *str, size_t len) return (t - str); } -char * +UCL_EXTERN char * ucl_copy_key_trash (ucl_object_t *obj) { if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { @@ -193,7 +262,7 @@ ucl_copy_key_trash (ucl_object_t *obj) return obj->trash_stack[UCL_TRASH_KEY]; } -char * +UCL_EXTERN char * ucl_copy_value_trash (ucl_object_t *obj) { if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { @@ -216,7 +285,7 @@ ucl_copy_value_trash (ucl_object_t *obj) return obj->trash_stack[UCL_TRASH_VALUE]; } -ucl_object_t* +UCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser) { if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) { @@ -226,7 +295,7 @@ ucl_parser_get_object (struct ucl_parser *parser) return NULL; } -void +UCL_EXTERN void ucl_parser_free (struct ucl_parser *parser) { struct ucl_stack *stack, *stmp; @@ -266,7 +335,7 @@ ucl_parser_free (struct ucl_parser *parser) UCL_FREE (sizeof (struct ucl_parser), parser); } -const char * +UCL_EXTERN const char * ucl_parser_get_error(struct ucl_parser *parser) { if (parser->err == NULL) @@ -275,7 +344,7 @@ ucl_parser_get_error(struct ucl_parser *parser) return utstring_body(parser->err); } -bool +UCL_EXTERN bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) { #ifndef HAVE_OPENSSL @@ -679,7 +748,7 @@ ucl_include_file (const unsigned char *data, size_t len, * @param err error ptr * @return */ -bool +UCL_EXTERN bool ucl_include_handler (const unsigned char *data, size_t len, void* ud) { struct ucl_parser *parser = ud; @@ -700,7 +769,7 @@ ucl_include_handler (const unsigned char *data, size_t len, void* ud) * @param err error ptr * @return */ -bool +UCL_EXTERN bool ucl_includes_handler (const unsigned char *data, size_t len, void* ud) { struct ucl_parser *parser = ud; @@ -714,7 +783,7 @@ ucl_includes_handler (const unsigned char *data, size_t len, void* ud) } -bool +UCL_EXTERN bool ucl_try_include_handler (const unsigned char *data, size_t len, void* ud) { struct ucl_parser *parser = ud; @@ -727,7 +796,7 @@ ucl_try_include_handler (const unsigned char *data, size_t len, void* ud) return ucl_include_url (data, len, parser, false, false); } -bool +UCL_EXTERN bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand) { char realbuf[PATH_MAX], *curdir; @@ -757,7 +826,7 @@ ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool n return true; } -bool +UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename) { unsigned char *buf; @@ -1055,6 +1124,29 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, return top; } +bool +ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen) +{ + ucl_object_t *found; + + found = ucl_object_find_keyl(top, key, keylen); + + if (found == NULL) + return false; + + ucl_hash_delete(top->value.ov, found); + ucl_object_unref (found); + top->len --; + + return true; +} + +bool +ucl_object_delete_key(ucl_object_t *top, const char *key) +{ + return ucl_object_delete_keyl(top, key, 0); +} + ucl_object_t * ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) diff --git a/libpkg/pkg.h.in b/libpkg/pkg.h.in index db91d21..9ae6c8b 100644 --- a/libpkg/pkg.h.in +++ b/libpkg/pkg.h.in @@ -56,6 +56,9 @@ #define PKG_PORTVERSION "%%PORTVERSION%%" +struct ucl_object_s; +typedef struct ucl_object_s pkg_object; + struct pkg; struct pkg_dep; struct pkg_conflict; @@ -1332,6 +1335,12 @@ typedef int(*pkg_plugin_callback)(void *data, struct pkgdb *db); int pkg_plugins_hook_run(pkg_plugin_hook_t hook, void *data, struct pkgdb *db); int pkg_plugin_hook_register(struct pkg_plugin *p, pkg_plugin_hook_t hook, pkg_plugin_callback callback); +/* + * pkg object + */ + +pkg_object *pkg_config_get(pkg_object *o, const char *key); + /** * Get the value of a configuration key */ diff --git a/libpkg/pkg_config.c b/libpkg/pkg_config.c index 8acdf73..6a366ca 100644 --- a/libpkg/pkg_config.c +++ b/libpkg/pkg_config.c @@ -58,7 +58,7 @@ struct config_entry { static char myabi[BUFSIZ]; static struct pkg_repo *repos = NULL; -static struct pkg_config *config = NULL; +static pkg_object *config = NULL; static struct pkg_config *config_by_key = NULL; static struct config_entry c[] = { @@ -357,125 +357,6 @@ connect_evpipe(const char *evpipe) { } -static void -obj_walk_array(ucl_object_t *obj, struct pkg_config *conf) -{ - struct pkg_config_value *v; - ucl_object_t *cur; - ucl_object_iter_t it = NULL; - - while ((cur = ucl_iterate_object(obj, &it, true))) { - if (cur->type != UCL_STRING) - continue; - v = malloc(sizeof(struct pkg_config_value)); - v->value = strdup(ucl_object_tostring(cur)); - HASH_ADD_STR(conf->list, value, v); - } -} - -static void -obj_walk_object(ucl_object_t *obj, struct pkg_config *conf) -{ - struct pkg_config_kv *kv; - ucl_object_t *cur; - ucl_object_iter_t it = NULL; - const char *key; - - while ((cur = ucl_iterate_object(obj, &it, true))) { - if (cur->type != UCL_STRING) - continue; - kv = malloc(sizeof(struct pkg_config_kv)); - key = ucl_object_key(cur); - if (key == NULL) - continue; - kv->key = strdup(key); - kv->value = strdup(ucl_object_tostring(cur)); - HASH_ADD_STR(conf->kvlist, value, kv); - } -} - -void -pkg_object_walk(ucl_object_t *obj, struct pkg_config *conf_by_key) -{ - ucl_object_t *cur; - ucl_object_iter_t it = NULL; - struct sbuf *b = sbuf_new_auto(); - struct pkg_config *conf; - const char *key; - size_t i; - - while ((cur = ucl_iterate_object(obj, &it, true))) { - sbuf_clear(b); - key = ucl_object_key(cur); - if (key == NULL) - continue; - for (i = 0; i < strlen(key); i++) - sbuf_putc(b, toupper(key[i])); - sbuf_finish(b); - - HASH_FIND(hhkey, conf_by_key, sbuf_data(b), (size_t)sbuf_len(b), conf); - if (conf != NULL) { - switch (conf->type) { - case PKG_CONFIG_STRING: - if (cur->type != UCL_STRING) { - pkg_emit_error("Expecting a string for key %s," - " ignoring...", key); - continue; - } - if (!conf->fromenv) { - free(conf->string); - conf->string = strdup(ucl_object_tostring(cur)); - } - break; - case PKG_CONFIG_INTEGER: - if (cur->type != UCL_INT) { - pkg_emit_error("Expecting an integer for key %s," - " ignoring...", key); - continue; - } - if (!conf->fromenv) - conf->integer = ucl_object_toint(cur); - break; - case PKG_CONFIG_BOOL: - if (cur->type != UCL_BOOLEAN) { - pkg_emit_error("Expecting a boolean for key %s," - " ignoring...", key); - continue; - } - - if (!conf->fromenv) - conf->boolean = ucl_object_toboolean(cur); - break; - case PKG_CONFIG_LIST: - if (cur->type != UCL_ARRAY) { - pkg_emit_error("Expecting a list for key %s," - " ignoring...", key); - continue; - } - if (!conf->fromenv) { - HASH_FREE(conf->list, pkg_config_value, pkg_config_value_free); - conf->list = NULL; - obj_walk_array(cur, conf); - } - break; - case PKG_CONFIG_KVLIST: - if (cur->type != UCL_OBJECT) { - pkg_emit_error("Expecting a mapping for key %s," - " ignoring...", key); - continue; - } - if (!conf->fromenv) { - HASH_FREE(conf->kvlist, pkg_config_kv, pkg_config_kv_free); - conf->kvlist = NULL; - obj_walk_object(cur, conf); - } - break; - } - } - } - sbuf_delete(b); -} - static char * subst_packagesite_str(const char *oldstr) { @@ -507,154 +388,10 @@ pkg_initialized(void) return (parsed); } -int -pkg_config_desc(pkg_config_key key, const char **desc) -{ - struct pkg_config *conf; - - if (parsed != true) { - pkg_emit_error("pkg_init() must be called before pkg_config_desc()"); - return (EPKG_FATAL); - } - - HASH_FIND_INT(config, &key, conf); - if (conf == NULL) - *desc = NULL; - else - *desc = conf->desc; - - return (EPKG_OK); -} - -int -pkg_config_string(pkg_config_key key, const char **val) -{ - struct pkg_config *conf; - - if (parsed != true) { - pkg_emit_error("pkg_init() must be called before pkg_config_string()"); - return (EPKG_FATAL); - } - - HASH_FIND_INT(config, &key, conf); - if (conf == NULL) - *val = NULL; - else - *val = conf->string; - - return (EPKG_OK); -} - -int -pkg_config_int64(pkg_config_key key, int64_t *val) -{ - struct pkg_config *conf; - - if (parsed != true) { - pkg_emit_error("pkg_init() must be called before pkg_config_int64()"); - return (EPKG_FATAL); - } - - HASH_FIND_INT(config, &key, conf); - if (conf == NULL) - return (EPKG_FATAL); - - *val = conf->integer; - - return (EPKG_OK); -} - -int -pkg_config_bool(pkg_config_key key, bool *val) -{ - struct pkg_config *conf; - - if (parsed != true) { - pkg_emit_error("pkg_init() must be called before pkg_config_bool()"); - return (EPKG_FATAL); - } - - HASH_FIND_INT(config, &key, conf); - if (conf == NULL) - return (EPKG_FATAL); - - *val = conf->boolean; - - return (EPKG_OK); -} - -int -pkg_config_kvlist(pkg_config_key key, struct pkg_config_kv **kv) -{ - struct pkg_config *conf; - - if (parsed != true) { - pkg_emit_error("pkg_init() must be called before pkg_config_kvlist()"); - return (EPKG_FATAL); - } - - HASH_FIND_INT(config, &key, conf); - if (conf == NULL) - return (EPKG_FATAL); - - if (conf->type != PKG_CONFIG_KVLIST) { - pkg_emit_error("this config entry is not a \"key: value\" list"); - return (EPKG_FATAL); - } - - HASH_NEXT(conf->kvlist, (*kv)); -} - -int -pkg_config_list(pkg_config_key key, struct pkg_config_value **v) -{ - struct pkg_config *conf; - - if (parsed != true) { - pkg_emit_error("pkg_init() must be called before pkg_config_list()"); - return (EPKG_FATAL); - } - - HASH_FIND_INT(config, &key, conf); - if (conf == NULL) - return (EPKG_FATAL); - - if (conf->type != PKG_CONFIG_LIST) { - pkg_emit_error("this config entry is not a list"); - return (EPKG_FATAL); - } - - HASH_NEXT(conf->list, (*v)); -} - -const char * -pkg_config_value(struct pkg_config_value *v) -{ - assert(v != NULL); - - return (v->value); -} - - -const char * -pkg_config_kv_get(struct pkg_config_kv *kv, pkg_config_kv_t type) -{ - assert(kv != NULL); - - switch (type) { - case PKG_CONFIG_KV_KEY: - return (kv->key); - break; - case PKG_CONFIG_KV_VALUE: - return (kv->value); - break; - } - return (NULL); -} - static void disable_plugins_if_static(void) { + pkg_object *o; void *dlh; struct pkg_config *conf; pkg_config_key k = PKG_CONFIG_ENABLE_PLUGINS; @@ -940,17 +677,19 @@ pkg_init(const char *path, const char *reposdir) struct ucl_parser *p = NULL; size_t i; const char *val = NULL; - const char *buf, *walk, *value, *key; + const char *buf, *walk, *key, *fkey; const char *errstr = NULL; const char *evkey = NULL; const char *nsname = NULL; const char *evpipe = NULL; - struct pkg_config *conf; struct pkg_config_value *v; struct pkg_config_kv *kv; - ucl_object_t *obj = NULL, *cur; + ucl_object_t *obj = NULL, *cur, *o; + ucl_object_t *value; ucl_object_iter_t it = NULL; + pkg_object *conf; bool fallback = false; + struct sbuf *lkey; pkg_get_myarch(myabi, BUFSIZ); if (parsed != false) { @@ -958,188 +697,163 @@ pkg_init(const char *path, const char *reposdir) return (EPKG_FATAL); } + if (path == NULL) + path = PREFIX"/etc/pkg.conf"; + + p = ucl_parser_new(0); + + errno = 0; + if (!ucl_parser_add_file(p, path)) { + if (errno == ENOENT) + goto parsed; + pkg_emit_error("%s", ucl_parser_get_error(p)); + return (EPKG_FATAL); + } + + /* Validate the first level of the configuration */ + obj = ucl_parser_get_object(p); + if (obj->type == UCL_OBJECT) { + while ((cur = ucl_iterate_object(obj, &it, true))) { + key = ucl_object_key(cur); + if (key == NULL) + continue; + if (strcasecmp(key, "REPOS_DIR") == 0 && + cur->type != UCL_ARRAY) { + ucl_object_delete_key(obj, "REPOS_DIR"); + pkg_emit_error("REPOS_DIR is not an array, ignoring"); + } else if (strcasecmp(key, "PKG_ENV") == 0 && + cur->type != UCL_OBJECT) { + ucl_object_delete_key(obj, "PKG_ENV"); + pkg_emit_error("PKG_ENV is not an object, ignoring"); + } else if (strcasecmp(key, "ALIAS") == 0 && + cur->type != UCL_OBJECT) { + ucl_object_delete_key(obj, "ALIAS"); + pkg_emit_error("ALIAS is not an object, ignoring"); + } + } + } + + lkey = sbuf_new_auto(); + for (i = 0; i < c_size; i++) { - conf = malloc(sizeof(struct pkg_config)); - conf->id = i; - conf->key = c[i].key; - conf->type = c[i].type; - conf->desc = c[i].desc; - conf->fromenv = false; + conf = ucl_object_typed_new(UCL_OBJECT); val = getenv(c[i].key); + sbuf_clear(lkey); + buf = c[i].key; + while (*buf != '\0') { + sbuf_putc(lkey, tolower(*buf)); + buf++; + } + sbuf_done(lkey); + + fkey = c[i].key; + if ((o = ucl_object_find_key(config, c[i].key)) == NULL) { + fkey = sbuf_data(lkey); + o = ucl_object_find_keyl(config, sbuf_data(lkey), sbuf_len(lkey)); + } + + value == NULL; + switch (c[i].type) { case PKG_CONFIG_STRING: - if (val != NULL) { - if (strcmp(c[i].key, "PACKAGESITE") == 0) - conf->string = subst_packagesite_str(val); + if (val != NULL) + value = ucl_object_fromstring(val); + else if (o == NULL) { + if (c[i].def != NULL) + value = ucl_object_fromstring(c[i].def); else - conf->string = strdup(val); - conf->fromenv = true; + value = ucl_object_typed_new(UCL_STRING); } - else if (c[i].def != NULL) - conf->string = strdup(c[i].def); - else - conf->string = NULL; - break; case PKG_CONFIG_INTEGER: - if (val == NULL) - val = c[i].def; - else - conf->fromenv = true; - conf->integer = strtonum(val, 0, INT64_MAX, &errstr); - if (errstr != NULL) { - pkg_emit_error("Unable to convert %s to int64: %s", - val, errstr); - free(conf); - return (EPKG_FATAL); + if (val != NULL) { + value = ucl_object_fromstring_common(val, UCL_STRING_PARSE_INT); + if (value->type != UCL_INT) { + ucl_object_free(value); + value = NULL; + } + } else if (o == NULL) { + if (c[i].def != NULL) + value = ucl_object_fromstring_common(c[i].def, UCL_STRING_PARSE_INT); + else + value = ucl_object_fromint(0); } break; case PKG_CONFIG_BOOL: - if (val == NULL) - val = c[i].def; - else - conf->fromenv = true; - if (val != NULL && ( - strcmp(val, "1") == 0 || - strcasecmp(val, "yes") == 0 || - strcasecmp(val, "true") == 0 || - strcasecmp(val, "on") == 0)) { - conf->boolean = true; - } else { - conf->boolean = false; + if (val != NULL) { + value = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN); + if (value->type != UCL_BOOLEAN) { + ucl_object_free(value); + value = NULL; + } + } else if (o == NULL) { + if (c[i].def != NULL) + value = ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN); + else + value = ucl_object_frombool(false); } break; case PKG_CONFIG_KVLIST: - conf->kvlist = NULL; - if (val == NULL) + if (val == NULL && o != NULL) + break; + + if (val == NULL && o == NULL) val = c[i].def; - else - conf->fromenv = false; - if (val != NULL) { - walk = buf = val; - while ((buf = strchr(buf, ',')) != NULL) { - key = walk; - value = walk; - while (*value != ',') { - if (*value == '=') - break; - value++; - } - if (value == buf || (value - key) == 0) { - pkg_emit_error("Malformed Key/Value for %s", c[i].key); - pkg_config_kv_free(conf->kvlist); - conf->kvlist = NULL; - break; - } - kv = malloc(sizeof(struct pkg_config_kv)); - kv->key = strndup(key, value - key); - kv->value = strndup(value + 1, buf - value -1); - HASH_ADD_STR(conf->kvlist, value, kv); - buf++; - walk = buf; - } + + if (val == NULL) { + value = ucl_object_typed_new(UCL_OBJECT); + break; + } + + walk = buf = val; + while ((buf = strchr(buf, ',')) != NULL) { key = walk; value = walk; - while (*value != '\0') { + while (*value != ',') { if (*value == '=') break; value++; } - if (*value == '\0' || (value - key) == 0) { - pkg_emit_error("Malformed Key/Value for %s: %s", c[i].key, val); - pkg_config_kv_free(conf->kvlist); - conf->kvlist = NULL; + if (value == buf || (value - key) == 0) { + pkg_emit_error("Malformed Key/Value for %s", c[i].key); + ucl_object_unref(value); + value = NULL; break; } - kv = malloc(sizeof(struct pkg_config_kv)); - kv->key = strndup(key, value - key); - kv->value = strdup(value + 1); - HASH_ADD_STR(conf->kvlist, value, kv); + value = ucl_object_insert_key(value, + ucl_object_fromstring_common(value + 1, buf - value -1, 0), + key, value - key, true); + buf++; + walk = buf; } break; case PKG_CONFIG_LIST: - conf->list = NULL; - if (val == NULL) - val = c[i].def; - else - conf->fromenv = true; - if (val != NULL) { - walk = buf = val; - while ((buf = strchr(buf, ',')) != NULL) { - v = malloc(sizeof(struct pkg_config_value)); - v->value = strndup(walk, buf - walk); - HASH_ADD_STR(conf->list, value, v); - buf++; - walk = buf; - } - v = malloc(sizeof(struct pkg_config_value)); - v->value = strdup(walk); - HASH_ADD_STR(conf->list, value, v); - } - break; - } - - HASH_ADD_INT(config, id, conf); - HASH_ADD_KEYPTR(hhkey, config_by_key, conf->key, - strlen(conf->key), conf); - } - - if (path == NULL) - path = PREFIX"/etc/pkg.conf"; + if (val == NULL && o != NULL) + break; - p = ucl_parser_new(0); + if (val == NULL && o == NULL) + val = c[i].def; - errno = 0; - if (!ucl_parser_add_file(p, path)) { - if (errno == ENOENT) - goto parsed; - fallback = true; - } + if (val == NULL) { + value = ucl_object_typed_new(UCL_ARRAY); + break; + } - if (!fallback) { - /* Validate the first level of the configuration */ - obj = ucl_parser_get_object(p); - if (obj->type == UCL_OBJECT) { - while ((cur = ucl_iterate_object(obj, &it, true))) { - key = ucl_object_key(cur); - if (key == NULL) - continue; - if (strcasecmp(key, "REPOS_DIR") == 0 && - cur->type != UCL_ARRAY) - fallback = true; - else if (strcasecmp(key, "PKG_ENV") == 0 && - cur->type != UCL_OBJECT) - fallback = true; - else if (strcasecmp(key, "ALIAS") == 0 && - cur->type != UCL_OBJECT) - fallback = true; - if (fallback) - break; + walk = buf = val; + while ((buf = strchr(buf, ',')) != NULL) { + value = ucl_array_append(value, ucl_object_fromstring_common(walk, buf - walk, 0)); + buf++; + walk = buf; } - } else { - fallback = true; + break; } - } - if (fallback) { - if (obj != NULL) - ucl_object_free(obj); - obj = yaml_to_ucl(path, NULL, 0); - if (obj == NULL) - return (EPKG_FATAL); - } + if (value != NULL) + ucl_object_replace_key(config, value, fkey, strlen(fkey), true); + ucl_object_insert_key(config, ucl_object_fromstring(c[i].desc, fkey, strlen(fkey), true); - if (fallback) { - pkg_emit_error("Your pkg.conf file is in deprecated format you " - "should convert it to the following format:\n" - "====== BEGIN pkg.conf ======\n" - "%s" - "\n====== END pkg.conf ======\n", - ucl_object_emit(obj, UCL_EMIT_YAML)); } - if (obj->type == UCL_OBJECT) - pkg_object_walk(obj, config_by_key); parsed: disable_plugins_if_static(); diff --git a/libpkg/private/pkg.h b/libpkg/private/pkg.h index 85c9cb8..36476b3 100644 --- a/libpkg/private/pkg.h +++ b/libpkg/private/pkg.h @@ -274,7 +274,7 @@ struct pkg_config { char *string; uint64_t integer; bool boolean; - struct pkg_config_kv *kvlist; + ucl_object_t *kvlist; struct pkg_config_value *list; }; UT_hash_handle hh;