#define SECTION_MAX_LENGTH 256
#define LINE_MAX_LENGTH 1024
-struct pakfire_config_entry {
- STAILQ_ENTRY(pakfire_config_entry) nodes;
+struct pakfire_config_section {
+ STAILQ_ENTRY(pakfire_config_section) nodes;
// Section name
- char section[SECTION_MAX_LENGTH];
+ char name[SECTION_MAX_LENGTH];
+
+ // Entries
+ STAILQ_HEAD(entries, pakfire_config_entry) entries;
+};
+
+struct pakfire_config_entry {
+ STAILQ_ENTRY(pakfire_config_entry) nodes;
// Key & Value
char key[KEY_MAX_LENGTH];
struct pakfire_config {
int nrefs;
- STAILQ_HEAD(entries, pakfire_config_entry) entries;
+ STAILQ_HEAD(sections, pakfire_config_section) sections;
};
int pakfire_config_create(struct pakfire_config** config) {
c->nrefs = 1;
// Initialise entries
- STAILQ_INIT(&c->entries);
+ STAILQ_INIT(&c->sections);
*config = c;
return 0;
}
-static void pakfire_config_entry_free(struct pakfire_config_entry* entry) {
+static void pakfire_config_free_entry(struct pakfire_config_entry* entry) {
free(entry);
}
+static void pakfire_config_free_section(struct pakfire_config_section* section) {
+ struct pakfire_config_entry* entry = NULL;
+
+ // Free all entries
+ while (!STAILQ_EMPTY(§ion->entries)) {
+ entry = STAILQ_FIRST(§ion->entries);
+ STAILQ_REMOVE_HEAD(§ion->entries, nodes);
+
+ pakfire_config_free_entry(entry);
+ }
+
+ free(section);
+}
+
static 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);
+ struct pakfire_config_section* section = NULL;
+
+ // Free all sections
+ while (!STAILQ_EMPTY(&config->sections)) {
+ section = STAILQ_FIRST(&config->sections);
+ STAILQ_REMOVE_HEAD(&config->sections, nodes);
- pakfire_config_entry_free(entry);
+ pakfire_config_free_section(section);
}
free(config);
return NULL;
}
+static struct pakfire_config_section* pakfire_config_create_section(
+ struct pakfire_config* config, const char* name) {
+ struct pakfire_config_section* section = NULL;
+ int r;
+
+ // Allocate a new section
+ section = calloc(1, sizeof(*section));
+ if (!section)
+ goto ERROR;
+
+ // Initialize entries
+ STAILQ_INIT(§ion->entries);
+
+ // Store name
+ r = pakfire_string_set(section->name, name);
+ if (r)
+ goto ERROR;
+
+ // Append it to the list of sections
+ STAILQ_INSERT_TAIL(&config->sections, section, nodes);
+
+ // Return the section
+ return section;
+
+ERROR:
+ if (section)
+ pakfire_config_free_section(section);
+
+ return NULL;
+}
+
+static struct pakfire_config_section* pakfire_config_get_section(
+ struct pakfire_config* config, const char* name) {
+ struct pakfire_config_section* section = NULL;
+
+ // Find an existing section
+ STAILQ_FOREACH(section, &config->sections, nodes) {
+ if (strcmp(section->name, name) == 0)
+ return section;
+ }
+
+ return NULL;
+}
+
static int pakfire_config_entry_is_multiline(const struct pakfire_config_entry* entry) {
const char* p = strchr(entry->value, '\n');
}
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;
-
+ struct pakfire_config* config, const char* name, const char* key) {
+ struct pakfire_config_section* section = NULL;
+ struct pakfire_config_entry* entry = NULL;
int r;
- // Store section
- r = pakfire_string_set(entry->section, section);
- if (r)
+ // Allocate a new entry
+ entry = calloc(1, sizeof(*entry));
+ if (!entry)
goto ERROR;
// Store key
if (r)
goto ERROR;
+ // Fetch the section
+ section = pakfire_config_get_section(config, name);
+ if (!section) {
+ section = pakfire_config_create_section(config, name);
+ if (!section)
+ goto ERROR;
+ }
+
// Append it to the list of entries
- STAILQ_INSERT_TAIL(&config->entries, entry, nodes);
+ STAILQ_INSERT_TAIL(§ion->entries, entry, nodes);
return entry;
ERROR:
- pakfire_config_entry_free(entry);
+ if (entry)
+ pakfire_config_free_entry(entry);
+
return NULL;
}
static struct pakfire_config_entry* pakfire_config_find(struct pakfire_config* config,
- const char* section, const char* key) {
+ const char* name, const char* key) {
+ struct pakfire_config_section* section = NULL;
struct pakfire_config_entry* entry = NULL;
// Check for valid input
}
// Treat NULL as an empty section
- if (!section)
- section = "";
+ if (!name)
+ name = "";
- 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;
+ // Fetch the section
+ section = pakfire_config_get_section(config, name);
+ if (!section)
+ return NULL;
- // Match!
- return entry;
+ STAILQ_FOREACH(entry, §ion->entries, nodes) {
+ if (strcmp(entry->key, key) == 0)
+ return entry;
}
// No match
return NULL;
}
-static int pakfire_section_in_sections(const char** sections, const char* section) {
- if (!sections)
- return 0;
-
- for (const char** s = sections; *s; s++) {
- if (strcmp(section, *s) == 0)
- return 1;
- }
-
- return 0;
-}
-
-const char** pakfire_config_sections(struct pakfire_config* config) {
- struct pakfire_config_entry* entry = NULL;
+int pakfire_config_walk_sections(struct pakfire_config* config,
+ pakfire_config_walk_callback callback, void* p) {
+ struct pakfire_config_section* default_section = NULL;
+ struct pakfire_config_section* section = NULL;
+ int r = 0;
- const char** sections = NULL;
- size_t num_sections = 0;
+ // Try to fetch the default section
+ default_section = pakfire_config_get_section(config, "");
- STAILQ_FOREACH(entry, &config->entries, nodes) {
- // Skip empty sections
- if (!*entry->section)
- continue;
+ // Run the default section first
+ if (default_section) {
+ r = callback(config, default_section->name, p);
+ if (r)
+ goto ERROR;
+ }
- // Skip if this section is already on the list
- if (pakfire_section_in_sections(sections, entry->section))
+ // Then iterate over all other sections
+ STAILQ_FOREACH(section, &config->sections, nodes) {
+ // Skip the default section
+ if (section == default_section)
continue;
- // Make space in the array
- sections = reallocarray(sections, sizeof(*sections), ++num_sections + 1);
- if (!sections)
- return NULL;
-
- sections[num_sections - 1] = entry->section;
-
- // Terminate the array
- sections[num_sections] = NULL;
+ r = callback(config, section->name, p);
+ if (r)
+ goto ERROR;
}
- return sections;
+ERROR:
+ return r;
}
-int pakfire_config_has_section(struct pakfire_config* config, const char* section) {
- struct pakfire_config_entry* entry = NULL;
+int pakfire_config_has_section(struct pakfire_config* config, const char* name) {
+ struct pakfire_config_section* section = NULL;
- STAILQ_FOREACH(entry, &config->entries, nodes) {
- if (strcmp(entry->section, section) == 0)
- return 1;
- }
+ // Fetch the section
+ section = pakfire_config_get_section(config, name);
+ if (section)
+ return 1;
return 0;
}
}
static int pakfire_config_dump_section(struct pakfire_config* config,
- const char* section, FILE* f) {
+ const char* name, void* p) {
+ struct pakfire_config_section* section = NULL;
struct pakfire_config_entry* entry = NULL;
int r = 0;
+ FILE* f = (FILE*)p;
+
+ // Fetch the section
+ section = pakfire_config_get_section(config, name);
+ if (!section)
+ return -errno;
+
// Print the section name
- if (*section) {
- r = fprintf(f, "\n[%s]\n", section);
+ if (*name) {
+ r = fprintf(f, "\n[%s]\n", name);
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;
- }
+ STAILQ_FOREACH(entry, §ion->entries, nodes) {
+ r = pakfire_config_dump_entry(entry, f);
+ if (r)
+ goto ERROR;
}
// Success
}
int pakfire_config_dump(struct pakfire_config* config, FILE* f) {
- int r;
-
- // Fetch a list of all available sections
- const 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 (const char** section = sections; *section; section++) {
- r = pakfire_config_dump_section(config, *section, f);
- if (r)
- goto ERROR;
- }
- }
-
-ERROR:
- if (sections)
- free(sections);
-
- return r;
+ return pakfire_config_walk_sections(config, pakfire_config_dump_section, f);
}
return r;
}
-int pakfire_repo_import(struct pakfire* pakfire, struct pakfire_config* config) {
- const char** sections = pakfire_config_sections(config);
-
- // The configuration seems to be empty
- if (!sections)
- return 0;
-
+static int __pakfire_repo_import( struct pakfire_config* config, const char* section, void* p) {
+ struct pakfire* pakfire = (struct pakfire*)p;
struct pakfire_repo* repo = NULL;
int r = 0;
- // Walk through all sections
- for (const char** section = sections; *section; section++) {
- // Skip sections that do not start with "repo:"
- if (!pakfire_string_startswith(*section, "repo:"))
- continue;
+ // Ignore if the section does not start with "repo:"
+ if (!pakfire_string_startswith(section, "repo:"))
+ return 0;
- const char* name = (*section) + strlen("repo:");
- if (!*name)
- continue;
+ // Extract the name
+ const char* name = section + strlen("repo:");
- DEBUG(pakfire, "Creating repository %s\n", name);
+ // Skip if the name is empty
+ if (!*name)
+ return 0;
- // Create a new repository
- r = pakfire_repo_create(&repo, pakfire, name);
- if (r) {
- ERROR(pakfire, "Could not create repository '%s': %m\n", name);
- goto ERROR;
- }
+ DEBUG(pakfire, "Creating repository %s\n", name);
- // Enabled
- int enabled = pakfire_config_get_bool(config, *section, "enabled", 1);
- pakfire_repo_set_enabled(repo, enabled);
+ // Create a new repository
+ r = pakfire_repo_create(&repo, pakfire, name);
+ if (r) {
+ ERROR(pakfire, "Could not create repository '%s': %m\n", name);
+ goto ERROR;
+ }
- // Priority
- int priority = pakfire_config_get_int(config, *section, "priority", 0);
- if (priority)
- pakfire_repo_set_priority(repo, priority);
+ // Enabled
+ int enabled = pakfire_config_get_bool(config, section, "enabled", 1);
+ pakfire_repo_set_enabled(repo, enabled);
- // Description
- const char* description = pakfire_config_get(config, *section, "description", NULL);
- if (description)
- pakfire_repo_set_description(repo, description);
+ // Priority
+ int priority = pakfire_config_get_int(config, section, "priority", 0);
+ if (priority)
+ pakfire_repo_set_priority(repo, priority);
- // baseurl
- const char* baseurl = pakfire_config_get(config, *section, "baseurl", NULL);
- if (baseurl) {
- r = pakfire_repo_set_baseurl(repo, baseurl);
- if (r)
- goto ERROR;
- }
+ // Description
+ const char* description = pakfire_config_get(config, section, "description", NULL);
+ if (description)
+ pakfire_repo_set_description(repo, description);
- // Refresh Interval
- const char* refresh = pakfire_config_get(config, *section, "refresh", NULL);
- if (refresh)
- repo->appdata->refresh = pakfire_string_parse_interval(refresh);
+ // baseurl
+ const char* baseurl = pakfire_config_get(config, section, "baseurl", NULL);
+ if (baseurl) {
+ r = pakfire_repo_set_baseurl(repo, baseurl);
+ if (r)
+ goto ERROR;
+ }
- // mirrors
- const char* mirrors = pakfire_config_get(config, *section, "mirrors", NULL);
- if (mirrors)
- pakfire_repo_set_mirrorlist_url(repo, mirrors);
+ // Refresh Interval
+ const char* refresh = pakfire_config_get(config, section, "refresh", NULL);
+ if (refresh)
+ repo->appdata->refresh = pakfire_string_parse_interval(refresh);
- // Key
- const char* key = pakfire_config_get(config, *section, "key", NULL);
- if (key) {
- r = pakfire_repo_import_key(repo, key);
- if (r) {
- pakfire_repo_unref(repo);
- goto ERROR;
- }
- }
+ // mirrors
+ const char* mirrors = pakfire_config_get(config, section, "mirrors", NULL);
+ if (mirrors)
+ pakfire_repo_set_mirrorlist_url(repo, mirrors);
- pakfire_repo_unref(repo);
+ // Key
+ const char* key = pakfire_config_get(config, section, "key", NULL);
+ if (key) {
+ r = pakfire_repo_import_key(repo, key);
+ if (r)
+ goto ERROR;
}
+ERROR:
+ if (repo)
+ pakfire_repo_unref(repo);
+
+ return r;
+}
+
+int pakfire_repo_import(struct pakfire* pakfire, struct pakfire_config* config) {
+ int r;
+
+ // Import all repositories from the configuration
+ r = pakfire_config_walk_sections(config, __pakfire_repo_import, pakfire);
+ if (r)
+ return r;
+
// Refresh repositories
r = pakfire_refresh(pakfire, 0);
if (r)
- goto ERROR;
-
-ERROR:
- if (sections)
- free(sections);
+ return r;
- return r;
+ return 0;
}
Id pakfire_repo_add_solvable(struct pakfire_repo* repo) {