1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-23 02:05:07 +03:00

Support tagged config files.

This commit is contained in:
Alasdair Kergon 2004-05-04 18:28:15 +00:00
parent 46cdd53323
commit c3941941ce
12 changed files with 546 additions and 269 deletions

View File

@ -1,3 +1,9 @@
Version 2.00.16 -
=============================
Support for tagged config files.
Don't abort operations if selinux present but disabled.
Fix typo in configure which left HAVE_LIBDL unset.
Version 2.00.15 - 19 Apr 2004
=============================
configure --with-owner= --with-group= to avoid -o and -g args to 'install'

View File

@ -173,13 +173,13 @@ int activation(void)
static int _passes_activation_filter(struct cmd_context *cmd,
struct logical_volume *lv)
{
struct config_node *cn;
const struct config_node *cn;
struct config_value *cv;
char *str;
char path[PATH_MAX];
if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
/* If no hosts tags defined, activate */
/* If no host tags defined, activate */
if (list_empty(&cmd->tags))
return 1;

View File

@ -116,8 +116,7 @@ static void _init_logging(struct cmd_context *cmd)
find_config_int(cmd->cft->root, "global/test", 0);
/* Settings for logging to file */
if (find_config_int(cmd->cft->root, "log/overwrite",
DEFAULT_OVERWRITE))
if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
append = 0;
log_file = find_config_str(cmd->cft->root, "log/file", 0);
@ -198,51 +197,260 @@ static int _process_config(struct cmd_context *cmd)
return 1;
}
/* Find and read config file */
static int _init_config(struct cmd_context *cmd)
static int _set_tag(struct cmd_context *cmd, const char *tag)
{
struct stat info;
char config_file[PATH_MAX] = "";
log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
if (!(cmd->cft = create_config_tree())) {
stack;
return 0;
}
/* No config file if LVM_SYSTEM_DIR is empty */
if (!*cmd->sys_dir)
return 1;
if (lvm_snprintf(config_file, sizeof(config_file),
"%s/lvm.conf", cmd->sys_dir) < 0) {
log_error("LVM_SYSTEM_DIR was too long");
destroy_config_tree(cmd->cft);
return 0;
}
/* Is there a config file? */
if (stat(config_file, &info) == -1) {
if (errno == ENOENT)
return 1;
log_sys_error("stat", config_file);
destroy_config_tree(cmd->cft);
return 0;
}
if (!read_config_file(cmd->cft, config_file)) {
log_error("Failed to load config file %s", config_file);
destroy_config_tree(cmd->cft);
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
log_error("_set_tag: str_list_add %s failed", tag);
return 0;
}
return 1;
}
static int _init_dev_cache(struct cmd_context *cmd)
static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
int *passes)
{
struct config_node *cn;
struct config_value *cv;
*passes = 1;
for (cn = hn; cn; cn = cn->sib) {
if (!cn->v)
continue;
if (!strcmp(cn->key, "host_list")) {
*passes = 0;
if (cn->v->type == CFG_EMPTY_ARRAY)
continue;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid hostname string "
"for tag %s", cn->key);
return 0;
}
if (!strcmp(cv->v.str, cmd->hostname)) {
*passes = 1;
return 1;
}
}
}
if (!strcmp(cn->key, "host_filter")) {
log_error("host_filter not supported yet");
return 0;
}
}
return 1;
}
static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
{
const struct config_node *tn, *cn;
const char *tag;
int passes;
if (!(tn = find_config_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",
DEFAULT_HOSTTAGS)) {
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
if (!_set_tag(cmd, cmd->hostname)) {
stack;
return 0;
}
cmd->hosttags = 1;
}
for (cn = tn->child; cn; cn = cn->sib) {
if (cn->v)
continue;
tag = cn->key;
if (*tag == '@')
tag++;
if (!validate_name(tag)) {
log_error("Invalid tag in config file: %s", cn->key);
return 0;
}
if (cn->child) {
passes = 0;
if (!_check_host_filters(cmd, cn->child, &passes)) {
stack;
return 0;
}
if (!passes)
continue;
}
if (!_set_tag(cmd, tag)) {
stack;
return 0;
}
}
return 1;
}
static int _load_config_file(struct cmd_context *cmd, const char *tag)
{
char config_file[PATH_MAX] = "";
const char *filler = "";
struct stat info;
struct config_tree_list *cfl;
if (*tag)
filler = "_";
if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
cmd->sys_dir, filler, tag) < 0) {
log_error("LVM_SYSTEM_DIR or tag was too long");
return 0;
}
if (!(cfl = pool_alloc(cmd->libmem, sizeof(*cfl)))) {
log_error("config_tree_list allocation failed");
return 0;
}
if (!(cfl->cft = create_config_tree(config_file))) {
log_error("config_tree allocation failed");
return 0;
}
/* Is there a config file? */
if (stat(config_file, &info) == -1) {
if (errno == ENOENT) {
list_add(&cmd->config_files, &cfl->list);
goto out;
}
log_sys_error("stat", config_file);
destroy_config_tree(cfl->cft);
return 0;
}
log_very_verbose("Loading config file: %s", config_file);
if (!read_config_file(cfl->cft)) {
log_error("Failed to load config file %s", config_file);
destroy_config_tree(cfl->cft);
return 0;
}
list_add(&cmd->config_files, &cfl->list);
out:
if (*tag)
_init_tags(cmd, cfl->cft);
else
/* Use temporary copy of lvm.conf while loading other files */
cmd->cft = cfl->cft;
return 1;
}
/* Find and read first config file */
static int _init_lvm_conf(struct cmd_context *cmd)
{
/* No config file if LVM_SYSTEM_DIR is empty */
if (!*cmd->sys_dir) {
if (!(cmd->cft = create_config_tree(NULL))) {
log_error("Failed to create config tree");
return 0;
}
return 1;
}
if (!_load_config_file(cmd, "")) {
stack;
return 0;
}
return 1;
}
/* Read any additional config files */
static int _init_tag_configs(struct cmd_context *cmd)
{
struct str_list *sl;
/* Tag list may grow while inside this loop */
list_iterate_items(sl, &cmd->tags) {
if (!_load_config_file(cmd, sl->str)) {
stack;
return 0;
}
}
return 1;
}
static int _merge_config_files(struct cmd_context *cmd)
{
struct config_tree_list *cfl;
/* Replace temporary duplicate copy of lvm.conf */
if (cmd->cft->root) {
if (!(cmd->cft = create_config_tree(NULL))) {
log_error("Failed to create config tree");
return 0;
}
}
list_iterate_items(cfl, &cmd->config_files) {
/* Merge all config trees into cmd->cft using merge/tag rules */
if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) {
stack;
return 0;
}
}
return 1;
}
static void _destroy_tags(struct cmd_context *cmd)
{
struct list *slh, *slht;
list_iterate_safe(slh, slht, &cmd->tags) {
list_del(slh);
}
}
int config_files_changed(struct cmd_context *cmd)
{
struct config_tree_list *cfl;
list_iterate_items(cfl, &cmd->config_files) {
if (config_file_changed(cfl->cft))
return 1;
}
return 0;
}
static void _destroy_tag_configs(struct cmd_context *cmd)
{
struct config_tree_list *cfl;
if (cmd->cft && cmd->cft->root) {
destroy_config_tree(cmd->cft);
cmd->cft = NULL;
}
list_iterate_items(cfl, &cmd->config_files) {
destroy_config_tree(cfl->cft);
}
list_init(&cmd->config_files);
}
static int _init_dev_cache(struct cmd_context *cmd)
{
const struct config_node *cn;
struct config_value *cv;
if (!dev_cache_init()) {
stack;
return 0;
@ -281,7 +489,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;
struct config_node *cn;
const struct config_node *cn;
struct dev_filter *filters[MAX_FILTERS];
memset(filters, 0, sizeof(filters));
@ -351,8 +559,8 @@ static int _init_filters(struct cmd_context *cmd)
return 0;
}
dev_cache =
find_config_str(cmd->cft->root, "devices/cache", cache_file);
dev_cache = find_config_str(cmd->cft->root, "devices/cache",
cache_file);
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
log_error("Failed to create persistent device filter");
return 0;
@ -384,7 +592,7 @@ static int _init_formats(struct cmd_context *cmd)
struct list *fmth;
#ifdef HAVE_LIBDL
struct config_node *cn;
const struct config_node *cn;
#endif
label_init();
@ -476,105 +684,6 @@ static int _init_hostname(struct cmd_context *cmd)
return 1;
}
static int _set_tag(struct cmd_context *cmd, const char *tag)
{
log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
log_error("_init_tags: str_list_add %s failed", tag);
return 0;
}
return 1;
}
static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
int *passes)
{
struct config_node *cn;
struct config_value *cv;
*passes = 1;
for (cn = hn; cn; cn = cn->sib) {
if (!cn->v)
continue;
if (!strcmp(cn->key, "host_list")) {
*passes = 0;
if (cn->v->type == CFG_EMPTY_ARRAY)
continue;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid hostname string "
"for tag %s", cn->key);
return 0;
}
if (!strcmp(cv->v.str, cmd->hostname)) {
*passes = 1;
return 1;
}
}
}
if (!strcmp(cn->key, "host_filter")) {
log_error("host_filter not supported yet");
return 0;
}
}
return 1;
}
static int _init_tags(struct cmd_context *cmd)
{
struct config_node *tn, *cn;
const char *tag;
int passes;
list_init(&cmd->tags);
if (!(tn = find_config_node(cmd->cft->root, "tags")) ||
!tn->child) {
log_very_verbose("No tags defined in config file");
return 1;
}
if (find_config_int(cmd->cft->root, "tags/hosttags",
DEFAULT_HOSTTAGS)) {
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
if (!_set_tag(cmd, cmd->hostname)) {
stack;
return 0;
}
}
for (cn = tn->child; cn; cn = cn->sib) {
if (cn->v)
continue;
tag = cn->key;
if (*tag == '@')
tag++;
if (!validate_name(tag)) {
log_error("Invalid tag in config file: %s", cn->key);
return 0;
}
if (cn->child) {
passes = 0;
if (!_check_host_filters(cmd, cn->child, &passes)) {
stack;
return 0;
}
if (!passes)
continue;
}
if (!_set_tag(cmd, tag)) {
stack;
return 0;
}
}
return 1;
}
/* Entry point */
struct cmd_context *create_toolcontext(struct arg *the_args)
{
@ -599,7 +708,10 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
}
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->tags);
list_init(&cmd->config_files);
strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
@ -610,16 +722,28 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
goto error;
if (!_init_config(cmd))
goto error;
_init_logging(cmd);
if (!(cmd->libmem = pool_create(4 * 1024))) {
log_error("Library memory pool creation failed");
return 0;
}
if (!_init_lvm_conf(cmd))
goto error;
_init_logging(cmd);
if (!_init_hostname(cmd))
goto error;
if (!_init_tags(cmd, cmd->cft))
goto error;
if (!_init_tag_configs(cmd))
goto error;
if (!_merge_config_files(cmd))
goto error;
if (!_process_config(cmd))
goto error;
@ -639,14 +763,9 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (!_init_formats(cmd))
goto error;
if (!_init_hostname(cmd))
goto error;
if (!_init_tags(cmd))
goto error;
cmd->current_settings = cmd->default_settings;
cmd->config_valid = 1;
return cmd;
error:
@ -654,16 +773,6 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
return NULL;
}
int refresh_toolcontext(struct cmd_context *cmd)
{
_init_logging(cmd);
_init_tags(cmd);
/* FIXME Reset filters and dev_cache */
return 1;
}
static void _destroy_formats(struct list *formats)
{
struct list *fmtl, *tmp;
@ -682,6 +791,61 @@ static void _destroy_formats(struct list *formats)
}
}
int refresh_toolcontext(struct cmd_context *cmd)
{
log_verbose("Reloading config files");
if (cmd->config_valid) {
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
}
activation_exit();
lvmcache_destroy();
label_exit();
_destroy_formats(&cmd->formats);
if (cmd->filter) {
cmd->filter->destroy(cmd->filter);
cmd->filter = NULL;
}
dev_cache_exit();
_destroy_tags(cmd);
_destroy_tag_configs(cmd);
cmd->config_valid = 0;
cmd->hosttags = 0;
if (!_init_lvm_conf(cmd))
return 0;
_init_logging(cmd);
if (!_init_tags(cmd, cmd->cft))
return 0;
if (!_init_tag_configs(cmd))
return 0;
if (!_merge_config_files(cmd))
return 0;
if (!_process_config(cmd))
return 0;
if (!_init_dev_cache(cmd))
return 0;
if (!_init_filters(cmd))
return 0;
if (!_init_formats(cmd))
return 0;
cmd->config_valid = 1;
return 1;
}
void destroy_toolcontext(struct cmd_context *cmd)
{
if (cmd->dump_filter)
@ -694,7 +858,8 @@ void destroy_toolcontext(struct cmd_context *cmd)
cmd->filter->destroy(cmd->filter);
pool_destroy(cmd->mem);
dev_cache_exit();
destroy_config_tree(cmd->cft);
_destroy_tags(cmd);
_destroy_tag_configs(cmd);
pool_destroy(cmd->libmem);
dbg_free(cmd);

View File

@ -17,9 +17,7 @@
#define _LVM_TOOLCONTEXT_H
#include "dev-cache.h"
#include "config.h"
#include "pool.h"
#include "metadata.h"
#include <stdio.h>
#include <limits.h>
@ -47,6 +45,8 @@ struct config_info {
mode_t umask;
};
struct config_tree;
/* FIXME Split into tool & library contexts */
/* command-instance-related variables needed by library */
struct cmd_context {
@ -68,12 +68,15 @@ struct cmd_context {
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
struct list config_files;
int config_valid;
struct config_tree *cft;
struct config_info default_settings;
struct config_info current_settings;
/* List of defined tags */
struct list tags;
int hosttags;
char sys_dir[PATH_MAX];
char dev_dir[PATH_MAX];
@ -83,5 +86,6 @@ struct cmd_context {
struct cmd_context *create_toolcontext(struct arg *the_args);
void destroy_toolcontext(struct cmd_context *cmd);
int refresh_toolcontext(struct cmd_context *cmd);
int config_files_changed(struct cmd_context *cmd);
#endif

View File

@ -18,6 +18,8 @@
#include "crc.h"
#include "pool.h"
#include "device.h"
#include "str_list.h"
#include "toolcontext.h"
#include <sys/stat.h>
#include <sys/mman.h>
@ -56,6 +58,7 @@ struct cs {
struct pool *mem;
time_t timestamp;
char *filename;
int exists;
};
static void _get_token(struct parser *p, int tok_prev);
@ -93,7 +96,7 @@ static int _tok_match(const char *str, const char *b, const char *e)
/*
* public interface
*/
struct config_tree *create_config_tree(void)
struct config_tree *create_config_tree(const char *filename)
{
struct cs *c;
struct pool *mem = pool_create(10 * 1024);
@ -103,7 +106,7 @@ struct config_tree *create_config_tree(void)
return 0;
}
if (!(c = pool_alloc(mem, sizeof(*c)))) {
if (!(c = pool_zalloc(mem, sizeof(*c)))) {
stack;
pool_destroy(mem);
return 0;
@ -112,7 +115,9 @@ struct config_tree *create_config_tree(void)
c->mem = mem;
c->cft.root = (struct config_node *) NULL;
c->timestamp = 0;
c->filename = NULL;
c->exists = 0;
if (filename)
c->filename = pool_strdup(c->mem, filename);
return &c->cft;
}
@ -204,29 +209,33 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
return r;
}
int read_config_file(struct config_tree *cft, const char *file)
int read_config_file(struct config_tree *cft)
{
struct cs *c = (struct cs *) cft;
struct stat info;
struct device *dev;
int r = 1;
if (stat(file, &info)) {
log_sys_error("stat", file);
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", file);
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", file);
log_verbose("%s is empty", c->filename);
return 1;
}
if (!(dev = dev_create_file(file, NULL, NULL))) {
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
stack;
return 0;
}
@ -242,7 +251,6 @@ int read_config_file(struct config_tree *cft, const char *file)
dev_close(dev);
c->timestamp = info.st_mtime;
c->filename = pool_strdup(c->mem, file);
return r;
}
@ -255,74 +263,43 @@ time_t config_file_timestamp(struct config_tree *cft)
}
/*
* Returns 1 if config file reloaded
* Return 1 if config files ought to be reloaded
*/
int reload_config_file(struct config_tree **cft)
int config_file_changed(struct config_tree *cft)
{
struct config_tree *new_cft;
struct cs *c = (struct cs *) *cft;
struct cs *new_cs;
struct cs *c = (struct cs *) cft;
struct stat info;
struct device *dev;
int r;
if (!c->filename)
return 0;
if (stat(c->filename, &info) == -1) {
if (errno == ENOENT)
return 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 file");
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);
return 0;
goto reload;
}
/* Unchanged? */
if (c->timestamp == info.st_mtime)
return 0;
log_verbose("Detected config file change: Reloading %s", c->filename);
if (info.st_size == 0) {
log_verbose("Config file reload: %s is empty", c->filename);
return 0;
}
if (!(new_cft = create_config_tree())) {
log_error("Allocation of new config_tree failed");
return 0;
}
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
stack;
return 0;
}
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
stack;
return 0;
}
r = read_config_fd(new_cft, dev, 0, (size_t) info.st_size,
0, 0, (checksum_fn_t) NULL, 0);
dev_close(dev);
if (r) {
new_cs = (struct cs *) new_cft;
new_cs->filename = pool_strdup(new_cs->mem, c->filename);
new_cs->timestamp = info.st_mtime;
destroy_config_tree(*cft);
*cft = new_cft;
}
return r;
reload:
log_verbose("Detected config file change to %s", c->filename);
return 1;
}
static void _write_value(FILE *fp, struct config_value *v)
@ -739,7 +716,8 @@ static char *_dup_tok(struct parser *p)
/*
* utility functions
*/
struct config_node *find_config_node(struct config_node *cn, const char *path)
struct config_node *find_config_node(const struct config_node *cn,
const char *path)
{
const char *e;
@ -767,13 +745,13 @@ struct config_node *find_config_node(struct config_node *cn, const char *path)
path = e;
}
return cn;
return (struct config_node *) cn;
}
const char *find_config_str(struct config_node *cn,
const char *find_config_str(const struct config_node *cn,
const char *path, const char *fail)
{
struct config_node *n = find_config_node(cn, path);
const struct config_node *n = find_config_node(cn, path);
if (n && n->v->type == CFG_STRING) {
if (*n->v->v.str)
@ -787,9 +765,9 @@ const char *find_config_str(struct config_node *cn,
return fail;
}
int find_config_int(struct config_node *cn, const char *path, int fail)
int find_config_int(const struct config_node *cn, const char *path, int fail)
{
struct config_node *n = find_config_node(cn, path);
const struct config_node *n = find_config_node(cn, path);
if (n && n->v->type == CFG_INT) {
log_very_verbose("Setting %s to %d", path, n->v->v.i);
@ -801,9 +779,10 @@ int find_config_int(struct config_node *cn, const char *path, int fail)
return fail;
}
float find_config_float(struct config_node *cn, const char *path, float fail)
float find_config_float(const struct config_node *cn, const char *path,
float fail)
{
struct config_node *n = find_config_node(cn, path);
const struct config_node *n = find_config_node(cn, path);
if (n && n->v->type == CFG_FLOAT) {
log_very_verbose("Setting %s to %f", path, n->v->v.r);
@ -843,9 +822,9 @@ static int _str_to_bool(const char *str, int fail)
return fail;
}
int find_config_bool(struct config_node *cn, const char *path, int fail)
int find_config_bool(const struct config_node *cn, const char *path, int fail)
{
struct config_node *n = find_config_node(cn, path);
const struct config_node *n = find_config_node(cn, path);
struct config_value *v;
if (!n)
@ -864,10 +843,10 @@ int find_config_bool(struct config_node *cn, const char *path, int fail)
return fail;
}
int get_config_uint32(struct config_node *cn, const char *path,
int get_config_uint32(const struct config_node *cn, const char *path,
uint32_t *result)
{
struct config_node *n;
const struct config_node *n;
n = find_config_node(cn, path);
@ -878,10 +857,10 @@ int get_config_uint32(struct config_node *cn, const char *path,
return 1;
}
int get_config_uint64(struct config_node *cn, const char *path,
int get_config_uint64(const struct config_node *cn, const char *path,
uint64_t *result)
{
struct config_node *n;
const struct config_node *n;
n = find_config_node(cn, path);
@ -893,9 +872,10 @@ int get_config_uint64(struct config_node *cn, const char *path,
return 1;
}
int get_config_str(struct config_node *cn, const char *path, char **result)
int get_config_str(const struct config_node *cn, const char *path,
char **result)
{
struct config_node *n;
const struct config_node *n;
n = find_config_node(cn, path);
@ -905,3 +885,115 @@ int get_config_str(struct config_node *cn, const char *path, char **result)
*result = n->v->v.str;
return 1;
}
/* Insert cn2 after cn1 */
static void _insert_config_node(struct config_node **cn1,
struct config_node *cn2)
{
if (!*cn1) {
*cn1 = cn2;
cn2->sib = NULL;
} else {
cn2->sib = (*cn1)->sib;
(*cn1)->sib = cn2;
}
}
/*
* 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)
{
struct config_node *cn, *nextn, *oldn;
struct config_value *cv;
for (cn = cn2->child; cn; cn = nextn) {
nextn = cn->sib;
/* Skip "tags" */
if (!strcmp(cn->key, "tags"))
continue;
/* Subsection? */
if (!cn->v)
/* Ignore - we don't have any of these yet */
continue;
/* Not already present? */
if (!(oldn = find_config_node(cn1->child, cn->key))) {
_insert_config_node(&cn1->child, cn);
continue;
}
/* Merge certain value lists */
if ((!strcmp(cn1->key, "activation") &&
!strcmp(cn->key, "volume_list")) ||
(!strcmp(cn1->key, "devices") &&
(!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
cv = cn->v;
while (cv->next)
cv = cv->next;
cv->next = oldn->v;
}
/* Replace values */
oldn->v = cn->v;
}
}
static int _match_host_tags(struct list *tags, struct config_node *tn)
{
struct config_value *tv;
const char *str;
for (tv = tn->v; tv; tv = tv->next) {
if (tv->type != CFG_STRING)
continue;
str = tv->v.str;
if (*str == '@')
str++;
if (!*str)
continue;
if (str_list_match_item(tags, str))
return 1;
}
return 0;
}
/* 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)
{
struct config_node *root = cft->root;
struct config_node *cn, *nextn, *oldn, *tn, *cn2;
for (cn = newdata->root; cn; cn = nextn) {
nextn = cn->sib;
/* Ignore tags section */
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 (!_match_host_tags(&cmd->tags, tn))
continue;
}
if (!(oldn = find_config_node(root, cn->key))) {
_insert_config_node(&cft->root, cn);
/* Remove any "tags" nodes */
for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
if (!strcmp(cn2->key, "tags")) {
cn->child = cn2->sib;
continue;
}
if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
cn2->sib = cn2->sib->sib;
continue;
}
}
continue;
}
_merge_section(oldn, cn);
}
return 1;
}

View File

@ -16,7 +16,8 @@
#ifndef _LVM_CONFIG_H
#define _LVM_CONFIG_H
#include "device.h"
struct device;
struct cmd_context;
enum {
CFG_STRING,
@ -45,42 +46,51 @@ struct config_tree {
struct config_node *root;
};
struct config_tree *create_config_tree(void);
void destroy_config_tree(struct config_tree *cf);
struct config_tree_list {
struct list list;
struct config_tree *cft;
};
struct config_tree *create_config_tree(const char *filename);
void destroy_config_tree(struct config_tree *cft);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
int read_config_fd(struct config_tree *cf, struct device *dev,
int read_config_fd(struct 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 *cf, const char *file);
int write_config_file(struct config_tree *cf, const char *file);
int reload_config_file(struct config_tree **cf);
time_t config_file_timestamp(struct config_tree *cf);
int read_config_file(struct config_tree *cft);
int write_config_file(struct config_tree *cft, const char *file);
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);
struct config_node *find_config_node(struct config_node *cn,
struct config_node *find_config_node(const struct config_node *cn,
const char *path);
const char *find_config_str(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(struct config_node *cn, const char *path, int fail);
int find_config_int(const struct config_node *cn, const char *path, int fail);
float find_config_float(struct config_node *cn, const char *path, float fail);
float find_config_float(const struct config_node *cn, const char *path,
float fail);
/*
* Understands (0, ~0), (y, n), (yes, no), (on,
* off), (true, false).
*/
int find_config_bool(struct config_node *cn, const char *path, int fail);
int find_config_bool(const struct config_node *cn, const char *path, int fail);
int get_config_uint32(struct config_node *cn, const char *path,
int get_config_uint32(const struct config_node *cn, const char *path,
uint32_t *result);
int get_config_uint64(struct config_node *cn, const char *path,
int get_config_uint64(const struct config_node *cn, const char *path,
uint64_t *result);
int get_config_str(struct config_node *cn, const char *path, char **result);
int get_config_str(const struct config_node *cn, const char *path,
char **result);
#endif

View File

@ -48,7 +48,7 @@ static void _destroy(struct dev_filter *f)
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
{
struct dev_filter **filters_copy, *cf;
struct dev_filter **filters_copy, *cft;
if (!filters) {
stack;
@ -63,15 +63,15 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
memcpy(filters_copy, filters, sizeof(*filters) * n);
filters_copy[n] = NULL;
if (!(cf = dbg_malloc(sizeof(*cf)))) {
if (!(cft = dbg_malloc(sizeof(*cft)))) {
log_error("compsoite filters allocation failed");
dbg_free(filters_copy);
return NULL;
}
cf->passes_filter = _and_p;
cf->destroy = _destroy;
cf->private = filters_copy;
cft->passes_filter = _and_p;
cft->destroy = _destroy;
cft->private = filters_copy;
return cf;
return cft;
}

View File

@ -63,7 +63,7 @@ int persistent_filter_wipe(struct dev_filter *f)
static int _read_array(struct pfilter *pf, struct config_tree *cft,
const char *path, void *data)
{
struct config_node *cn;
const struct config_node *cn;
struct config_value *cv;
if (!(cn = find_config_node(cft->root, path))) {
@ -99,12 +99,12 @@ int persistent_filter_load(struct dev_filter *f)
int r = 0;
struct config_tree *cft;
if (!(cft = create_config_tree())) {
if (!(cft = create_config_tree(pf->file))) {
stack;
return 0;
}
if (!read_config_file(cft, pf->file)) {
if (!read_config_file(cft)) {
stack;
goto out;
}

View File

@ -82,7 +82,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
return 1;
}
static int *_scan_proc_dev(const char *proc, struct config_node *cn)
static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
{
char line[80];
char proc_devices[PATH_MAX];
@ -199,7 +199,7 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
}
struct dev_filter *lvm_type_filter_create(const char *proc,
struct config_node *cn)
const struct config_node *cn)
{
struct dev_filter *f;

View File

@ -29,7 +29,7 @@
#endif
struct dev_filter *lvm_type_filter_create(const char *proc,
struct config_node *cn);
const struct config_node *cn);
void lvm_type_filter_destroy(struct dev_filter *f);

View File

@ -49,12 +49,12 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
*desc = NULL;
*when = 0;
if (!(cft = create_config_tree())) {
if (!(cft = create_config_tree(file))) {
stack;
goto out;
}
if ((!dev && !read_config_file(cft, file)) ||
if ((!dev && !read_config_file(cft)) ||
(dev && !read_config_fd(cft, dev, offset, size,
offset2, size2, checksum_fn, checksum))) {
log_error("Couldn't read volume group metadata.");

View File

@ -758,7 +758,7 @@ static int _run_command(struct cmd_context *cmd, int argc, char **argv)
set_cmd_name(cmd->command->name);
if (reload_config_file(&cmd->cft)) {
if (!cmd->config_valid || config_files_changed(cmd)) {
/* Reinitialise various settings inc. logging, filters */
if (!refresh_toolcontext(cmd)) {
log_error("Updated config file invalid. Aborting.");