Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/config.c
Show All 30 Lines | |||||
#include <assert.h> | #include <assert.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include "config.h" | #include "config.h" | ||||
static nvlist_t *config_root; | static config_node_t *config_root; | ||||
void | void | ||||
init_config(void) | init_config(void) | ||||
{ | { | ||||
nvlist_t *nvl = nvlist_create(0); | |||||
config_root = nvlist_create(0); | if (nvl == NULL) | ||||
yuripv: you probably meant to check nvl? | |||||
if (config_root == NULL) | |||||
err(4, "Failed to create configuration root nvlist"); | err(4, "Failed to create configuration root nvlist"); | ||||
config_root = (config_node_t *)nvl; | |||||
} | } | ||||
static nvlist_t * | static config_node_t * | ||||
_lookup_config_node(nvlist_t *parent, const char *path, bool create) | _lookup_config_node(const config_node_t *parent, const char *path, bool create) | ||||
jhbUnsubmitted Not Done Inline ActionsYou could drop this 'const' if you do from the public APIs, then you don't need any of the casts there since the compiler will see they are correct. My understanding is that illumos will use a completely separate config.c anyway, so this one can assume that config_node_t == nvlist_t in the implementation. jhb: You could drop this 'const' if you do from the public APIs, then you don't need any of the… | |||||
{ | { | ||||
char *copy, *name, *tofree; | char *copy, *name, *tofree; | ||||
nvlist_t *nvl, *new_nvl; | nvlist_t *nvl, *new_nvl; | ||||
copy = strdup(path); | copy = strdup(path); | ||||
if (copy == NULL) | if (copy == NULL) | ||||
errx(4, "Failed to allocate memory"); | errx(4, "Failed to allocate memory"); | ||||
tofree = copy; | tofree = copy; | ||||
nvl = parent; | nvl = (nvlist_t *)parent; | ||||
while ((name = strsep(©, ".")) != NULL) { | while ((name = strsep(©, ".")) != NULL) { | ||||
if (*name == '\0') { | if (*name == '\0') { | ||||
warnx("Invalid configuration node: %s", path); | warnx("Invalid configuration node: %s", path); | ||||
nvl = NULL; | nvl = NULL; | ||||
break; | break; | ||||
} | } | ||||
if (nvlist_exists_nvlist(nvl, name)) | if (nvlist_exists_nvlist(nvl, name)) | ||||
nvl = (nvlist_t *)nvlist_get_nvlist(nvl, name); | nvl = (nvlist_t *)nvlist_get_nvlist(nvl, name); | ||||
Show All 13 Lines | else if (nvlist_exists(nvl, name)) { | ||||
nvlist_move_nvlist(nvl, name, new_nvl); | nvlist_move_nvlist(nvl, name, new_nvl); | ||||
nvl = new_nvl; | nvl = new_nvl; | ||||
} else { | } else { | ||||
nvl = NULL; | nvl = NULL; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
free(tofree); | free(tofree); | ||||
return (nvl); | return ((config_node_t *)nvl); | ||||
} | } | ||||
nvlist_t * | config_node_t * | ||||
create_config_node(const char *path) | create_config_node(const char *path) | ||||
{ | { | ||||
return (_lookup_config_node(config_root, path, true)); | return (_lookup_config_node(config_root, path, true)); | ||||
} | } | ||||
nvlist_t * | config_node_t * | ||||
find_config_node(const char *path) | find_config_node(const char *path) | ||||
{ | { | ||||
return (_lookup_config_node(config_root, path, false)); | return (_lookup_config_node(config_root, path, false)); | ||||
} | } | ||||
nvlist_t * | config_node_t * | ||||
create_relative_config_node(nvlist_t *parent, const char *path) | create_relative_config_node(const config_node_t *parent, const char *path) | ||||
{ | { | ||||
return (_lookup_config_node(parent, path, true)); | return (_lookup_config_node(parent, path, true)); | ||||
} | } | ||||
nvlist_t * | config_node_t * | ||||
find_relative_config_node(nvlist_t *parent, const char *path) | find_relative_config_node(const config_node_t *parent, const char *path) | ||||
{ | { | ||||
return (_lookup_config_node(parent, path, false)); | return (_lookup_config_node(parent, path, false)); | ||||
} | } | ||||
void | void | ||||
set_config_value_node(nvlist_t *parent, const char *name, const char *value) | set_config_value_node(const config_node_t *node, const char *name, | ||||
const char *value) | |||||
{ | { | ||||
nvlist_t *parent = (nvlist_t *)node; | |||||
if (strchr(name, '.') != NULL) | if (strchr(name, '.') != NULL) | ||||
errx(4, "Invalid config node name %s", name); | errx(4, "Invalid config node name %s", name); | ||||
if (parent == NULL) | if (parent == NULL) | ||||
parent = config_root; | parent = (nvlist_t *)config_root; | ||||
if (nvlist_exists_string(parent, name)) | if (nvlist_exists_string(parent, name)) | ||||
nvlist_free_string(parent, name); | nvlist_free_string(parent, name); | ||||
else if (nvlist_exists(parent, name)) | else if (nvlist_exists(parent, name)) | ||||
errx(4, | errx(4, | ||||
"Attemping to add value %s to existing node %s of list %p", | "Attemping to add value %s to existing node %s of list %p", | ||||
value, name, parent); | value, name, parent); | ||||
nvlist_add_string(parent, name, value); | nvlist_add_string(parent, name, value); | ||||
} | } | ||||
void | void | ||||
set_config_value(const char *path, const char *value) | set_config_value(const char *path, const char *value) | ||||
{ | { | ||||
const char *name; | const char *name; | ||||
char *node_name; | char *node_name; | ||||
nvlist_t *nvl; | nvlist_t *nvl; | ||||
/* Look for last separator. */ | /* Look for last separator. */ | ||||
name = strrchr(path, '.'); | name = strrchr(path, '.'); | ||||
if (name == NULL) { | if (name == NULL) { | ||||
nvl = config_root; | nvl = (nvlist_t *)config_root; | ||||
name = path; | name = path; | ||||
} else { | } else { | ||||
node_name = strndup(path, name - path); | node_name = strndup(path, name - path); | ||||
if (node_name == NULL) | if (node_name == NULL) | ||||
errx(4, "Failed to allocate memory"); | errx(4, "Failed to allocate memory"); | ||||
nvl = create_config_node(node_name); | nvl = (nvlist_t *)create_config_node(node_name); | ||||
if (nvl == NULL) | if (nvl == NULL) | ||||
errx(4, "Failed to create configuration node %s", | errx(4, "Failed to create configuration node %s", | ||||
node_name); | node_name); | ||||
free(node_name); | free(node_name); | ||||
/* Skip over '.'. */ | /* Skip over '.'. */ | ||||
name++; | name++; | ||||
} | } | ||||
if (nvlist_exists_nvlist(nvl, name)) | if (nvlist_exists_nvlist(nvl, name)) | ||||
errx(4, "Attempting to add value %s to existing node %s", | errx(4, "Attempting to add value %s to existing node %s", | ||||
value, path); | value, path); | ||||
set_config_value_node(nvl, name, value); | set_config_value_node((config_node_t *)nvl, name, value); | ||||
} | } | ||||
static const char * | static const char * | ||||
get_raw_config_value(const char *path) | get_raw_config_value(const char *path) | ||||
{ | { | ||||
const char *name; | const char *name; | ||||
char *node_name; | char *node_name; | ||||
nvlist_t *nvl; | nvlist_t *nvl; | ||||
/* Look for last separator. */ | /* Look for last separator. */ | ||||
name = strrchr(path, '.'); | name = strrchr(path, '.'); | ||||
if (name == NULL) { | if (name == NULL) { | ||||
nvl = config_root; | nvl = (nvlist_t *)config_root; | ||||
name = path; | name = path; | ||||
} else { | } else { | ||||
node_name = strndup(path, name - path); | node_name = strndup(path, name - path); | ||||
if (node_name == NULL) | if (node_name == NULL) | ||||
errx(4, "Failed to allocate memory"); | errx(4, "Failed to allocate memory"); | ||||
nvl = find_config_node(node_name); | nvl = (nvlist_t *)find_config_node(node_name); | ||||
free(node_name); | free(node_name); | ||||
if (nvl == NULL) | if (nvl == NULL) | ||||
return (NULL); | return (NULL); | ||||
/* Skip over '.'. */ | /* Skip over '.'. */ | ||||
name++; | name++; | ||||
} | } | ||||
Show All 21 Lines | while (*vp != '\0') { | ||||
switch (*vp) { | switch (*vp) { | ||||
case '%': | case '%': | ||||
if (depth > 15) { | if (depth > 15) { | ||||
warnx( | warnx( | ||||
"Too many recursive references in configuration value"); | "Too many recursive references in configuration value"); | ||||
fputc('%', valfp); | fputc('%', valfp); | ||||
vp++; | vp++; | ||||
break; | break; | ||||
} | } | ||||
if (vp[1] != '(' || vp[2] == '\0') | if (vp[1] != '(' || vp[2] == '\0') | ||||
cp = NULL; | cp = NULL; | ||||
else | else | ||||
cp = strchr(vp + 2, ')'); | cp = strchr(vp + 2, ')'); | ||||
if (cp == NULL) { | if (cp == NULL) { | ||||
warnx( | warnx( | ||||
"Invalid reference in configuration value \"%s\"", | "Invalid reference in configuration value \"%s\"", | ||||
value); | value); | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | get_config_value(const char *path) | ||||
value = get_raw_config_value(path); | value = get_raw_config_value(path); | ||||
if (value == NULL) | if (value == NULL) | ||||
return (NULL); | return (NULL); | ||||
return (expand_config_value(value)); | return (expand_config_value(value)); | ||||
} | } | ||||
const char * | const char * | ||||
get_config_value_node(const nvlist_t *parent, const char *name) | get_config_value_node(const config_node_t *parent, const char *name) | ||||
{ | { | ||||
nvlist_t *nvl = (nvlist_t *)parent; | |||||
if (strchr(name, '.') != NULL) | if (strchr(name, '.') != NULL) | ||||
errx(4, "Invalid config node name %s", name); | errx(4, "Invalid config node name %s", name); | ||||
if (parent == NULL) | if (nvl == NULL) | ||||
parent = config_root; | nvl = (nvlist_t *)config_root; | ||||
if (nvlist_exists_nvlist(parent, name)) | if (nvlist_exists_nvlist(nvl, name)) | ||||
warnx("Attempt to fetch value of node %s of list %p", name, | warnx("Attempt to fetch value of node %s of list %p", name, | ||||
parent); | parent); | ||||
if (!nvlist_exists_string(parent, name)) | if (!nvlist_exists_string(nvl, name)) | ||||
return (NULL); | return (NULL); | ||||
return (expand_config_value(nvlist_get_string(parent, name))); | return (expand_config_value(nvlist_get_string(nvl, name))); | ||||
} | } | ||||
bool | bool | ||||
_bool_value(const char *name, const char *value) | _bool_value(const char *name, const char *value) | ||||
{ | { | ||||
if (strcasecmp(value, "true") == 0 || | if (strcasecmp(value, "true") == 0 || | ||||
strcasecmp(value, "on") == 0 || | strcasecmp(value, "on") == 0 || | ||||
Show All 26 Lines | get_config_bool_default(const char *path, bool def) | ||||
value = get_config_value(path); | value = get_config_value(path); | ||||
if (value == NULL) | if (value == NULL) | ||||
return (def); | return (def); | ||||
return (_bool_value(path, value)); | return (_bool_value(path, value)); | ||||
} | } | ||||
bool | bool | ||||
get_config_bool_node(const nvlist_t *parent, const char *name) | get_config_bool_node(const config_node_t *parent, const char *name) | ||||
{ | { | ||||
const char *value; | const char *value; | ||||
value = get_config_value_node(parent, name); | value = get_config_value_node(parent, name); | ||||
if (value == NULL) | if (value == NULL) | ||||
err(4, "Failed to fetch boolean variable %s", name); | err(4, "Failed to fetch boolean variable %s", name); | ||||
return (_bool_value(name, value)); | return (_bool_value(name, value)); | ||||
} | } | ||||
bool | bool | ||||
get_config_bool_node_default(const nvlist_t *parent, const char *name, | get_config_bool_node_default(const config_node_t *parent, const char *name, | ||||
bool def) | bool def) | ||||
{ | { | ||||
const char *value; | const char *value; | ||||
value = get_config_value_node(parent, name); | value = get_config_value_node(parent, name); | ||||
if (value == NULL) | if (value == NULL) | ||||
return (def); | return (def); | ||||
return (_bool_value(name, value)); | return (_bool_value(name, value)); | ||||
} | } | ||||
void | void | ||||
set_config_bool(const char *path, bool value) | set_config_bool(const char *path, bool value) | ||||
{ | { | ||||
set_config_value(path, value ? "true" : "false"); | set_config_value(path, value ? "true" : "false"); | ||||
} | } | ||||
void | void | ||||
set_config_bool_node(nvlist_t *parent, const char *name, bool value) | set_config_bool_node(config_node_t *parent, const char *name, bool value) | ||||
{ | { | ||||
set_config_value_node(parent, name, value ? "true" : "false"); | set_config_value_node(parent, name, value ? "true" : "false"); | ||||
} | } | ||||
const char * | |||||
config_node_next(const config_node_t *node, int *type, void **cookie) | |||||
{ | |||||
nvlist_t *nvl = (nvlist_t *)node; | |||||
return (nvlist_next(nvl, type, cookie)); | |||||
Done Inline Actionsparentheses around return value yuripv: parentheses around return value | |||||
} | |||||
static void | static void | ||||
dump_tree(const char *prefix, const nvlist_t *nvl) | dump_tree(const char *prefix, const nvlist_t *nvl) | ||||
{ | { | ||||
const char *name; | const char *name; | ||||
void *cookie; | void *cookie; | ||||
int type; | int type; | ||||
cookie = NULL; | cookie = NULL; | ||||
Show All 10 Lines | if (type == NV_TYPE_NVLIST) { | ||||
nvlist_get_string(nvl, name)); | nvlist_get_string(nvl, name)); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void | void | ||||
dump_config(void) | dump_config(void) | ||||
{ | { | ||||
dump_tree("", config_root); | dump_tree("", (nvlist_t *)config_root); | ||||
} | } |
you probably meant to check nvl?