static void test_cascade(void) { struct dm_config_tree *t1 = dm_config_from_string(conf), *t2 = dm_config_from_string(overlay), *tree = dm_config_insert_cascaded_tree(t2, t1); CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "id", "foo"), "yoda-soda")); CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "idt", "foo"), "foo")); CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv0/bb", "foo"), "foo")); CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv1/id", "foo"), "hgfe-dcba")); CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv3/id", "foo"), "dbcd-efgh")); dm_config_destroy(t1); dm_config_destroy(t2); }
static void test_parse(void) { struct dm_config_tree *tree = dm_config_from_string(conf); const struct dm_config_value *value; CU_ASSERT((long) tree); CU_ASSERT(dm_config_has_node(tree->root, "id")); CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes")); CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0")); CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0/id")); CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "id", "foo"), "yada-yada")); CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "idt", "foo"), "foo")); CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/bb", "foo"), "foo")); CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/id", "foo"), "abcd-efgh")); CU_ASSERT(!dm_config_get_uint32(tree->root, "id", NULL)); CU_ASSERT(dm_config_get_uint32(tree->root, "extent_size", NULL)); /* FIXME: Currently everything parses as a list, even if it's not */ // CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL)); // CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL)); CU_ASSERT(dm_config_get_list(tree->root, "flags", &value)); CU_ASSERT(value->next == NULL); /* an empty list */ CU_ASSERT(dm_config_get_list(tree->root, "status", &value)); CU_ASSERT(value->next != NULL); /* a non-empty list */ dm_config_destroy(tree); }
int override_config_tree_from_string(struct cmd_context *cmd, const char *config_settings) { struct dm_config_tree *cft_new; struct config_source *cs = dm_config_get_custom(cmd->cft); /* * Follow this sequence: * CONFIG_STRING -> CONFIG_PROFILE -> CONFIG_FILE/CONFIG_MERGED_FILES */ if (cs->type == CONFIG_STRING) { log_error(INTERNAL_ERROR "override_config_tree_from_string: " "config cascade already contains a string config."); return 0; } if (!(cft_new = dm_config_from_string(config_settings))) { log_error("Failed to set overridden configuration entries."); return 0; } if (!(cs = dm_pool_zalloc(cft_new->mem, sizeof(struct config_source)))) { log_error("Failed to allocate config source."); dm_config_destroy(cft_new); return 0; } cs->type = CONFIG_STRING; dm_config_set_custom(cft_new, cs); cmd->cft = dm_config_insert_cascaded_tree(cft_new, cmd->cft); return 1; }
/* * public interface */ struct dm_config_tree *config_file_open(const char *filename, int keep_open) { struct dm_config_tree *cft = dm_config_create(); struct config_file *cf; if (!cft) return NULL; cf = dm_pool_zalloc(cft->mem, sizeof(struct config_file)); if (!cf) goto fail; cf->timestamp = 0; cf->exists = 0; cf->keep_open = keep_open; dm_config_set_custom(cft, cf); if (filename && !(cf->filename = dm_pool_strdup(cft->mem, filename))) { log_error("Failed to duplicate filename."); goto fail; } return cft; fail: dm_config_destroy(cft); return NULL; }
void config_file_destroy(struct dm_config_tree *cft) { struct config_file *cf = dm_config_get_custom(cft); if (cf && cf->dev) if (!dev_close(cf->dev)) stack; dm_config_destroy(cft); }
struct dm_config_tree *dm_config_from_string(const char *config_settings) { struct dm_config_tree *cft; if (!(cft = dm_config_create())) return_NULL; if (!dm_config_parse(cft, config_settings, config_settings + strlen(config_settings))) { dm_config_destroy(cft); return_NULL; } return cft; }
void config_destroy(struct dm_config_tree *cft) { struct config_source *cs; struct config_file *cf; if (!cft) return; cs = dm_config_get_custom(cft); if ((cs->type == CONFIG_FILE) || (cs->type == CONFIG_PROFILE)) { cf = cs->source.file; if (cf && cf->dev) if (!dev_close(cf->dev)) stack; } dm_config_destroy(cft); }
/* * public interface */ struct dm_config_tree *config_open(config_source_t source, const char *filename, int keep_open) { struct dm_config_tree *cft = dm_config_create(); struct config_source *cs; struct config_file *cf; if (!cft) return NULL; if (!(cs = dm_pool_zalloc(cft->mem, sizeof(struct config_source)))) { log_error("Failed to allocate config source."); goto fail; } if ((source == CONFIG_FILE) || (source == CONFIG_PROFILE)) { if (!(cf = dm_pool_zalloc(cft->mem, sizeof(struct config_file)))) { log_error("Failed to allocate config file."); goto fail; } cf->keep_open = keep_open; if (filename && !(cf->filename = dm_pool_strdup(cft->mem, filename))) { log_error("Failed to duplicate filename."); goto fail; } cs->source.file = cf; } cs->type = source; dm_config_set_custom(cft, cs); return cft; fail: dm_config_destroy(cft); return NULL; }
static void test_clone(void) { struct dm_config_tree *tree = dm_config_from_string(conf); struct dm_config_node *n = dm_config_clone_node(tree, tree->root, 1); const struct dm_config_value *value; /* Check that the nodes are actually distinct. */ CU_ASSERT(n != tree->root); CU_ASSERT(n->sib != tree->root->sib); CU_ASSERT(dm_config_find_node(n, "physical_volumes") != NULL); CU_ASSERT(dm_config_find_node(tree->root, "physical_volumes") != NULL); CU_ASSERT(dm_config_find_node(n, "physical_volumes") != dm_config_find_node(tree->root, "physical_volumes")); CU_ASSERT(dm_config_has_node(n, "id")); CU_ASSERT(dm_config_has_node(n, "physical_volumes")); CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0")); CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0/id")); CU_ASSERT(!strcmp(dm_config_find_str(n, "id", "foo"), "yada-yada")); CU_ASSERT(!strcmp(dm_config_find_str(n, "idt", "foo"), "foo")); CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/bb", "foo"), "foo")); CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/id", "foo"), "abcd-efgh")); CU_ASSERT(!dm_config_get_uint32(n, "id", NULL)); CU_ASSERT(dm_config_get_uint32(n, "extent_size", NULL)); /* FIXME: Currently everything parses as a list, even if it's not */ // CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL)); // CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL)); CU_ASSERT(dm_config_get_list(n, "flags", &value)); CU_ASSERT(value->next == NULL); /* an empty list */ CU_ASSERT(dm_config_get_list(n, "status", &value)); CU_ASSERT(value->next != NULL); /* a non-empty list */ dm_config_destroy(tree); }
int dumpconfig(struct cmd_context *cmd, int argc, char **argv) { const char *file = arg_str_value(cmd, file_ARG, NULL); const char *type = arg_str_value(cmd, configtype_ARG, arg_count(cmd, list_ARG) ? "list" : "current"); struct config_def_tree_spec tree_spec = {0}; struct dm_config_tree *cft = NULL; struct cft_check_handle *cft_check_handle = NULL; struct profile *profile = NULL; int r = ECMD_PROCESSED; tree_spec.cmd = cmd; if (arg_count(cmd, configtype_ARG) && arg_count(cmd, validate_ARG)) { log_error("Only one of --type and --validate permitted."); return EINVALID_CMD_LINE; } if (arg_count(cmd, configtype_ARG) && arg_count(cmd, list_ARG)) { log_error("Only one of --type and --list permitted."); return EINVALID_CMD_LINE; } if (arg_count(cmd, atversion_ARG)) { if (arg_count(cmd, sinceversion_ARG)) { log_error("Only one of --atversion and --sinceversion permitted."); return EINVALID_CMD_LINE; } if (!arg_count(cmd, configtype_ARG) && !arg_count(cmd, list_ARG)) { log_error("--atversion requires --type or --list"); return EINVALID_CMD_LINE; } } else if (arg_count(cmd, sinceversion_ARG)) { if (!arg_count(cmd, configtype_ARG) || strcmp(type, "new")) { log_error("--sinceversion requires --type new"); return EINVALID_CMD_LINE; } } if (arg_count(cmd, ignoreadvanced_ARG)) tree_spec.ignoreadvanced = 1; if (arg_count(cmd, ignoreunsupported_ARG)) { if (arg_count(cmd, showunsupported_ARG)) { log_error("Only one of --ignoreunsupported and --showunsupported permitted."); return EINVALID_CMD_LINE; } tree_spec.ignoreunsupported = 1; } else if (arg_count(cmd, showunsupported_ARG)) { tree_spec.ignoreunsupported = 0; } else if (strcmp(type, "current") && strcmp(type, "diff")) { /* * By default hide unsupported settings * for all display types except "current" * and "diff". */ tree_spec.ignoreunsupported = 1; } if (strcmp(type, "current") && strcmp(type, "diff")) { /* * By default hide deprecated settings * for all display types except "current" * and "diff" unless --showdeprecated is set. * * N.B. Deprecated settings are visible if * --atversion is used with a version that * is lower than the version in which the * setting was deprecated. */ if (!arg_count(cmd, showdeprecated_ARG)) tree_spec.ignoredeprecated = 1; } if (arg_count(cmd, ignorelocal_ARG)) tree_spec.ignorelocal = 1; if (!strcmp(type, "current") || !strcmp(type, "full")) { if (arg_count(cmd, atversion_ARG)) { log_error("--atversion has no effect with --type %s", type); return EINVALID_CMD_LINE; } if ((arg_count(cmd, ignoreunsupported_ARG) || arg_count(cmd, ignoreadvanced_ARG)) && !strcmp(type, "current")) { /* FIXME: allow these even for --type current */ log_error("--ignoreadvanced and --ignoreunsupported has " "no effect with --type current"); return EINVALID_CMD_LINE; } } else if (arg_count(cmd, mergedconfig_ARG)) { log_error("--mergedconfig has no effect without --type current or --type full"); return EINVALID_CMD_LINE; } if (!_get_vsn(cmd, &tree_spec.version)) return EINVALID_CMD_LINE; /* * The profile specified by --profile cmd arg is like --commandprofile, * but it is used just for dumping the profile content and not for * application. */ if (arg_count(cmd, profile_ARG) && (!(profile = add_profile(cmd, arg_str_value(cmd, profile_ARG, NULL), CONFIG_PROFILE_COMMAND)) || !override_config_tree_from_profile(cmd, profile))) { log_error("Failed to load profile %s.", arg_str_value(cmd, profile_ARG, NULL)); return ECMD_FAILED; } /* * Set the 'cft' to work with based on whether we need the plain * config tree or merged config tree cascade if --mergedconfig is used. */ if ((arg_count(cmd, mergedconfig_ARG) || !strcmp(type, "full")) && cmd->cft->cascade) { if (!_merge_config_cascade(cmd, cmd->cft, &cft)) { log_error("Failed to merge configuration."); r = ECMD_FAILED; goto out; } } else cft = cmd->cft; tree_spec.current_cft = cft; if (arg_count(cmd, validate_ARG)) { if (_config_validate(cmd, cft)) { log_print("LVM configuration valid."); goto out; } else { log_error("LVM configuration invalid."); r = ECMD_FAILED; goto out; } } if (!strcmp(type, "list") || arg_count(cmd, list_ARG)) { tree_spec.type = CFG_DEF_TREE_LIST; if (arg_count(cmd, withcomments_ARG)) { log_error("--withcomments has no effect with --type list"); return EINVALID_CMD_LINE; } /* list type does not require status check */ } else if (!strcmp(type, "full")) { tree_spec.type = CFG_DEF_TREE_FULL; if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { r = ECMD_FAILED; goto_out; } } else if (!strcmp(type, "current")) { tree_spec.type = CFG_DEF_TREE_CURRENT; if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { r = ECMD_FAILED; goto_out; } } else if (!strcmp(type, "missing")) { tree_spec.type = CFG_DEF_TREE_MISSING; if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { r = ECMD_FAILED; goto_out; } } else if (!strcmp(type, "default")) { tree_spec.type = CFG_DEF_TREE_DEFAULT; /* default type does not require check status */ } else if (!strcmp(type, "diff")) { tree_spec.type = CFG_DEF_TREE_DIFF; if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { r = ECMD_FAILED; goto_out; } } else if (!strcmp(type, "new")) { tree_spec.type = arg_count(cmd, sinceversion_ARG) ? CFG_DEF_TREE_NEW_SINCE : CFG_DEF_TREE_NEW; /* new type does not require check status */ } else if (!strcmp(type, "profilable")) { tree_spec.type = CFG_DEF_TREE_PROFILABLE; /* profilable type does not require check status */ } else if (!strcmp(type, "profilable-command")) { tree_spec.type = CFG_DEF_TREE_PROFILABLE_CMD; /* profilable-command type does not require check status */ } else if (!strcmp(type, "profilable-metadata")) { tree_spec.type = CFG_DEF_TREE_PROFILABLE_MDA; /* profilable-metadata type does not require check status */ } else { log_error("Incorrect type of configuration specified. " "Expected one of: current, default, diff, full, list, missing, " "new, profilable, profilable-command, profilable-metadata."); r = EINVALID_CMD_LINE; goto out; } if (arg_count(cmd, withsummary_ARG) || arg_count(cmd, list_ARG)) tree_spec.withsummary = 1; if (arg_count(cmd, withcomments_ARG)) tree_spec.withcomments = 1; if (arg_count(cmd, unconfigured_ARG)) tree_spec.unconfigured = 1; if (arg_count(cmd, withversions_ARG)) tree_spec.withversions = 1; if (arg_count(cmd, withspaces_ARG)) tree_spec.withspaces = 1; if (cft_check_handle) tree_spec.check_status = cft_check_handle->status; if ((tree_spec.type != CFG_DEF_TREE_CURRENT) && (tree_spec.type != CFG_DEF_TREE_DIFF) && !(cft = config_def_create_tree(&tree_spec))) { r = ECMD_FAILED; goto_out; } if (!config_write(cft, &tree_spec, file, argc, argv)) { stack; r = ECMD_FAILED; } out: if (tree_spec.current_cft && (tree_spec.current_cft != cft) && (tree_spec.current_cft != cmd->cft)) /* * This happens in case of CFG_DEF_TREE_FULL where we * have merged explicitly defined config trees and also * we have used default tree. */ dm_config_destroy(tree_spec.current_cft); if (cft && (cft != cmd->cft)) dm_config_destroy(cft); else if (profile) remove_config_tree_by_source(cmd, CONFIG_PROFILE_COMMAND); /* * The cmd->cft (the "current" tree) is destroyed * together with cmd context destroy... */ return r; }