/** * @file debconf-copydb.c * @brief Allows the user to load template/question from * one database to another */ #include "confmodule.h" #include "configuration.h" #include "frontend.h" #include "database.h" #include "question.h" #include "template.h" #include #include #include #include #include #include #include #include static struct option g_dpc_args[] = { { "help", 0, NULL, 'h' }, { "pattern", 1, NULL, 'p' }, { 0, 0, 0, 0 } }; static void usage(const char *exename) { printf("%s [-h|--help] [-p|--pattern pattern] source-db dest-db\n", exename); printf("\tsource-db, dest-db - config databases to copy from/to\n"); printf("\t-h, --help - this help message\n"); printf("\t-p, --pattern pattern - copy only names matching this pattern\n"); exit(0); } int main(int argc, char **argv) { struct configuration *config; struct template_db *tdb1, *tdb2; struct question_db *db1, *db2; struct question *q; struct template *t; char *configpath1, *configpath2; const char *tdb1name, *tdb2name; char *db1name = 0, *db2name = 0; char *pattern = 0; regex_t pattern_regex; void *iter; int c; bool tdb2_changed = false; setlocale(LC_ALL, ""); while ((c = getopt_long(argc, argv, "hp:", g_dpc_args, NULL)) > 0) { switch (c) { case 'h': usage(argv[0]); break; case 'p': pattern = optarg; break; } } if (optind + 2 > argc) usage(argv[0]); /* always load all translations */ unsetenv("DEBCONF_DROP_TRANSLATIONS"); db1name = argv[optind]; db2name = argv[optind+1]; if (db1name == NULL || db2name == NULL) usage(argv[0]); /* parse the configuration info */ config = config_new(); if (config->read(config, DEBCONFCONFIG) == 0) DIE("Error reading configuration information"); /* find out which template databases to load; fall back to global * default if not configured otherwise */ if (asprintf(&configpath1, "config::instance::%s::template", db1name) == -1) DIE("Out of memory"); tdb1name = config->get(config, configpath1, NULL); if (asprintf(&configpath2, "config::instance::%s::template", db2name) == -1) DIE("Out of memory"); tdb2name = config->get(config, configpath2, NULL); /* initialize database modules */ if ((tdb1 = template_db_new(config, tdb1name)) == 0) DIE("Cannot initialize first DebConf template database"); if ((tdb2 = template_db_new(config, tdb2name)) == 0) DIE("Cannot initialize second DebConf template database"); if ((db1 = question_db_new(config, tdb1, db1name)) == 0) DIE("Cannot initialize first DebConf database"); if ((db2 = question_db_new(config, tdb2, db2name)) == 0) DIE("Cannot initialize second DebConf database"); /* load database */ tdb1->methods.load(tdb1); tdb2->methods.load(tdb2); db1->methods.load(db1); db2->methods.load(db2); /* maybe compile pattern regex */ if (pattern) { int err = regcomp(&pattern_regex, pattern, REG_EXTENDED | REG_NOSUB); if (err != 0) { int errmsgsize = regerror(err, &pattern_regex, NULL, 0); char *errmsg = malloc(errmsgsize); if (errmsg == NULL) DIE("Out of memory"); regerror(err, &pattern_regex, errmsg, errmsgsize); DIE("regcomp: %s", errmsg); } } /* * Iterate through all the questions and put them into db2 */ /* TODO: error checking */ iter = 0; while ((q = db1->methods.iterate(db1, &iter)) != NULL) { if (pattern) { if (regexec(&pattern_regex, q->tag, 0, 0, 0) != 0) goto nextq; } db2->methods.set(db2, q); if ((t = tdb2->methods.get(tdb2, q->template->tag)) == NULL) { /* Must copy the template as well */ t = tdb1->methods.get(tdb1, q->template->tag); tdb2->methods.set(tdb2, t); tdb2_changed = true; } template_deref(t); nextq: question_deref(q); } if (pattern) regfree(&pattern_regex); db2->methods.save(db2); if (tdb2_changed) tdb2->methods.save(tdb2); question_db_delete(db1); question_db_delete(db2); template_db_delete(tdb1); template_db_delete(tdb2); return 0; }