]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Add a simple config file tool
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 16 Apr 2021 12:08:27 +0000 (12:08 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 16 Apr 2021 12:08:27 +0000 (12:08 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
.gitignore
Makefile.am
src/libpakfire/config.c [new file with mode: 0644]
src/libpakfire/include/pakfire/config.h [new file with mode: 0644]
tests/libpakfire/config.c [new file with mode: 0644]

index 8a58e7ac87451787c1b338f5d9744094d0c37fee..915a046b9f07489a9af92bc65c888201cc9ab962 100644 (file)
@@ -1,6 +1,8 @@
 /.vscode
 /Makefile
 /build-aux
+/config.h
+/config.h.in
 /intltool-*
 /libtool
 /missing
@@ -14,6 +16,7 @@
 /tests/libpakfire/archive
 /tests/libpakfire/cgroup
 /tests/libpakfire/compress
+/tests/libpakfire/config
 /tests/libpakfire/db
 /tests/libpakfire/downloader
 /tests/libpakfire/execute
@@ -47,8 +50,6 @@
 .libs
 Makefile.in
 aclocal.m4
-config.h
-config.h.in
 config.log
 config.status
 configure
index 745b14c413f9f84c915e3e28a76ef44eb157b95d..e82b4abb1bb24492af6c396fcf4c92fd04e50402 100644 (file)
@@ -258,6 +258,7 @@ libpakfire_la_SOURCES = \
        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 \
@@ -292,6 +293,7 @@ pkginclude_HEADERS += \
        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 \
@@ -375,6 +377,7 @@ check_PROGRAMS += \
        tests/libpakfire/archive \
        tests/libpakfire/cgroup \
        tests/libpakfire/compress \
+       tests/libpakfire/config \
        tests/libpakfire/db \
        tests/libpakfire/downloader \
        tests/libpakfire/execute \
@@ -448,6 +451,18 @@ tests_libpakfire_compress_LDADD = \
        $(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
 
diff --git a/src/libpakfire/config.c b/src/libpakfire/config.c
new file mode 100644 (file)
index 0000000..1488872
--- /dev/null
@@ -0,0 +1,201 @@
+/*#############################################################################
+#                                                                             #
+# 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;
+}
diff --git a/src/libpakfire/include/pakfire/config.h b/src/libpakfire/include/pakfire/config.h
new file mode 100644 (file)
index 0000000..9edeeb1
--- /dev/null
@@ -0,0 +1,43 @@
+/*#############################################################################
+#                                                                             #
+# 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 */
diff --git a/tests/libpakfire/config.c b/tests/libpakfire/config.c
new file mode 100644 (file)
index 0000000..f4b04ca
--- /dev/null
@@ -0,0 +1,71 @@
+/*#############################################################################
+#                                                                             #
+# 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();
+}