From e6c5897a14b31f0f4edb91fc8d314debfe4b57fb Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Tue, 11 Oct 2022 14:37:18 +0000 Subject: [PATCH] config: Dump configuration files Signed-off-by: Michael Tremer --- src/libpakfire/config.c | 120 ++++++++++++++++++++++++ src/libpakfire/include/pakfire/config.h | 2 + tests/libpakfire/config.c | 9 ++ 3 files changed, 131 insertions(+) diff --git a/src/libpakfire/config.c b/src/libpakfire/config.c index a3509a237..2697b48f3 100644 --- a/src/libpakfire/config.c +++ b/src/libpakfire/config.c @@ -94,6 +94,15 @@ struct pakfire_config* pakfire_config_unref(struct pakfire_config* config) { return NULL; } +static int pakfire_config_entry_is_multiline(const struct pakfire_config_entry* entry) { + const char* p = strchr(entry->value, '\n'); + + if (p) + return 1; + + return 0; +} + static struct pakfire_config_entry* pakfire_config_create_entry( struct pakfire_config* config, const char* section, const char* key) { struct pakfire_config_entry* entry = calloc(1, sizeof(*entry)); @@ -451,3 +460,114 @@ ERROR: return r; } + +static int pakfire_config_dump_multiline_entry(struct pakfire_config_entry* entry, FILE* f) { + char* value = NULL; + char* p = NULL; + int r; + + // Write the key line + r = fprintf(f, "%s =\n", entry->key); + if (r <= 0) + goto ERROR; + + // Copy the value + value = strdup(entry->value); + if (!value) { + r = 1; + goto ERROR; + } + + // Write it line by line + char* line = strtok_r(value, "\n", &p); + while (line) { + r = fprintf(f, " %s\n", line); + if (r <= 0) + goto ERROR; + + line = strtok_r(NULL, "\n", &p); + } + + // Success + r = 0; + +ERROR: + if (value) + free(value); + + return r; +} + +static int pakfire_config_dump_entry(struct pakfire_config_entry* entry, FILE* f) { + int r; + + // Handle multiline entries separately + if (pakfire_config_entry_is_multiline(entry)) + return pakfire_config_dump_multiline_entry(entry, f); + + // Write the entry + r = fprintf(f, "%s = %s\n", entry->key, entry->value); + if (r <= 0) + return r; + + return 0; +} + +static int pakfire_config_dump_section(struct pakfire_config* config, + const char* section, FILE* f) { + struct pakfire_config_entry* entry = NULL; + int r = 0; + + // Print the section name + if (*section) { + r = fprintf(f, "\n[%s]\n", section); + if (r <= 0) + goto ERROR; + } + + // Iterate over all entries + STAILQ_FOREACH(entry, &config->entries, nodes) { + // Dump all entries that match this section + if (strcmp(entry->section, section) == 0) { + r = pakfire_config_dump_entry(entry, f); + if (r) + goto ERROR; + } + } + + // Success + r = 0; + +ERROR: + return r; +} + +int pakfire_config_dump(struct pakfire_config* config, FILE* f) { + int r; + + // Fetch a list of all available sections + char** sections = pakfire_config_sections(config); + + // Dump the default section + r = pakfire_config_dump_section(config, "", f); + if (r) + goto ERROR; + + // Dump all sections + if (sections) { + for (char** section = sections; *section; section++) { + r = pakfire_config_dump_section(config, *section, f); + if (r) + goto ERROR; + } + } + +ERROR: + if (sections) { + for (char** section = sections; *section; section++) + free(*section); + free(sections); + } + + return r; +} diff --git a/src/libpakfire/include/pakfire/config.h b/src/libpakfire/include/pakfire/config.h index cad1b5e31..5688c015b 100644 --- a/src/libpakfire/include/pakfire/config.h +++ b/src/libpakfire/include/pakfire/config.h @@ -50,6 +50,8 @@ int pakfire_config_has_section(struct pakfire_config* config, const char* sectio int pakfire_config_read(struct pakfire_config* config, FILE* f); +int pakfire_config_dump(struct pakfire_config* config, FILE* f); + #endif #endif /* PAKFIRE_CONFIG_H */ diff --git a/tests/libpakfire/config.c b/tests/libpakfire/config.c index 8ac2571d9..946fd2ba9 100644 --- a/tests/libpakfire/config.c +++ b/tests/libpakfire/config.c @@ -64,6 +64,9 @@ static int test_get_and_set(const struct test* t) { ASSERT(pakfire_config_has_section(config, "section1")); ASSERT(!pakfire_config_has_section(config, "section3")); + // Dump the configuration file + ASSERT_SUCCESS(pakfire_config_dump(config, stdout)); + // Everything passed r = EXIT_SUCCESS; @@ -99,6 +102,9 @@ static int test_parse(const struct test* t) { ASSERT_SUCCESS(pakfire_config_create(&config)); ASSERT_SUCCESS(pakfire_config_read(config, f)); + // Dump the configuration file + ASSERT_SUCCESS(pakfire_config_dump(config, stdout)); + ASSERT_STRING_EQUALS(pakfire_config_get(config, "", "key1", NULL), "value1"); ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "key1", NULL), "value1"); ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "key2", NULL), "value2"); @@ -162,6 +168,9 @@ static int test_parse_multiline(const struct test* t) { ASSERT_SUCCESS(pakfire_config_create(&config)); ASSERT_SUCCESS(pakfire_config_read(config, f)); + // Dump the configuration file + ASSERT_SUCCESS(pakfire_config_dump(config, stdout)); + ASSERT_STRING_EQUALS(pakfire_config_get(config, "", "key1", NULL), "value1\nvalue2"); ASSERT_STRING_EQUALS(pakfire_config_get(config, "", "key2", NULL), "value1"); -- 2.39.5