/.vscode
/Makefile
/build-aux
+/config.h
+/config.h.in
/intltool-*
/libtool
/missing
/tests/libpakfire/archive
/tests/libpakfire/cgroup
/tests/libpakfire/compress
+/tests/libpakfire/config
/tests/libpakfire/db
/tests/libpakfire/downloader
/tests/libpakfire/execute
.libs
Makefile.in
aclocal.m4
-config.h
-config.h.in
config.log
config.status
configure
src/libpakfire/archive.c \
src/libpakfire/cgroup.c \
src/libpakfire/compress.c \
+ src/libpakfire/config.c \
src/libpakfire/db.c \
src/libpakfire/dist.c \
src/libpakfire/downloader.c \
src/libpakfire/include/pakfire/archive.h \
src/libpakfire/include/pakfire/cgroup.h \
src/libpakfire/include/pakfire/compress.h \
+ src/libpakfire/include/pakfire/config.h \
src/libpakfire/include/pakfire/constants.h \
src/libpakfire/include/pakfire/db.h \
src/libpakfire/include/pakfire/dist.h \
tests/libpakfire/archive \
tests/libpakfire/cgroup \
tests/libpakfire/compress \
+ tests/libpakfire/config \
tests/libpakfire/db \
tests/libpakfire/downloader \
tests/libpakfire/execute \
$(LZMA_LIBS) \
$(ZSTD_LIBS)
+dist_tests_libpakfire_config_SOURCES = \
+ tests/libpakfire/config.c \
+ src/libpakfire/config.c
+
+tests_libpakfire_config_CPPFLAGS = \
+ $(TESTSUITE_CPPFLAGS) \
+ -DPAKFIRE_PRIVATE
+
+tests_libpakfire_config_LDADD = \
+ $(TESTSUITE_LDADD) \
+ $(PAKFIRE_LIBS)
+
tests_libpakfire_db_SOURCES = \
tests/libpakfire/db.c
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2021 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include <pakfire/config.h>
+#include <pakfire/util.h>
+
+struct pakfire_config_entry {
+ STAILQ_ENTRY(pakfire_config_entry) nodes;
+
+ // Section name
+ char section[32];
+
+ // Key & Value
+ char key[32];
+ char value[1024];
+};
+
+struct pakfire_config {
+ STAILQ_HEAD(entries, pakfire_config_entry) entries;
+};
+
+int pakfire_config_create(struct pakfire_config** config) {
+ struct pakfire_config* c = calloc(1, sizeof(*c));
+ if (!c)
+ return ENOMEM;
+
+ // Initialise entries
+ STAILQ_INIT(&c->entries);
+
+ *config = c;
+ return 0;
+}
+
+static void pakfire_config_entry_free(struct pakfire_config_entry* entry) {
+ free(entry);
+}
+
+void pakfire_config_free(struct pakfire_config* config) {
+ while (!STAILQ_EMPTY(&config->entries)) {
+ struct pakfire_config_entry* entry = STAILQ_FIRST(&config->entries);
+ STAILQ_REMOVE_HEAD(&config->entries, nodes);
+
+ pakfire_config_entry_free(entry);
+ }
+
+ free(config);
+}
+
+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));
+ if (!entry)
+ return NULL;
+
+ int r;
+
+ // Store section
+ r = pakfire_string_set(entry->section, section);
+ if (r < 0) {
+ errno = ENOBUFS;
+ goto ERROR;
+ }
+
+ // Store key
+ r = pakfire_string_set(entry->key, key);
+ if (r < 0) {
+ errno = ENOBUFS;
+ goto ERROR;
+ }
+
+ // Append it to the list of entries
+ STAILQ_INSERT_TAIL(&config->entries, entry, nodes);
+
+ return entry;
+
+ERROR:
+ pakfire_config_entry_free(entry);
+ return NULL;
+}
+
+static struct pakfire_config_entry* pakfire_config_find(struct pakfire_config* config,
+ const char* section, const char* key) {
+ struct pakfire_config_entry* entry;
+
+ // Check for valid input
+ if (!section || !key)
+ return NULL;
+
+ STAILQ_FOREACH(entry, &config->entries, nodes) {
+ // Section must match
+ if (strcmp(entry->section, section) != 0)
+ continue;
+
+ // Key must match
+ if (strcmp(entry->key, key) != 0)
+ continue;
+
+ // Match!
+ return entry;
+ }
+
+ // No match
+ return NULL;
+}
+
+int pakfire_config_set(struct pakfire_config* config,
+ const char* section, const char* key, const char* value) {
+ // Check if this entry exists
+ struct pakfire_config_entry* entry = pakfire_config_find(config, section, key);
+
+ // Create a new entry if it doesn't
+ if (!entry) {
+ entry = pakfire_config_create_entry(config, section, key);
+ if (!entry)
+ return ENOMEM;
+ }
+
+ // Store the value
+ int r = pakfire_string_set(entry->value, value);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+const char* pakfire_config_get(struct pakfire_config* config,
+ const char* section, const char* key, const char* _default) {
+ struct pakfire_config_entry* entry = pakfire_config_find(config, section, key);
+
+ // Return the value if set
+ if (entry && *entry->value)
+ return entry->value;
+
+ // Otherwise return the default value
+ return _default;
+}
+
+long int pakfire_config_get_int(struct pakfire_config* config,
+ const char* section, const char* key, long int _default) {
+ struct pakfire_config_entry* entry = pakfire_config_find(config, section, key);
+
+ // Return the value if set
+ if (entry && *entry->value)
+ return strtol(entry->value, NULL, 10);
+
+ // Otherwise return the default value
+ return _default;
+}
+
+int pakfire_config_get_bool(struct pakfire_config* config,
+ const char* section, const char* key, int _default) {
+ struct pakfire_config_entry* entry = pakfire_config_find(config, section, key);
+
+ // Return the value if set
+ if (entry && *entry->value) {
+ static const struct boolean {
+ const char* string;
+ int ret;
+ } booleans[] = {
+ { "true", 1 },
+ { "yes", 1 },
+ { "on", 1 },
+ { "1", 1 },
+ { "false", 1 },
+ { "no", 1 },
+ { "off", 1 },
+ { "0", 1 },
+ { NULL, 0 },
+ };
+
+ for (const struct boolean* boolean = booleans; boolean->string; boolean++) {
+ if (strcmp(entry->value, boolean->string) == 0)
+ return boolean->ret;
+ }
+ }
+
+ // Otherwise return the default value
+ return _default;
+}
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2021 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef PAKFIRE_CONFIG_H
+#define PAKFIRE_CONFIG_H
+
+#ifdef PAKFIRE_PRIVATE
+
+struct pakfire_config;
+
+int pakfire_config_create(struct pakfire_config** config);
+void pakfire_config_free(struct pakfire_config* config);
+
+int pakfire_config_set(struct pakfire_config* config,
+ const char* section, const char* key, const char* value);
+
+const char* pakfire_config_get(struct pakfire_config* config,
+ const char* section, const char* key, const char* _default);
+long int pakfire_config_get_int(struct pakfire_config* config,
+ const char* section, const char* key, long int _default);
+int pakfire_config_get_bool(struct pakfire_config* config,
+ const char* section, const char* key, int _default);
+
+#endif
+
+#endif /* PAKFIRE_CONFIG_H */
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2021 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <pakfire/config.h>
+
+#include "../testsuite.h"
+
+static int test_get_and_set(const struct test* t) {
+ struct pakfire_config* config;
+
+ ASSERT_SUCCESS(pakfire_config_create(&config));
+
+ // Set some values
+ ASSERT_SUCCESS(pakfire_config_set(config, "section1", "A", "1"));
+ ASSERT_SUCCESS(pakfire_config_set(config, "section1", "B", "2"));
+ ASSERT_SUCCESS(pakfire_config_set(config, "section1", "C", "3"));
+
+ // And some more in another section
+ ASSERT_SUCCESS(pakfire_config_set(config, "section2", "A", "1"));
+ ASSERT_SUCCESS(pakfire_config_set(config, "section2", "B", "2"));
+ ASSERT_SUCCESS(pakfire_config_set(config, "section2", "C", "3"));
+
+ // Try reading back the values
+ ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "A", NULL), "1");
+ ASSERT_STRING_EQUALS(pakfire_config_get(config, "section2", "A", NULL), "1");
+
+ // Read other data types
+ ASSERT(pakfire_config_get_int(config, "section1", "A", 0) == 1);
+ ASSERT(pakfire_config_get_int(config, "section1", "B", 0) == 2);
+ ASSERT(pakfire_config_get_int(config, "section1", "C", 0) == 3);
+ ASSERT(pakfire_config_get_bool(config, "section1", "A", 0) == 1);
+ ASSERT(pakfire_config_get_bool(config, "section1", "B", 0) == 0);
+ ASSERT(pakfire_config_get_bool(config, "section1", "C", 0) == 0);
+
+ // Change a value
+ ASSERT_SUCCESS(pakfire_config_set(config, "section1", "A", "ABC"));
+ ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "A", NULL), "ABC");
+
+ // Try to access a non-existant value
+ ASSERT_NULL(pakfire_config_get(config, "section1", "D", NULL));
+
+ // Return default instead of NULL
+ ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "D", "XXX"), "XXX");
+
+ pakfire_config_free(config);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char** argv) {
+ testsuite_add_test(test_get_and_set);
+
+ return testsuite_run();
+}