summaryrefslogtreecommitdiffstats
path: root/lib/config/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/config/config.c')
-rw-r--r--lib/config/config.c1255
1 files changed, 62 insertions, 1193 deletions
diff --git a/lib/config/config.c b/lib/config/config.c
index d7b70425..39dded0c 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -13,7 +13,9 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include "lib.h"
+
#include "config.h"
#include "crc.h"
#include "device.h"
@@ -28,170 +30,20 @@
#include <fcntl.h>
#include <ctype.h>
-#define SECTION_B_CHAR '{'
-#define SECTION_E_CHAR '}'
-
-enum {
- TOK_INT,
- TOK_FLOAT,
- TOK_STRING, /* Single quotes */
- TOK_STRING_ESCAPED, /* Double quotes */
- TOK_EQ,
- TOK_SECTION_B,
- TOK_SECTION_E,
- TOK_ARRAY_B,
- TOK_ARRAY_E,
- TOK_IDENTIFIER,
- TOK_COMMA,
- TOK_EOF
-};
-
-struct parser {
- const char *fb, *fe; /* file limits */
-
- int t; /* token limits and type */
- const char *tb, *te;
-
- int fd; /* descriptor for file being parsed */
- int line; /* line number we are on */
-
- struct dm_pool *mem;
-};
-
-struct cs {
- struct config_tree cft;
- struct dm_pool *mem;
- time_t timestamp;
- off_t st_size;
- char *filename;
- int exists;
- int keep_open;
- struct device *dev;
-};
-
-struct output_line {
- FILE *fp;
- struct dm_pool *mem;
- putline_fn putline;
- void *putline_baton;
-};
-
-static void _get_token(struct parser *p, int tok_prev);
-static void _eat_space(struct parser *p);
-static struct config_node *_file(struct parser *p);
-static struct config_node *_section(struct parser *p);
-static struct config_value *_value(struct parser *p);
-static struct config_value *_type(struct parser *p);
-static int _match_aux(struct parser *p, int t);
-static struct config_value *_create_value(struct dm_pool *mem);
-static struct config_node *_create_node(struct dm_pool *mem);
-static char *_dup_tok(struct parser *p);
-
-static const int sep = '/';
-
-#define MAX_INDENT 32
-
-#define match(t) do {\
- if (!_match_aux(p, (t))) {\
- log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
- p->tb - p->fb + 1, p->line); \
- return 0;\
- } \
-} while(0);
-
-static int _tok_match(const char *str, const char *b, const char *e)
+void destroy_config_tree(struct dm_config_tree *cft)
{
- while (*str && (b != e)) {
- if (*str++ != *b++)
- return 0;
- }
+ struct device *dev = dm_config_get_custom(cft);
- return !(*str || (b != e));
-}
+ if (dev)
+ dev_close(dev);
-/*
- * public interface
- */
-struct config_tree *create_config_tree(const char *filename, int keep_open)
-{
- struct cs *c;
- struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
-
- if (!mem) {
- log_error("Failed to allocate config pool.");
- return 0;
- }
-
- if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
- log_error("Failed to allocate config tree.");
- dm_pool_destroy(mem);
- return 0;
- }
-
- c->mem = mem;
- c->cft.root = (struct config_node *) NULL;
- c->timestamp = 0;
- c->exists = 0;
- c->keep_open = keep_open;
- c->dev = 0;
- if (filename)
- c->filename = dm_pool_strdup(c->mem, filename);
- return &c->cft;
-}
-
-void destroy_config_tree(struct config_tree *cft)
-{
- struct cs *c = (struct cs *) cft;
-
- if (c->dev)
- dev_close(c->dev);
-
- dm_pool_destroy(c->mem);
-}
-
-static int _parse_config_file(struct parser *p, struct config_tree *cft)
-{
- p->tb = p->te = p->fb;
- p->line = 1;
- _get_token(p, TOK_SECTION_E);
- if (!(cft->root = _file(p)))
- return_0;
-
- return 1;
-}
-
-struct config_tree *create_config_tree_from_string(const char *config_settings)
-{
- struct cs *c;
- struct config_tree *cft;
- struct parser *p;
-
- if (!(cft = create_config_tree(NULL, 0)))
- return_NULL;
-
- c = (struct cs *) cft;
- if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
- log_error("Failed to allocate config tree parser.");
- destroy_config_tree(cft);
- return NULL;
- }
-
- p->mem = c->mem;
- p->fb = config_settings;
- p->fe = config_settings + strlen(config_settings);
-
- if (!_parse_config_file(p, cft)) {
- destroy_config_tree(cft);
- return_NULL;
- }
-
- return cft;
+ dm_config_destroy(cft);
}
int override_config_tree_from_string(struct cmd_context *cmd,
const char *config_settings)
{
- if (!(cmd->cft_override = create_config_tree_from_string(config_settings))) {
+ if (!(cmd->cft_override = dm_config_from_string(config_settings))) {
log_error("Failed to set overridden configuration entries.");
return 1;
}
@@ -199,21 +51,16 @@ int override_config_tree_from_string(struct cmd_context *cmd,
return 0;
}
-int read_config_fd(struct config_tree *cft, struct device *dev,
+int read_config_fd(struct dm_config_tree *cft, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum)
{
- struct cs *c = (struct cs *) cft;
- struct parser *p;
+ const char *fb, *fe;
int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
char *buf = NULL;
- if (!(p = dm_pool_alloc(c->mem, sizeof(*p))))
- return_0;
- p->mem = c->mem;
-
/* Only use mmap with regular files */
if (!(dev->flags & DEV_REGULAR) || size2)
use_mmap = 0;
@@ -221,13 +68,13 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
if (use_mmap) {
mmap_offset = offset % lvm_getpagesize();
/* memory map the file */
- p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
- MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
- if (p->fb == (caddr_t) (-1)) {
+ fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
+ MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
+ if (fb == (caddr_t) (-1)) {
log_sys_error("mmap", dev_name(dev));
goto out;
}
- p->fb = p->fb + mmap_offset;
+ fb = fb + mmap_offset;
} else {
if (!(buf = dm_malloc(size + size2)))
return_0;
@@ -235,19 +82,18 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
(uint64_t) offset2, size2, buf)) {
goto out;
}
- p->fb = buf;
+ fb = buf;
}
if (checksum_fn && checksum !=
- (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)p->fb, size),
- (const uint8_t *)(p->fb + size), size2))) {
+ (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
+ (const uint8_t *)(fb + size), size2))) {
log_error("%s: Checksum error", dev_name(dev));
goto out;
}
- p->fe = p->fb + size + size2;
-
- if (!_parse_config_file(p, cft))
+ fe = fb + size + size2;
+ if (!dm_config_parse(cft, fb, fe))
goto_out;
r = 1;
@@ -257,7 +103,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
dm_free(buf);
else {
/* unmap the file */
- if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
+ if (munmap((char *) (fb - mmap_offset), size + mmap_offset)) {
log_sys_error("munmap", dev_name(dev));
r = 0;
}
@@ -266,906 +112,85 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
return r;
}
-int read_config_file(struct config_tree *cft)
+int read_config_file(struct dm_config_tree *cft)
{
- struct cs *c = (struct cs *) cft;
+ const char *filename;
+ struct device *dev = dm_config_get_custom(cft);
struct stat info;
- int r = 1;
-
- if (stat(c->filename, &info)) {
- log_sys_error("stat", c->filename);
- c->exists = 0;
- return 0;
- }
+ int r;
- if (!S_ISREG(info.st_mode)) {
- log_error("%s is not a regular file", c->filename);
- c->exists = 0;
+ if (!dm_config_check_file(cft, &filename, &info))
return 0;
- }
-
- c->exists = 1;
- if (info.st_size == 0) {
- log_verbose("%s is empty", c->filename);
- return 1;
- }
-
- if (!c->dev) {
- if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
+ if (!dev) {
+ if (!(dev = dev_create_file(filename, NULL, NULL, 1)))
return_0;
- if (!dev_open_readonly_buffered(c->dev)) {
- c->dev = 0;
+ if (!dev_open_readonly_buffered(dev))
return_0;
- }
}
- r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
+ dm_config_set_custom(cft, dev);
+ r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0);
- if (!c->keep_open) {
- dev_close(c->dev);
- c->dev = 0;
+ if (!dm_config_keep_open(cft)) {
+ dev_close(dev);
+ dm_config_set_custom(cft, NULL);
}
- c->timestamp = info.st_ctime;
- c->st_size = info.st_size;
-
return r;
}
-time_t config_file_timestamp(struct config_tree *cft)
-{
- struct cs *c = (struct cs *) cft;
-
- return c->timestamp;
-}
-
-/*
- * Return 1 if config files ought to be reloaded
- */
-int config_file_changed(struct config_tree *cft)
-{
- struct cs *c = (struct cs *) cft;
- struct stat info;
-
- if (!c->filename)
- return 0;
-
- if (stat(c->filename, &info) == -1) {
- /* Ignore a deleted config file: still use original data */
- if (errno == ENOENT) {
- if (!c->exists)
- return 0;
- log_very_verbose("Config file %s has disappeared!",
- c->filename);
- goto reload;
- }
- log_sys_error("stat", c->filename);
- log_error("Failed to reload configuration files");
- return 0;
- }
-
- if (!S_ISREG(info.st_mode)) {
- log_error("Configuration file %s is not a regular file",
- c->filename);
- goto reload;
- }
-
- /* Unchanged? */
- if (c->timestamp == info.st_ctime && c->st_size == info.st_size)
- return 0;
-
- reload:
- log_verbose("Detected config file change to %s", c->filename);
- return 1;
-}
-
-static int _line_start(struct output_line *outline)
+static struct dm_config_tree *_setup_context_tree(struct cmd_context *cmd)
{
- if (!dm_pool_begin_object(outline->mem, 128)) {
- log_error("dm_pool_begin_object failed for config line");
- return 0;
- }
-
- return 1;
-}
-
-static int _line_append(struct output_line *outline, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-static int _line_append(struct output_line *outline, const char *fmt, ...)
-{
- char buf[4096];
- va_list ap;
- int n;
-
- va_start(ap, fmt);
- n = vsnprintf(&buf[0], sizeof buf - 1, fmt, ap);
- va_end(ap);
-
- if (n < 0 || n > (int) sizeof buf - 1) {
- log_error("vsnprintf failed for config line");
- return 0;
- }
-
- if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
- log_error("dm_pool_grow_object failed for config line");
- return 0;
- }
-
- return 1;
-}
-
-#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
-
-static int _line_end(struct output_line *outline)
-{
- const char *line;
-
- if (!dm_pool_grow_object(outline->mem, "\0", 1)) {
- log_error("dm_pool_grow_object failed for config line");
- return 0;
- }
-
- line = dm_pool_end_object(outline->mem);
- if (outline->putline)
- outline->putline(line, outline->putline_baton);
- else {
- if (!outline->fp)
- log_print("%s", line);
- else
- fprintf(outline->fp, "%s\n", line);
- }
+ struct dm_config_tree *r = cmd->cft_override;
- return 1;
-}
-
-static int _write_value(struct output_line *outline, const struct config_value *v)
-{
- char *buf;
-
- switch (v->type) {
- case CFG_STRING:
- if (!(buf = alloca(escaped_len(v->v.str)))) {
- log_error("temporary stack allocation for a config "
- "string failed");
- return 0;
- }
- line_append("\"%s\"", escape_double_quotes(buf, v->v.str));
- break;
-
- case CFG_FLOAT:
- line_append("%f", v->v.r);
- break;
-
- case CFG_INT:
- line_append("%" PRId64, v->v.i);
- break;
-
- case CFG_EMPTY_ARRAY:
- line_append("[]");
- break;
-
- default:
- log_error("_write_value: Unknown value type: %d", v->type);
-
- }
-
- return 1;
-}
-
-static int _write_config(const struct config_node *n, int only_one,
- struct output_line *outline, int level)
-{
- char space[MAX_INDENT + 1];
- int l = (level < MAX_INDENT) ? level : MAX_INDENT;
- int i;
-
- if (!n)
- return 1;
-
- for (i = 0; i < l; i++)
- space[i] = '\t';
- space[i] = '\0';
-
- do {
- if (!_line_start(outline))
- return_0;
- line_append("%s%s", space, n->key);
- if (!n->v) {
- /* it's a sub section */
- line_append(" {");
- if (!_line_end(outline))
- return_0;
- _write_config(n->child, 0, outline, level + 1);
- if (!_line_start(outline))
- return_0;
- line_append("%s}", space);
- } else {
- /* it's a value */
- const struct config_value *v = n->v;
- line_append("=");
- if (v->next) {
- line_append("[");
- while (v && v->type != CFG_EMPTY_ARRAY) {
- if (!_write_value(outline, v))
- return_0;
- v = v->next;
- if (v && v->type != CFG_EMPTY_ARRAY)
- line_append(", ");
- }
- line_append("]");
- } else
- if (!_write_value(outline, v))
- return_0;
- }
- if (!_line_end(outline))
- return_0;
- n = n->sib;
- } while (n && !only_one);
- /* FIXME: add error checking */
- return 1;
-}
-
-int write_config_node(const struct config_node *cn, putline_fn putline, void *baton)
-{
- struct output_line outline;
- outline.fp = NULL;
- if (!(outline.mem = dm_pool_create("config_line", 1024)))
- return_0;
- outline.putline = putline;
- outline.putline_baton = baton;
- if (!_write_config(cn, 0, &outline, 0)) {
- dm_pool_destroy(outline.mem);
- return_0;
- }
- dm_pool_destroy(outline.mem);
- return 1;
-}
-
-int write_config_file(struct config_tree *cft, const char *file,
- int argc, char **argv)
-{
- const struct config_node *cn;
- int r = 1;
- struct output_line outline;
- outline.fp = NULL;
- outline.putline = NULL;
-
- if (!file)
- file = "stdout";
- else if (!(outline.fp = fopen(file, "w"))) {
- log_sys_error("open", file);
- return 0;
- }
-
- if (!(outline.mem = dm_pool_create("config_line", 1024))) {
- r = 0;
- goto_out;
- }
-
- log_verbose("Dumping configuration to %s", file);
- if (!argc) {
- if (!_write_config(cft->root, 0, &outline, 0)) {
- log_error("Failure while writing to %s", file);
- r = 0;
- }
- } else while (argc--) {
- if ((cn = find_config_node(cft->root, *argv))) {
- if (!_write_config(cn, 1, &outline, 0)) {
- log_error("Failure while writing to %s", file);
- r = 0;
- }
- } else {
- log_error("Configuration node %s not found", *argv);
- r = 0;
- }
- argv++;
- }
-
- dm_pool_destroy(outline.mem);
-
-out:
- if (outline.fp && lvm_fclose(outline.fp, file)) {
- stack;
- r = 0;
- }
+ if (r)
+ r->cascade = cmd->cft;
+ else
+ r = cmd->cft;
return r;
}
-/*
- * parser
- */
-static struct config_node *_file(struct parser *p)
-{
- struct config_node *root = NULL, *n, *l = NULL;
- while (p->t != TOK_EOF) {
- if (!(n = _section(p)))
- return_0;
-
- if (!root)
- root = n;
- else
- l->sib = n;
- n->parent = root;
- l = n;
- }
- return root;
-}
-
-static struct config_node *_section(struct parser *p)
-{
- /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
- struct config_node *root, *n, *l = NULL;
- if (!(root = _create_node(p->mem)))
- return_0;
-
- if (!(root->key = _dup_tok(p)))
- return_0;
-
- match(TOK_IDENTIFIER);
-
- if (p->t == TOK_SECTION_B) {
- match(TOK_SECTION_B);
- while (p->t != TOK_SECTION_E) {
- if (!(n = _section(p)))
- return_0;
-
- if (!root->child)
- root->child = n;
- else
- l->sib = n;
- n->parent = root;
- l = n;
- }
- match(TOK_SECTION_E);
- } else {
- match(TOK_EQ);
- if (!(root->v = _value(p)))
- return_0;
- }
-
- return root;
-}
-
-static struct config_value *_value(struct parser *p)
-{
- /* '[' TYPE* ']' | TYPE */
- struct config_value *h = NULL, *l, *ll = NULL;
- if (p->t == TOK_ARRAY_B) {
- match(TOK_ARRAY_B);
- while (p->t != TOK_ARRAY_E) {
- if (!(l = _type(p)))
- return_0;
-
- if (!h)
- h = l;
- else
- ll->next = l;
- ll = l;
-
- if (p->t == TOK_COMMA)
- match(TOK_COMMA);
- }
- match(TOK_ARRAY_E);
- /*
- * Special case for an empty array.
- */
- if (!h) {
- if (!(h = _create_value(p->mem)))
- return NULL;
-
- h->type = CFG_EMPTY_ARRAY;
- }
-
- } else
- h = _type(p);
-
- return h;
-}
-
-static struct config_value *_type(struct parser *p)
-{
- /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
- struct config_value *v = _create_value(p->mem);
- char *str;
-
- if (!v)
- return NULL;
-
- switch (p->t) {
- case TOK_INT:
- v->type = CFG_INT;
- v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
- match(TOK_INT);
- break;
-
- case TOK_FLOAT:
- v->type = CFG_FLOAT;
- v->v.r = strtod(p->tb, NULL); /* FIXME: check error */
- match(TOK_FLOAT);
- break;
-
- case TOK_STRING:
- v->type = CFG_STRING;
-
- p->tb++, p->te--; /* strip "'s */
- if (!(v->v.str = _dup_tok(p)))
- return_0;
- p->te++;
- match(TOK_STRING);
- break;
-
- case TOK_STRING_ESCAPED:
- v->type = CFG_STRING;
-
- p->tb++, p->te--; /* strip "'s */
- if (!(str = _dup_tok(p)))
- return_0;
- unescape_double_quotes(str);
- v->v.str = str;
- p->te++;
- match(TOK_STRING_ESCAPED);
- break;
-
- default:
- log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
- p->tb - p->fb + 1, p->line);
- return 0;
- }
- return v;
-}
-
-static int _match_aux(struct parser *p, int t)
-{
- if (p->t != t)
- return 0;
-
- _get_token(p, t);
- return 1;
-}
-
-/*
- * tokeniser
- */
-static void _get_token(struct parser *p, int tok_prev)
-{
- int values_allowed = 0;
-
- const char *te;
-
- p->tb = p->te;
- _eat_space(p);
- if (p->tb == p->fe || !*p->tb) {
- p->t = TOK_EOF;
- return;
- }
-
- /* Should next token be interpreted as value instead of identifier? */
- if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
- tok_prev == TOK_COMMA)
- values_allowed = 1;
-
- p->t = TOK_INT; /* fudge so the fall through for
- floats works */
-
- te = p->te;
- switch (*te) {
- case SECTION_B_CHAR:
- p->t = TOK_SECTION_B;
- te++;
- break;
-
- case SECTION_E_CHAR:
- p->t = TOK_SECTION_E;
- te++;
- break;
-
- case '[':
- p->t = TOK_ARRAY_B;
- te++;
- break;
-
- case ']':
- p->t = TOK_ARRAY_E;
- te++;
- break;
-
- case ',':
- p->t = TOK_COMMA;
- te++;
- break;
-
- case '=':
- p->t = TOK_EQ;
- te++;
- break;
-
- case '"':
- p->t = TOK_STRING_ESCAPED;
- te++;
- while ((te != p->fe) && (*te) && (*te != '"')) {
- if ((*te == '\\') && (te + 1 != p->fe) &&
- *(te + 1))
- te++;
- te++;
- }
-
- if ((te != p->fe) && (*te))
- te++;
- break;
-
- case '\'':
- p->t = TOK_STRING;
- te++;
- while ((te != p->fe) && (*te) && (*te != '\''))
- te++;
-
- if ((te != p->fe) && (*te))
- te++;
- break;
-
- case '.':
- p->t = TOK_FLOAT;
- /* Fall through */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '+':
- case '-':
- if (values_allowed) {
- while (++te != p->fe) {
- if (!isdigit((int) *te)) {
- if (*te == '.') {
- if (p->t != TOK_FLOAT) {
- p->t = TOK_FLOAT;
- continue;
- }
- }
- break;
- }
- }
- break;
- }
- /* fall through */
-
- default:
- p->t = TOK_IDENTIFIER;
- while ((te != p->fe) && (*te) && !isspace(*te) &&
- (*te != '#') && (*te != '=') &&
- (*te != SECTION_B_CHAR) &&
- (*te != SECTION_E_CHAR))
- te++;
- break;
- }
-
- p->te = te;
-}
-
-static void _eat_space(struct parser *p)
-{
- while (p->tb != p->fe) {
- if (*p->te == '#')
- while ((p->te != p->fe) && (*p->te != '\n') && (*p->te))
- ++p->te;
-
- else if (!isspace(*p->te))
- break;
-
- while ((p->te != p->fe) && isspace(*p->te)) {
- if (*p->te == '\n')
- ++p->line;
- ++p->te;
- }
-
- p->tb = p->te;
- }
-}
-
-/*
- * memory management
- */
-static struct config_value *_create_value(struct dm_pool *mem)
-{
- return dm_pool_zalloc(mem, sizeof(struct config_value));
-}
-
-static struct config_node *_create_node(struct dm_pool *mem)
-{
- return dm_pool_zalloc(mem, sizeof(struct config_node));
-}
-
-static char *_dup_tok(struct parser *p)
-{
- size_t len = p->te - p->tb;
- char *str = dm_pool_alloc(p->mem, len + 1);
- if (!str) {
- log_error("Failed to duplicate token.");
- return 0;
- }
- memcpy(str, p->tb, len);
- str[len] = '\0';
- return str;
-}
-
-/*
- * utility functions
- */
-static const struct config_node *_find_config_node(const struct config_node *cn,
+const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd,
const char *path)
{
- const char *e;
- const struct config_node *cn_found = NULL;
-
- while (cn) {
- /* trim any leading slashes */
- while (*path && (*path == sep))
- path++;
-
- /* find the end of this segment */
- for (e = path; *e && (*e != sep); e++) ;
-
- /* hunt for the node */
- cn_found = NULL;
- while (cn) {
- if (_tok_match(cn->key, path, e)) {
- /* Inefficient */
- if (!cn_found)
- cn_found = cn;
- else
- log_warn("WARNING: Ignoring duplicate"
- " config node: %s ("
- "seeking %s)", cn->key, path);
- }
-
- cn = cn->sib;
- }
-
- if (cn_found && *e)
- cn = cn_found->child;
- else
- break; /* don't move into the last node */
-
- path = e;
- }
-
- return cn_found;
-}
-
-static const struct config_node *_find_first_config_node(const struct config_node *cn1,
- const struct config_node *cn2,
- const char *path)
-{
- const struct config_node *cn;
-
- if (cn1 && (cn = _find_config_node(cn1, path)))
- return cn;
-
- if (cn2 && (cn = _find_config_node(cn2, path)))
- return cn;
-
- return NULL;
-}
-
-const struct config_node *find_config_node(const struct config_node *cn,
- const char *path)
-{
- return _find_config_node(cn, path);
-}
-
-static const char *_find_config_str(const struct config_node *cn1,
- const struct config_node *cn2,
- const char *path, const char *fail)
-{
- const struct config_node *n = _find_first_config_node(cn1, cn2, path);
-
- /* Empty strings are ignored */
- if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
- log_very_verbose("Setting %s to %s", path, n->v->v.str);
- return n->v->v.str;
- }
-
- if (fail)
- log_very_verbose("%s not found in config: defaulting to %s",
- path, fail);
- return fail;
-}
-
-const char *find_config_str(const struct config_node *cn,
- const char *path, const char *fail)
-{
- return _find_config_str(cn, NULL, path, fail);
-}
-
-static int64_t _find_config_int64(const struct config_node *cn1,
- const struct config_node *cn2,
- const char *path, int64_t fail)
-{
- const struct config_node *n = _find_first_config_node(cn1, cn2, path);
-
- if (n && n->v && n->v->type == CFG_INT) {
- log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i);
- return n->v->v.i;
- }
-
- log_very_verbose("%s not found in config: defaulting to %" PRId64,
- path, fail);
- return fail;
-}
-
-int find_config_int(const struct config_node *cn, const char *path, int fail)
-{
- /* FIXME Add log_error message on overflow */
- return (int) _find_config_int64(cn, NULL, path, (int64_t) fail);
-}
-
-static float _find_config_float(const struct config_node *cn1,
- const struct config_node *cn2,
- const char *path, float fail)
-{
- const struct config_node *n = _find_first_config_node(cn1, cn2, path);
-
- if (n && n->v && n->v->type == CFG_FLOAT) {
- log_very_verbose("Setting %s to %f", path, n->v->v.r);
- return n->v->v.r;
- }
-
- log_very_verbose("%s not found in config: defaulting to %f",
- path, fail);
-
- return fail;
-
-}
-
-float find_config_float(const struct config_node *cn, const char *path,
- float fail)
-{
- return _find_config_float(cn, NULL, path, fail);
-}
-
-const struct config_node *find_config_tree_node(struct cmd_context *cmd,
- const char *path)
-{
- return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
+ return dm_config_tree_find_node(_setup_context_tree(cmd), path);
}
const char *find_config_tree_str(struct cmd_context *cmd,
const char *path, const char *fail)
{
- return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
+ return dm_config_tree_find_str(_setup_context_tree(cmd), path, fail);
}
int find_config_tree_int(struct cmd_context *cmd, const char *path,
int fail)
{
- /* FIXME Add log_error message on overflow */
- return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail);
+ return dm_config_tree_find_int(_setup_context_tree(cmd), path, fail);
}
int64_t find_config_tree_int64(struct cmd_context *cmd, const char *path, int64_t fail)
{
- return _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL,
- cmd->cft->root, path, fail);
+ return dm_config_tree_find_int64(_setup_context_tree(cmd), path, fail);
}
float find_config_tree_float(struct cmd_context *cmd, const char *path,
float fail)
{
- return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
-}
-
-static int _str_in_array(const char *str, const char * const values[])
-{
- int i;
-
- for (i = 0; values[i]; i++)
- if (!strcasecmp(str, values[i]))
- return 1;
-
- return 0;
-}
-
-static int _str_to_bool(const char *str, int fail)
-{
- const char * const _true_values[] = { "y", "yes", "on", "true", NULL };
- const char * const _false_values[] = { "n", "no", "off", "false", NULL };
-
- if (_str_in_array(str, _true_values))
- return 1;
-
- if (_str_in_array(str, _false_values))
- return 0;
-
- return fail;
-}
-
-static int _find_config_bool(const struct config_node *cn1,
- const struct config_node *cn2,
- const char *path, int fail)
-{
- const struct config_node *n = _find_first_config_node(cn1, cn2, path);
- const struct config_value *v;
-
- if (!n)
- return fail;
-
- v = n->v;
-
- switch (v->type) {
- case CFG_INT:
- return v->v.i ? 1 : 0;
-
- case CFG_STRING:
- return _str_to_bool(v->v.str, fail);
- }
-
- return fail;
-}
-
-int find_config_bool(const struct config_node *cn, const char *path, int fail)
-{
- return _find_config_bool(cn, NULL, path, fail);
+ return dm_config_tree_find_float(_setup_context_tree(cmd), path, fail);
}
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
{
- return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
-}
-
-int get_config_uint32(const struct config_node *cn, const char *path,
- uint32_t *result)
-{
- const struct config_node *n;
-
- n = find_config_node(cn, path);
-
- if (!n || !n->v || n->v->type != CFG_INT)
- return 0;
-
- *result = n->v->v.i;
- return 1;
-}
-
-int get_config_uint64(const struct config_node *cn, const char *path,
- uint64_t *result)
-{
- const struct config_node *n;
-
- n = find_config_node(cn, path);
-
- if (!n || !n->v || n->v->type != CFG_INT)
- return 0;
-
- *result = (uint64_t) n->v->v.i;
- return 1;
-}
-
-int get_config_str(const struct config_node *cn, const char *path,
- const char **result)
-{
- const struct config_node *n;
-
- n = find_config_node(cn, path);
-
- if (!n || !n->v || n->v->type != CFG_STRING)
- return 0;
-
- *result = n->v->v.str;
- return 1;
+ return dm_config_tree_find_bool(_setup_context_tree(cmd), path, fail);
}
/* Insert cn2 after cn1 */
-static void _insert_config_node(struct config_node **cn1,
- struct config_node *cn2)
+static void _insert_config_node(struct dm_config_node **cn1,
+ struct dm_config_node *cn2)
{
if (!*cn1) {
*cn1 = cn2;
@@ -1180,10 +205,10 @@ static void _insert_config_node(struct config_node **cn1,
* Merge section cn2 into section cn1 (which has the same name)
* overwriting any existing cn1 nodes with matching names.
*/
-static void _merge_section(struct config_node *cn1, struct config_node *cn2)
+static void _merge_section(struct dm_config_node *cn1, struct dm_config_node *cn2)
{
- struct config_node *cn, *nextn, *oldn;
- struct config_value *cv;
+ struct dm_config_node *cn, *nextn, *oldn;
+ struct dm_config_value *cv;
for (cn = cn2->child; cn; cn = nextn) {
nextn = cn->sib;
@@ -1197,7 +222,7 @@ static void _merge_section(struct config_node *cn1, struct config_node *cn2)
/* Ignore - we don't have any of these yet */
continue;
/* Not already present? */
- if (!(oldn = (struct config_node*)find_config_node(cn1->child, cn->key))) {
+ if (!(oldn = (struct dm_config_node*)dm_config_find_node(cn1->child, cn->key))) {
_insert_config_node(&cn1->child, cn);
continue;
}
@@ -1217,13 +242,13 @@ static void _merge_section(struct config_node *cn1, struct config_node *cn2)
}
}
-static int _match_host_tags(struct dm_list *tags, const struct config_node *tn)
+static int _match_host_tags(struct dm_list *tags, const struct dm_config_node *tn)
{
- const struct config_value *tv;
+ const struct dm_config_value *tv;
const char *str;
for (tv = tn->v; tv; tv = tv->next) {
- if (tv->type != CFG_STRING)
+ if (tv->type != DM_CFG_STRING)
continue;
str = tv->v.str;
if (*str == '@')
@@ -1238,12 +263,12 @@ static int _match_host_tags(struct dm_list *tags, const struct config_node *tn)
}
/* Destructively merge a new config tree into an existing one */
-int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
- struct config_tree *newdata)
+int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft,
+ struct dm_config_tree *newdata)
{
- const struct config_node *root = cft->root;
- struct config_node *cn, *nextn, *oldn, *cn2;
- const struct config_node *tn;
+ const struct dm_config_node *root = cft->root;
+ struct dm_config_node *cn, *nextn, *oldn, *cn2;
+ const struct dm_config_node *tn;
for (cn = newdata->root; cn; cn = nextn) {
nextn = cn->sib;
@@ -1251,11 +276,11 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
if (!strcmp(cn->key, "tags"))
continue;
/* If there's a tags node, skip if host tags don't match */
- if ((tn = find_config_node(cn->child, "tags"))) {
+ if ((tn = dm_config_find_node(cn->child, "tags"))) {
if (!_match_host_tags(&cmd->tags, tn))
continue;
}
- if (!(oldn = (struct config_node *)find_config_node(root, cn->key))) {
+ if (!(oldn = (struct dm_config_node *)dm_config_find_node(root, cn->key))) {
_insert_config_node(&cft->root, cn);
/* Remove any "tags" nodes */
for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
@@ -1276,159 +301,3 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
return 1;
}
-/*
- * Convert a token type to the char it represents.
- */
-static char _token_type_to_char(int type)
-{
- switch (type) {
- case TOK_SECTION_B:
- return SECTION_B_CHAR;
- case TOK_SECTION_E:
- return SECTION_E_CHAR;
- default:
- return 0;
- }
-}
-
-/*
- * Returns:
- * # of 'type' tokens in 'str'.
- */
-static unsigned _count_tokens(const char *str, unsigned len, int type)
-{
- char c;
-
- c = _token_type_to_char(type);
-
- return count_chars(str, len, c);
-}
-
-const char *config_parent_name(const struct config_node *n)
-{
- return (n->parent ? n->parent->key : "(root)");
-}
-/*
- * Heuristic function to make a quick guess as to whether a text
- * region probably contains a valid config "section". (Useful for
- * scanning areas of the disk for old metadata.)
- * Config sections contain various tokens, may contain other sections
- * and strings, and are delimited by begin (type 'TOK_SECTION_B') and
- * end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just
- * count the number of begin and end tokens, and see if they are
- * non-zero and the counts match.
- * Full validation of the section should be done with another function
- * (for example, read_config_fd).
- *
- * Returns:
- * 0 - probably is not a valid config section
- * 1 - probably _is_ a valid config section
- */
-unsigned maybe_config_section(const char *str, unsigned len)
-{
- int begin_count;
- int end_count;
-
- begin_count = _count_tokens(str, len, TOK_SECTION_B);
- end_count = _count_tokens(str, len, TOK_SECTION_E);
-
- if (begin_count && end_count && (begin_count == end_count))
- return 1;
- else
- return 0;
-}
-
-static struct config_value *_clone_config_value(struct dm_pool *mem, const struct config_value *v)
-{
- struct config_value *new_cv;
-
- if (!v)
- return NULL;
-
- if (!(new_cv = _create_value(mem))) {
- log_error("Failed to clone config value.");
- return NULL;
- }
-
- new_cv->type = v->type;
- if (v->type == CFG_STRING) {
- if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) {
- log_error("Failed to clone config string value.");
- return NULL;
- }
- } else
- new_cv->v = v->v;
-
- if (v->next && !(new_cv->next = _clone_config_value(mem, v->next)))
- return_NULL;
-
- return new_cv;
-}
-
-struct config_node *clone_config_node_with_mem(struct dm_pool *mem, const struct config_node *cn,
- int siblings)
-{
- struct config_node *new_cn;
-
- if (!cn)
- return NULL;
-
- if (!(new_cn = _create_node(mem))) {
- log_error("Failed to clone config node.");
- return NULL;
- }
-
- if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) {
- log_error("Failed to clone config node key.");
- return NULL;
- }
-
- if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) ||
- (cn->child && !(new_cn->child = clone_config_node_with_mem(mem, cn->child, 1))) ||
- (siblings && cn->sib && !(new_cn->sib = clone_config_node_with_mem(mem, cn->sib, siblings))))
- return_NULL; /* 'new_cn' released with mem pool */
-
- return new_cn;
-}
-
-struct config_node *clone_config_node(struct config_tree *cft, const struct config_node *node, int sib)
-{
- struct cs *c = (struct cs *) cft;
- return clone_config_node_with_mem(c->mem, node, sib);
-}
-
-struct config_node *create_config_node(struct config_tree *cft, const char *key)
-{
- struct cs *c = (struct cs *) cft;
- struct config_node *cn;
-
- if (!(cn = _create_node(c->mem))) {
- log_error("Failed to create config node.");
- return NULL;
- }
- if (!(cn->key = dm_pool_strdup(c->mem, key))) {
- log_error("Failed to create config node's key.");
- return NULL;
- }
- if (!(cn->v = _create_value(c->mem))) {
- log_error("Failed to create config node's value.");
- return NULL;
- }
- cn->parent = NULL;
- cn->v->type = CFG_INT;
- cn->v->v.i = 0;
- cn->v->next = NULL;
- return cn;
-}
-
-struct config_value *create_config_value(struct config_tree *cft)
-{
- struct cs *c = (struct cs *) cft;
- return _create_value(c->mem);
-}
-
-struct dm_pool *config_tree_memory(struct config_tree *cft)
-{
- struct cs *c = (struct cs *) cft;
- return c->mem;
-}