Home | History | Annotate | Line # | Download | only in config
      1 /*	$NetBSD: config.c,v 1.1.1.2 2009/12/02 00:26:28 haad Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
      6  *
      7  * This file is part of LVM2.
      8  *
      9  * This copyrighted material is made available to anyone wishing to use,
     10  * modify, copy, or redistribute it subject to the terms and conditions
     11  * of the GNU Lesser General Public License v.2.1.
     12  *
     13  * You should have received a copy of the GNU Lesser General Public License
     14  * along with this program; if not, write to the Free Software Foundation,
     15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16  */
     17 
     18 #include "lib.h"
     19 #include "config.h"
     20 #include "crc.h"
     21 #include "device.h"
     22 #include "str_list.h"
     23 #include "toolcontext.h"
     24 #include "lvm-string.h"
     25 #include "lvm-file.h"
     26 
     27 #include <sys/stat.h>
     28 #include <sys/mman.h>
     29 #include <unistd.h>
     30 #include <fcntl.h>
     31 #include <ctype.h>
     32 
     33 #define SECTION_B_CHAR '{'
     34 #define SECTION_E_CHAR '}'
     35 
     36 enum {
     37 	TOK_INT,
     38 	TOK_FLOAT,
     39 	TOK_STRING,		/* Single quotes */
     40 	TOK_STRING_ESCAPED,	/* Double quotes */
     41 	TOK_EQ,
     42 	TOK_SECTION_B,
     43 	TOK_SECTION_E,
     44 	TOK_ARRAY_B,
     45 	TOK_ARRAY_E,
     46 	TOK_IDENTIFIER,
     47 	TOK_COMMA,
     48 	TOK_EOF
     49 };
     50 
     51 struct parser {
     52 	const char *fb, *fe;		/* file limits */
     53 
     54 	int t;			/* token limits and type */
     55 	const char *tb, *te;
     56 
     57 	int fd;			/* descriptor for file being parsed */
     58 	int line;		/* line number we are on */
     59 
     60 	struct dm_pool *mem;
     61 };
     62 
     63 struct cs {
     64 	struct config_tree cft;
     65 	struct dm_pool *mem;
     66 	time_t timestamp;
     67 	char *filename;
     68 	int exists;
     69 	int keep_open;
     70 	struct device *dev;
     71 };
     72 
     73 struct output_line {
     74 	FILE *fp;
     75 	struct dm_pool *mem;
     76 	putline_fn putline;
     77 	void *putline_baton;
     78 };
     79 
     80 static void _get_token(struct parser *p, int tok_prev);
     81 static void _eat_space(struct parser *p);
     82 static struct config_node *_file(struct parser *p);
     83 static struct config_node *_section(struct parser *p);
     84 static struct config_value *_value(struct parser *p);
     85 static struct config_value *_type(struct parser *p);
     86 static int _match_aux(struct parser *p, int t);
     87 static struct config_value *_create_value(struct dm_pool *mem);
     88 static struct config_node *_create_node(struct dm_pool *mem);
     89 static char *_dup_tok(struct parser *p);
     90 
     91 static const int sep = '/';
     92 
     93 #define MAX_INDENT 32
     94 
     95 #define match(t) do {\
     96    if (!_match_aux(p, (t))) {\
     97 	log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
     98 		  p->tb - p->fb + 1, p->line); \
     99       return 0;\
    100    } \
    101 } while(0);
    102 
    103 static int _tok_match(const char *str, const char *b, const char *e)
    104 {
    105 	while (*str && (b != e)) {
    106 		if (*str++ != *b++)
    107 			return 0;
    108 	}
    109 
    110 	return !(*str || (b != e));
    111 }
    112 
    113 /*
    114  * public interface
    115  */
    116 struct config_tree *create_config_tree(const char *filename, int keep_open)
    117 {
    118 	struct cs *c;
    119 	struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
    120 
    121 	if (!mem) {
    122 		log_error("Failed to allocate config pool.");
    123 		return 0;
    124 	}
    125 
    126 	if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
    127 		log_error("Failed to allocate config tree.");
    128 		dm_pool_destroy(mem);
    129 		return 0;
    130 	}
    131 
    132 	c->mem = mem;
    133 	c->cft.root = (struct config_node *) NULL;
    134 	c->timestamp = 0;
    135 	c->exists = 0;
    136 	c->keep_open = keep_open;
    137 	c->dev = 0;
    138 	if (filename)
    139 		c->filename = dm_pool_strdup(c->mem, filename);
    140 	return &c->cft;
    141 }
    142 
    143 void destroy_config_tree(struct config_tree *cft)
    144 {
    145 	struct cs *c = (struct cs *) cft;
    146 
    147 	if (c->dev)
    148 		dev_close(c->dev);
    149 
    150 	dm_pool_destroy(c->mem);
    151 }
    152 
    153 static int _parse_config_file(struct parser *p, struct config_tree *cft)
    154 {
    155 	p->tb = p->te = p->fb;
    156 	p->line = 1;
    157 	_get_token(p, TOK_SECTION_E);
    158 	if (!(cft->root = _file(p)))
    159 		return_0;
    160 
    161 	return 1;
    162 }
    163 
    164 struct config_tree *create_config_tree_from_string(struct cmd_context *cmd __attribute((unused)),
    165 						   const char *config_settings)
    166 {
    167 	struct cs *c;
    168 	struct config_tree *cft;
    169 	struct parser *p;
    170 
    171 	if (!(cft = create_config_tree(NULL, 0)))
    172 		return_NULL;
    173 
    174 	c = (struct cs *) cft;
    175 	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
    176 		log_error("Failed to allocate config tree parser.");
    177 		destroy_config_tree(cft);
    178 		return NULL;
    179 	}
    180 
    181 	p->mem = c->mem;
    182 	p->fb = config_settings;
    183 	p->fe = config_settings + strlen(config_settings);
    184 
    185 	if (!_parse_config_file(p, cft)) {
    186 		destroy_config_tree(cft);
    187 		return_NULL;
    188 	}
    189 
    190 	return cft;
    191 }
    192 
    193 int override_config_tree_from_string(struct cmd_context *cmd,
    194 				     const char *config_settings)
    195 {
    196 	if (!(cmd->cft_override = create_config_tree_from_string(cmd,config_settings))) {
    197 		log_error("Failed to set overridden configuration entries.");
    198 		return 1;
    199 	}
    200 
    201 	return 0;
    202 }
    203 
    204 int read_config_fd(struct config_tree *cft, struct device *dev,
    205 		   off_t offset, size_t size, off_t offset2, size_t size2,
    206 		   checksum_fn_t checksum_fn, uint32_t checksum)
    207 {
    208 	struct cs *c = (struct cs *) cft;
    209 	struct parser *p;
    210 	int r = 0;
    211 	int use_mmap = 1;
    212 	off_t mmap_offset = 0;
    213 	char *buf = NULL;
    214 
    215 	if (!(p = dm_pool_alloc(c->mem, sizeof(*p))))
    216 		return_0;
    217 	p->mem = c->mem;
    218 
    219 	/* Only use mmap with regular files */
    220 	if (!(dev->flags & DEV_REGULAR) || size2)
    221 		use_mmap = 0;
    222 
    223 	if (use_mmap) {
    224 		mmap_offset = offset % lvm_getpagesize();
    225 		/* memory map the file */
    226 		p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
    227 			     MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
    228 		if (p->fb == (caddr_t) (-1)) {
    229 			log_sys_error("mmap", dev_name(dev));
    230 			goto out;
    231 		}
    232 		p->fb = p->fb + mmap_offset;
    233 	} else {
    234 		if (!(buf = dm_malloc(size + size2)))
    235 			return_0;
    236 		if (!dev_read_circular(dev, (uint64_t) offset, size,
    237 				       (uint64_t) offset2, size2, buf)) {
    238 			goto out;
    239 		}
    240 		p->fb = buf;
    241 	}
    242 
    243 	if (checksum_fn && checksum !=
    244 	    (checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
    245 			 p->fb + size, size2))) {
    246 		log_error("%s: Checksum error", dev_name(dev));
    247 		goto out;
    248 	}
    249 
    250 	p->fe = p->fb + size + size2;
    251 
    252 	if (!_parse_config_file(p, cft))
    253 		goto_out;
    254 
    255 	r = 1;
    256 
    257       out:
    258 	if (!use_mmap)
    259 		dm_free(buf);
    260 	else {
    261 		/* unmap the file */
    262 		if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
    263 			log_sys_error("munmap", dev_name(dev));
    264 			r = 0;
    265 		}
    266 	}
    267 
    268 	return r;
    269 }
    270 
    271 int read_config_file(struct config_tree *cft)
    272 {
    273 	struct cs *c = (struct cs *) cft;
    274 	struct stat info;
    275 	int r = 1;
    276 
    277 	if (stat(c->filename, &info)) {
    278 		log_sys_error("stat", c->filename);
    279 		c->exists = 0;
    280 		return 0;
    281 	}
    282 
    283 	if (!S_ISREG(info.st_mode)) {
    284 		log_error("%s is not a regular file", c->filename);
    285 		c->exists = 0;
    286 		return 0;
    287 	}
    288 
    289 	c->exists = 1;
    290 
    291 	if (info.st_size == 0) {
    292 		log_verbose("%s is empty", c->filename);
    293 		return 1;
    294 	}
    295 
    296 	if (!c->dev) {
    297 		if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
    298 			return_0;
    299 
    300 		if (!dev_open_flags(c->dev, O_RDONLY, 0, 0))
    301 			return_0;
    302 	}
    303 
    304 	r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
    305 			   (checksum_fn_t) NULL, 0);
    306 
    307 	if (!c->keep_open) {
    308 		dev_close(c->dev);
    309 		c->dev = 0;
    310 	}
    311 
    312 	c->timestamp = info.st_ctime;
    313 
    314 	return r;
    315 }
    316 
    317 time_t config_file_timestamp(struct config_tree *cft)
    318 {
    319 	struct cs *c = (struct cs *) cft;
    320 
    321 	return c->timestamp;
    322 }
    323 
    324 /*
    325  * Return 1 if config files ought to be reloaded
    326  */
    327 int config_file_changed(struct config_tree *cft)
    328 {
    329 	struct cs *c = (struct cs *) cft;
    330 	struct stat info;
    331 
    332 	if (!c->filename)
    333 		return 0;
    334 
    335 	if (stat(c->filename, &info) == -1) {
    336 		/* Ignore a deleted config file: still use original data */
    337 		if (errno == ENOENT) {
    338 			if (!c->exists)
    339 				return 0;
    340 			log_very_verbose("Config file %s has disappeared!",
    341 					 c->filename);
    342 			goto reload;
    343 		}
    344 		log_sys_error("stat", c->filename);
    345 		log_error("Failed to reload configuration files");
    346 		return 0;
    347 	}
    348 
    349 	if (!S_ISREG(info.st_mode)) {
    350 		log_error("Configuration file %s is not a regular file",
    351 			  c->filename);
    352 		goto reload;
    353 	}
    354 
    355 	/* Unchanged? */
    356 	if (c->timestamp == info.st_ctime)
    357 		return 0;
    358 
    359       reload:
    360 	log_verbose("Detected config file change to %s", c->filename);
    361 	return 1;
    362 }
    363 
    364 static int _line_start(struct output_line *outline)
    365 {
    366 	if (!dm_pool_begin_object(outline->mem, 128)) {
    367 		log_error("dm_pool_begin_object failed for config line");
    368 		return 0;
    369 	}
    370 
    371 	return 1;
    372 }
    373 
    374 static int _line_append(struct output_line *outline, const char *fmt, ...)
    375   __attribute__ ((format(printf, 2, 3)));
    376 static int _line_append(struct output_line *outline, const char *fmt, ...)
    377 {
    378 	char buf[4096];
    379 	va_list ap;
    380 	int n;
    381 
    382 	va_start(ap, fmt);
    383 	n = vsnprintf(&buf[0], sizeof buf - 1, fmt, ap);
    384 	if (n < 0 || n > (int) sizeof buf - 1) {
    385 		log_error("vsnprintf failed for config line");
    386 		return 0;
    387 	}
    388 	va_end(ap);
    389 
    390 	if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
    391 		log_error("dm_pool_grow_object failed for config line");
    392 		return 0;
    393 	}
    394 
    395 	return 1;
    396 }
    397 
    398 #define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
    399 
    400 static int _line_end(struct output_line *outline)
    401 {
    402 	const char *line;
    403 
    404 	if (!dm_pool_grow_object(outline->mem, "\0", 1)) {
    405 		log_error("dm_pool_grow_object failed for config line");
    406 		return 0;
    407 	}
    408 
    409 	line = dm_pool_end_object(outline->mem);
    410 	if (outline->putline)
    411 		outline->putline(line, outline->putline_baton);
    412 	else {
    413 		if (!outline->fp)
    414 			log_print("%s", line);
    415 		else
    416 			fprintf(outline->fp, "%s\n", line);
    417 	}
    418 
    419 	return 1;
    420 }
    421 
    422 static int _write_value(struct output_line *outline, struct config_value *v)
    423 {
    424 	char *buf;
    425 
    426 	switch (v->type) {
    427 	case CFG_STRING:
    428 		if (!(buf = alloca(escaped_len(v->v.str)))) {
    429 			log_error("temporary stack allocation for a config "
    430 				  "string failed");
    431 			return 0;
    432 		}
    433 		line_append("\"%s\"", escape_double_quotes(buf, v->v.str));
    434 		break;
    435 
    436 	case CFG_FLOAT:
    437 		line_append("%f", v->v.r);
    438 		break;
    439 
    440 	case CFG_INT:
    441 		line_append("%" PRId64, v->v.i);
    442 		break;
    443 
    444 	case CFG_EMPTY_ARRAY:
    445 		line_append("[]");
    446 		break;
    447 
    448 	default:
    449 		log_error("_write_value: Unknown value type: %d", v->type);
    450 
    451 	}
    452 
    453 	return 1;
    454 }
    455 
    456 static int _write_config(const struct config_node *n, int only_one,
    457 			 struct output_line *outline, int level)
    458 {
    459 	char space[MAX_INDENT + 1];
    460 	int l = (level < MAX_INDENT) ? level : MAX_INDENT;
    461 	int i;
    462 
    463 	if (!n)
    464 		return 1;
    465 
    466 	for (i = 0; i < l; i++)
    467 		space[i] = '\t';
    468 	space[i] = '\0';
    469 
    470 	do {
    471 		if (!_line_start(outline))
    472 			return_0;
    473 		line_append("%s%s", space, n->key);
    474 		if (!n->v) {
    475 			/* it's a sub section */
    476 			line_append(" {");
    477 			if (!_line_end(outline))
    478 				return_0;
    479 			_write_config(n->child, 0, outline, level + 1);
    480 			if (!_line_start(outline))
    481 				return_0;
    482 			line_append("%s}", space);
    483 		} else {
    484 			/* it's a value */
    485 			struct config_value *v = n->v;
    486 			line_append("=");
    487 			if (v->next) {
    488 				line_append("[");
    489 				while (v) {
    490 					if (!_write_value(outline, v))
    491 						return_0;
    492 					v = v->next;
    493 					if (v)
    494 						line_append(", ");
    495 				}
    496 				line_append("]");
    497 			} else
    498 				if (!_write_value(outline, v))
    499 					return_0;
    500 		}
    501 		if (!_line_end(outline))
    502 			return_0;
    503 		n = n->sib;
    504 	} while (n && !only_one);
    505 	/* FIXME: add error checking */
    506 	return 1;
    507 }
    508 
    509 int write_config_node(const struct config_node *cn, putline_fn putline, void *baton)
    510 {
    511 	struct output_line outline;
    512 	outline.fp = NULL;
    513 	outline.mem = dm_pool_create("config_line", 1024);
    514 	outline.putline = putline;
    515 	outline.putline_baton = baton;
    516 	if (!_write_config(cn, 0, &outline, 0)) {
    517 		dm_pool_destroy(outline.mem);
    518 		return_0;
    519 	}
    520 	dm_pool_destroy(outline.mem);
    521 	return 1;
    522 }
    523 
    524 int write_config_file(struct config_tree *cft, const char *file,
    525 		      int argc, char **argv)
    526 {
    527 	struct config_node *cn;
    528 	int r = 1;
    529 	struct output_line outline;
    530 	outline.fp = NULL;
    531 	outline.putline = NULL;
    532 
    533 	if (!file)
    534 		file = "stdout";
    535 	else if (!(outline.fp = fopen(file, "w"))) {
    536 		log_sys_error("open", file);
    537 		return 0;
    538 	}
    539 
    540 	outline.mem = dm_pool_create("config_line", 1024);
    541 
    542 	log_verbose("Dumping configuration to %s", file);
    543 	if (!argc) {
    544 		if (!_write_config(cft->root, 0, &outline, 0)) {
    545 			log_error("Failure while writing to %s", file);
    546 			r = 0;
    547 		}
    548 	} else while (argc--) {
    549 		if ((cn = find_config_node(cft->root, *argv))) {
    550 			if (!_write_config(cn, 1, &outline, 0)) {
    551 				log_error("Failure while writing to %s", file);
    552 				r = 0;
    553 			}
    554 		} else {
    555 			log_error("Configuration node %s not found", *argv);
    556 			r = 0;
    557 		}
    558 		argv++;
    559 	}
    560 
    561 	if (outline.fp && lvm_fclose(outline.fp, file)) {
    562 		stack;
    563 		r = 0;
    564 	}
    565 
    566 	dm_pool_destroy(outline.mem);
    567 	return r;
    568 }
    569 
    570 /*
    571  * parser
    572  */
    573 static struct config_node *_file(struct parser *p)
    574 {
    575 	struct config_node *root = NULL, *n, *l = NULL;
    576 	while (p->t != TOK_EOF) {
    577 		if (!(n = _section(p)))
    578 			return_0;
    579 
    580 		if (!root)
    581 			root = n;
    582 		else
    583 			l->sib = n;
    584 		n->parent = root;
    585 		l = n;
    586 	}
    587 	return root;
    588 }
    589 
    590 static struct config_node *_section(struct parser *p)
    591 {
    592 	/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
    593 	struct config_node *root, *n, *l = NULL;
    594 	if (!(root = _create_node(p->mem)))
    595 		return_0;
    596 
    597 	if (!(root->key = _dup_tok(p)))
    598 		return_0;
    599 
    600 	match(TOK_IDENTIFIER);
    601 
    602 	if (p->t == TOK_SECTION_B) {
    603 		match(TOK_SECTION_B);
    604 		while (p->t != TOK_SECTION_E) {
    605 			if (!(n = _section(p)))
    606 				return_0;
    607 
    608 			if (!root->child)
    609 				root->child = n;
    610 			else
    611 				l->sib = n;
    612 			n->parent = root;
    613 			l = n;
    614 		}
    615 		match(TOK_SECTION_E);
    616 	} else {
    617 		match(TOK_EQ);
    618 		if (!(root->v = _value(p)))
    619 			return_0;
    620 	}
    621 
    622 	return root;
    623 }
    624 
    625 static struct config_value *_value(struct parser *p)
    626 {
    627 	/* '[' TYPE* ']' | TYPE */
    628 	struct config_value *h = NULL, *l, *ll = NULL;
    629 	if (p->t == TOK_ARRAY_B) {
    630 		match(TOK_ARRAY_B);
    631 		while (p->t != TOK_ARRAY_E) {
    632 			if (!(l = _type(p)))
    633 				return_0;
    634 
    635 			if (!h)
    636 				h = l;
    637 			else
    638 				ll->next = l;
    639 			ll = l;
    640 
    641 			if (p->t == TOK_COMMA)
    642 				match(TOK_COMMA);
    643 		}
    644 		match(TOK_ARRAY_E);
    645 		/*
    646 		 * Special case for an empty array.
    647 		 */
    648 		if (!h) {
    649 			if (!(h = _create_value(p->mem)))
    650 				return NULL;
    651 
    652 			h->type = CFG_EMPTY_ARRAY;
    653 		}
    654 
    655 	} else
    656 		h = _type(p);
    657 
    658 	return h;
    659 }
    660 
    661 static struct config_value *_type(struct parser *p)
    662 {
    663 	/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
    664 	struct config_value *v = _create_value(p->mem);
    665 
    666 	if (!v)
    667 		return NULL;
    668 
    669 	switch (p->t) {
    670 	case TOK_INT:
    671 		v->type = CFG_INT;
    672 		v->v.i = strtoll(p->tb, NULL, 0);	/* FIXME: check error */
    673 		match(TOK_INT);
    674 		break;
    675 
    676 	case TOK_FLOAT:
    677 		v->type = CFG_FLOAT;
    678 		v->v.r = strtod(p->tb, NULL);	/* FIXME: check error */
    679 		match(TOK_FLOAT);
    680 		break;
    681 
    682 	case TOK_STRING:
    683 		v->type = CFG_STRING;
    684 
    685 		p->tb++, p->te--;	/* strip "'s */
    686 		if (!(v->v.str = _dup_tok(p)))
    687 			return_0;
    688 		p->te++;
    689 		match(TOK_STRING);
    690 		break;
    691 
    692 	case TOK_STRING_ESCAPED:
    693 		v->type = CFG_STRING;
    694 
    695 		p->tb++, p->te--;	/* strip "'s */
    696 		if (!(v->v.str = _dup_tok(p)))
    697 			return_0;
    698 		unescape_double_quotes(v->v.str);
    699 		p->te++;
    700 		match(TOK_STRING_ESCAPED);
    701 		break;
    702 
    703 	default:
    704 		log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
    705 			  p->tb - p->fb + 1, p->line);
    706 		return 0;
    707 	}
    708 	return v;
    709 }
    710 
    711 static int _match_aux(struct parser *p, int t)
    712 {
    713 	if (p->t != t)
    714 		return 0;
    715 
    716 	_get_token(p, t);
    717 	return 1;
    718 }
    719 
    720 /*
    721  * tokeniser
    722  */
    723 static void _get_token(struct parser *p, int tok_prev)
    724 {
    725 	int values_allowed = 0;
    726 
    727 	p->tb = p->te;
    728 	_eat_space(p);
    729 	if (p->tb == p->fe || !*p->tb) {
    730 		p->t = TOK_EOF;
    731 		return;
    732 	}
    733 
    734 	/* Should next token be interpreted as value instead of identifier? */
    735 	if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
    736 	    tok_prev == TOK_COMMA)
    737 		values_allowed = 1;
    738 
    739 	p->t = TOK_INT;		/* fudge so the fall through for
    740 				   floats works */
    741 	switch (*p->te) {
    742 	case SECTION_B_CHAR:
    743 		p->t = TOK_SECTION_B;
    744 		p->te++;
    745 		break;
    746 
    747 	case SECTION_E_CHAR:
    748 		p->t = TOK_SECTION_E;
    749 		p->te++;
    750 		break;
    751 
    752 	case '[':
    753 		p->t = TOK_ARRAY_B;
    754 		p->te++;
    755 		break;
    756 
    757 	case ']':
    758 		p->t = TOK_ARRAY_E;
    759 		p->te++;
    760 		break;
    761 
    762 	case ',':
    763 		p->t = TOK_COMMA;
    764 		p->te++;
    765 		break;
    766 
    767 	case '=':
    768 		p->t = TOK_EQ;
    769 		p->te++;
    770 		break;
    771 
    772 	case '"':
    773 		p->t = TOK_STRING_ESCAPED;
    774 		p->te++;
    775 		while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
    776 			if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
    777 			    *(p->te + 1))
    778 				p->te++;
    779 			p->te++;
    780 		}
    781 
    782 		if ((p->te != p->fe) && (*p->te))
    783 			p->te++;
    784 		break;
    785 
    786 	case '\'':
    787 		p->t = TOK_STRING;
    788 		p->te++;
    789 		while ((p->te != p->fe) && (*p->te) && (*p->te != '\''))
    790 			p->te++;
    791 
    792 		if ((p->te != p->fe) && (*p->te))
    793 			p->te++;
    794 		break;
    795 
    796 	case '.':
    797 		p->t = TOK_FLOAT;
    798 	case '0':
    799 	case '1':
    800 	case '2':
    801 	case '3':
    802 	case '4':
    803 	case '5':
    804 	case '6':
    805 	case '7':
    806 	case '8':
    807 	case '9':
    808 	case '+':
    809 	case '-':
    810 		if (values_allowed) {
    811 			p->te++;
    812 			while ((p->te != p->fe) && (*p->te)) {
    813 				if (*p->te == '.') {
    814 					if (p->t == TOK_FLOAT)
    815 						break;
    816 					p->t = TOK_FLOAT;
    817 				} else if (!isdigit((int) *p->te))
    818 					break;
    819 				p->te++;
    820 			}
    821 			break;
    822 		}
    823 
    824 	default:
    825 		p->t = TOK_IDENTIFIER;
    826 		while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
    827 		       (*p->te != '#') && (*p->te != '=') &&
    828 		       (*p->te != SECTION_B_CHAR) &&
    829 		       (*p->te != SECTION_E_CHAR))
    830 			p->te++;
    831 		break;
    832 	}
    833 }
    834 
    835 static void _eat_space(struct parser *p)
    836 {
    837 	while ((p->tb != p->fe) && (*p->tb)) {
    838 		if (*p->te == '#')
    839 			while ((p->te != p->fe) && (*p->te) && (*p->te != '\n'))
    840 				p->te++;
    841 
    842 		else if (isspace(*p->te)) {
    843 			while ((p->te != p->fe) && (*p->te) && isspace(*p->te)) {
    844 				if (*p->te == '\n')
    845 					p->line++;
    846 				p->te++;
    847 			}
    848 		}
    849 
    850 		else
    851 			return;
    852 
    853 		p->tb = p->te;
    854 	}
    855 }
    856 
    857 /*
    858  * memory management
    859  */
    860 static struct config_value *_create_value(struct dm_pool *mem)
    861 {
    862 	struct config_value *v = dm_pool_alloc(mem, sizeof(*v));
    863 
    864 	if (v)
    865 		memset(v, 0, sizeof(*v));
    866 
    867 	return v;
    868 }
    869 
    870 static struct config_node *_create_node(struct dm_pool *mem)
    871 {
    872 	struct config_node *n = dm_pool_alloc(mem, sizeof(*n));
    873 
    874 	if (n)
    875 		memset(n, 0, sizeof(*n));
    876 
    877 	return n;
    878 }
    879 
    880 static char *_dup_tok(struct parser *p)
    881 {
    882 	size_t len = p->te - p->tb;
    883 	char *str = dm_pool_alloc(p->mem, len + 1);
    884 	if (!str)
    885 		return_0;
    886 	strncpy(str, p->tb, len);
    887 	str[len] = '\0';
    888 	return str;
    889 }
    890 
    891 /*
    892  * utility functions
    893  */
    894 static struct config_node *_find_config_node(const struct config_node *cn,
    895 					     const char *path)
    896 {
    897 	const char *e;
    898 	const struct config_node *cn_found = NULL;
    899 
    900 	while (cn) {
    901 		/* trim any leading slashes */
    902 		while (*path && (*path == sep))
    903 			path++;
    904 
    905 		/* find the end of this segment */
    906 		for (e = path; *e && (*e != sep); e++) ;
    907 
    908 		/* hunt for the node */
    909 		cn_found = NULL;
    910 		while (cn) {
    911 			if (_tok_match(cn->key, path, e)) {
    912 				/* Inefficient */
    913 				if (!cn_found)
    914 					cn_found = cn;
    915 				else
    916 					log_error("WARNING: Ignoring duplicate"
    917 						  " config node: %s ("
    918 						  "seeking %s)", cn->key, path);
    919 			}
    920 
    921 			cn = cn->sib;
    922 		}
    923 
    924 		if (cn_found && *e)
    925 			cn = cn_found->child;
    926 		else
    927 			break;	/* don't move into the last node */
    928 
    929 		path = e;
    930 	}
    931 
    932 	return (struct config_node *) cn_found;
    933 }
    934 
    935 static struct config_node *_find_first_config_node(const struct config_node *cn1,
    936 						   const struct config_node *cn2,
    937 						   const char *path)
    938 {
    939 	struct config_node *cn;
    940 
    941 	if (cn1 && (cn = _find_config_node(cn1, path)))
    942 		return cn;
    943 
    944 	if (cn2 && (cn = _find_config_node(cn2, path)))
    945 		return cn;
    946 
    947 	return NULL;
    948 }
    949 
    950 struct config_node *find_config_node(const struct config_node *cn,
    951 				     const char *path)
    952 {
    953 	return _find_config_node(cn, path);
    954 }
    955 
    956 static const char *_find_config_str(const struct config_node *cn1,
    957 				    const struct config_node *cn2,
    958 				    const char *path, const char *fail)
    959 {
    960 	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
    961 
    962 	/* Empty strings are ignored */
    963 	if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
    964 		log_very_verbose("Setting %s to %s", path, n->v->v.str);
    965 		return n->v->v.str;
    966 	}
    967 
    968 	if (fail)
    969 		log_very_verbose("%s not found in config: defaulting to %s",
    970 				 path, fail);
    971 	return fail;
    972 }
    973 
    974 const char *find_config_str(const struct config_node *cn,
    975 			    const char *path, const char *fail)
    976 {
    977 	return _find_config_str(cn, NULL, path, fail);
    978 }
    979 
    980 static int64_t _find_config_int64(const struct config_node *cn1,
    981 				  const struct config_node *cn2,
    982 				  const char *path, int64_t fail)
    983 {
    984 	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
    985 
    986 	if (n && n->v && n->v->type == CFG_INT) {
    987 		log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i);
    988 		return n->v->v.i;
    989 	}
    990 
    991 	log_very_verbose("%s not found in config: defaulting to %" PRId64,
    992 			 path, fail);
    993 	return fail;
    994 }
    995 
    996 int find_config_int(const struct config_node *cn, const char *path, int fail)
    997 {
    998 	/* FIXME Add log_error message on overflow */
    999 	return (int) _find_config_int64(cn, NULL, path, (int64_t) fail);
   1000 }
   1001 
   1002 static float _find_config_float(const struct config_node *cn1,
   1003 				const struct config_node *cn2,
   1004 				const char *path, float fail)
   1005 {
   1006 	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
   1007 
   1008 	if (n && n->v && n->v->type == CFG_FLOAT) {
   1009 		log_very_verbose("Setting %s to %f", path, n->v->v.r);
   1010 		return n->v->v.r;
   1011 	}
   1012 
   1013 	log_very_verbose("%s not found in config: defaulting to %f",
   1014 			 path, fail);
   1015 
   1016 	return fail;
   1017 
   1018 }
   1019 
   1020 float find_config_float(const struct config_node *cn, const char *path,
   1021 			float fail)
   1022 {
   1023 	return _find_config_float(cn, NULL, path, fail);
   1024 }
   1025 
   1026 struct config_node *find_config_tree_node(struct cmd_context *cmd,
   1027 					  const char *path)
   1028 {
   1029 	return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
   1030 }
   1031 
   1032 const char *find_config_tree_str(struct cmd_context *cmd,
   1033 				 const char *path, const char *fail)
   1034 {
   1035 	return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
   1036 }
   1037 
   1038 int find_config_tree_int(struct cmd_context *cmd, const char *path,
   1039 			 int fail)
   1040 {
   1041 	/* FIXME Add log_error message on overflow */
   1042 	return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail);
   1043 }
   1044 
   1045 float find_config_tree_float(struct cmd_context *cmd, const char *path,
   1046 			     float fail)
   1047 {
   1048 	return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
   1049 }
   1050 
   1051 static int _str_in_array(const char *str, const char * const values[])
   1052 {
   1053 	int i;
   1054 
   1055 	for (i = 0; values[i]; i++)
   1056 		if (!strcasecmp(str, values[i]))
   1057 			return 1;
   1058 
   1059 	return 0;
   1060 }
   1061 
   1062 static int _str_to_bool(const char *str, int fail)
   1063 {
   1064 	const char * const _true_values[]  = { "y", "yes", "on", "true", NULL };
   1065 	const char * const _false_values[] = { "n", "no", "off", "false", NULL };
   1066 
   1067 	if (_str_in_array(str, _true_values))
   1068 		return 1;
   1069 
   1070 	if (_str_in_array(str, _false_values))
   1071 		return 0;
   1072 
   1073 	return fail;
   1074 }
   1075 
   1076 static int _find_config_bool(const struct config_node *cn1,
   1077 			     const struct config_node *cn2,
   1078 			     const char *path, int fail)
   1079 {
   1080 	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
   1081 	struct config_value *v;
   1082 
   1083 	if (!n)
   1084 		return fail;
   1085 
   1086 	v = n->v;
   1087 
   1088 	switch (v->type) {
   1089 	case CFG_INT:
   1090 		return v->v.i ? 1 : 0;
   1091 
   1092 	case CFG_STRING:
   1093 		return _str_to_bool(v->v.str, fail);
   1094 	}
   1095 
   1096 	return fail;
   1097 }
   1098 
   1099 int find_config_bool(const struct config_node *cn, const char *path, int fail)
   1100 {
   1101 	return _find_config_bool(cn, NULL, path, fail);
   1102 }
   1103 
   1104 int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
   1105 {
   1106 	return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
   1107 }
   1108 
   1109 int get_config_uint32(const struct config_node *cn, const char *path,
   1110 		      uint32_t *result)
   1111 {
   1112 	const struct config_node *n;
   1113 
   1114 	n = find_config_node(cn, path);
   1115 
   1116 	if (!n || !n->v || n->v->type != CFG_INT)
   1117 		return 0;
   1118 
   1119 	*result = n->v->v.i;
   1120 	return 1;
   1121 }
   1122 
   1123 int get_config_uint64(const struct config_node *cn, const char *path,
   1124 		      uint64_t *result)
   1125 {
   1126 	const struct config_node *n;
   1127 
   1128 	n = find_config_node(cn, path);
   1129 
   1130 	if (!n || !n->v || n->v->type != CFG_INT)
   1131 		return 0;
   1132 
   1133 	*result = (uint64_t) n->v->v.i;
   1134 	return 1;
   1135 }
   1136 
   1137 int get_config_str(const struct config_node *cn, const char *path,
   1138 		   char **result)
   1139 {
   1140 	const struct config_node *n;
   1141 
   1142 	n = find_config_node(cn, path);
   1143 
   1144 	if (!n || !n->v || n->v->type != CFG_STRING)
   1145 		return 0;
   1146 
   1147 	*result = n->v->v.str;
   1148 	return 1;
   1149 }
   1150 
   1151 /* Insert cn2 after cn1 */
   1152 static void _insert_config_node(struct config_node **cn1,
   1153 				struct config_node *cn2)
   1154 {
   1155 	if (!*cn1) {
   1156 		*cn1 = cn2;
   1157 		cn2->sib = NULL;
   1158 	} else {
   1159 		cn2->sib = (*cn1)->sib;
   1160 		(*cn1)->sib = cn2;
   1161 	}
   1162 }
   1163 
   1164 /*
   1165  * Merge section cn2 into section cn1 (which has the same name)
   1166  * overwriting any existing cn1 nodes with matching names.
   1167  */
   1168 static void _merge_section(struct config_node *cn1, struct config_node *cn2)
   1169 {
   1170 	struct config_node *cn, *nextn, *oldn;
   1171 	struct config_value *cv;
   1172 
   1173 	for (cn = cn2->child; cn; cn = nextn) {
   1174 		nextn = cn->sib;
   1175 
   1176 		/* Skip "tags" */
   1177 		if (!strcmp(cn->key, "tags"))
   1178 			continue;
   1179 
   1180 		/* Subsection? */
   1181 		if (!cn->v)
   1182 			/* Ignore - we don't have any of these yet */
   1183 			continue;
   1184 		/* Not already present? */
   1185 		if (!(oldn = find_config_node(cn1->child, cn->key))) {
   1186 			_insert_config_node(&cn1->child, cn);
   1187 			continue;
   1188 		}
   1189 		/* Merge certain value lists */
   1190 		if ((!strcmp(cn1->key, "activation") &&
   1191 		     !strcmp(cn->key, "volume_list")) ||
   1192 		    (!strcmp(cn1->key, "devices") &&
   1193 		     (!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
   1194 			cv = cn->v;
   1195 			while (cv->next)
   1196 				cv = cv->next;
   1197 			cv->next = oldn->v;
   1198 		}
   1199 
   1200 		/* Replace values */
   1201 		oldn->v = cn->v;
   1202 	}
   1203 }
   1204 
   1205 static int _match_host_tags(struct dm_list *tags, struct config_node *tn)
   1206 {
   1207 	struct config_value *tv;
   1208 	const char *str;
   1209 
   1210 	for (tv = tn->v; tv; tv = tv->next) {
   1211 		if (tv->type != CFG_STRING)
   1212 			continue;
   1213 		str = tv->v.str;
   1214 		if (*str == '@')
   1215 			str++;
   1216 		if (!*str)
   1217 			continue;
   1218 		if (str_list_match_item(tags, str))
   1219 			return 1;
   1220 	}
   1221 
   1222 	return 0;
   1223 }
   1224 
   1225 /* Destructively merge a new config tree into an existing one */
   1226 int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
   1227 		      struct config_tree *newdata)
   1228 {
   1229 	struct config_node *root = cft->root;
   1230 	struct config_node *cn, *nextn, *oldn, *tn, *cn2;
   1231 
   1232 	for (cn = newdata->root; cn; cn = nextn) {
   1233 		nextn = cn->sib;
   1234 		/* Ignore tags section */
   1235 		if (!strcmp(cn->key, "tags"))
   1236 			continue;
   1237 		/* If there's a tags node, skip if host tags don't match */
   1238 		if ((tn = find_config_node(cn->child, "tags"))) {
   1239 			if (!_match_host_tags(&cmd->tags, tn))
   1240 				continue;
   1241 		}
   1242 		if (!(oldn = find_config_node(root, cn->key))) {
   1243 			_insert_config_node(&cft->root, cn);
   1244 			/* Remove any "tags" nodes */
   1245 			for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
   1246 				if (!strcmp(cn2->key, "tags")) {
   1247 					cn->child = cn2->sib;
   1248 					continue;
   1249 				}
   1250 				if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
   1251 					cn2->sib = cn2->sib->sib;
   1252 					continue;
   1253 				}
   1254 			}
   1255 			continue;
   1256 		}
   1257 		_merge_section(oldn, cn);
   1258 	}
   1259 
   1260 	return 1;
   1261 }
   1262 
   1263 /*
   1264  * Convert a token type to the char it represents.
   1265  */
   1266 static char _token_type_to_char(int type)
   1267 {
   1268 	switch (type) {
   1269 		case TOK_SECTION_B:
   1270 			return SECTION_B_CHAR;
   1271 		case TOK_SECTION_E:
   1272 			return SECTION_E_CHAR;
   1273 		default:
   1274 			return 0;
   1275 	}
   1276 }
   1277 
   1278 /*
   1279  * Returns:
   1280  *  # of 'type' tokens in 'str'.
   1281  */
   1282 static unsigned _count_tokens(const char *str, unsigned len, int type)
   1283 {
   1284 	char c;
   1285 
   1286 	c = _token_type_to_char(type);
   1287 
   1288 	return count_chars(str, len, c);
   1289 }
   1290 
   1291 const char *config_parent_name(const struct config_node *n)
   1292 {
   1293 	return (n->parent ? n->parent->key : "(root)");
   1294 }
   1295 /*
   1296  * Heuristic function to make a quick guess as to whether a text
   1297  * region probably contains a valid config "section".  (Useful for
   1298  * scanning areas of the disk for old metadata.)
   1299  * Config sections contain various tokens, may contain other sections
   1300  * and strings, and are delimited by begin (type 'TOK_SECTION_B') and
   1301  * end (type 'TOK_SECTION_E') tokens.  As a quick heuristic, we just
   1302  * count the number of begin and end tokens, and see if they are
   1303  * non-zero and the counts match.
   1304  * Full validation of the section should be done with another function
   1305  * (for example, read_config_fd).
   1306  *
   1307  * Returns:
   1308  *  0 - probably is not a valid config section
   1309  *  1 - probably _is_ a valid config section
   1310  */
   1311 unsigned maybe_config_section(const char *str, unsigned len)
   1312 {
   1313 	int begin_count;
   1314 	int end_count;
   1315 
   1316 	begin_count = _count_tokens(str, len, TOK_SECTION_B);
   1317 	end_count = _count_tokens(str, len, TOK_SECTION_E);
   1318 
   1319 	if (begin_count && end_count && (begin_count == end_count))
   1320 		return 1;
   1321 	else
   1322 		return 0;
   1323 }
   1324 
   1325 static struct config_value *_clone_config_value(struct dm_pool *mem, const struct config_value *v)
   1326 {
   1327 	if (!v)
   1328 		return NULL;
   1329 	struct config_value *new = _create_value(mem);
   1330 	new->type = v->type;
   1331 	if (v->type == CFG_STRING)
   1332 		new->v.str = dm_pool_strdup(mem, v->v.str);
   1333 	else
   1334 		new->v = v->v;
   1335 	new->next = _clone_config_value(mem, v->next);
   1336 	return new;
   1337 }
   1338 
   1339 struct config_node *clone_config_node(struct dm_pool *mem, const struct config_node *cn,
   1340 				      int siblings)
   1341 {
   1342 	if (!cn)
   1343 		return NULL;
   1344 	struct config_node *new = _create_node(mem);
   1345 	new->key = dm_pool_strdup(mem, cn->key);
   1346 	new->child = clone_config_node(mem, cn->child, 1);
   1347 	new->v = _clone_config_value(mem, cn->v);
   1348 	if (siblings)
   1349 		new->sib = clone_config_node(mem, cn->sib, siblings);
   1350 	else
   1351 		new->sib = NULL;
   1352 	return new;
   1353 }
   1354