diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 5dcfb79f2..ae769dde3 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -273,8 +273,8 @@ int activation(void) static int _passes_activation_filter(struct cmd_context *cmd, struct logical_volume *lv) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; const char *str; char path[PATH_MAX]; @@ -304,7 +304,7 @@ static int _passes_activation_filter(struct cmd_context *cmd, lv->vg->name, lv->name); for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Ignoring invalid string in config file " "activation/volume_list"); continue; diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index d1195a1fc..b5b4b9eda 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -269,7 +269,7 @@ int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv, char *dlid, *name; int r; - if (!(name = build_dm_name(mem, lv->vg->name, lv->name, layer))) { + if (!(name = dm_build_dm_name(mem, lv->vg->name, lv->name, layer))) { log_error("name build failed for %s", lv->name); return 0; } @@ -723,7 +723,7 @@ int dev_manager_snapshot_percent(struct dev_manager *dm, /* * Build a name for the top layer. */ - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) return_0; if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, NULL))) @@ -757,7 +757,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm, /* * Build a name for the top layer. */ - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; /* FIXME dm_pool_free ? */ @@ -800,7 +800,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm, /* Rename? */ if ((suffix = strrchr(dl->dlid + sizeof(UUID_PREFIX) - 1, '-'))) suffix++; - new_name = build_dm_name(dm->mem, dm->vg_name, dl->lv->name, + new_name = dm_build_dm_name(dm->mem, dm->vg_name, dl->lv->name, suffix); static int _belong_to_vg(const char *vgname, const char *name) @@ -843,7 +843,7 @@ static int _dev_manager_lv_mknodes(const struct logical_volume *lv) { char *name; - if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name, + if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL))) return_0; @@ -861,7 +861,7 @@ int dev_manager_mknodes(const struct logical_volume *lv) char *name; int r = 0; - if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL))) + if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL))) return_0; if ((r = _info_run(name, NULL, &dminfo, NULL, 1, 0, 0, 0, 0))) { @@ -933,7 +933,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, char *dlid, *name; struct dm_info info, info2; - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer))) @@ -1163,7 +1163,7 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree, if (!(id = build_dm_uuid(dm->mem, seg->lv->lvid.s, errid))) return_NULL; - if (!(name = build_dm_name(dm->mem, seg->lv->vg->name, + if (!(name = dm_build_dm_name(dm->mem, seg->lv->vg->name, seg->lv->name, errid))) return_NULL; if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0))) @@ -1558,7 +1558,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, } } - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer))) diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index 50333dcb0..cde807f34 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -677,7 +677,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted) /* Build config tree from vgmetadata, if not yet cached */ if (!vginfo->cft && !(vginfo->cft = - create_config_tree_from_string(vginfo->vgmetadata))) + dm_config_from_string(vginfo->vgmetadata))) goto_bad; if (!(vg = import_vg_from_config_tree(vginfo->cft, fid))) diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 2cf02362a..3a8c406b9 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -33,7 +33,7 @@ struct cmd_context; struct format_type; struct volume_group; -struct config_tree; +struct dm_config_tree; /* One per VG */ struct lvmcache_vginfo { @@ -48,8 +48,8 @@ struct lvmcache_vginfo { char *creation_host; size_t vgmetadata_size; char *vgmetadata; /* Copy of VG metadata as format_text string */ - struct config_tree *cft; /* Config tree created from vgmetadata */ - /* Lifetime is directly tied to vgmetadata */ + struct dm_config_tree *cft; /* Config tree created from vgmetadata */ + /* Lifetime is directly tied to vgmetadata */ struct volume_group *cached_vg; unsigned holders; unsigned vg_use_count; /* Counter of vg reusage */ diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index a91ccc7d8..8c8ac45c1 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -222,8 +222,8 @@ static int _process_config(struct cmd_context *cmd) mode_t old_umask; const char *read_ahead; struct stat st; - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; int64_t pv_min_kb; /* umask */ @@ -358,7 +358,7 @@ static int _process_config(struct cmd_context *cmd) if ((cn = find_config_tree_node(cmd, "activation/mlock_filter"))) for (cv = cn->v; cv; cv = cv->next) - if ((cv->type != CFG_STRING) || !cv->v.str[0]) + if ((cv->type != DM_CFG_STRING) || !cv->v.str[0]) log_error("Ignoring invalid activation/mlock_filter entry in config file"); cmd->metadata_read_only = find_config_tree_int(cmd, "global/metadata_read_only", @@ -392,11 +392,11 @@ static int _set_tag(struct cmd_context *cmd, const char *tag) return 1; } -static int _check_host_filters(struct cmd_context *cmd, const struct config_node *hn, +static int _check_host_filters(struct cmd_context *cmd, const struct dm_config_node *hn, int *passes) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; *passes = 1; @@ -405,10 +405,10 @@ static int _check_host_filters(struct cmd_context *cmd, const struct config_node continue; if (!strcmp(cn->key, "host_list")) { *passes = 0; - if (cn->v->type == CFG_EMPTY_ARRAY) + if (cn->v->type == DM_CFG_EMPTY_ARRAY) continue; for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid hostname string " "for tag %s", cn->key); return 0; @@ -428,17 +428,17 @@ static int _check_host_filters(struct cmd_context *cmd, const struct config_node return 1; } -static int _init_tags(struct cmd_context *cmd, struct config_tree *cft) +static int _init_tags(struct cmd_context *cmd, struct dm_config_tree *cft) { - const struct config_node *tn, *cn; + const struct dm_config_node *tn, *cn; const char *tag; int passes; - if (!(tn = find_config_node(cft->root, "tags")) || !tn->child) + if (!(tn = dm_config_find_node(cft->root, "tags")) || !tn->child) return 1; /* NB hosttags 0 when already 1 intentionally does not delete the tag */ - if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags", + if (!cmd->hosttags && dm_config_find_int(cft->root, "tags/hosttags", DEFAULT_HOSTTAGS)) { /* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */ if (!_set_tag(cmd, cmd->hostname)) @@ -491,7 +491,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag) return 0; } - if (!(cfl->cft = create_config_tree(config_file, 0))) { + if (!(cfl->cft = dm_config_create(config_file, 0))) { log_error("config_tree allocation failed"); return 0; } @@ -531,7 +531,7 @@ static int _init_lvm_conf(struct cmd_context *cmd) { /* No config file if LVM_SYSTEM_DIR is empty */ if (!*cmd->system_dir) { - if (!(cmd->cft = create_config_tree(NULL, 0))) { + if (!(cmd->cft = dm_config_create(NULL, 0))) { log_error("Failed to create config tree"); return 0; } @@ -564,7 +564,7 @@ static int _merge_config_files(struct cmd_context *cmd) /* Replace temporary duplicate copy of lvm.conf */ if (cmd->cft->root) { - if (!(cmd->cft = create_config_tree(NULL, 0))) { + if (!(cmd->cft = dm_config_create(NULL, 0))) { log_error("Failed to create config tree"); return 0; } @@ -593,7 +593,7 @@ int config_files_changed(struct cmd_context *cmd) struct config_tree_list *cfl; dm_list_iterate_items(cfl, &cmd->config_files) { - if (config_file_changed(cfl->cft)) + if (dm_config_changed(cfl->cft)) return 1; } @@ -620,8 +620,8 @@ static void _destroy_tag_configs(struct cmd_context *cmd) static int _init_dev_cache(struct cmd_context *cmd) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; size_t uninitialized_var(udev_dir_len), len; int device_list_from_udev; const char *uninitialized_var(udev_dir); @@ -653,7 +653,7 @@ static int _init_dev_cache(struct cmd_context *cmd) } for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "devices/scan"); return 0; @@ -680,7 +680,7 @@ static int _init_dev_cache(struct cmd_context *cmd) return 1; for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "devices/loopfiles"); return 0; @@ -702,7 +702,7 @@ static int _init_dev_cache(struct cmd_context *cmd) static struct dev_filter *_init_filter_components(struct cmd_context *cmd) { unsigned nr_filt = 0; - const struct config_node *cn; + const struct dm_config_node *cn; struct dev_filter *filters[MAX_FILTERS]; memset(filters, 0, sizeof(filters)); @@ -823,7 +823,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache */ if (load_persistent_cache && !cmd->is_long_lived && !stat(dev_cache, &st) && - (st.st_ctime > config_file_timestamp(cmd->cft)) && + (st.st_ctime > dm_config_timestamp(cmd->cft)) && !persistent_filter_load(f4, NULL)) log_verbose("Failed to load existing device cache from %s", dev_cache); @@ -853,7 +853,7 @@ static int _init_formats(struct cmd_context *cmd) struct format_type *fmt; #ifdef HAVE_LIBDL - const struct config_node *cn; + const struct dm_config_node *cn; #endif label_init(); @@ -877,12 +877,12 @@ static int _init_formats(struct cmd_context *cmd) if (!is_static() && (cn = find_config_tree_node(cmd, "global/format_libraries"))) { - const struct config_value *cv; + const struct dm_config_value *cv; struct format_type *(*init_format_fn) (struct cmd_context *); void *lib; for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "global/format_libraries"); return 0; @@ -1010,7 +1010,7 @@ static int _init_segtypes(struct cmd_context *cmd) }; #ifdef HAVE_LIBDL - const struct config_node *cn; + const struct dm_config_node *cn; #endif for (i = 0; init_segtype_array[i]; i++) { @@ -1040,12 +1040,12 @@ static int _init_segtypes(struct cmd_context *cmd) if (!is_static() && (cn = find_config_tree_node(cmd, "global/segment_libraries"))) { - const struct config_value *cv; + const struct dm_config_value *cv; int (*init_multiple_segtypes_fn) (struct cmd_context *, struct segtype_library *); for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "global/segment_libraries"); return 0; diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index fb28a0371..978d34f10 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -47,11 +47,16 @@ struct config_info { char _padding[1]; }; -struct config_tree; +struct dm_config_tree; struct archive_params; struct backup_params; struct arg_values; +struct config_tree_list { + struct dm_list list; + struct dm_config_tree *cft; +}; + /* FIXME Split into tool & library contexts */ /* command-instance-related variables needed by library */ struct cmd_context { @@ -87,8 +92,8 @@ struct cmd_context { struct dm_list config_files; int config_valid; - struct config_tree *cft; - struct config_tree *cft_override; + struct dm_config_tree *cft; + struct dm_config_tree *cft_override; struct config_info default_settings; struct config_info current_settings; diff --git a/lib/config/config.c b/lib/config/config.c index d7b704259..39dded0c7 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 #include -#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; + int r; - if (stat(c->filename, &info)) { - log_sys_error("stat", c->filename); - c->exists = 0; + if (!dm_config_check_file(cft, &filename, &info)) return 0; - } - if (!S_ISREG(info.st_mode)) { - log_error("%s is not a regular file", c->filename); - c->exists = 0; - 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; - } - - 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) -{ - 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); - } - - 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 (!dm_config_keep_open(cft)) { + dev_close(dev); + dm_config_set_custom(cft, NULL); } return r; } -/* - * parser - */ -static struct config_node *_file(struct parser *p) +static struct dm_config_tree *_setup_context_tree(struct cmd_context *cmd) { - struct config_node *root = NULL, *n, *l = NULL; - while (p->t != TOK_EOF) { - if (!(n = _section(p))) - return_0; + struct dm_config_tree *r = cmd->cft_override; - if (!root) - root = n; - else - l->sib = n; - n->parent = root; - l = n; - } - return root; + if (r) + r->cascade = cmd->cft; + else + r = cmd->cft; + + return r; } -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; -} diff --git a/lib/config/config.h b/lib/config/config.h index acdc47a19..c2a93ad74 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -21,76 +21,26 @@ struct device; struct cmd_context; -enum { - CFG_STRING, - CFG_FLOAT, - CFG_INT, - CFG_EMPTY_ARRAY -}; - -struct config_value { - int type; - union { - int64_t i; - float r; - const char *str; - } v; - struct config_value *next; /* for arrays */ -}; - -struct config_node { - const char *key; - struct config_node *parent, *sib, *child; - struct config_value *v; -}; - -struct config_tree { - struct config_node *root; -}; - -struct config_tree_list { - struct dm_list list; - struct config_tree *cft; -}; - -struct config_tree *create_config_tree(const char *filename, int keep_open); -struct config_tree *create_config_tree_from_string(const char *config_settings); - int override_config_tree_from_string(struct cmd_context *cmd, const char *config_settings); -void destroy_config_tree(struct config_tree *cft); +void destroy_config_tree(struct dm_config_tree *cft); typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_t size); -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); -int read_config_file(struct config_tree *cft); -int write_config_file(struct config_tree *cft, const char *file, - int argc, char **argv); +int read_config_file(struct dm_config_tree *cft); -typedef int (*putline_fn)(const char *line, void *baton); -int write_config_node(const struct config_node *cn, putline_fn putline, void *baton); - -time_t config_file_timestamp(struct config_tree *cft); -int config_file_changed(struct config_tree *cft); -int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft, - struct config_tree *newdata); - -const struct config_node *find_config_node(const struct config_node *cn, - const char *path); -const char *find_config_str(const struct config_node *cn, const char *path, - const char *fail); -int find_config_int(const struct config_node *cn, const char *path, int fail); -float find_config_float(const struct config_node *cn, const char *path, - float fail); +int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft, + struct dm_config_tree *newdata); /* * These versions check an override tree, if present, first. */ -const struct config_node *find_config_tree_node(struct cmd_context *cmd, - const char *path); +const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, + const char *path); const char *find_config_tree_str(struct cmd_context *cmd, const char *path, const char *fail); int find_config_tree_int(struct cmd_context *cmd, const char *path, @@ -100,34 +50,6 @@ int64_t find_config_tree_int64(struct cmd_context *cmd, const char *path, float find_config_tree_float(struct cmd_context *cmd, const char *path, float fail); -/* - * Understands (0, ~0), (y, n), (yes, no), (on, - * off), (true, false). - */ -int find_config_bool(const struct config_node *cn, const char *path, int fail); int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail); -int get_config_uint32(const struct config_node *cn, const char *path, - uint32_t *result); - -int get_config_uint64(const struct config_node *cn, const char *path, - uint64_t *result); - -int get_config_str(const struct config_node *cn, const char *path, - const char **result); - -unsigned maybe_config_section(const char *str, unsigned len); - -const char *config_parent_name(const struct config_node *n); - -struct config_node *clone_config_node_with_mem(struct dm_pool *mem, - const struct config_node *node, - int siblings); -struct config_node *create_config_node(struct config_tree *cft, const char *key); -struct config_value *create_config_value(struct config_tree *cft); -struct config_node *clone_config_node(struct config_tree *cft, const struct config_node *cn, - int siblings); - -struct dm_pool *config_tree_memory(struct config_tree *cft); - #endif diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index 0da0c3421..3c4433333 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -644,8 +644,8 @@ void dev_cache_scan(int do_scan) static int _init_preferred_names(struct cmd_context *cmd) { - const struct config_node *cn; - const struct config_value *v; + const struct dm_config_node *cn; + const struct dm_config_value *v; struct dm_pool *scratch = NULL; const char **regex; unsigned count = 0; @@ -654,14 +654,14 @@ static int _init_preferred_names(struct cmd_context *cmd) _cache.preferred_names_matcher = NULL; if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) || - cn->v->type == CFG_EMPTY_ARRAY) { + cn->v->type == DM_CFG_EMPTY_ARRAY) { log_very_verbose("devices/preferred_names not found in config file: " "using built-in preferences"); return 1; } for (v = cn->v; v; v = v->next) { - if (v->type != CFG_STRING) { + if (v->type != DM_CFG_STRING) { log_error("preferred_names patterns must be enclosed in quotes"); return 0; } diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c index 8570bac92..52f3758c9 100644 --- a/lib/filters/filter-persistent.c +++ b/lib/filters/filter-persistent.c @@ -64,13 +64,13 @@ int persistent_filter_wipe(struct dev_filter *f) return 1; } -static int _read_array(struct pfilter *pf, struct config_tree *cft, +static int _read_array(struct pfilter *pf, struct dm_config_tree *cft, const char *path, void *data) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; - if (!(cn = find_config_node(cft->root, path))) { + if (!(cn = dm_config_find_node(cft->root, path))) { log_very_verbose("Couldn't find %s array in '%s'", path, pf->file); return 0; @@ -81,7 +81,7 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft, * devices as we go. */ for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_verbose("Devices array contains a value " "which is not a string ... ignoring"); continue; @@ -96,10 +96,10 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft, return 1; } -int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out) +int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out) { struct pfilter *pf = (struct pfilter *) f->private; - struct config_tree *cft; + struct dm_config_tree *cft; struct stat info; int r = 0; @@ -122,7 +122,7 @@ int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out) return_0; } - if (!(cft = create_config_tree(pf->file, 1))) + if (!(cft = dm_config_create(pf->file, 1))) return_0; if (!read_config_file(cft)) @@ -173,7 +173,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path, first = 0; } - escape_double_quotes(buf, dm_hash_get_key(pf->devices, n)); + dm_escape_double_quotes(buf, dm_hash_get_key(pf->devices, n)); fprintf(fp, "\t\t\"%s\"", buf); } @@ -186,7 +186,7 @@ int persistent_filter_dump(struct dev_filter *f, int merge_existing) struct pfilter *pf; char *tmp_file; struct stat info, info2; - struct config_tree *cft = NULL; + struct dm_config_tree *cft = NULL; FILE *fp; int lockfd; int r = 0; diff --git a/lib/filters/filter-persistent.h b/lib/filters/filter-persistent.h index a7f1245e0..ad56a62bb 100644 --- a/lib/filters/filter-persistent.h +++ b/lib/filters/filter-persistent.h @@ -22,7 +22,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *f, const char *file); int persistent_filter_wipe(struct dev_filter *f); -int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out); +int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out); int persistent_filter_dump(struct dev_filter *f, int merge_existing); #endif diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c index fc83469d5..1b460312d 100644 --- a/lib/filters/filter-regex.c +++ b/lib/filters/filter-regex.c @@ -87,10 +87,10 @@ static int _extract_pattern(struct dm_pool *mem, const char *pat, return 1; } -static int _build_matcher(struct rfilter *rf, const struct config_value *val) +static int _build_matcher(struct rfilter *rf, const struct dm_config_value *val) { struct dm_pool *scratch; - const struct config_value *v; + const struct dm_config_value *v; char **regex; unsigned count = 0; int i, r = 0; @@ -102,7 +102,7 @@ static int _build_matcher(struct rfilter *rf, const struct config_value *val) * count how many patterns we have. */ for (v = val; v; v = v->next) { - if (v->type != CFG_STRING) { + if (v->type != DM_CFG_STRING) { log_error("Filter patterns must be enclosed in quotes."); goto out; } @@ -188,7 +188,7 @@ static void _regex_destroy(struct dev_filter *f) dm_pool_destroy(rf->mem); } -struct dev_filter *regex_filter_create(const struct config_value *patterns) +struct dev_filter *regex_filter_create(const struct dm_config_value *patterns) { struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024); struct rfilter *rf; diff --git a/lib/filters/filter-regex.h b/lib/filters/filter-regex.h index a009c911b..bb71f56f5 100644 --- a/lib/filters/filter-regex.h +++ b/lib/filters/filter-regex.h @@ -27,6 +27,6 @@ * r|.*| - reject everything else */ -struct dev_filter *regex_filter_create(const struct config_value *patterns); +struct dev_filter *regex_filter_create(const struct dm_config_value *patterns); #endif diff --git a/lib/filters/filter.c b/lib/filters/filter.c index a9b99a538..f2398a1f2 100644 --- a/lib/filters/filter.c +++ b/lib/filters/filter.c @@ -177,7 +177,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute__((un return ret; } -static int _scan_proc_dev(const char *proc, const struct config_node *cn) +static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) { char line[80]; char proc_devices[PATH_MAX]; @@ -186,7 +186,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn) int line_maj = 0; int blocksection = 0; size_t dev_len = 0; - const struct config_value *cv; + const struct dm_config_value *cv; const char *name; @@ -269,7 +269,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn) /* Check devices/types for local variations */ for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Expecting string in devices/types " "in config file"); if (fclose(pd)) @@ -279,7 +279,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn) dev_len = strlen(cv->v.str); name = cv->v.str; cv = cv->next; - if (!cv || cv->type != CFG_INT) { + if (!cv || cv->type != DM_CFG_INT) { log_error("Max partition count missing for %s " "in devices/types in config file", name); @@ -316,7 +316,7 @@ int max_partitions(int major) } struct dev_filter *lvm_type_filter_create(const char *proc, - const struct config_node *cn) + const struct dm_config_node *cn) { struct dev_filter *f; diff --git a/lib/filters/filter.h b/lib/filters/filter.h index 07611f9eb..5c6047a44 100644 --- a/lib/filters/filter.h +++ b/lib/filters/filter.h @@ -31,7 +31,7 @@ #endif struct dev_filter *lvm_type_filter_create(const char *proc, - const struct config_node *cn); + const struct dm_config_node *cn); void lvm_type_filter_destroy(struct dev_filter *f); diff --git a/lib/format_text/export.c b/lib/format_text/export.c index 35945cc8e..2bead7fd5 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -319,9 +319,9 @@ static int _out_line(const char *line, void *_f) { return out_text(f, "%s", line); } -int out_config_node(struct formatter *f, const struct config_node *cn) +int out_config_node(struct formatter *f, const struct dm_config_node *cn) { - return write_config_node(cn, _out_line, f); + return dm_config_write_node(cn, _out_line, f); } static int _print_header(struct formatter *f, @@ -337,12 +337,12 @@ static int _print_header(struct formatter *f, outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE); outnl(f); - if (!(buf = alloca(escaped_len(desc)))) { + if (!(buf = alloca(dm_escaped_len(desc)))) { log_error("temporary stack allocation for description" "string failed"); return 0; } - outf(f, "description = \"%s\"", escape_double_quotes(buf, desc)); + outf(f, "description = \"%s\"", dm_escape_double_quotes(buf, desc)); outnl(f); outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename, _utsname.sysname, _utsname.nodename, _utsname.release, @@ -465,14 +465,14 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg) outf(f, "id = \"%s\"", buffer); - if (!(buf = alloca(escaped_len(pv_dev_name(pv))))) { + if (!(buf = alloca(dm_escaped_len(pv_dev_name(pv))))) { log_error("temporary stack allocation for device name" "string failed"); return 0; } outhint(f, "device = \"%s\"", - escape_double_quotes(buf, pv_dev_name(pv))); + dm_escape_double_quotes(buf, pv_dev_name(pv))); outnl(f); if (!_print_flag_config(f, pv->status, PV_FLAGS)) diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c index 7a0e9bd50..8ee9536b2 100644 --- a/lib/format_text/flags.c +++ b/lib/format_text/flags.c @@ -140,7 +140,7 @@ int print_flags(uint64_t status, int type, char *buffer, size_t size) return 1; } -int read_flags(uint64_t *status, int type, const struct config_value *cv) +int read_flags(uint64_t *status, int type, const struct dm_config_value *cv) { int f; uint64_t s = UINT64_C(0); @@ -149,11 +149,11 @@ int read_flags(uint64_t *status, int type, const struct config_value *cv) if (!(flags = _get_flags(type))) return_0; - if (cv->type == CFG_EMPTY_ARRAY) + if (cv->type == DM_CFG_EMPTY_ARRAY) goto out; while (cv) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Status value is not a string."); return 0; } diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index 513ac96a1..5e1db36ed 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -223,7 +223,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt, * area->start to area->start+area->size is not used. * Only ~32KB seems to contain valid metadata records * (LVM2 format - format_text). As a result, I end up with - * "maybe_config_section" returning true when there's no valid + * "dm_config_maybe_section" returning true when there's no valid * metadata in a sector (sectors with all nulls). */ if (!(buf = dm_malloc(size + size2))) @@ -236,7 +236,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt, /* * FIXME: We could add more sophisticated metadata detection */ - if (maybe_config_section(buf, size + size2)) { + if (dm_config_maybe_section(buf, size + size2)) { /* FIXME: Validate region, pull out timestamp?, etc */ /* FIXME: Do something with this region */ log_verbose ("Found LVM2 metadata record at " @@ -2277,7 +2277,7 @@ static int _add_dir(const char *dir, struct dm_list *dir_list) } static int _get_config_disk_area(struct cmd_context *cmd, - const struct config_node *cn, struct dm_list *raw_list) + const struct dm_config_node *cn, struct dm_list *raw_list) { struct device_area dev_area; const char *id_str; @@ -2288,21 +2288,21 @@ static int _get_config_disk_area(struct cmd_context *cmd, return 0; } - if (!get_config_uint64(cn, "start_sector", &dev_area.start)) { + if (!dm_config_get_uint64(cn, "start_sector", &dev_area.start)) { log_error("Missing start_sector in metadata disk_area section " "of config file"); return 0; } dev_area.start <<= SECTOR_SHIFT; - if (!get_config_uint64(cn, "size", &dev_area.size)) { + if (!dm_config_get_uint64(cn, "size", &dev_area.size)) { log_error("Missing size in metadata disk_area section " "of config file"); return 0; } dev_area.size <<= SECTOR_SHIFT; - if (!get_config_str(cn, "id", &id_str)) { + if (!dm_config_get_str(cn, "id", &id_str)) { log_error("Missing uuid in metadata disk_area section " "of config file"); return 0; @@ -2332,8 +2332,8 @@ static int _get_config_disk_area(struct cmd_context *cmd, struct format_type *create_text_format(struct cmd_context *cmd) { struct format_type *fmt; - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; struct mda_lists *mda_lists; if (!(fmt = dm_malloc(sizeof(*fmt)))) @@ -2374,7 +2374,7 @@ struct format_type *create_text_format(struct cmd_context *cmd) if ((cn = find_config_tree_node(cmd, "metadata/dirs"))) { for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "metadata/dirs"); goto err; diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h index 3b56f086d..4ecbf9b65 100644 --- a/lib/format_text/import-export.h +++ b/lib/format_text/import-export.h @@ -44,14 +44,14 @@ enum { }; struct text_vg_version_ops { - int (*check_version) (const struct config_tree * cf); + int (*check_version) (const struct dm_config_tree * cf); struct volume_group *(*read_vg) (struct format_instance * fid, - const struct config_tree *cf, + const struct dm_config_tree *cf, unsigned use_cached_pvs); - void (*read_desc) (struct dm_pool * mem, const struct config_tree *cf, + void (*read_desc) (struct dm_pool * mem, const struct dm_config_tree *cf, time_t *when, char **desc); const char *(*read_vgname) (const struct format_type *fmt, - const struct config_tree *cft, + const struct dm_config_tree *cft, struct id *vgid, uint64_t *vgstatus, char **creation_host); }; @@ -59,10 +59,10 @@ struct text_vg_version_ops { struct text_vg_version_ops *text_vg_vsn1_init(void); int print_flags(uint64_t status, int type, char *buffer, size_t size); -int read_flags(uint64_t *status, int type, const struct config_value *cv); +int read_flags(uint64_t *status, int type, const struct dm_config_value *cv); char *alloc_printed_tags(struct dm_list *tags); -int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct config_value *cv); +int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct dm_config_value *cv); int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp); int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf); diff --git a/lib/format_text/import.c b/lib/format_text/import.c index 2297164f8..4b347cc84 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -43,13 +43,13 @@ const char *text_vgname_import(const struct format_type *fmt, struct id *vgid, uint64_t *vgstatus, char **creation_host) { - struct config_tree *cft; + struct dm_config_tree *cft; struct text_vg_version_ops **vsn; const char *vgname = NULL; _init_text_import(); - if (!(cft = create_config_tree(NULL, 0))) + if (!(cft = dm_config_create(NULL, 0))) return_NULL; if ((!dev && !read_config_file(cft)) || @@ -86,7 +86,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, time_t *when, char **desc) { struct volume_group *vg = NULL; - struct config_tree *cft; + struct dm_config_tree *cft; struct text_vg_version_ops **vsn; _init_text_import(); @@ -94,7 +94,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, *desc = NULL; *when = 0; - if (!(cft = create_config_tree(file, 0))) + if (!(cft = dm_config_create(file, 0))) return_NULL; if ((!dev && !read_config_file(cft)) || @@ -131,7 +131,7 @@ struct volume_group *text_vg_import_file(struct format_instance *fid, when, desc); } -struct volume_group *import_vg_from_config_tree(const struct config_tree *cft, +struct volume_group *import_vg_from_config_tree(const struct dm_config_tree *cft, struct format_instance *fid) { struct volume_group *vg = NULL; diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 3232cc05c..ecd4b8b3a 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -26,21 +26,21 @@ #include "defaults.h" typedef int (*section_fn) (struct format_instance * fid, struct dm_pool * mem, - struct volume_group * vg, const struct config_node * pvn, - const struct config_node * vgn, + struct volume_group * vg, const struct dm_config_node * pvn, + const struct dm_config_node * vgn, struct dm_hash_table * pv_hash, struct dm_hash_table * lv_hash, unsigned *scan_done_once, unsigned report_missing_devices); #define _read_int32(root, path, result) \ - get_config_uint32(root, path, (uint32_t *) result) + dm_config_get_uint32(root, path, (uint32_t *) result) #define _read_uint32(root, path, result) \ - get_config_uint32(root, path, result) + dm_config_get_uint32(root, path, result) #define _read_int64(root, path, result) \ - get_config_uint64(root, path, result) + dm_config_get_uint64(root, path, result) /* * Logs an attempt to read an invalid format file. @@ -54,21 +54,21 @@ static void _invalid_format(const char *str) * Checks that the config file contains vg metadata, and that it * we recognise the version number, */ -static int _vsn1_check_version(const struct config_tree *cft) +static int _vsn1_check_version(const struct dm_config_tree *cft) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; /* * Check the contents field. */ - if (!(cn = find_config_node(cft->root, CONTENTS_FIELD))) { + if (!(cn = dm_config_find_node(cft->root, CONTENTS_FIELD))) { _invalid_format("missing contents field"); return 0; } cv = cn->v; - if (!cv || cv->type != CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) { + if (!cv || cv->type != DM_CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) { _invalid_format("unrecognised contents field"); return 0; } @@ -76,13 +76,13 @@ static int _vsn1_check_version(const struct config_tree *cft) /* * Check the version number. */ - if (!(cn = find_config_node(cft->root, FORMAT_VERSION_FIELD))) { + if (!(cn = dm_config_find_node(cft->root, FORMAT_VERSION_FIELD))) { _invalid_format("missing version number"); return 0; } cv = cn->v; - if (!cv || cv->type != CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) { + if (!cv || cv->type != DM_CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) { _invalid_format("unrecognised version number"); return 0; } @@ -106,11 +106,11 @@ static int _is_converting(struct logical_volume *lv) return 0; } -static int _read_id(struct id *id, const struct config_node *cn, const char *path) +static int _read_id(struct id *id, const struct dm_config_node *cn, const char *path) { - const struct config_value *cv; + const struct dm_config_value *cv; - if (!(cn = find_config_node(cn, path))) { + if (!(cn = dm_config_find_node(cn, path))) { log_error("Couldn't find uuid."); return 0; } @@ -129,12 +129,12 @@ static int _read_id(struct id *id, const struct config_node *cn, const char *pat return 1; } -static int _read_flag_config(const struct config_node *n, uint64_t *status, int type) +static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, int type) { - const struct config_node *cn; + const struct dm_config_node *cn; *status = 0; - if (!(cn = find_config_node(n, "status"))) { + if (!(cn = dm_config_find_node(n, "status"))) { log_error("Could not find status flags."); return 0; } @@ -144,7 +144,7 @@ static int _read_flag_config(const struct config_node *n, uint64_t *status, int return 0; } - if ((cn = find_config_node(n, "flags"))) { + if ((cn = dm_config_find_node(n, "flags"))) { if (!(read_flags(status, type, cn->v))) { log_error("Could not read flags."); return 0; @@ -155,8 +155,8 @@ static int _read_flag_config(const struct config_node *n, uint64_t *status, int } static int _read_pv(struct format_instance *fid, struct dm_pool *mem, - struct volume_group *vg, const struct config_node *pvn, - const struct config_node *vgn __attribute__((unused)), + struct volume_group *vg, const struct dm_config_node *pvn, + const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash, struct dm_hash_table *lv_hash __attribute__((unused)), unsigned *scan_done_once, @@ -164,7 +164,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem, { struct physical_volume *pv; struct pv_list *pvl; - const struct config_node *cn; + const struct dm_config_node *cn; uint64_t size; if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) || @@ -238,7 +238,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem, dm_list_init(&pv->segments); /* Optional tags */ - if ((cn = find_config_node(pvn, "tags")) && + if ((cn = dm_config_find_node(pvn, "tags")) && !(read_tags(mem, &pv->tags, cn->v))) { log_error("Couldn't read tags for physical volume %s in %s.", pv_dev_name(pv), vg->name); @@ -292,13 +292,13 @@ static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg) } static int _read_segment(struct dm_pool *mem, struct volume_group *vg, - struct logical_volume *lv, const struct config_node *sn, + struct logical_volume *lv, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { uint32_t area_count = 0u; struct lv_segment *seg; - const struct config_node *cn, *sn_child = sn->child; - const struct config_value *cv; + const struct dm_config_node *cn, *sn_child = sn->child; + const struct dm_config_value *cv; uint32_t start_extent, extent_count; struct segment_type *segtype; const char *segtype_str; @@ -322,7 +322,7 @@ static int _read_segment(struct dm_pool *mem, struct volume_group *vg, segtype_str = "striped"; - if ((cn = find_config_node(sn_child, "type"))) { + if ((cn = dm_config_find_node(sn_child, "type"))) { cv = cn->v; if (!cv || !cv->v.str) { log_error("Segment type must be a string."); @@ -350,7 +350,7 @@ static int _read_segment(struct dm_pool *mem, struct volume_group *vg, return_0; /* Optional tags */ - if ((cn = find_config_node(sn_child, "tags")) && + if ((cn = dm_config_find_node(sn_child, "tags")) && !(read_tags(mem, &seg->tags, cn->v))) { log_error("Couldn't read tags for a segment of %s/%s.", vg->name, lv->name); @@ -377,15 +377,15 @@ static int _read_segment(struct dm_pool *mem, struct volume_group *vg, return 1; } -int text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn, struct dm_hash_table *pv_hash, +int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, + const struct dm_config_node *cn, struct dm_hash_table *pv_hash, uint64_t status) { unsigned int s; - const struct config_value *cv; + const struct dm_config_value *cv; struct logical_volume *lv1; struct physical_volume *pv; - const char *seg_name = config_parent_name(sn); + const char *seg_name = dm_config_parent_name(sn); if (!seg->area_count) { log_error("Zero areas not allowed for segment %s", seg_name); @@ -395,7 +395,7 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn, for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { /* first we read the pv */ - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Bad volume name in areas array for segment %s.", seg_name); return 0; } @@ -405,7 +405,7 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn, return 0; } - if (cv->next->type != CFG_INT) { + if (cv->next->type != DM_CFG_INT) { log_error("Bad offset in areas array for segment %s.", seg_name); return 0; } @@ -442,10 +442,10 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn, } static int _read_segments(struct dm_pool *mem, struct volume_group *vg, - struct logical_volume *lv, const struct config_node *lvn, + struct logical_volume *lv, const struct dm_config_node *lvn, struct dm_hash_table *pv_hash) { - const struct config_node *sn; + const struct dm_config_node *sn; int count = 0, seg_count; for (sn = lvn; sn; sn = sn->sib) { @@ -495,15 +495,15 @@ static int _read_segments(struct dm_pool *mem, struct volume_group *vg, static int _read_lvnames(struct format_instance *fid __attribute__((unused)), struct dm_pool *mem, - struct volume_group *vg, const struct config_node *lvn, - const struct config_node *vgn __attribute__((unused)), + struct volume_group *vg, const struct dm_config_node *lvn, + const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash __attribute__((unused)), struct dm_hash_table *lv_hash, unsigned *scan_done_once __attribute__((unused)), unsigned report_missing_devices __attribute__((unused))) { struct logical_volume *lv; - const struct config_node *cn; + const struct dm_config_node *cn; if (!(lv = alloc_lv(mem))) return_0; @@ -523,8 +523,8 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)), } lv->alloc = ALLOC_INHERIT; - if ((cn = find_config_node(lvn, "allocation_policy"))) { - const struct config_value *cv = cn->v; + if ((cn = dm_config_find_node(lvn, "allocation_policy"))) { + const struct dm_config_value *cv = cn->v; if (!cv || !cv->v.str) { log_error("allocation_policy must be a string."); return 0; @@ -554,7 +554,7 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)), } /* Optional tags */ - if ((cn = find_config_node(lvn, "tags")) && + if ((cn = dm_config_find_node(lvn, "tags")) && !(read_tags(mem, &lv->tags, cn->v))) { log_error("Couldn't read tags for logical volume %s/%s.", vg->name, lv->name); @@ -569,8 +569,8 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)), static int _read_lvsegs(struct format_instance *fid __attribute__((unused)), struct dm_pool *mem, - struct volume_group *vg, const struct config_node *lvn, - const struct config_node *vgn __attribute__((unused)), + struct volume_group *vg, const struct dm_config_node *lvn, + const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash, struct dm_hash_table *lv_hash, unsigned *scan_done_once __attribute__((unused)), @@ -623,17 +623,17 @@ static int _read_lvsegs(struct format_instance *fid __attribute__((unused)), static int _read_sections(struct format_instance *fid, const char *section, section_fn fn, struct dm_pool *mem, - struct volume_group *vg, const struct config_node *vgn, + struct volume_group *vg, const struct dm_config_node *vgn, struct dm_hash_table *pv_hash, struct dm_hash_table *lv_hash, int optional, unsigned *scan_done_once) { - const struct config_node *n; + const struct dm_config_node *n; /* Only report missing devices when doing a scan */ unsigned report_missing_devices = scan_done_once ? !*scan_done_once : 1; - if (!(n = find_config_node(vgn, section))) { + if (!(n = dm_config_find_node(vgn, section))) { if (!optional) { log_error("Couldn't find section '%s'.", section); return 0; @@ -652,10 +652,10 @@ static int _read_sections(struct format_instance *fid, } static struct volume_group *_read_vg(struct format_instance *fid, - const struct config_tree *cft, + const struct dm_config_tree *cft, unsigned use_cached_pvs) { - const struct config_node *vgn, *cn; + const struct dm_config_node *vgn, *cn; struct volume_group *vg; struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL; unsigned scan_done_once = use_cached_pvs; @@ -677,7 +677,7 @@ static struct volume_group *_read_vg(struct format_instance *fid, vgn = vgn->child; - if ((cn = find_config_node(vgn, "system_id")) && cn->v) { + if ((cn = dm_config_find_node(vgn, "system_id")) && cn->v) { if (!cn->v->v.str) { log_error("system_id must be a string"); goto bad; @@ -725,8 +725,8 @@ static struct volume_group *_read_vg(struct format_instance *fid, goto bad; } - if ((cn = find_config_node(vgn, "allocation_policy"))) { - const struct config_value *cv = cn->v; + if ((cn = dm_config_find_node(vgn, "allocation_policy"))) { + const struct dm_config_value *cv = cn->v; if (!cv || !cv->v.str) { log_error("allocation_policy must be a string."); goto bad; @@ -760,7 +760,7 @@ static struct volume_group *_read_vg(struct format_instance *fid, } /* Optional tags */ - if ((cn = find_config_node(vgn, "tags")) && + if ((cn = dm_config_find_node(vgn, "tags")) && !(read_tags(vg->vgmem, &vg->tags, cn->v))) { log_error("Couldn't read tags for volume group %s.", vg->name); goto bad; @@ -819,33 +819,33 @@ static struct volume_group *_read_vg(struct format_instance *fid, } static void _read_desc(struct dm_pool *mem, - const struct config_tree *cft, time_t *when, char **desc) + const struct dm_config_tree *cft, time_t *when, char **desc) { const char *d; unsigned int u = 0u; int old_suppress; old_suppress = log_suppress(1); - d = find_config_str(cft->root, "description", ""); + d = dm_config_find_str(cft->root, "description", ""); log_suppress(old_suppress); *desc = dm_pool_strdup(mem, d); - (void) get_config_uint32(cft->root, "creation_time", &u); + (void) dm_config_get_uint32(cft->root, "creation_time", &u); *when = u; } static const char *_read_vgname(const struct format_type *fmt, - const struct config_tree *cft, struct id *vgid, + const struct dm_config_tree *cft, struct id *vgid, uint64_t *vgstatus, char **creation_host) { - const struct config_node *vgn; + const struct dm_config_node *vgn; struct dm_pool *mem = fmt->cmd->mem; char *vgname; int old_suppress; old_suppress = log_suppress(2); *creation_host = dm_pool_strdup(mem, - find_config_str(cft->root, + dm_config_find_str(cft->root, "creation_host", "")); log_suppress(old_suppress); diff --git a/lib/format_text/tags.c b/lib/format_text/tags.c index 76d42db62..b0f0732aa 100644 --- a/lib/format_text/tags.c +++ b/lib/format_text/tags.c @@ -61,13 +61,13 @@ bad: return_NULL; } -int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct config_value *cv) +int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct dm_config_value *cv) { - if (cv->type == CFG_EMPTY_ARRAY) + if (cv->type == DM_CFG_EMPTY_ARRAY) return 1; while (cv) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Found a tag that is not a string"); return 0; } diff --git a/lib/format_text/text_export.h b/lib/format_text/text_export.h index 39a691645..991203c25 100644 --- a/lib/format_text/text_export.h +++ b/lib/format_text/text_export.h @@ -24,7 +24,7 @@ struct formatter; struct lv_segment; -struct config_node; +struct dm_config_node; int out_size(struct formatter *f, uint64_t size, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); @@ -35,7 +35,7 @@ int out_hint(struct formatter *f, const char *fmt, ...) int out_text(struct formatter *f, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); -int out_config_node(struct formatter *f, const struct config_node *cn); +int out_config_node(struct formatter *f, const struct dm_config_node *cn); int out_areas(struct formatter *f, const struct lv_segment *seg, const char *type); diff --git a/lib/format_text/text_import.h b/lib/format_text/text_import.h index 99d222f1f..4f5cde26a 100644 --- a/lib/format_text/text_import.h +++ b/lib/format_text/text_import.h @@ -17,10 +17,10 @@ #define _LVM_TEXT_IMPORT_H struct lv_segment; -struct config_node; +struct dm_config_node; -int text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn, struct dm_hash_table *pv_hash, +int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, + const struct dm_config_node *cn, struct dm_hash_table *pv_hash, uint64_t status); #endif diff --git a/lib/locking/cluster_locking.c b/lib/locking/cluster_locking.c index 1e5b3a4ae..4401bc7b7 100644 --- a/lib/locking/cluster_locking.c +++ b/lib/locking/cluster_locking.c @@ -36,7 +36,7 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags); int query_resource(const char *resource, int *mode); void locking_end(void); -int locking_init(int type, struct config_tree *cf, uint32_t *flags); +int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags); #endif typedef struct lvm_response { @@ -606,7 +606,7 @@ int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd, return 1; } #else -int locking_init(int type, struct config_tree *cf, uint32_t *flags) +int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags) { _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) diff --git a/lib/locking/external_locking.c b/lib/locking/external_locking.c index c9c4848e1..4dacbe4d3 100644 --- a/lib/locking/external_locking.c +++ b/lib/locking/external_locking.c @@ -26,7 +26,7 @@ static void (*_reset_fn) (void) = NULL; static void (*_end_fn) (void) = NULL; static int (*_lock_fn) (struct cmd_context * cmd, const char *resource, uint32_t flags) = NULL; -static int (*_init_fn) (int type, struct config_tree * cft, +static int (*_init_fn) (int type, struct dm_config_tree * cft, uint32_t *flags) = NULL; static int (*_lock_query_fn) (const char *resource, int *mode) = NULL; diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 51f038db6..30256cbfe 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -628,7 +628,7 @@ struct alloc_handle { */ unsigned alloc_and_split_meta; - const struct config_node *cling_tag_list_cn; + const struct dm_config_node *cling_tag_list_cn; struct dm_list *parallel_areas; /* PVs to avoid */ @@ -1161,7 +1161,7 @@ struct pv_match { struct pv_area_used *areas; struct pv_area *pva; uint32_t areas_size; - const struct config_node *cling_tag_list_cn; + const struct dm_config_node *cling_tag_list_cn; int s; /* Area index of match */ }; @@ -1182,12 +1182,12 @@ static int _is_same_pv(struct pv_match *pvmatch __attribute((unused)), struct pv */ static int _has_matching_pv_tag(struct pv_match *pvmatch, struct pv_segment *pvseg, struct pv_area *pva) { - const struct config_value *cv; + const struct dm_config_value *cv; const char *str; const char *tag_matched; for (cv = pvmatch->cling_tag_list_cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Ignoring invalid string in config file entry " "allocation/cling_tag_list"); continue; @@ -1292,7 +1292,7 @@ static int _is_condition(struct cmd_context *cmd __attribute__((unused)), * Is pva on same PV as any existing areas? */ static int _check_cling(struct alloc_handle *ah, - const struct config_node *cling_tag_list_cn, + const struct dm_config_node *cling_tag_list_cn, struct lv_segment *prev_lvseg, struct pv_area *pva, struct alloc_state *alloc_state) { diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index ebab99f23..0e4fea699 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -687,7 +687,7 @@ int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names log_error("Failed to duplicate pv name %s.", pv_names[i]); return 0; } - unescape_colons_and_at_signs(pv_name, NULL, NULL); + dm_unescape_colons_and_at_signs(pv_name, NULL, NULL); if (!vg_extend_single_pv(vg, pv_name, pp)) { log_error("Unable to add physical volume '%s' to " "volume group '%s'.", pv_name, vg->name); diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 9b85cfba8..97bb22452 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -98,7 +98,7 @@ //#define FMT_RESIZE_PV 0x00000080U /* Supports pvresize? */ //#define FMT_UNLIMITED_STRIPESIZE 0x00000100U /* Unlimited stripe size? */ -struct config_tree; +struct dm_config_tree; struct metadata_area; /* Per-format per-metadata area operations */ @@ -455,9 +455,10 @@ void lv_calculate_readahead(const struct logical_volume *lv, uint32_t *read_ahea * For internal metadata caching. */ int export_vg_to_buffer(struct volume_group *vg, char **buf); +int export_vg_to_config_tree(struct volume_group *vg, struct dm_config_tree **cft); struct volume_group *import_vg_from_buffer(const char *buf, struct format_instance *fid); -struct volume_group *import_vg_from_config_tree(const struct config_tree *cft, +struct volume_group *import_vg_from_config_tree(const struct dm_config_tree *cft, struct format_instance *fid); /* diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c index aa31d463d..768e91733 100644 --- a/lib/metadata/mirror.c +++ b/lib/metadata/mirror.c @@ -1179,13 +1179,13 @@ static int get_mirror_fault_policy(struct cmd_context *cmd __attribute__((unused const char *policy; if (log_policy) - policy = find_config_str(NULL, "activation/mirror_log_fault_policy", + policy = dm_config_find_str(NULL, "activation/mirror_log_fault_policy", DEFAULT_MIRROR_LOG_FAULT_POLICY); else { - policy = find_config_str(NULL, "activation/mirror_image_fault_policy", + policy = dm_config_find_str(NULL, "activation/mirror_image_fault_policy", NULL); if (!policy) - policy = find_config_str(NULL, "activation/mirror_device_fault_policy", + policy = dm_config_find_str(NULL, "activation/mirror_device_fault_policy", DEFAULT_MIRROR_IMAGE_FAULT_POLICY); } diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h index 1b43c6b38..664619436 100644 --- a/lib/metadata/segtype.h +++ b/lib/metadata/segtype.h @@ -20,11 +20,11 @@ struct segtype_handler; struct cmd_context; -struct config_tree; +struct dm_config_tree; struct lv_segment; struct lv_activate_opts; struct formatter; -struct config_node; +struct dm_config_node; struct dev_manager; /* Feature flags */ @@ -87,10 +87,10 @@ struct segtype_handler { void (*display) (const struct lv_segment * seg); int (*text_export) (const struct lv_segment * seg, struct formatter * f); - int (*text_import_area_count) (const struct config_node * sn, + int (*text_import_area_count) (const struct dm_config_node * sn, uint32_t *area_count); int (*text_import) (struct lv_segment * seg, - const struct config_node * sn, + const struct dm_config_node * sn, struct dm_hash_table * pv_hash); int (*merge_segments) (struct lv_segment * seg1, struct lv_segment * seg2); diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c index 49b39e74c..96fa92776 100644 --- a/lib/mirror/mirrored.c +++ b/lib/mirror/mirrored.c @@ -69,46 +69,46 @@ static void _mirrored_display(const struct lv_segment *seg) log_print(" "); } -static int _mirrored_text_import_area_count(const struct config_node *sn, uint32_t *area_count) +static int _mirrored_text_import_area_count(const struct dm_config_node *sn, uint32_t *area_count) { - if (!get_config_uint32(sn, "mirror_count", area_count)) { + if (!dm_config_get_uint32(sn, "mirror_count", area_count)) { log_error("Couldn't read 'mirror_count' for " - "segment '%s'.", config_parent_name(sn)); + "segment '%s'.", dm_config_parent_name(sn)); return 0; } return 1; } -static int _mirrored_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct config_node *cn; + const struct dm_config_node *cn; const char *logname = NULL; - if (find_config_node(sn, "extents_moved")) { - if (get_config_uint32(sn, "extents_moved", + if (dm_config_find_node(sn, "extents_moved")) { + if (dm_config_get_uint32(sn, "extents_moved", &seg->extents_copied)) seg->status |= PVMOVE; else { log_error("Couldn't read 'extents_moved' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if (find_config_node(sn, "region_size")) { - if (!get_config_uint32(sn, "region_size", + if (dm_config_find_node(sn, "region_size")) { + if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if ((cn = find_config_node(sn, "mirror_log"))) { + if ((cn = dm_config_find_node(sn, "mirror_log"))) { if (!cn->v || !cn->v->v.str) { log_error("Mirror log type must be a string."); return 0; @@ -117,7 +117,7 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct config_nod if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) { log_error("Unrecognised mirror log in " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } seg->log_lv->status |= MIRROR_LOG; @@ -126,14 +126,14 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct config_nod if (logname && !seg->region_size) { log_error("Missing region size for mirror log for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } - if (!(cn = find_config_node(sn, "mirrors"))) { + if (!(cn = dm_config_find_node(sn, "mirrors"))) { log_error("Couldn't find mirrors array for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c index d195e76e6..5e2dd38c4 100644 --- a/lib/misc/lvm-string.c +++ b/lib/misc/lvm-string.c @@ -43,248 +43,6 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...) return 1; } -/* - * Count occurences of 'c' in 'str' until we reach a null char. - * - * Returns: - * len - incremented for each char we encounter. - * count - number of occurrences of 'c' and 'c2'. - */ -static void _count_chars(const char *str, size_t *len, int *count, - const int c1, const int c2) -{ - const char *ptr; - - for (ptr = str; *ptr; ptr++, (*len)++) - if (*ptr == c1 || *ptr == c2) - (*count)++; -} - -/* - * Count occurences of 'c' in 'str' of length 'size'. - * - * Returns: - * Number of occurrences of 'c' - */ -unsigned count_chars(const char *str, size_t len, const int c) -{ - size_t i; - unsigned count = 0; - - for (i = 0; i < len; i++) - if (str[i] == c) - count++; - - return count; -} - -/* - * Length of string after escaping double quotes and backslashes. - */ -size_t escaped_len(const char *str) -{ - size_t len = 1; - int count = 0; - - _count_chars(str, &len, &count, '\"', '\\'); - - return count + len; -} - -/* - * Copies a string, quoting orig_char with quote_char. - * Optionally also quote quote_char. - */ -static void _quote_characters(char **out, const char *src, - const int orig_char, const int quote_char, - int quote_quote_char) -{ - while (*src) { - if (*src == orig_char || - (*src == quote_char && quote_quote_char)) - *(*out)++ = quote_char; - - *(*out)++ = *src++; - } -} - -static void _unquote_one_character(char *src, const char orig_char, - const char quote_char) -{ - char *out; - char s, n; - - /* Optimise for the common case where no changes are needed. */ - while ((s = *src++)) { - if (s == quote_char && - ((n = *src) == orig_char || n == quote_char)) { - out = src++; - *(out - 1) = n; - - while ((s = *src++)) { - if (s == quote_char && - ((n = *src) == orig_char || n == quote_char)) { - s = n; - src++; - } - *out = s; - out++; - } - - *out = '\0'; - return; - } - } -} - -/* - * Unquote each character given in orig_char array and unquote quote_char - * as well. Also save the first occurrence of each character from orig_char - * that was found unquoted in arr_substr_first_unquoted array. This way we can - * process several characters in one go. - */ -static void _unquote_characters(char *src, const char *orig_chars, - size_t num_orig_chars, - const char quote_char, - char *arr_substr_first_unquoted[]) -{ - char *out = src; - char c, s, n; - unsigned i; - - while ((s = *src++)) { - for (i = 0; i < num_orig_chars; i++) { - c = orig_chars[i]; - if (s == quote_char && - ((n = *src) == c || n == quote_char)) { - s = n; - src++; - break; - } - if (arr_substr_first_unquoted && (s == c) && - !arr_substr_first_unquoted[i]) - arr_substr_first_unquoted[i] = out; - }; - *out++ = s; - } - - *out = '\0'; -} - -/* - * Copies a string, quoting hyphens with hyphens. - */ -static void _quote_hyphens(char **out, const char *src) -{ - _quote_characters(out, src, '-', '-', 0); -} - -/* - * -- or if !layer just -. - */ -char *build_dm_name(struct dm_pool *mem, const char *vgname, - const char *lvname, const char *layer) -{ - size_t len = 1; - int hyphens = 1; - char *r, *out; - - _count_chars(vgname, &len, &hyphens, '-', 0); - _count_chars(lvname, &len, &hyphens, '-', 0); - - if (layer && *layer) { - _count_chars(layer, &len, &hyphens, '-', 0); - hyphens++; - } - - len += hyphens; - - if (!(r = dm_pool_alloc(mem, len))) { - log_error("build_dm_name: Allocation failed for %" PRIsize_t - " for %s %s %s.", len, vgname, lvname, layer); - return NULL; - } - - out = r; - _quote_hyphens(&out, vgname); - *out++ = '-'; - _quote_hyphens(&out, lvname); - - if (layer && *layer) { - /* No hyphen if the layer begins with _ e.g. _mlog */ - if (*layer != '_') - *out++ = '-'; - _quote_hyphens(&out, layer); - } - *out = '\0'; - - return r; -} - -char *build_dm_uuid(struct dm_pool *mem, const char *lvid, const char *layer) -{ - char *dmuuid; - size_t len; - - if (!layer) - layer = ""; - - len = sizeof(UUID_PREFIX) + strlen(lvid) + strlen(layer) + 1; - - if (!(dmuuid = dm_pool_alloc(mem, len))) { - log_error("build_dm_name: Allocation failed for %" PRIsize_t - " %s %s.", len, lvid, layer); - return NULL; - } - - sprintf(dmuuid, UUID_PREFIX "%s%s%s", lvid, (*layer) ? "-" : "", layer); - - return dmuuid; -} - -/* - * Copies a string, quoting double quotes with backslashes. - */ -char *escape_double_quotes(char *out, const char *src) -{ - char *buf = out; - - _quote_characters(&buf, src, '\"', '\\', 1); - *buf = '\0'; - - return out; -} - -/* - * Undo quoting in situ. - */ -void unescape_double_quotes(char *src) -{ - _unquote_one_character(src, '\"', '\\'); -} - -/* - * Unescape colons and "at" signs in situ and save the substrings - * starting at the position of the first unescaped colon and the - * first unescaped "at" sign. This is normally used to unescape - * device names used as PVs. - */ -void unescape_colons_and_at_signs(char *src, - char **substr_first_unquoted_colon, - char **substr_first_unquoted_at_sign) -{ - const char *orig_chars = ":@"; - char *arr_substr_first_unquoted[] = {NULL, NULL, NULL}; - - _unquote_characters(src, orig_chars, 2, '\\', arr_substr_first_unquoted); - - if (substr_first_unquoted_colon) - *substr_first_unquoted_colon = arr_substr_first_unquoted[0]; - - if (substr_first_unquoted_at_sign) - *substr_first_unquoted_at_sign = arr_substr_first_unquoted[1]; -} - /* * A-Za-z0-9._-+/=!:&# */ @@ -392,3 +150,9 @@ int is_reserved_lvname(const char *name) return rc; } + +char *build_dm_uuid(struct dm_pool *mem, const char *lvid, + const char *layer) +{ + return dm_build_dm_uuid(mem, UUID_PREFIX, lvid, layer); +} diff --git a/lib/misc/lvm-string.h b/lib/misc/lvm-string.h index 20f45c939..6be048d05 100644 --- a/lib/misc/lvm-string.h +++ b/lib/misc/lvm-string.h @@ -27,8 +27,6 @@ struct pool; int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); -char *build_dm_name(struct dm_pool *mem, const char *vg, - const char *lv, const char *layer); char *build_dm_uuid(struct dm_pool *mem, const char *lvid, const char *layer); @@ -38,36 +36,4 @@ int validate_tag(const char *n); int apply_lvname_restrictions(const char *name); int is_reserved_lvname(const char *name); -/* - * Returns number of occurrences of c in first len characters of str. - */ -unsigned count_chars(const char *str, size_t len, const int c); - -/* - * Returns what length of escaped string would be including terminating NUL. - */ -size_t escaped_len(const char *str); - -/* - * Copies a string from src to out. - * Double quotation marks and backslashes are quoted with a backslash. - * Caller must ensure *out has enough space - see escaped_len(). - * Returns *out. - */ -char *escape_double_quotes(char *out, const char *src); - -/* - * Removes quoting of double quotation marks and backslashes in situ. - */ -void unescape_double_quotes(char *src); - -/* - * Unescape colons and at signs in situ and save the substring starting - * at the position of the first unescaped colon and the first unescaped - * "at" sign. - */ -void unescape_colons_and_at_signs(char *src, - char **substr_first_unquoted_colon, - char **substr_first_unquoted_at_sign); - #endif diff --git a/lib/mm/memlock.c b/lib/mm/memlock.c index bdda2ca5a..8bf9f22d8 100644 --- a/lib/mm/memlock.c +++ b/lib/mm/memlock.c @@ -146,10 +146,10 @@ static void _release_memory(void) * mlock/munlock memory areas from /proc/self/maps * format described in kernel/Documentation/filesystem/proc.txt */ -static int _maps_line(const struct config_node *cn, lvmlock_t lock, +static int _maps_line(const struct dm_config_node *cn, lvmlock_t lock, const char* line, size_t* mstats) { - const struct config_value *cv; + const struct dm_config_value *cv; long from, to; int pos; unsigned i; @@ -188,7 +188,7 @@ static int _maps_line(const struct config_node *cn, lvmlock_t lock, } } else { for (cv = cn->v; cv; cv = cv->next) { - if ((cv->type != CFG_STRING) || !cv->v.str[0]) + if ((cv->type != DM_CFG_STRING) || !cv->v.str[0]) continue; if (strstr(line + pos, cv->v.str)) { log_debug("mlock_filter '%s' matches '%s': Skipping.", @@ -228,7 +228,7 @@ static int _maps_line(const struct config_node *cn, lvmlock_t lock, static int _memlock_maps(struct cmd_context *cmd, lvmlock_t lock, size_t *mstats) { - const struct config_node *cn; + const struct dm_config_node *cn; char *line, *line_end; size_t len; ssize_t n; diff --git a/lib/raid/raid.c b/lib/raid/raid.c index a03f45337..f4ba9803b 100644 --- a/lib/raid/raid.c +++ b/lib/raid/raid.c @@ -32,25 +32,25 @@ static const char *_raid_name(const struct lv_segment *seg) return seg->segtype->name; } -static int _raid_text_import_area_count(const struct config_node *sn, +static int _raid_text_import_area_count(const struct dm_config_node *sn, uint32_t *area_count) { - if (!get_config_uint32(sn, "device_count", area_count)) { + if (!dm_config_get_uint32(sn, "device_count", area_count)) { log_error("Couldn't read 'device_count' for " - "segment '%s'.", config_parent_name(sn)); + "segment '%s'.", dm_config_parent_name(sn)); return 0; } return 1; } static int _raid_text_import_areas(struct lv_segment *seg, - const struct config_node *sn, - const struct config_node *cn) + const struct dm_config_node *sn, + const struct dm_config_node *cn) { unsigned int s; - const struct config_value *cv; + const struct dm_config_value *cv; struct logical_volume *lv1; - const char *seg_name = config_parent_name(sn); + const char *seg_name = dm_config_parent_name(sn); if (!seg->area_count) { log_error("No areas found for segment %s", seg_name); @@ -58,7 +58,7 @@ static int _raid_text_import_areas(struct lv_segment *seg, } for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Bad volume name in areas array for segment %s.", seg_name); return 0; } @@ -101,31 +101,31 @@ static int _raid_text_import_areas(struct lv_segment *seg, } static int _raid_text_import(struct lv_segment *seg, - const struct config_node *sn, + const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct config_node *cn; + const struct dm_config_node *cn; - if (find_config_node(sn, "region_size")) { - if (!get_config_uint32(sn, "region_size", &seg->region_size)) { + if (dm_config_find_node(sn, "region_size")) { + if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if (find_config_node(sn, "stripe_size")) { - if (!get_config_uint32(sn, "stripe_size", &seg->stripe_size)) { + if (dm_config_find_node(sn, "stripe_size")) { + if (!dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) { log_error("Couldn't read 'stripe_size' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if (!(cn = find_config_node(sn, "raids"))) { + if (!(cn = dm_config_find_node(sn, "raids"))) { log_error("Couldn't find RAID array for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } diff --git a/lib/replicator/replicator.c b/lib/replicator/replicator.c index ef11c419c..f6428fdaf 100644 --- a/lib/replicator/replicator.c +++ b/lib/replicator/replicator.c @@ -36,7 +36,7 @@ */ #define SEG_LOG_ERROR(t, p...) \ log_error(t " segment %s of logical volume %s.", ## p, \ - config_parent_name(sn), seg->lv->name), 0; + dm_config_parent_name(sn), seg->lv->name), 0; /* @@ -58,24 +58,24 @@ static void _replicator_display(const struct lv_segment *seg) log_print(" Replicator volume\t%s", seg->rlog_lv->name); } -/* Wrapper for get_config_uint32() with default value */ -static uint32_t _get_config_uint32(const struct config_node *cn, +/* Wrapper for dm_config_get_uint32() with default value */ +static uint32_t _get_config_uint32(const struct dm_config_node *cn, const char *path, uint32_t def) { uint32_t t; - return get_config_uint32(cn, path, &t) ? t : def; + return dm_config_get_uint32(cn, path, &t) ? t : def; } -/* Wrapper for get_config_uint64() with default value */ -static uint64_t _get_config_uint64(const struct config_node *cn, +/* Wrapper for dm_config_get_uint64() with default value */ +static uint64_t _get_config_uint64(const struct dm_config_node *cn, const char *path, uint64_t def) { uint64_t t; - return get_config_uint64(cn, path, &t) ? t : def; + return dm_config_get_uint64(cn, path, &t) ? t : def; } @@ -86,13 +86,13 @@ static const char _state_txt[NUM_REPLICATOR_STATE][8] = { }; /* Parse state string */ -static replicator_state_t _get_state(const struct config_node *sn, +static replicator_state_t _get_state(const struct dm_config_node *sn, const char *path, replicator_state_t def) { const char *str; unsigned i; - if (get_config_str(sn, path, &str)) { + if (dm_config_get_str(sn, path, &str)) { for (i = 0; i < sizeof(_state_txt)/sizeof(_state_txt[0]); ++i) if (strcasecmp(str, _state_txt[i]) == 0) return (replicator_state_t) i; @@ -115,13 +115,13 @@ static const char _op_mode_txt[NUM_DM_REPLICATOR_MODES][8] = { /* Parse action string */ -static dm_replicator_mode_t _get_op_mode(const struct config_node *sn, +static dm_replicator_mode_t _get_op_mode(const struct dm_config_node *sn, const char *path, dm_replicator_mode_t def) { const char *str; unsigned i; - if (get_config_str(sn, path, &str)) { + if (dm_config_get_str(sn, path, &str)) { for (i = 0; i < sizeof(_op_mode_txt)/sizeof(_op_mode_txt[0]); ++i) if (strcasecmp(str, _op_mode_txt[i]) == 0) { log_very_verbose("Setting %s to %s", @@ -162,16 +162,16 @@ static struct replicator_site *_get_site(struct logical_volume *replicator, /* Parse replicator site element */ static int _add_site(struct lv_segment *seg, const char *key, - const struct config_node *sn) + const struct dm_config_node *sn) { struct dm_pool *mem = seg->lv->vg->vgmem; - const struct config_node *cn; + const struct dm_config_node *cn; struct replicator_site *rsite; if (!(rsite = _get_site(seg->lv, key))) return_0; - if (!find_config_node(sn, "site_index")) + if (!dm_config_find_node(sn, "site_index")) return SEG_LOG_ERROR("Mandatory site_index is missing for"); rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE); @@ -204,8 +204,8 @@ static int _add_site(struct lv_segment *seg, rsite->op_mode); } - if ((cn = find_config_node(sn, "volume_group"))) { - if (!cn->v || cn->v->type != CFG_STRING) + if ((cn = dm_config_find_node(sn, "volume_group"))) { + if (!cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("volume_group must be a string in"); if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str))) @@ -220,25 +220,25 @@ static int _add_site(struct lv_segment *seg, /* Import replicator segment */ static int _replicator_text_import(struct lv_segment *seg, - const struct config_node *sn, + const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; struct logical_volume *rlog_lv; if (!replicator_add_replicator_dev(seg->lv, NULL)) return_0; - if (!(cn = find_config_node(sn, "replicator_log")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "replicator_log")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Replicator log type must be a string in"); if (!(rlog_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown replicator log %s in", cn->v->v.str); - if (!(cn = find_config_node(sn, "replicator_log_type")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "replicator_log_type")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Replicator log's type must be a string in"); if (strcasecmp(cn->v->v.str, "ringbuffer")) return SEG_LOG_ERROR("Only ringbuffer replicator log type is supported in"); @@ -443,7 +443,7 @@ static void _replicator_dev_display(const struct lv_segment *seg) static int _add_device(struct lv_segment *seg, const char *site_name, - const struct config_node *sn, + const struct dm_config_node *sn, uint64_t devidx) { struct dm_pool *mem = seg->lv->vg->vgmem; @@ -453,19 +453,19 @@ static int _add_device(struct lv_segment *seg, struct replicator_device *rdev; const char *dev_str = NULL; const char *slog_str = NULL; - const struct config_node *cn; + const struct dm_config_node *cn; dm_list_iterate_items(rdev, &rsite->rdevices) if (rdev->replicator_dev == seg) return SEG_LOG_ERROR("Duplicate site found in"); - if ((cn = find_config_node(sn, "sync_log"))) { + if ((cn = dm_config_find_node(sn, "sync_log"))) { if (!cn->v || !cn->v->v.str) return SEG_LOG_ERROR("Sync log must be a string in"); slog_str = cn->v->v.str; } - if (!(cn = find_config_node(sn, "logical_volume")) || + if (!(cn = dm_config_find_node(sn, "logical_volume")) || !cn->v || !cn->v->v.str) return SEG_LOG_ERROR("Logical volume must be a string in"); @@ -520,14 +520,14 @@ static int _add_device(struct lv_segment *seg, /* Import replicator segment */ static int _replicator_dev_text_import(struct lv_segment *seg, - const struct config_node *sn, + const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; struct logical_volume *replicator; uint64_t devidx; - if (!(cn = find_config_node(sn, "replicator"))) + if (!(cn = dm_config_find_node(sn, "replicator"))) return SEG_LOG_ERROR("Replicator is missing for"); if (!cn->v || !cn->v->v.str) @@ -542,8 +542,8 @@ static int _replicator_dev_text_import(struct lv_segment *seg, log_very_verbose("replicator=%s", replicator->name); /* Mandatory */ - if (!find_config_node(sn, "device_index") || - !get_config_uint64(sn, "device_index", &devidx)) + if (!dm_config_find_node(sn, "device_index") || + !dm_config_get_uint64(sn, "device_index", &devidx)) return SEG_LOG_ERROR("Could not read 'device_index' for"); /* Read devices from sites */ diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c index 8c4830895..ddb9f7f50 100644 --- a/lib/snapshot/snapshot.c +++ b/lib/snapshot/snapshot.c @@ -37,7 +37,7 @@ static const char *_snap_target_name(const struct lv_segment *seg, return _snap_name(seg); } -static int _snap_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { uint32_t chunk_size; @@ -45,28 +45,28 @@ static int _snap_text_import(struct lv_segment *seg, const struct config_node *s struct logical_volume *org, *cow; int old_suppress, merge = 0; - if (!get_config_uint32(sn, "chunk_size", &chunk_size)) { + if (!dm_config_get_uint32(sn, "chunk_size", &chunk_size)) { log_error("Couldn't read chunk size for snapshot."); return 0; } old_suppress = log_suppress(1); - if ((cow_name = find_config_str(sn, "merging_store", NULL))) { - if (find_config_str(sn, "cow_store", NULL)) { + if ((cow_name = dm_config_find_str(sn, "merging_store", NULL))) { + if (dm_config_find_str(sn, "cow_store", NULL)) { log_suppress(old_suppress); log_error("Both snapshot cow and merging storage were specified."); return 0; } merge = 1; } - else if (!(cow_name = find_config_str(sn, "cow_store", NULL))) { + else if (!(cow_name = dm_config_find_str(sn, "cow_store", NULL))) { log_suppress(old_suppress); log_error("Snapshot cow storage not specified."); return 0; } - if (!(org_name = find_config_str(sn, "origin", NULL))) { + if (!(org_name = dm_config_find_str(sn, "origin", NULL))) { log_suppress(old_suppress); log_error("Snapshot origin not specified."); return 0; diff --git a/lib/striped/striped.c b/lib/striped/striped.c index 6fa49e329..fee2a9628 100644 --- a/lib/striped/striped.c +++ b/lib/striped/striped.c @@ -57,32 +57,32 @@ static void _striped_display(const struct lv_segment *seg) log_print(" "); } -static int _striped_text_import_area_count(const struct config_node *sn, uint32_t *area_count) +static int _striped_text_import_area_count(const struct dm_config_node *sn, uint32_t *area_count) { - if (!get_config_uint32(sn, "stripe_count", area_count)) { + if (!dm_config_get_uint32(sn, "stripe_count", area_count)) { log_error("Couldn't read 'stripe_count' for " - "segment '%s'.", config_parent_name(sn)); + "segment '%s'.", dm_config_parent_name(sn)); return 0; } return 1; } -static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct config_node *cn; + const struct dm_config_node *cn; if ((seg->area_count != 1) && - !get_config_uint32(sn, "stripe_size", &seg->stripe_size)) { + !dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) { log_error("Couldn't read stripe_size for segment %s " - "of logical volume %s.", config_parent_name(sn), seg->lv->name); + "of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; } - if (!(cn = find_config_node(sn, "stripes"))) { + if (!(cn = dm_config_find_node(sn, "stripes"))) { log_error("Couldn't find stripes array for segment %s " - "of logical volume %s.", config_parent_name(sn), seg->lv->name); + "of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; } diff --git a/lib/thin/thin.c b/lib/thin/thin.c index 0bc7c1321..153bab2c9 100644 --- a/lib/thin/thin.c +++ b/lib/thin/thin.c @@ -36,39 +36,39 @@ */ #define SEG_LOG_ERROR(t, p...) \ log_error(t " segment %s of logical volume %s.", ## p, \ - config_parent_name(sn), seg->lv->name), 0; + dm_config_parent_name(sn), seg->lv->name), 0; static const char *_thin_pool_name(const struct lv_segment *seg) { return seg->segtype->name; } -static int _thin_pool_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _thin_pool_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; - if (!(cn = find_config_node(sn, "data")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "data")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool data must be a string in"); if (!(seg->data_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown pool data %s in", cn->v->v.str); - if (!(cn = find_config_node(sn, "metadata")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "metadata")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool metadata must be a string in"); if (!(seg->metadata_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown pool metadata %s in", cn->v->v.str); - if (!get_config_uint64(sn, "transaction_id", &seg->transaction_id)) + if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id)) return SEG_LOG_ERROR("Could not read transaction_id for"); - if (find_config_node(sn, "zero_new_blocks") && - !get_config_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) + if (dm_config_find_node(sn, "zero_new_blocks") && + !dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) return SEG_LOG_ERROR("Could not read zero_new_blocks for"); return 1; @@ -90,21 +90,21 @@ static const char *_thin_name(const struct lv_segment *seg) return seg->segtype->name; } -static int _thin_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _thin_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; - if (!(cn = find_config_node(sn, "thin_pool")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "thin_pool")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool must be a string in"); if (!(seg->thin_pool_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown thin pool %s in", cn->v->v.str); - if ((cn = find_config_node(sn, "origin"))) { - if (!cn->v || cn->v->type != CFG_STRING) + if ((cn = dm_config_find_node(sn, "origin"))) { + if (!cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool origin must be a string in"); if (!(seg->origin = find_lv(seg->lv->vg, cn->v->v.str))) @@ -112,7 +112,7 @@ static int _thin_text_import(struct lv_segment *seg, const struct config_node *s cn->v->v.str); } - if (!get_config_uint64(sn, "device_id", &seg->device_id)) + if (!dm_config_get_uint64(sn, "device_id", &seg->device_id)) return SEG_LOG_ERROR("Could not read device_id for"); return 1; diff --git a/lib/unknown/unknown.c b/lib/unknown/unknown.c index 105da98b9..de449bfe0 100644 --- a/lib/unknown/unknown.c +++ b/lib/unknown/unknown.c @@ -32,17 +32,17 @@ static const char *_unknown_name(const struct lv_segment *seg) return seg->segtype->name; } -static int _unknown_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _unknown_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - struct config_node *new, *last = NULL, *head = NULL; - const struct config_node *current; + struct dm_config_node *new, *last = NULL, *head = NULL; + const struct dm_config_node *current; log_verbose("importing unknown segment"); for (current = sn; current != NULL; current = current->sib) { if (!strcmp(current->key, "type") || !strcmp(current->key, "start_extent") || !strcmp(current->key, "tags") || !strcmp(current->key, "extent_count")) continue; - new = clone_config_node_with_mem(seg->lv->vg->vgmem, current, 0); + new = dm_config_clone_node_with_mem(seg->lv->vg->vgmem, current, 0); if (!new) return_0; if (last) @@ -57,7 +57,7 @@ static int _unknown_text_import(struct lv_segment *seg, const struct config_node static int _unknown_text_export(const struct lv_segment *seg, struct formatter *f) { - struct config_node *cn = seg->segtype_private; + struct dm_config_node *cn = seg->segtype_private; return out_config_node(f, cn); } diff --git a/libdm/Makefile.in b/libdm/Makefile.in index 70be30950..b4f137a15 100644 --- a/libdm/Makefile.in +++ b/libdm/Makefile.in @@ -25,6 +25,7 @@ SOURCES =\ libdm-deptree.c \ libdm-string.c \ libdm-report.c \ + libdm-config.c \ mm/dbg_malloc.c \ mm/pool.c \ regex/matcher.c \ diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index ea75376b3..62f56ae9b 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef linux # include @@ -1014,6 +1015,46 @@ int dm_snprintf(char *buf, size_t bufsize, const char *format, ...) */ const char *dm_basename(const char *path); +/* + * Count occurences of 'c' in 'str' of length 'size'. + * + * Returns: + * Number of occurrences of 'c' + */ +unsigned dm_count_chars(const char *str, size_t len, const int c); + +/* + * Length of string after escaping double quotes and backslashes. + */ +size_t dm_escaped_len(const char *str); + +/* + * -- or if !layer just -. + */ +char *dm_build_dm_name(struct dm_pool *mem, const char *vgname, + const char *lvname, const char *layer); +char *dm_build_dm_uuid(struct dm_pool *mem, const char *prefix, const char *lvid, const char *layer); + +/* + * Copies a string, quoting double quotes with backslashes. + */ +char *dm_escape_double_quotes(char *out, const char *src); + +/* + * Undo quoting in situ. + */ +void dm_unescape_double_quotes(char *src); + +/* + * Unescape colons and "at" signs in situ and save the substrings + * starting at the position of the first unescaped colon and the + * first unescaped "at" sign. This is normally used to unescape + * device names used as PVs. + */ +void dm_unescape_colons_and_at_signs(char *src, + char **substr_first_unquoted_colon, + char **substr_first_unquoted_at_sign); + /************************** * file/stream manipulation **************************/ @@ -1181,6 +1222,108 @@ int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field, void dm_report_field_set_value(struct dm_report_field *field, const void *value, const void *sortvalue); + +/********************************* + * config file parse/prettyprint + *********************************/ +enum { + DM_CFG_STRING, + DM_CFG_FLOAT, + DM_CFG_INT, + DM_CFG_EMPTY_ARRAY +}; + +struct dm_config_value { + int type; + union { + int64_t i; + float r; + const char *str; + } v; + struct dm_config_value *next; /* for arrays */ +}; + +struct dm_config_node { + const char *key; + struct dm_config_node *parent, *sib, *child; + struct dm_config_value *v; +}; + +struct dm_config_tree { + struct dm_config_node *root; + struct dm_config_tree *cascade; +}; + +struct dm_config_tree *dm_config_create(const char *filename, int keep_open); +struct dm_config_tree *dm_config_from_string(const char *config_settings); +int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end); + +void *dm_config_get_custom(struct dm_config_tree *cft); +int dm_config_check_file(struct dm_config_tree *cft, const char **filename, struct stat *info); +int dm_config_keep_open(struct dm_config_tree *ctf); + +void dm_config_set_custom(struct dm_config_tree *cft, void *custom); + +void dm_config_destroy(struct dm_config_tree *cft); + +int dm_config_write(struct dm_config_tree *cft, const char *file, + int argc, char **argv); + +typedef int (*dm_putline_fn)(const char *line, void *baton); +int dm_config_write_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton); + +time_t dm_config_timestamp(struct dm_config_tree *cft); +int dm_config_changed(struct dm_config_tree *cft); + +const struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path); +const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail); +int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail); +float dm_config_find_float(const struct dm_config_node *cn, const char *path, float fail); + +const struct dm_config_node *dm_config_tree_find_node( + const struct dm_config_tree *cft, const char *path); +const char *dm_config_tree_find_str(const struct dm_config_tree *cft, + const char *path, const char *fail); +int dm_config_tree_find_int(const struct dm_config_tree *cft, + const char *path, int fail); +int64_t dm_config_tree_find_int64(const struct dm_config_tree *cft, + const char *path, int64_t fail); +float dm_config_tree_find_float(const struct dm_config_tree *cft, + const char *path, float fail); +int dm_config_tree_find_bool(const struct dm_config_tree *cft, + const char *path, int fail); + +/* + * Understands (0, ~0), (y, n), (yes, no), (on, + * off), (true, false). + */ +int dm_config_find_bool(const struct dm_config_node *cn, const char *path, int fail); + +int dm_config_get_uint32(const struct dm_config_node *cn, const char *path, + uint32_t *result); + +int dm_config_get_uint64(const struct dm_config_node *cn, const char *path, + uint64_t *result); + +int dm_config_get_str(const struct dm_config_node *cn, const char *path, + const char **result); + +unsigned dm_config_maybe_section(const char *str, unsigned len); + +const char *dm_config_parent_name(const struct dm_config_node *n); + +struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, + const struct dm_config_node *node, + int siblings); +struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key); +struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft); +struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, + const struct dm_config_node *cn, + int siblings); + +struct dm_pool *dm_config_memory(struct dm_config_tree *cft); + + /* Cookie prefixes. * The cookie value consists of a prefix (16 bits) and a base (16 bits). * We can use the prefix to store the flags. These flags are sent to diff --git a/libdm/libdm-config.c b/libdm/libdm-config.c new file mode 100644 index 000000000..688d9a7c4 --- /dev/null +++ b/libdm/libdm-config.c @@ -0,0 +1,1237 @@ +/* + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. + * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "dmlib.h" + +#include +#include +#include +#include +#include + +#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 line; /* line number we are on */ + + struct dm_pool *mem; +}; + +struct cs { + struct dm_config_tree cft; + struct dm_pool *mem; + time_t timestamp; + off_t st_size; + char *filename; + int exists; + int keep_open; + void *custom; /* LVM uses this for a device pointer */ +}; + +struct output_line { + FILE *fp; + struct dm_pool *mem; + dm_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 dm_config_node *_file(struct parser *p); +static struct dm_config_node *_section(struct parser *p); +static struct dm_config_value *_value(struct parser *p); +static struct dm_config_value *_type(struct parser *p); +static int _match_aux(struct parser *p, int t); +static struct dm_config_value *_create_value(struct dm_pool *mem); +static struct dm_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) +{ + while (*str && (b != e)) { + if (*str++ != *b++) + return 0; + } + + return !(*str || (b != e)); +} + +/* + * public interface + */ +struct dm_config_tree *dm_config_create(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 dm_config_node *) NULL; + c->cft.cascade = NULL; + c->timestamp = 0; + c->exists = 0; + c->keep_open = keep_open; + c->custom = NULL; + if (filename) + c->filename = dm_pool_strdup(c->mem, filename); + return &c->cft; +} + +void dm_config_set_custom(struct dm_config_tree *cft, void *custom) +{ + struct cs *c = (struct cs *) cft; + c->custom = custom; +} + +void *dm_config_get_custom(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->custom; +} + +int dm_config_keep_open(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->keep_open; +} + +void dm_config_destroy(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + dm_pool_destroy(c->mem); +} + +int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end) +{ + /* TODO? if (start == end) return 1; */ + + struct cs *c = (struct cs *) cft; + struct parser *p; + if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) + return_0; + + p->mem = c->mem; + p->fb = start; + p->fe = end; + 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 dm_config_tree *dm_config_from_string(const char *config_settings) +{ + struct dm_config_tree *cft; + + if (!(cft = dm_config_create(NULL, 0))) + return_NULL; + + if (!dm_config_parse(cft, config_settings, config_settings + strlen(config_settings))) { + dm_config_destroy(cft); + return_NULL; + } + + return cft; +} + +int dm_config_check_file(struct dm_config_tree *cft, const char **filename, struct stat *info) +{ + struct cs *c = (struct cs *) cft; + struct stat _info; + if (!info) + info = &_info; + if (filename) + *filename = c->filename; + + if (stat(c->filename, info)) { + log_sys_error("stat", c->filename); + c->exists = 0; + return 0; + } + + if (!S_ISREG(info->st_mode)) { + log_error("%s is not a regular file", c->filename); + c->exists = 0; + return 0; + } + + c->exists = 1; + + if (info->st_size == 0) + log_verbose("%s is empty", c->filename); + + c->timestamp = info->st_ctime; + c->st_size = info->st_size; + + return 1; +} + +time_t dm_config_timestamp(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->timestamp; +} + +/* + * Return 1 if config files ought to be reloaded + */ +int dm_config_changed(struct dm_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) +{ + 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); + } + + return 1; +} + +static int _write_value(struct output_line *outline, const struct dm_config_value *v) +{ + char *buf; + + switch (v->type) { + case DM_CFG_STRING: + if (!(buf = alloca(dm_escaped_len(v->v.str)))) { + log_error("temporary stack allocation for a config " + "string failed"); + return 0; + } + line_append("\"%s\"", dm_escape_double_quotes(buf, v->v.str)); + break; + + case DM_CFG_FLOAT: + line_append("%f", v->v.r); + break; + + case DM_CFG_INT: + line_append("%" PRId64, v->v.i); + break; + + case DM_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 dm_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 dm_config_value *v = n->v; + line_append("="); + if (v->next) { + line_append("["); + while (v && v->type != DM_CFG_EMPTY_ARRAY) { + if (!_write_value(outline, v)) + return_0; + v = v->next; + if (v && v->type != DM_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 dm_config_write_node(const struct dm_config_node *cn, dm_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 dm_config_write(struct dm_config_tree *cft, const char *file, + int argc, char **argv) +{ + const struct dm_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 = dm_config_find_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 && dm_fclose(outline.fp)) { + stack; + r = 0; + } + + return r; +} + +/* + * parser + */ +static struct dm_config_node *_file(struct parser *p) +{ + struct dm_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 dm_config_node *_section(struct parser *p) +{ + /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */ + struct dm_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 dm_config_value *_value(struct parser *p) +{ + /* '[' TYPE* ']' | TYPE */ + struct dm_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 = DM_CFG_EMPTY_ARRAY; + } + + } else + h = _type(p); + + return h; +} + +static struct dm_config_value *_type(struct parser *p) +{ + /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */ + struct dm_config_value *v = _create_value(p->mem); + char *str; + + if (!v) + return NULL; + + switch (p->t) { + case TOK_INT: + v->type = DM_CFG_INT; + v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */ + match(TOK_INT); + break; + + case TOK_FLOAT: + v->type = DM_CFG_FLOAT; + v->v.r = strtod(p->tb, NULL); /* FIXME: check error */ + match(TOK_FLOAT); + break; + + case TOK_STRING: + v->type = DM_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 = DM_CFG_STRING; + + p->tb++, p->te--; /* strip "'s */ + if (!(str = _dup_tok(p))) + return_0; + dm_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 dm_config_value *_create_value(struct dm_pool *mem) +{ + return dm_pool_zalloc(mem, sizeof(struct dm_config_value)); +} + +static struct dm_config_node *_create_node(struct dm_pool *mem) +{ + return dm_pool_zalloc(mem, sizeof(struct dm_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 dm_config_node *_find_config_node(const void *start, + const char *path) +{ + const char *e; + const struct dm_config_node *cn = start; + const struct dm_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; +} + +typedef const struct dm_config_node *_node_lookup_fn(const void *start, const char *path); + +static const struct dm_config_node *_find_first_config_node(const void *start, const char *path) +{ + const struct dm_config_tree *cft = start; + const struct dm_config_node *cn = NULL; + + while (cft) { + if ((cn = _find_config_node(cft->root, path))) + return cn; + cft = cft->cascade; + } + + return NULL; +} + +static const char *_find_config_str(const void *start, _node_lookup_fn find, + const char *path, const char *fail) +{ + const struct dm_config_node *n = find(start, path); + + /* Empty strings are ignored */ + if ((n && n->v && n->v->type == DM_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 *dm_config_find_str(const struct dm_config_node *cn, + const char *path, const char *fail) +{ + return _find_config_str(cn, _find_config_node, path, fail); +} + +static int64_t _find_config_int64(const void *start, _node_lookup_fn find, + const char *path, int64_t fail) +{ + const struct dm_config_node *n = find(start, path); + + if (n && n->v && n->v->type == DM_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; +} + +static float _find_config_float(const void *start, _node_lookup_fn find, + const char *path, float fail) +{ + const struct dm_config_node *n = find(start, path); + + if (n && n->v && n->v->type == DM_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; + +} + +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 void *start, _node_lookup_fn find, + const char *path, int fail) +{ + const struct dm_config_node *n = find(start, path); + const struct dm_config_value *v; + + if (!n) + return fail; + + v = n->v; + + switch (v->type) { + case DM_CFG_INT: + return v->v.i ? 1 : 0; + + case DM_CFG_STRING: + return _str_to_bool(v->v.str, fail); + } + + return fail; +} + +/*********************************** + * node-based lookup + **/ + +const struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, + const char *path) +{ + return _find_config_node(cn, path); +} + +int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail) +{ + /* FIXME Add log_error message on overflow */ + return (int) _find_config_int64(cn, _find_config_node, path, (int64_t) fail); +} + +float dm_config_find_float(const struct dm_config_node *cn, const char *path, + float fail) +{ + return _find_config_float(cn, _find_config_node, path, fail); +} + +int dm_config_find_bool(const struct dm_config_node *cn, const char *path, int fail) +{ + return _find_config_bool(cn, _find_config_node, path, fail); +} + +/*********************************** + * tree-based lookup + **/ + +const struct dm_config_node *dm_config_tree_find_node(const struct dm_config_tree *cft, + const char *path) +{ + return _find_first_config_node(cft, path); +} + +const char *dm_config_tree_find_str(const struct dm_config_tree *cft, const char *path, + const char *fail) +{ + return _find_config_str(cft, _find_first_config_node, path, fail); +} + +int dm_config_tree_find_int(const struct dm_config_tree *cft, const char *path, int fail) +{ + /* FIXME Add log_error message on overflow */ + return (int) _find_config_int64(cft, _find_first_config_node, path, (int64_t) fail); +} + +int64_t dm_config_tree_find_int64(const struct dm_config_tree *cft, const char *path, int64_t fail) +{ + return _find_config_int64(cft, _find_first_config_node, path, fail); +} + +float dm_config_tree_find_float(const struct dm_config_tree *cft, const char *path, + float fail) +{ + return _find_config_float(cft, _find_first_config_node, path, fail); +} + +int dm_config_tree_find_bool(const struct dm_config_tree *cft, const char *path, int fail) +{ + return _find_config_bool(cft, _find_first_config_node, path, fail); +} + +/************************************/ + + +int dm_config_get_uint32(const struct dm_config_node *cn, const char *path, + uint32_t *result) +{ + const struct dm_config_node *n; + + n = dm_config_find_node(cn, path); + + if (!n || !n->v || n->v->type != DM_CFG_INT) + return 0; + + *result = n->v->v.i; + return 1; +} + +int dm_config_get_uint64(const struct dm_config_node *cn, const char *path, + uint64_t *result) +{ + const struct dm_config_node *n; + + n = dm_config_find_node(cn, path); + + if (!n || !n->v || n->v->type != DM_CFG_INT) + return 0; + + *result = (uint64_t) n->v->v.i; + return 1; +} + +int dm_config_get_str(const struct dm_config_node *cn, const char *path, + const char **result) +{ + const struct dm_config_node *n; + + n = dm_config_find_node(cn, path); + + if (!n || !n->v || n->v->type != DM_CFG_STRING) + return 0; + + *result = n->v->v.str; + 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 dm_count_chars(str, len, c); +} + +const char *dm_config_parent_name(const struct dm_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 dm_config_maybe_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 dm_config_value *_clone_config_value(struct dm_pool *mem, + const struct dm_config_value *v) +{ + struct dm_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 == DM_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 dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *cn, int siblings) +{ + struct dm_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 = dm_config_clone_node_with_mem(mem, cn->child, 1))) || + (siblings && cn->sib && !(new_cn->sib = dm_config_clone_node_with_mem(mem, cn->sib, siblings)))) + return_NULL; /* 'new_cn' released with mem pool */ + + return new_cn; +} + +struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *node, int sib) +{ + struct cs *c = (struct cs *) cft; + return dm_config_clone_node_with_mem(c->mem, node, sib); +} + +struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key) +{ + struct cs *c = (struct cs *) cft; + struct dm_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 = DM_CFG_INT; + cn->v->v.i = 0; + cn->v->next = NULL; + return cn; +} + +struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return _create_value(c->mem); +} + +struct dm_pool *dm_config_memory(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->mem; +} diff --git a/libdm/libdm-string.c b/libdm/libdm-string.c index 365e7ec0d..25080c047 100644 --- a/libdm/libdm-string.c +++ b/libdm/libdm-string.c @@ -161,3 +161,225 @@ int dm_asprintf(char **result, const char *format, ...) dm_free(buf); return n + 1; } + +/* + * Count occurences of 'c' in 'str' until we reach a null char. + * + * Returns: + * len - incremented for each char we encounter. + * count - number of occurrences of 'c' and 'c2'. + */ +static void _count_chars(const char *str, size_t *len, int *count, + const int c1, const int c2) +{ + const char *ptr; + + for (ptr = str; *ptr; ptr++, (*len)++) + if (*ptr == c1 || *ptr == c2) + (*count)++; +} + +unsigned dm_count_chars(const char *str, size_t len, const int c) +{ + size_t i; + unsigned count = 0; + + for (i = 0; i < len; i++) + if (str[i] == c) + count++; + + return count; +} + +size_t dm_escaped_len(const char *str) +{ + size_t len = 1; + int count = 0; + + _count_chars(str, &len, &count, '\"', '\\'); + + return count + len; +} + +/* + * Copies a string, quoting orig_char with quote_char. + * Optionally also quote quote_char. + */ +static void _quote_characters(char **out, const char *src, + const int orig_char, const int quote_char, + int quote_quote_char) +{ + while (*src) { + if (*src == orig_char || + (*src == quote_char && quote_quote_char)) + *(*out)++ = quote_char; + + *(*out)++ = *src++; + } +} + +static void _unquote_one_character(char *src, const char orig_char, + const char quote_char) +{ + char *out; + char s, n; + + /* Optimise for the common case where no changes are needed. */ + while ((s = *src++)) { + if (s == quote_char && + ((n = *src) == orig_char || n == quote_char)) { + out = src++; + *(out - 1) = n; + + while ((s = *src++)) { + if (s == quote_char && + ((n = *src) == orig_char || n == quote_char)) { + s = n; + src++; + } + *out = s; + out++; + } + + *out = '\0'; + return; + } + } +} + +/* + * Unquote each character given in orig_char array and unquote quote_char + * as well. Also save the first occurrence of each character from orig_char + * that was found unquoted in arr_substr_first_unquoted array. This way we can + * process several characters in one go. + */ +static void _unquote_characters(char *src, const char *orig_chars, + size_t num_orig_chars, + const char quote_char, + char *arr_substr_first_unquoted[]) +{ + char *out = src; + char c, s, n; + unsigned i; + + while ((s = *src++)) { + for (i = 0; i < num_orig_chars; i++) { + c = orig_chars[i]; + if (s == quote_char && + ((n = *src) == c || n == quote_char)) { + s = n; + src++; + break; + } + if (arr_substr_first_unquoted && (s == c) && + !arr_substr_first_unquoted[i]) + arr_substr_first_unquoted[i] = out; + }; + *out++ = s; + } + + *out = '\0'; +} + +/* + * Copies a string, quoting hyphens with hyphens. + */ +static void _quote_hyphens(char **out, const char *src) +{ + _quote_characters(out, src, '-', '-', 0); +} + +char *dm_build_dm_name(struct dm_pool *mem, const char *vgname, + const char *lvname, const char *layer) +{ + size_t len = 1; + int hyphens = 1; + char *r, *out; + + _count_chars(vgname, &len, &hyphens, '-', 0); + _count_chars(lvname, &len, &hyphens, '-', 0); + + if (layer && *layer) { + _count_chars(layer, &len, &hyphens, '-', 0); + hyphens++; + } + + len += hyphens; + + if (!(r = dm_pool_alloc(mem, len))) { + log_error("build_dm_name: Allocation failed for %" PRIsize_t + " for %s %s %s.", len, vgname, lvname, layer); + return NULL; + } + + out = r; + _quote_hyphens(&out, vgname); + *out++ = '-'; + _quote_hyphens(&out, lvname); + + if (layer && *layer) { + /* No hyphen if the layer begins with _ e.g. _mlog */ + if (*layer != '_') + *out++ = '-'; + _quote_hyphens(&out, layer); + } + *out = '\0'; + + return r; +} + +char *dm_build_dm_uuid(struct dm_pool *mem, const char *prefix, const char *lvid, const char *layer) +{ + char *dmuuid; + size_t len; + + if (!layer) + layer = ""; + + len = strlen(prefix) + strlen(lvid) + strlen(layer) + 1; + + if (!(dmuuid = dm_pool_alloc(mem, len))) { + log_error("build_dm_name: Allocation failed for %" PRIsize_t + " %s %s.", len, lvid, layer); + return NULL; + } + + sprintf(dmuuid, "%s%s%s%s", prefix, lvid, (*layer) ? "-" : "", layer); + + return dmuuid; +} + +/* + * Copies a string, quoting double quotes with backslashes. + */ +char *dm_escape_double_quotes(char *out, const char *src) +{ + char *buf = out; + + _quote_characters(&buf, src, '\"', '\\', 1); + *buf = '\0'; + + return out; +} + +void dm_unescape_double_quotes(char *src) +{ + _unquote_one_character(src, '\"', '\\'); +} + +void dm_unescape_colons_and_at_signs(char *src, + char **substr_first_unquoted_colon, + char **substr_first_unquoted_at_sign) +{ + const char *orig_chars = ":@"; + char *arr_substr_first_unquoted[] = {NULL, NULL, NULL}; + + _unquote_characters(src, orig_chars, 2, '\\', arr_substr_first_unquoted); + + if (substr_first_unquoted_colon) + *substr_first_unquoted_colon = arr_substr_first_unquoted[0]; + + if (substr_first_unquoted_at_sign) + *substr_first_unquoted_at_sign = arr_substr_first_unquoted[1]; +} + diff --git a/tools/dumpconfig.c b/tools/dumpconfig.c index 981147c58..c3f664a15 100644 --- a/tools/dumpconfig.c +++ b/tools/dumpconfig.c @@ -19,7 +19,7 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv) { const char *file = arg_str_value(cmd, file_ARG, NULL); - if (!write_config_file(cmd->cft, file, argc, argv)) { + if (!dm_config_write(cmd->cft, file, argc, argv)) { stack; return ECMD_FAILED; } diff --git a/tools/pvchange.c b/tools/pvchange.c index 990d0f21f..f6d1abd31 100644 --- a/tools/pvchange.c +++ b/tools/pvchange.c @@ -209,7 +209,7 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv) log_verbose("Using physical volume(s) on command line"); for (; opt < argc; opt++) { pv_name = argv[opt]; - unescape_colons_and_at_signs(pv_name, NULL, NULL); + dm_unescape_colons_and_at_signs(pv_name, NULL, NULL); vg_name = find_vgname_from_pvname(cmd, pv_name); if (!vg_name) { log_error("Failed to read physical volume %s", diff --git a/tools/pvck.c b/tools/pvck.c index 2ec75976f..e45e77af6 100644 --- a/tools/pvck.c +++ b/tools/pvck.c @@ -31,7 +31,7 @@ int pvck(struct cmd_context *cmd, int argc, char **argv) /* FIXME: warning and/or check if in use? */ log_verbose("Scanning %s", argv[i]); - unescape_colons_and_at_signs(argv[i], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); pv_analyze(cmd, argv[i], arg_uint64_value(cmd, labelsector_ARG, UINT64_C(0))); diff --git a/tools/pvcreate.c b/tools/pvcreate.c index 7b50f70c6..da3862d53 100644 --- a/tools/pvcreate.c +++ b/tools/pvcreate.c @@ -110,7 +110,7 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - unescape_colons_and_at_signs(argv[i], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); if (!(pv = pvcreate_single(cmd, argv[i], &pp, 1))) { stack; diff --git a/tools/pvmove.c b/tools/pvmove.c index 7a2fd14a3..19ebf1788 100644 --- a/tools/pvmove.c +++ b/tools/pvmove.c @@ -664,7 +664,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - unescape_colons_and_at_signs(pv_name, &colon, NULL); + dm_unescape_colons_and_at_signs(pv_name, &colon, NULL); /* Drop any PE lists from PV name */ if (colon) diff --git a/tools/pvremove.c b/tools/pvremove.c index 5a2a43e00..5a8884c95 100644 --- a/tools/pvremove.c +++ b/tools/pvremove.c @@ -150,7 +150,7 @@ int pvremove(struct cmd_context *cmd, int argc, char **argv) } for (i = 0; i < argc; i++) { - unescape_colons_and_at_signs(argv[i], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); r = pvremove_single(cmd, argv[i], NULL); if (r > ret) ret = r; diff --git a/tools/toollib.c b/tools/toollib.c index b606df842..49c94244f 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -707,7 +707,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv, if (argc) { log_verbose("Using physical volume(s) on command line"); for (; opt < argc; opt++) { - unescape_colons_and_at_signs(argv[opt], NULL, &at_sign); + dm_unescape_colons_and_at_signs(argv[opt], NULL, &at_sign); if (at_sign && (at_sign == argv[opt])) { tagname = at_sign + 1; @@ -1129,7 +1129,7 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int dm_list_init(&arg_pvnames); for (i = 0; i < argc; i++) { - unescape_colons_and_at_signs(argv[i], &colon, &at_sign); + dm_unescape_colons_and_at_signs(argv[i], &colon, &at_sign); if (at_sign && (at_sign == argv[i])) { tagname = at_sign + 1; diff --git a/tools/vgsplit.c b/tools/vgsplit.c index 0538459e9..95b7d38dc 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -395,7 +395,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) /* Move PVs across to new structure */ for (opt = 0; opt < argc; opt++) { - unescape_colons_and_at_signs(argv[opt], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[opt], NULL, NULL); if (!move_pv(vg_from, vg_to, argv[opt])) goto_bad; }