4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
23 #include "toolcontext.h"
24 #include "lvm-string.h"
33 #define SECTION_B_CHAR '{'
34 #define SECTION_E_CHAR '}'
39 TOK_STRING
, /* Single quotes */
40 TOK_STRING_ESCAPED
, /* Double quotes */
52 const char *fb
, *fe
; /* file limits */
54 int t
; /* token limits and type */
57 int fd
; /* descriptor for file being parsed */
58 int line
; /* line number we are on */
64 struct config_tree cft
;
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
);
91 static const int sep
= '/';
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); \
103 static int _tok_match(const char *str
, const char *b
, const char *e
)
105 while (*str
&& (b
!= e
)) {
110 return !(*str
|| (b
!= e
));
116 struct config_tree
*create_config_tree(const char *filename
, int keep_open
)
119 struct dm_pool
*mem
= dm_pool_create("config", 10 * 1024);
122 log_error("Failed to allocate config pool.");
126 if (!(c
= dm_pool_zalloc(mem
, sizeof(*c
)))) {
127 log_error("Failed to allocate config tree.");
128 dm_pool_destroy(mem
);
133 c
->cft
.root
= (struct config_node
*) NULL
;
136 c
->keep_open
= keep_open
;
139 c
->filename
= dm_pool_strdup(c
->mem
, filename
);
143 void destroy_config_tree(struct config_tree
*cft
)
145 struct cs
*c
= (struct cs
*) cft
;
150 dm_pool_destroy(c
->mem
);
153 static int _parse_config_file(struct parser
*p
, struct config_tree
*cft
)
155 p
->tb
= p
->te
= p
->fb
;
157 _get_token(p
, TOK_SECTION_E
);
158 if (!(cft
->root
= _file(p
)))
164 struct config_tree
*create_config_tree_from_string(struct cmd_context
*cmd
__attribute((unused
)),
165 const char *config_settings
)
168 struct config_tree
*cft
;
171 if (!(cft
= create_config_tree(NULL
, 0)))
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
);
182 p
->fb
= config_settings
;
183 p
->fe
= config_settings
+ strlen(config_settings
);
185 if (!_parse_config_file(p
, cft
)) {
186 destroy_config_tree(cft
);
193 int override_config_tree_from_string(struct cmd_context
*cmd
,
194 const char *config_settings
)
196 if (!(cmd
->cft_override
= create_config_tree_from_string(cmd
,config_settings
))) {
197 log_error("Failed to set overridden configuration entries.");
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
)
208 struct cs
*c
= (struct cs
*) cft
;
212 off_t mmap_offset
= 0;
215 if (!(p
= dm_pool_alloc(c
->mem
, sizeof(*p
))))
219 /* Only use mmap with regular files */
220 if (!(dev
->flags
& DEV_REGULAR
) || size2
)
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
));
232 p
->fb
= p
->fb
+ mmap_offset
;
234 if (!(buf
= dm_malloc(size
+ size2
)))
236 if (!dev_read_circular(dev
, (uint64_t) offset
, size
,
237 (uint64_t) offset2
, size2
, buf
)) {
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
));
250 p
->fe
= p
->fb
+ size
+ size2
;
252 if (!_parse_config_file(p
, cft
))
262 if (munmap((char *) (p
->fb
- mmap_offset
), size
+ mmap_offset
)) {
263 log_sys_error("munmap", dev_name(dev
));
271 int read_config_file(struct config_tree
*cft
)
273 struct cs
*c
= (struct cs
*) cft
;
277 if (stat(c
->filename
, &info
)) {
278 log_sys_error("stat", c
->filename
);
283 if (!S_ISREG(info
.st_mode
)) {
284 log_error("%s is not a regular file", c
->filename
);
291 if (info
.st_size
== 0) {
292 log_verbose("%s is empty", c
->filename
);
297 if (!(c
->dev
= dev_create_file(c
->filename
, NULL
, NULL
, 1)))
300 if (!dev_open_flags(c
->dev
, O_RDONLY
, 0, 0))
304 r
= read_config_fd(cft
, c
->dev
, 0, (size_t) info
.st_size
, 0, 0,
305 (checksum_fn_t
) NULL
, 0);
312 c
->timestamp
= info
.st_ctime
;
317 time_t config_file_timestamp(struct config_tree
*cft
)
319 struct cs
*c
= (struct cs
*) cft
;
325 * Return 1 if config files ought to be reloaded
327 int config_file_changed(struct config_tree
*cft
)
329 struct cs
*c
= (struct cs
*) cft
;
335 if (stat(c
->filename
, &info
) == -1) {
336 /* Ignore a deleted config file: still use original data */
337 if (errno
== ENOENT
) {
340 log_very_verbose("Config file %s has disappeared!",
344 log_sys_error("stat", c
->filename
);
345 log_error("Failed to reload configuration files");
349 if (!S_ISREG(info
.st_mode
)) {
350 log_error("Configuration file %s is not a regular file",
356 if (c
->timestamp
== info
.st_ctime
)
360 log_verbose("Detected config file change to %s", c
->filename
);
364 static int _line_start(struct output_line
*outline
)
366 if (!dm_pool_begin_object(outline
->mem
, 128)) {
367 log_error("dm_pool_begin_object failed for config line");
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
, ...)
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");
390 if (!dm_pool_grow_object(outline
->mem
, &buf
[0], strlen(buf
))) {
391 log_error("dm_pool_grow_object failed for config line");
398 #define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
400 static int _line_end(struct output_line
*outline
)
404 if (!dm_pool_grow_object(outline
->mem
, "\0", 1)) {
405 log_error("dm_pool_grow_object failed for config line");
409 line
= dm_pool_end_object(outline
->mem
);
410 if (outline
->putline
)
411 outline
->putline(line
, outline
->putline_baton
);
414 log_print("%s", line
);
416 fprintf(outline
->fp
, "%s\n", line
);
422 static int _write_value(struct output_line
*outline
, struct config_value
*v
)
428 if (!(buf
= alloca(escaped_len(v
->v
.str
)))) {
429 log_error("temporary stack allocation for a config "
433 line_append("\"%s\"", escape_double_quotes(buf
, v
->v
.str
));
437 line_append("%f", v
->v
.r
);
441 line_append("%" PRId64
, v
->v
.i
);
444 case CFG_EMPTY_ARRAY
:
449 log_error("_write_value: Unknown value type: %d", v
->type
);
456 static int _write_config(const struct config_node
*n
, int only_one
,
457 struct output_line
*outline
, int level
)
459 char space
[MAX_INDENT
+ 1];
460 int l
= (level
< MAX_INDENT
) ? level
: MAX_INDENT
;
466 for (i
= 0; i
< l
; i
++)
471 if (!_line_start(outline
))
473 line_append("%s%s", space
, n
->key
);
475 /* it's a sub section */
477 if (!_line_end(outline
))
479 _write_config(n
->child
, 0, outline
, level
+ 1);
480 if (!_line_start(outline
))
482 line_append("%s}", space
);
485 struct config_value
*v
= n
->v
;
490 if (!_write_value(outline
, v
))
498 if (!_write_value(outline
, v
))
501 if (!_line_end(outline
))
504 } while (n
&& !only_one
);
505 /* FIXME: add error checking */
509 int write_config_node(const struct config_node
*cn
, putline_fn putline
, void *baton
)
511 struct output_line outline
;
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
);
520 dm_pool_destroy(outline
.mem
);
524 int write_config_file(struct config_tree
*cft
, const char *file
,
525 int argc
, char **argv
)
527 struct config_node
*cn
;
529 struct output_line outline
;
531 outline
.putline
= NULL
;
535 else if (!(outline
.fp
= fopen(file
, "w"))) {
536 log_sys_error("open", file
);
540 outline
.mem
= dm_pool_create("config_line", 1024);
542 log_verbose("Dumping configuration to %s", file
);
544 if (!_write_config(cft
->root
, 0, &outline
, 0)) {
545 log_error("Failure while writing to %s", file
);
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
);
555 log_error("Configuration node %s not found", *argv
);
561 if (outline
.fp
&& lvm_fclose(outline
.fp
, file
)) {
566 dm_pool_destroy(outline
.mem
);
573 static struct config_node
*_file(struct parser
*p
)
575 struct config_node
*root
= NULL
, *n
, *l
= NULL
;
576 while (p
->t
!= TOK_EOF
) {
577 if (!(n
= _section(p
)))
590 static struct config_node
*_section(struct parser
*p
)
592 /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
593 struct config_node
*root
, *n
, *l
= NULL
;
594 if (!(root
= _create_node(p
->mem
)))
597 if (!(root
->key
= _dup_tok(p
)))
600 match(TOK_IDENTIFIER
);
602 if (p
->t
== TOK_SECTION_B
) {
603 match(TOK_SECTION_B
);
604 while (p
->t
!= TOK_SECTION_E
) {
605 if (!(n
= _section(p
)))
615 match(TOK_SECTION_E
);
618 if (!(root
->v
= _value(p
)))
625 static struct config_value
*_value(struct parser
*p
)
627 /* '[' TYPE* ']' | TYPE */
628 struct config_value
*h
= NULL
, *l
, *ll
= NULL
;
629 if (p
->t
== TOK_ARRAY_B
) {
631 while (p
->t
!= TOK_ARRAY_E
) {
641 if (p
->t
== TOK_COMMA
)
646 * Special case for an empty array.
649 if (!(h
= _create_value(p
->mem
)))
652 h
->type
= CFG_EMPTY_ARRAY
;
661 static struct config_value
*_type(struct parser
*p
)
663 /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
664 struct config_value
*v
= _create_value(p
->mem
);
672 v
->v
.i
= strtoll(p
->tb
, NULL
, 0); /* FIXME: check error */
678 v
->v
.r
= strtod(p
->tb
, NULL
); /* FIXME: check error */
683 v
->type
= CFG_STRING
;
685 p
->tb
++, p
->te
--; /* strip "'s */
686 if (!(v
->v
.str
= _dup_tok(p
)))
692 case TOK_STRING_ESCAPED
:
693 v
->type
= CFG_STRING
;
695 p
->tb
++, p
->te
--; /* strip "'s */
696 if (!(v
->v
.str
= _dup_tok(p
)))
698 unescape_double_quotes(v
->v
.str
);
700 match(TOK_STRING_ESCAPED
);
704 log_error("Parse error at byte %" PRIptrdiff_t
" (line %d): expected a value",
705 p
->tb
- p
->fb
+ 1, p
->line
);
711 static int _match_aux(struct parser
*p
, int t
)
723 static void _get_token(struct parser
*p
, int tok_prev
)
725 int values_allowed
= 0;
729 if (p
->tb
== p
->fe
|| !*p
->tb
) {
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
)
739 p
->t
= TOK_INT
; /* fudge so the fall through for
743 p
->t
= TOK_SECTION_B
;
748 p
->t
= TOK_SECTION_E
;
773 p
->t
= TOK_STRING_ESCAPED
;
775 while ((p
->te
!= p
->fe
) && (*p
->te
) && (*p
->te
!= '"')) {
776 if ((*p
->te
== '\\') && (p
->te
+ 1 != p
->fe
) &&
782 if ((p
->te
!= p
->fe
) && (*p
->te
))
789 while ((p
->te
!= p
->fe
) && (*p
->te
) && (*p
->te
!= '\''))
792 if ((p
->te
!= p
->fe
) && (*p
->te
))
810 if (values_allowed
) {
812 while ((p
->te
!= p
->fe
) && (*p
->te
)) {
814 if (p
->t
== TOK_FLOAT
)
817 } else if (!isdigit((int) *p
->te
))
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
))
835 static void _eat_space(struct parser
*p
)
837 while ((p
->tb
!= p
->fe
) && (*p
->tb
)) {
839 while ((p
->te
!= p
->fe
) && (*p
->te
) && (*p
->te
!= '\n'))
842 else if (isspace(*p
->te
)) {
843 while ((p
->te
!= p
->fe
) && (*p
->te
) && isspace(*p
->te
)) {
860 static struct config_value
*_create_value(struct dm_pool
*mem
)
862 struct config_value
*v
= dm_pool_alloc(mem
, sizeof(*v
));
865 memset(v
, 0, sizeof(*v
));
870 static struct config_node
*_create_node(struct dm_pool
*mem
)
872 struct config_node
*n
= dm_pool_alloc(mem
, sizeof(*n
));
875 memset(n
, 0, sizeof(*n
));
880 static char *_dup_tok(struct parser
*p
)
882 size_t len
= p
->te
- p
->tb
;
883 char *str
= dm_pool_alloc(p
->mem
, len
+ 1);
886 strncpy(str
, p
->tb
, len
);
894 static struct config_node
*_find_config_node(const struct config_node
*cn
,
898 const struct config_node
*cn_found
= NULL
;
901 /* trim any leading slashes */
902 while (*path
&& (*path
== sep
))
905 /* find the end of this segment */
906 for (e
= path
; *e
&& (*e
!= sep
); e
++) ;
908 /* hunt for the node */
911 if (_tok_match(cn
->key
, path
, e
)) {
916 log_error("WARNING: Ignoring duplicate"
918 "seeking %s)", cn
->key
, path
);
925 cn
= cn_found
->child
;
927 break; /* don't move into the last node */
932 return (struct config_node
*) cn_found
;
935 static struct config_node
*_find_first_config_node(const struct config_node
*cn1
,
936 const struct config_node
*cn2
,
939 struct config_node
*cn
;
941 if (cn1
&& (cn
= _find_config_node(cn1
, path
)))
944 if (cn2
&& (cn
= _find_config_node(cn2
, path
)))
950 struct config_node
*find_config_node(const struct config_node
*cn
,
953 return _find_config_node(cn
, path
);
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
)
960 const struct config_node
*n
= _find_first_config_node(cn1
, cn2
, path
);
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
);
969 log_very_verbose("%s not found in config: defaulting to %s",
974 const char *find_config_str(const struct config_node
*cn
,
975 const char *path
, const char *fail
)
977 return _find_config_str(cn
, NULL
, path
, fail
);
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
)
984 const struct config_node
*n
= _find_first_config_node(cn1
, cn2
, path
);
986 if (n
&& n
->v
&& n
->v
->type
== CFG_INT
) {
987 log_very_verbose("Setting %s to %" PRId64
, path
, n
->v
->v
.i
);
991 log_very_verbose("%s not found in config: defaulting to %" PRId64
,
996 int find_config_int(const struct config_node
*cn
, const char *path
, int fail
)
998 /* FIXME Add log_error message on overflow */
999 return (int) _find_config_int64(cn
, NULL
, path
, (int64_t) fail
);
1002 static float _find_config_float(const struct config_node
*cn1
,
1003 const struct config_node
*cn2
,
1004 const char *path
, float fail
)
1006 const struct config_node
*n
= _find_first_config_node(cn1
, cn2
, path
);
1008 if (n
&& n
->v
&& n
->v
->type
== CFG_FLOAT
) {
1009 log_very_verbose("Setting %s to %f", path
, n
->v
->v
.r
);
1013 log_very_verbose("%s not found in config: defaulting to %f",
1020 float find_config_float(const struct config_node
*cn
, const char *path
,
1023 return _find_config_float(cn
, NULL
, path
, fail
);
1026 struct config_node
*find_config_tree_node(struct cmd_context
*cmd
,
1029 return _find_first_config_node(cmd
->cft_override
? cmd
->cft_override
->root
: NULL
, cmd
->cft
->root
, path
);
1032 const char *find_config_tree_str(struct cmd_context
*cmd
,
1033 const char *path
, const char *fail
)
1035 return _find_config_str(cmd
->cft_override
? cmd
->cft_override
->root
: NULL
, cmd
->cft
->root
, path
, fail
);
1038 int find_config_tree_int(struct cmd_context
*cmd
, const char *path
,
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
);
1045 float find_config_tree_float(struct cmd_context
*cmd
, const char *path
,
1048 return _find_config_float(cmd
->cft_override
? cmd
->cft_override
->root
: NULL
, cmd
->cft
->root
, path
, fail
);
1051 static int _str_in_array(const char *str
, const char * const values
[])
1055 for (i
= 0; values
[i
]; i
++)
1056 if (!strcasecmp(str
, values
[i
]))
1062 static int _str_to_bool(const char *str
, int fail
)
1064 const char * const _true_values
[] = { "y", "yes", "on", "true", NULL
};
1065 const char * const _false_values
[] = { "n", "no", "off", "false", NULL
};
1067 if (_str_in_array(str
, _true_values
))
1070 if (_str_in_array(str
, _false_values
))
1076 static int _find_config_bool(const struct config_node
*cn1
,
1077 const struct config_node
*cn2
,
1078 const char *path
, int fail
)
1080 const struct config_node
*n
= _find_first_config_node(cn1
, cn2
, path
);
1081 struct config_value
*v
;
1090 return v
->v
.i
? 1 : 0;
1093 return _str_to_bool(v
->v
.str
, fail
);
1099 int find_config_bool(const struct config_node
*cn
, const char *path
, int fail
)
1101 return _find_config_bool(cn
, NULL
, path
, fail
);
1104 int find_config_tree_bool(struct cmd_context
*cmd
, const char *path
, int fail
)
1106 return _find_config_bool(cmd
->cft_override
? cmd
->cft_override
->root
: NULL
, cmd
->cft
->root
, path
, fail
);
1109 int get_config_uint32(const struct config_node
*cn
, const char *path
,
1112 const struct config_node
*n
;
1114 n
= find_config_node(cn
, path
);
1116 if (!n
|| !n
->v
|| n
->v
->type
!= CFG_INT
)
1119 *result
= n
->v
->v
.i
;
1123 int get_config_uint64(const struct config_node
*cn
, const char *path
,
1126 const struct config_node
*n
;
1128 n
= find_config_node(cn
, path
);
1130 if (!n
|| !n
->v
|| n
->v
->type
!= CFG_INT
)
1133 *result
= (uint64_t) n
->v
->v
.i
;
1137 int get_config_str(const struct config_node
*cn
, const char *path
,
1140 const struct config_node
*n
;
1142 n
= find_config_node(cn
, path
);
1144 if (!n
|| !n
->v
|| n
->v
->type
!= CFG_STRING
)
1147 *result
= n
->v
->v
.str
;
1151 /* Insert cn2 after cn1 */
1152 static void _insert_config_node(struct config_node
**cn1
,
1153 struct config_node
*cn2
)
1159 cn2
->sib
= (*cn1
)->sib
;
1165 * Merge section cn2 into section cn1 (which has the same name)
1166 * overwriting any existing cn1 nodes with matching names.
1168 static void _merge_section(struct config_node
*cn1
, struct config_node
*cn2
)
1170 struct config_node
*cn
, *nextn
, *oldn
;
1171 struct config_value
*cv
;
1173 for (cn
= cn2
->child
; cn
; cn
= nextn
) {
1177 if (!strcmp(cn
->key
, "tags"))
1182 /* Ignore - we don't have any of these yet */
1184 /* Not already present? */
1185 if (!(oldn
= find_config_node(cn1
->child
, cn
->key
))) {
1186 _insert_config_node(&cn1
->child
, cn
);
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")))) {
1200 /* Replace values */
1205 static int _match_host_tags(struct dm_list
*tags
, struct config_node
*tn
)
1207 struct config_value
*tv
;
1210 for (tv
= tn
->v
; tv
; tv
= tv
->next
) {
1211 if (tv
->type
!= CFG_STRING
)
1218 if (str_list_match_item(tags
, str
))
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
)
1229 struct config_node
*root
= cft
->root
;
1230 struct config_node
*cn
, *nextn
, *oldn
, *tn
, *cn2
;
1232 for (cn
= newdata
->root
; cn
; cn
= nextn
) {
1234 /* Ignore tags section */
1235 if (!strcmp(cn
->key
, "tags"))
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
))
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
;
1250 if (cn2
->sib
&& !strcmp(cn2
->sib
->key
, "tags")) {
1251 cn2
->sib
= cn2
->sib
->sib
;
1257 _merge_section(oldn
, cn
);
1264 * Convert a token type to the char it represents.
1266 static char _token_type_to_char(int type
)
1270 return SECTION_B_CHAR
;
1272 return SECTION_E_CHAR
;
1280 * # of 'type' tokens in 'str'.
1282 static unsigned _count_tokens(const char *str
, unsigned len
, int type
)
1286 c
= _token_type_to_char(type
);
1288 return count_chars(str
, len
, c
);
1291 const char *config_parent_name(const struct config_node
*n
)
1293 return (n
->parent
? n
->parent
->key
: "(root)");
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).
1308 * 0 - probably is not a valid config section
1309 * 1 - probably _is_ a valid config section
1311 unsigned maybe_config_section(const char *str
, unsigned len
)
1316 begin_count
= _count_tokens(str
, len
, TOK_SECTION_B
);
1317 end_count
= _count_tokens(str
, len
, TOK_SECTION_E
);
1319 if (begin_count
&& end_count
&& (begin_count
== end_count
))
1325 static struct config_value
*_clone_config_value(struct dm_pool
*mem
, const struct config_value
*v
)
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
);
1335 new->next
= _clone_config_value(mem
, v
->next
);
1339 struct config_node
*clone_config_node(struct dm_pool
*mem
, const struct config_node
*cn
,
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
);
1349 new->sib
= clone_config_node(mem
, cn
->sib
, siblings
);