From 2e717c968d86b3b4d4671aea0019ba47e59bcc2c Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 13 Feb 2019 18:00:06 +0100 Subject: [PATCH] Add multipatch capability to osmo-config-merge That's pretty straightforward and convenient extention: handle all extra positional arguments as patch file names. This makes it similar to 'cp' and other coreutils basic tools. For example: osmo-config-merge base.cfg patch1.cfg patch2.cfg patch3.cfg will apply 3 patches to the base config file. Change-Id: I212cbdc3bf6f251c1a3175737ac74242fb004c6d --- utils/osmo-config-merge.c | 66 ++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c index afaf86b53..477bb0289 100644 --- a/utils/osmo-config-merge.c +++ b/utils/osmo-config-merge.c @@ -49,6 +49,7 @@ #include #include #include +#include struct node { struct node *parent; /* back-pointer */ @@ -57,6 +58,11 @@ struct node { char *line; }; +struct osmo_patch_entry { + struct llist_head list; + struct node *tree; +}; + /* allocate a new node */ static struct node *node_alloc(void *ctx) { @@ -225,49 +231,67 @@ static void dump_node(struct node *root, FILE *out, bool print_node_depth) static void exit_usage(int rc) { - fprintf(stderr, "Usage: osmo-config-merge [--debug]\n"); + fprintf(stderr, "Usage: osmo-config-merge ... [--debug]\n"); exit(rc); } int main(int argc, char **argv) { - const char *base_fname, *patch_fname; - struct node *base_tree, *patch_tree; + struct node *base_tree; + struct osmo_config_list *trees; + struct osmo_patch_entry *entry; bool debug_enabled = false; + unsigned i; void *ctx; if (argc < 3) exit_usage(1); - base_fname = argv[1]; - patch_fname = argv[2]; - - if (argc > 3) { - if (!strcmp(argv[3], "--debug")) - debug_enabled = true; - else - exit_usage(1); - } - ctx = talloc_named_const(NULL, 0, "root"); - base_tree = file_read(ctx, base_fname); - patch_tree = file_read(ctx, patch_fname); - - if (!base_tree || ! patch_tree) { + base_tree = file_read(ctx, argv[1]); + trees = talloc_zero(ctx, struct osmo_config_list); + if (!base_tree || !trees) { talloc_free(ctx); return 2; } + INIT_LLIST_HEAD(&trees->entry); + for (i = 2; i < argc; i++) { + if (!strcmp(argv[i], "--debug")) + debug_enabled = true; + else { + entry = talloc_zero(trees, struct osmo_patch_entry); + if (!entry) { + talloc_free(ctx); + return 3; + } + + entry->tree = file_read(ctx, argv[i]); + if (!entry->tree) { + talloc_free(ctx); + return 4; + } + llist_add_tail(&entry->list, &trees->entry); + } + } + + if (llist_empty(&trees->entry)) + exit_usage(1); + if (debug_enabled) { fprintf(stderr, "====== dumping tree (base)\n"); dump_node(base_tree, stderr, true); - fprintf(stderr, "====== dumping tree (patch)\n"); - dump_node(patch_tree, stderr, true); } - append_patch(base_tree, patch_tree); + llist_for_each_entry(entry, &trees->entry, list) { + append_patch(base_tree, entry->tree); + if (debug_enabled) { + fprintf(stderr, "====== dumping tree (patch)\n"); + dump_node(entry->tree, stderr, true); + } + } if (debug_enabled) fprintf(stderr, "====== dumping tree (patched)\n"); @@ -275,7 +299,7 @@ int main(int argc, char **argv) fflush(stdout); /* make AddressSanitizer / LeakSanitizer happy by recursively freeing the trees */ - talloc_free(patch_tree); + talloc_free(trees); talloc_free(base_tree); talloc_free(ctx);