/* * Checks that the config file contains vg metadata, and that it * we recognise the version number, */ static int _check_version(struct config_tree *cft) { struct config_node *cn; struct config_value *cv; /* * Check the contents field. */ if (!(cn = find_config_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)) { _invalid_format("unrecognised contents field"); return 0; } /* * Check the version number. */ if (!(cn = find_config_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) { _invalid_format("unrecognised version number"); return 0; } return 1; }
static int _mirrored_text_import(struct lv_segment *seg, const struct config_node *sn, struct dm_hash_table *pv_hash) { const struct config_node *cn; char *logname = NULL; if (find_config_node(sn, "extents_moved")) { if (get_config_uint32(sn, "extents_moved", &seg->extents_copied)) seg->status |= PVMOVE; else { log_error("Couldn't read 'extents_moved' for " "segment '%s'.", sn->key); return 0; } } if (find_config_node(sn, "region_size")) { if (!get_config_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " "segment '%s'.", sn->key); return 0; } } if ((cn = find_config_node(sn, "mirror_log"))) { if (!cn->v || !cn->v->v.str) { log_error("Mirror log type must be a string."); return 0; } logname = cn->v->v.str; if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) { log_error("Unrecognised mirror log in segment %s.", sn->key); return 0; } seg->log_lv->status |= MIRROR_LOG; } if (logname && !seg->region_size) { log_error("Missing region size for mirror log for segment " "'%s'.", sn->key); return 0; } if (!(cn = find_config_node(sn, "mirrors"))) { log_error("Couldn't find mirrors array for segment " "'%s'.", sn->key); return 0; } return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE); }
static int _read_array(struct pfilter *pf, struct config_tree *cft, const char *path, void *data) { const struct config_node *cn; struct config_value *cv; if (!(cn = find_config_node(cft->root, path))) { log_very_verbose("Couldn't find %s array in '%s'", path, pf->file); return 0; } /* * iterate through the array, adding * devices as we go. */ for (cv = cn->v; cv; cv = cv->next) { if (cv->type != CFG_STRING) { log_verbose("Devices array contains a value " "which is not a string ... ignoring"); continue; } if (!dm_hash_insert(pf->devices, cv->v.str, data)) log_verbose("Couldn't add '%s' to filter ... ignoring", cv->v.str); /* Populate dev_cache ourselves */ dev_cache_get(cv->v.str, NULL); } 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; }
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 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; } return r; }
/* 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) { const struct config_node *root = cft->root; struct config_node *cn, *nextn, *oldn, *cn2; const struct config_node *tn; 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 = (struct config_node *)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; }
static int _read_flag_config(struct config_node *n, uint64_t *status, int type) { struct config_node *cn; *status = 0; if (!(cn = find_config_node(n, "status"))) { log_error("Could not find status flags."); return 0; } if (!(read_flags(status, type | STATUS_FLAG, cn->v))) { log_error("Could not read status flags."); return 0; } if ((cn = find_config_node(n, "flags"))) { if (!(read_flags(status, type, cn->v))) { log_error("Could not read flags."); return 0; } } return 1; }
static int _read_id(struct id *id, struct config_node *cn, const char *path) { struct config_value *cv; if (!(cn = find_config_node(cn, path))) { log_error("Couldn't find uuid."); return 0; } cv = cn->v; if (!cv || !cv->v.str) { log_error("uuid must be a string."); return 0; } if (!id_read_format(id, cv->v.str)) { log_error("Invalid uuid."); return 0; } return 1; }
static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn, struct dm_hash_table *pv_hash) { struct config_node *cn; if ((seg->area_count != 1) && !get_config_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); return 0; } if (!(cn = find_config_node(sn, "stripes"))) { log_error("Couldn't find stripes array for segment %s " "of logical volume %s.", config_parent_name(sn), seg->lv->name); return 0; } seg->area_len /= seg->area_count; return text_import_areas(seg, sn, cn, pv_hash, 0); }
/* * 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 = (struct config_node*)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; } }