From d46646e5abfa9145397e00aa882ac4530589a7c6 Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Mon, 16 Sep 2024 11:37:48 +0200 Subject: [PATCH 1/6] taking own group list --- include/libeconf.h | 2 +- lib/getfilecontents.c | 4 ++-- lib/helpers.c | 33 +++++++++++++++++++++++++++++++-- lib/helpers.h | 4 ++++ lib/keyfile.c | 5 ++--- lib/keyfile.h | 4 ++++ lib/libeconf.c | 12 ++++++++---- lib/mergefiles.c | 1 + lib/readconfig.c | 6 +++++- 9 files changed, 58 insertions(+), 13 deletions(-) diff --git a/include/libeconf.h b/include/libeconf.h index 498a3e3..a25fb29 100644 --- a/include/libeconf.h +++ b/include/libeconf.h @@ -647,7 +647,7 @@ extern econf_err econf_newKeyFile(econf_file **result, char delimiter, char comm * List of directories from which the configuration files have to be parsed. * The list is a string, divides by ":". The last entry has the highest * priority. E.g.: "PARSING_DIRS=/usr/etc/:/run:/etc" - * CONFIG_DIRS (default ) + * CONFIG_DIRS (default \) * List of directory structures (with order) which describes the directories * in which the files have to be parsed. * The list is a string, divides by ":". The last entry has the highest diff --git a/lib/getfilecontents.c b/lib/getfilecontents.c index 7a1a1e2..0d6df84 100644 --- a/lib/getfilecontents.c +++ b/lib/getfilecontents.c @@ -205,9 +205,9 @@ store (econf_file *ef, const char *group, const char *key, ef->file_entry[ef->length-1].quotes = quotes; if (group) - ef->file_entry[ef->length-1].group = strdup(group); + ef->file_entry[ef->length-1].group = setGroupList(ef, group); else - ef->file_entry[ef->length-1].group = strdup(KEY_FILE_NULL_VALUE); + ef->file_entry[ef->length-1].group = setGroupList(ef, KEY_FILE_NULL_VALUE); if (key) { /* remove space at the end of the key */ diff --git a/lib/helpers.c b/lib/helpers.c index d16f6be..ddcaa8b 100644 --- a/lib/helpers.c +++ b/lib/helpers.c @@ -42,7 +42,7 @@ char *combine_strings(const char *string_one, const char *string_two, // Set null value defined in include/defines.h void initialize(econf_file *key_file, size_t num) { - key_file->file_entry[num].group = strdup(KEY_FILE_NULL_VALUE); + key_file->file_entry[num].group = setGroupList(key_file, KEY_FILE_NULL_VALUE); key_file->file_entry[num].key = strdup(KEY_FILE_NULL_VALUE); key_file->file_entry[num].value = strdup(KEY_FILE_NULL_VALUE); key_file->file_entry[num].comment_before_key = NULL; @@ -193,7 +193,7 @@ econf_err setKeyValue(econf_err (*function) (econf_file*, size_t, const void*), struct file_entry cpy_file_entry(struct file_entry fe) { struct file_entry copied_fe; - copied_fe.group = strdup(fe.group); + copied_fe.group = fe.group; copied_fe.key = strdup(fe.key); if (fe.value) copied_fe.value = strdup(fe.value); @@ -211,3 +211,32 @@ struct file_entry cpy_file_entry(struct file_entry fe) { copied_fe.quotes = false; return copied_fe; } + +/* Handle groups in an string array */ +char *getFromGroupList(econf_file *key_file, const char *name) { + char *ret = NULL; + for (int i = 0; i < key_file->group_count; i++) { + if (!strcmp(key_file->groups[i], name)) { + ret = key_file->groups[i]; + i = key_file->group_count; + } + } + return ret; +} + +char *setGroupList(econf_file *key_file, const char *name) { + char *ret = getFromGroupList(key_file, name); + if (ret != NULL) + return ret; + key_file->group_count++; + key_file->groups = + realloc(key_file->groups, (key_file->group_count +1) * sizeof(char *)); + if (key_file->groups == NULL) { + key_file->group_count--; + } else { + key_file->groups[key_file->group_count] = NULL; + key_file->groups[key_file->group_count-1] = strdup(name); + ret = key_file->groups[key_file->group_count-1]; + } + return ret; +} diff --git a/lib/helpers.h b/lib/helpers.h index b4c1674..54665b1 100644 --- a/lib/helpers.h +++ b/lib/helpers.h @@ -70,3 +70,7 @@ econf_err setKeyValue(econf_err (*function) (econf_file*, size_t, const void*), /* Copy the contents of a file_entry struct */ struct file_entry cpy_file_entry(struct file_entry fe); + +/* Handle groups in an string array */ +char *getFromGroupList(econf_file *key_file, const char *name); +char *setGroupList(econf_file *key_file, const char *name); diff --git a/lib/keyfile.c b/lib/keyfile.c index 91f2073..9df53b9 100644 --- a/lib/keyfile.c +++ b/lib/keyfile.c @@ -196,9 +196,8 @@ econf_err getPath(econf_file key_file, char **path) { econf_err setGroup(econf_file *key_file, size_t num, const char *value) { if (key_file == NULL || value == NULL) return ECONF_ERROR; - if (key_file->file_entry[num].group) - free(key_file->file_entry[num].group); - key_file->file_entry[num].group = strdup(value); + + key_file->file_entry[num].group = setGroupList(key_file, value); if (key_file->file_entry[num].group == NULL) return ECONF_NOMEM; diff --git a/lib/keyfile.h b/lib/keyfile.h index a49fbf2..3558f2e 100644 --- a/lib/keyfile.h +++ b/lib/keyfile.h @@ -78,6 +78,10 @@ typedef struct econf_file { char **conf_dirs; int conf_count; + // groups + char **groups; + int group_count; + } econf_file; /* Increases both length and alloc_length of key_file by one and initializes diff --git a/lib/libeconf.c b/lib/libeconf.c index e4a3a03..e01cc96 100644 --- a/lib/libeconf.c +++ b/lib/libeconf.c @@ -115,6 +115,8 @@ econf_newKeyFile(econf_file **result, char delimiter, char comment) key_file->parse_dirs_count = 0; key_file->conf_dirs = NULL; key_file->conf_count = 0; + key_file->groups = NULL; + key_file->group_count = 0; key_file->file_entry = malloc(KEY_FILE_DEFAULT_LENGTH * sizeof(struct file_entry)); if (key_file->file_entry == NULL) { @@ -145,6 +147,9 @@ econf_newKeyFile_with_options(econf_file **result, const char *options) { (*result)->parse_dirs_count = 0; (*result)->conf_dirs = NULL; (*result)->conf_count = 0; + (*result)->groups = NULL; + (*result)->group_count = 0; + if (options == NULL || strlen(options) == 0) return ECONF_SUCCESS; @@ -764,8 +769,9 @@ libeconf_setValue(Bool, const char *, value) void econf_freeArray(char** array) { if (!array) { return; } char *tmp = (char*) array; - while (*array) + while (*array) { free(*array++); + } free(tmp); } @@ -777,8 +783,6 @@ void econf_freeFile(econf_file *key_file) { if (key_file->file_entry) { for (size_t i = 0; i < key_file->alloc_length; i++) { - if (key_file->file_entry[i].group) - free(key_file->file_entry[i].group); if (key_file->file_entry[i].key) free(key_file->file_entry[i].key); if (key_file->file_entry[i].value) @@ -795,6 +799,6 @@ void econf_freeFile(econf_file *key_file) { free(key_file->path); econf_freeArray(key_file->parse_dirs); - + econf_freeArray(key_file->groups); free(key_file); } diff --git a/lib/mergefiles.c b/lib/mergefiles.c index 02eab6c..a0bb6ef 100644 --- a/lib/mergefiles.c +++ b/lib/mergefiles.c @@ -138,6 +138,7 @@ check_conf_dir(econf_file ***key_files, size_t *size, const char *path, key_file->python_style = python_style; error = read_file_with_callback(&key_file, file_path, delim, comment, callback, callback_data); + print_key_file(*key_file); free(file_path); if(!error && key_file) { key_file->on_merge_delete = 1; diff --git a/lib/readconfig.c b/lib/readconfig.c index d859cb2..98e9222 100644 --- a/lib/readconfig.c +++ b/lib/readconfig.c @@ -84,6 +84,8 @@ econf_err readConfigHistoryWithCallback(econf_file ***key_files, } } } + + print_key_file(*key_file); /* create space to store the econf_files for merging */ *size = *size+1; @@ -164,6 +166,7 @@ econf_err readConfigHistoryWithCallback(econf_file ***key_files, *key_files = NULL; return ECONF_NOFILE; } + return ECONF_SUCCESS; } @@ -223,7 +226,8 @@ econf_err readConfigWithCallback(econf_file **result, // Merge the list of acquired key_files into merged_file error = merge_econf_files(key_files, result); free(key_files); - + printf("rrrrrrrrrrrrressult\n"); + print_key_file(**result); return error; } From 7ce1b3a5f95f6d0a82d626baff1f95e92549429d Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Mon, 16 Sep 2024 16:05:10 +0200 Subject: [PATCH 2/6] merging correctly --- lib/helpers.c | 4 ++-- lib/helpers.h | 3 ++- lib/libeconf.c | 8 +++++--- lib/mergefiles.c | 21 +++++++++++---------- lib/mergefiles.h | 7 ++++--- lib/readconfig.c | 5 +---- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/helpers.c b/lib/helpers.c index ddcaa8b..4704119 100644 --- a/lib/helpers.c +++ b/lib/helpers.c @@ -191,9 +191,9 @@ econf_err setKeyValue(econf_err (*function) (econf_file*, size_t, const void*), return function(kf, num, value); } -struct file_entry cpy_file_entry(struct file_entry fe) { +struct file_entry cpy_file_entry(econf_file *dest_kf, struct file_entry fe) { struct file_entry copied_fe; - copied_fe.group = fe.group; + copied_fe.group = setGroupList(dest_kf, fe.group); copied_fe.key = strdup(fe.key); if (fe.value) copied_fe.value = strdup(fe.value); diff --git a/lib/helpers.h b/lib/helpers.h index 54665b1..ffc0980 100644 --- a/lib/helpers.h +++ b/lib/helpers.h @@ -69,7 +69,8 @@ econf_err setKeyValue(econf_err (*function) (econf_file*, size_t, const void*), const void *value); /* Copy the contents of a file_entry struct */ -struct file_entry cpy_file_entry(struct file_entry fe); +/* dest_kf contains the list of group names */ +struct file_entry cpy_file_entry(econf_file *dest_kf, struct file_entry fe); /* Handle groups in an string array */ char *getFromGroupList(econf_file *key_file, const char *name); diff --git a/lib/libeconf.c b/lib/libeconf.c index e01cc96..0e03061 100644 --- a/lib/libeconf.c +++ b/lib/libeconf.c @@ -301,10 +301,12 @@ econf_err econf_mergeFiles(econf_file **merged_file, econf_file *usr_file, econf !strcmp(etc_file->file_entry->group, KEY_FILE_NULL_VALUE)) && (usr_file->file_entry == NULL || strcmp(usr_file->file_entry->group, KEY_FILE_NULL_VALUE))) { - merge_length = insert_nogroup(&fe, etc_file); + merge_length = insert_nogroup(*merged_file, &fe, etc_file); } - merge_length = merge_existing_groups(&fe, usr_file, etc_file, merge_length); - merge_length = add_new_groups(&fe, usr_file, etc_file, merge_length); + merge_length = merge_existing_groups(*merged_file,&fe, usr_file, + etc_file, merge_length); + merge_length = add_new_groups(*merged_file, &fe, usr_file, + etc_file, merge_length); (*merged_file)->length = merge_length; (*merged_file)->alloc_length = merge_length; diff --git a/lib/mergefiles.c b/lib/mergefiles.c index a0bb6ef..bdf56d7 100644 --- a/lib/mergefiles.c +++ b/lib/mergefiles.c @@ -35,12 +35,13 @@ // Insert the content of "etc_file.file_entry" into "fe" if there is no // group specified -size_t insert_nogroup(struct file_entry **fe, econf_file *ef) { +size_t insert_nogroup(econf_file *dest_kf, struct file_entry **fe, + econf_file *ef) { size_t etc_start = 0; if (ef) { while (etc_start < ef->length && !strcmp(ef->file_entry[etc_start].group, KEY_FILE_NULL_VALUE)) { - (*fe)[etc_start] = cpy_file_entry(ef->file_entry[etc_start]); + (*fe)[etc_start] = cpy_file_entry(dest_kf, ef->file_entry[etc_start]); etc_start++; } } @@ -49,8 +50,8 @@ size_t insert_nogroup(struct file_entry **fe, econf_file *ef) { // Merge contents from existing usr_file groups // uf: usr_file, ef: etc_file -size_t merge_existing_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, - const size_t etc_start) { +size_t merge_existing_groups(econf_file *dest_kf, struct file_entry **fe, econf_file *uf, + econf_file *ef, const size_t etc_start) { bool new_key; size_t merge_length = etc_start, tmp = etc_start, added_keys = etc_start; if (uf && ef) { @@ -73,7 +74,7 @@ size_t merge_existing_groups(struct file_entry **fe, econf_file *uf, econf_file } // If a new key is found for an existing group append it to the group if (new_key) - (*fe)[i + added_keys++] = cpy_file_entry(ef->file_entry[j]); + (*fe)[i + added_keys++] = cpy_file_entry(dest_kf, ef->file_entry[j]); } } merge_length = i + added_keys; @@ -81,15 +82,16 @@ size_t merge_existing_groups(struct file_entry **fe, econf_file *uf, econf_file tmp = added_keys; } if (i != uf->length) - (*fe)[i + added_keys] = cpy_file_entry(uf->file_entry[i]); + (*fe)[i + added_keys] = cpy_file_entry(dest_kf, uf->file_entry[i]); } } return merge_length; } // Add entries from etc_file exclusive groups -size_t add_new_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, - const size_t merge_length) { +size_t add_new_groups(econf_file *dest_kf, struct file_entry **fe, + econf_file *uf, econf_file *ef, + const size_t merge_length) { size_t added_keys = merge_length; bool new_key; if (uf && ef) { @@ -104,7 +106,7 @@ size_t add_new_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, } } if (new_key) - (*fe)[added_keys++] = cpy_file_entry(ef->file_entry[i]); + (*fe)[added_keys++] = cpy_file_entry(dest_kf, ef->file_entry[i]); } *fe = realloc(*fe, added_keys * sizeof(struct file_entry)); } @@ -138,7 +140,6 @@ check_conf_dir(econf_file ***key_files, size_t *size, const char *path, key_file->python_style = python_style; error = read_file_with_callback(&key_file, file_path, delim, comment, callback, callback_data); - print_key_file(*key_file); free(file_path); if(!error && key_file) { key_file->on_merge_delete = 1; diff --git a/lib/mergefiles.h b/lib/mergefiles.h index b0354e5..222537c 100644 --- a/lib/mergefiles.h +++ b/lib/mergefiles.h @@ -33,14 +33,15 @@ /* Insert the content of "etc_file.file_entry" into "fe" if there is no group specified. */ -size_t insert_nogroup(struct file_entry **fe, econf_file *ef); +size_t insert_nogroup(econf_file *dest_kf, struct file_entry **fe, econf_file *ef); /* Merge contents from existing usr_file groups */ -size_t merge_existing_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, +size_t merge_existing_groups(econf_file *dest_kf, struct file_entry **fe, econf_file *uf, econf_file *ef, const size_t etc_start); /* Add entries from etc_file exclusive groups */ -size_t add_new_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, +size_t add_new_groups(econf_file *dest_kf, struct file_entry **fe, + econf_file *uf, econf_file *ef, const size_t merge_length); /* Returns the default dirs to iterate through when merging */ diff --git a/lib/readconfig.c b/lib/readconfig.c index 98e9222..72c249f 100644 --- a/lib/readconfig.c +++ b/lib/readconfig.c @@ -84,8 +84,6 @@ econf_err readConfigHistoryWithCallback(econf_file ***key_files, } } } - - print_key_file(*key_file); /* create space to store the econf_files for merging */ *size = *size+1; @@ -226,8 +224,7 @@ econf_err readConfigWithCallback(econf_file **result, // Merge the list of acquired key_files into merged_file error = merge_econf_files(key_files, result); free(key_files); - printf("rrrrrrrrrrrrressult\n"); - print_key_file(**result); + return error; } From ffc80dee06a9f59f24f7b932528b737e06ad5bf5 Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Tue, 17 Sep 2024 09:33:36 +0200 Subject: [PATCH 3/6] fixed getGroups --- lib/getfilecontents.c | 6 +- lib/libeconf.c | 51 +++++---------- tests/meson.build | 5 +- tests/tst-groups5-data/groups.conf | 1 + tests/tst-groups5.c | 55 ++++++++++++++++ tests/tst-groups6-data/groups.conf | 10 +++ tests/tst-groups6.c | 102 +++++++++++++++++++++++++++++ 7 files changed, 188 insertions(+), 42 deletions(-) create mode 100644 tests/tst-groups5-data/groups.conf create mode 100644 tests/tst-groups5.c create mode 100644 tests/tst-groups6-data/groups.conf create mode 100644 tests/tst-groups6.c diff --git a/lib/getfilecontents.c b/lib/getfilecontents.c index 0d6df84..29e1b46 100644 --- a/lib/getfilecontents.c +++ b/lib/getfilecontents.c @@ -453,9 +453,7 @@ read_file(econf_file *ef, const char *file, retval = ECONF_EMPTY_SECTION_NAME; goto out; } - if (current_group) - free (current_group); - current_group = strdup (name); + current_group = setGroupList(ef, name); continue; } @@ -633,8 +631,6 @@ read_file(econf_file *ef, const char *file, out: free(buf); fclose (kf); - if (current_group) - free (current_group); if (current_comment_before_key) free(current_comment_before_key); if (current_comment_after_value) diff --git a/lib/libeconf.c b/lib/libeconf.c index 0e03061..4f46c24 100644 --- a/lib/libeconf.c +++ b/lib/libeconf.c @@ -618,52 +618,32 @@ extern char *econf_getPath(econf_file *kf) } /* GETTER FUNCTIONS */ -// TODO: Currently only works with a sorted econf_file. If a new -// key with an existing group is appended at the end the group -// will show twice. So the key file either needs to be sorted -// upon entering a new key or the function must ensure only -// unique values are returned. econf_err econf_getGroups(econf_file *kf, size_t *length, char ***groups) { if (!kf || groups == NULL) return ECONF_ERROR; - size_t tmp = 0; - bool *uniques = calloc(kf->length,sizeof(bool)); - if (uniques == NULL) - return ECONF_NOMEM; - - for (size_t i = 0; i < kf->length; i++) { - if ((!i || strcmp(kf->file_entry[i].group, kf->file_entry[i - 1].group)) && - strcmp(kf->file_entry[i].group, KEY_FILE_NULL_VALUE)) { - uniques[i] = 1; - tmp++; - } - } - if (!tmp) { - free(uniques); + if (kf->group_count <= 0) return ECONF_NOGROUP; + *groups = NULL; + *length = 0; + for (int i = 0; i < kf->group_count; i++) { + if (strcmp(kf->groups[i], KEY_FILE_NULL_VALUE)) { + (*length)++; + *groups = realloc(*groups, (*length +1) * sizeof(char *)); + if (*groups == NULL) + return ECONF_NOMEM; + (*groups)[*length] = NULL; + (*groups)[*length-1] = strdup(kf->groups[i]); + if ((*groups)[*length-1] == NULL) + return ECONF_NOMEM; + } } - *groups = calloc(tmp + 1, sizeof(char*)); - if (*groups == NULL) { - free(uniques); - return ECONF_NOMEM; - } - - tmp = 0; - for (size_t i = 0; i < kf->length; i++) - if (uniques[i]) - (*groups)[tmp++] = strdup(kf->file_entry[i].group); - if (length != NULL) - *length = tmp; - - free(uniques); return ECONF_SUCCESS; } -// TODO: Same issue as with getGroups() econf_err econf_getKeys(econf_file *kf, const char *grp, size_t *length, char ***keys) { @@ -684,8 +664,7 @@ econf_getKeys(econf_file *kf, const char *grp, size_t *length, char ***keys) return ECONF_NOMEM; } for (size_t i = 0; i < kf->length; i++) { - if (!strcmp(kf->file_entry[i].group, group) && - (!i || strcmp(kf->file_entry[i].key, kf->file_entry[i - 1].key))) { + if (!strcmp(kf->file_entry[i].group, group)) { uniques[i] = 1; tmp++; } diff --git a/tests/meson.build b/tests/meson.build index b147a72..768a69d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -181,7 +181,10 @@ tst_groups3_exe = executable('tst-groups3', 'tst-groups3.c', c_args: test_args, test('tst-groups3', tst_groups3_exe) tst_groups4_exe = executable('tst-groups4', 'tst-groups4.c', c_args: test_args, dependencies : libeconf_dep) test('tst-groups4', tst_groups4_exe) - +tst_groups5_exe = executable('tst-groups5', 'tst-groups5.c', c_args: test_args, dependencies : libeconf_dep) +test('tst-groups5', tst_groups5_exe) +tst_groups6_exe = executable('tst-groups6', 'tst-groups6.c', c_args: test_args, dependencies : libeconf_dep) +test('tst-groups6', tst_groups6_exe) tst_parseconfig1_exe = executable('tst-parseconfig1', 'tst-parseconfig1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-parseconfig1', tst_parseconfig1_exe) diff --git a/tests/tst-groups5-data/groups.conf b/tests/tst-groups5-data/groups.conf new file mode 100644 index 0000000..20ea016 --- /dev/null +++ b/tests/tst-groups5-data/groups.conf @@ -0,0 +1 @@ +[global] \ No newline at end of file diff --git a/tests/tst-groups5.c b/tests/tst-groups5.c new file mode 100644 index 0000000..af9198b --- /dev/null +++ b/tests/tst-groups5.c @@ -0,0 +1,55 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "libeconf.h" + +/* Test case: + Open file with one empty group entry and list it. +*/ + +int +main(void) +{ + econf_file *key_file = (econf_file *)-1; + char **groups; + size_t group_number; + econf_err error; + int retval = 0; + + if ((error = econf_readFile (&key_file, TESTSDIR"tst-groups5-data/groups.conf", "=", "#"))) + { + fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); + return 1; + } + + if ((error = econf_getGroups(key_file, &group_number, &groups))) + { + fprintf (stderr, "Error getting all groups: %s\n", econf_errString(error)); + econf_free (key_file); + return 1; + } + if (group_number == 0) + { + fprintf (stderr, "No groups found?\n"); + econf_free (key_file); + return 1; + } + if (group_number != 1) + { + fprintf (stderr, "Wrong number of groups found, got %zu, expected 1\n", + group_number); + retval = 1; + } + printf ("Found the following groups:\n"); + for (size_t i = 0; i < group_number; i++) + printf ("%zu: %s\n", i, groups[i]); + + econf_free (groups); + econf_free (key_file); + + return retval; +} diff --git a/tests/tst-groups6-data/groups.conf b/tests/tst-groups6-data/groups.conf new file mode 100644 index 0000000..75f84ce --- /dev/null +++ b/tests/tst-groups6-data/groups.conf @@ -0,0 +1,10 @@ +[section1] +key=yes +key1=no +key2=yes + +[section2] +key=yes + +[section3] +key=yes diff --git a/tests/tst-groups6.c b/tests/tst-groups6.c new file mode 100644 index 0000000..e720e00 --- /dev/null +++ b/tests/tst-groups6.c @@ -0,0 +1,102 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "libeconf.h" + +/* Test case: + Open file and read all group entries and list them. +*/ + +int +main(void) +{ + econf_file *key_file = (econf_file *)-1; + char **groups; + size_t group_number; + char *val; + econf_err error; + int retval = 0; + + if ((error = econf_readFile (&key_file, TESTSDIR"tst-groups6-data/groups.conf", "=", "#"))) + { + fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); + return 1; + } + + if ((error = econf_getGroups(key_file, &group_number, &groups))) + { + fprintf (stderr, "Error getting all groups: %s\n", econf_errString(error)); + econf_free (key_file); + return 1; + } + + if (group_number == 0) + { + fprintf (stderr, "No groups found?\n"); + econf_free (key_file); + return 1; + } + + if (group_number != 3) + { + fprintf (stderr, "Wrong number of groups found, got %zu, expected 3\n", + group_number); + retval = 1; + } + + printf ("Found the following groups:\n"); + for (size_t i = 0; i < group_number; i++) + printf ("%zu: %s\n", i, groups[i]); + + /* Try to get the key for each group and check, it is the correct one */ + for (size_t i = 0; i < group_number; i++) + { + char **keys; + size_t key_number; + + error = econf_getKeys (key_file, groups[i], &key_number, &keys); + if (error) + { + fprintf (stderr, "Error getting all keys for [%s]: %s\n", + groups[i], econf_errString(error)); + retval = 1; + } + else + { + for (size_t j = 0; j < key_number; j++) + { + if ((error = econf_getStringValue (key_file, groups[i], keys[j], &val))) + { + fprintf (stderr, "Error reading \"%s\" from [%s]: %s\n", + keys[j], groups[i], econf_errString(error)); + retval = 1; + } + + printf ("%zu: Group: %s, Key: %s, Value: %s\n", j, groups[i], keys[j], val); + free (val); + } + econf_free (keys); + } + + if ((error = econf_getStringValue (key_file, groups[i], "key", &val))) + { + fprintf (stderr, "Error getting key for group '%s': %s\n", + groups[i], econf_errString(error)); + retval = 1; + } + else + { + printf ("Key: key, Group: %s, Value: %s\n", groups[i], val); + free (val); + } + } + + econf_free (groups); + econf_free (key_file); + + return retval; +} From 28a19e6cbff4f651c8f27ace1a82a58432e9be33 Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Tue, 17 Sep 2024 11:30:11 +0200 Subject: [PATCH 4/6] adapted tests --- tests/tst-groups6.c | 73 +++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/tests/tst-groups6.c b/tests/tst-groups6.c index e720e00..01c0972 100644 --- a/tests/tst-groups6.c +++ b/tests/tst-groups6.c @@ -11,13 +11,43 @@ Open file and read all group entries and list them. */ +static int +check_key(econf_file *key_file, char *group, char *key, char *expected_val) +{ + char *val = NULL; + econf_err error = econf_getStringValue (key_file, group, key, &val); + + if (expected_val == NULL) + { + if (val == NULL) + return 0; + + fprintf (stderr, "ERROR: %s/%s has value \"%s\"\n", group, key, val); + return 1; + } + if (val == NULL || strlen(val) == 0) + { + fprintf (stderr, "ERROR: %s/%s returns nothing! (%s)\n", group, key, + econf_errString(error)); + return 1; + } + if (strcmp (val, expected_val) != 0) + { + fprintf (stderr, "ERROR: %s/%s is not \"%s\"\n", group, key, expected_val); + return 1; + } + + printf("Ok: %s/%s=%s\n", group, key, val); + free (val); + return 0; +} + int main(void) { econf_file *key_file = (econf_file *)-1; char **groups; size_t group_number; - char *val; econf_err error; int retval = 0; @@ -67,33 +97,24 @@ main(void) } else { - for (size_t j = 0; j < key_number; j++) - { - if ((error = econf_getStringValue (key_file, groups[i], keys[j], &val))) - { - fprintf (stderr, "Error reading \"%s\" from [%s]: %s\n", - keys[j], groups[i], econf_errString(error)); - retval = 1; - } - - printf ("%zu: Group: %s, Key: %s, Value: %s\n", j, groups[i], keys[j], val); - free (val); - } - econf_free (keys); - } - - if ((error = econf_getStringValue (key_file, groups[i], "key", &val))) - { - fprintf (stderr, "Error getting key for group '%s': %s\n", - groups[i], econf_errString(error)); - retval = 1; - } - else - { - printf ("Key: key, Group: %s, Value: %s\n", groups[i], val); - free (val); + if (!strcmp("section1", groups[i]) && key_number != 3 ) { + fprintf (stderr, "Wrong number of keys found for group %s, got %zu, expected 3\n", + groups[i], key_number); + retval = 1; + } + if ((!strcmp("section1", groups[i]) || !strcmp("section1", groups[i])) && key_number != 3 ) { + fprintf (stderr, "Wrong number of keys found for group %s, got %zu, expected 1\n", + groups[i], key_number); + retval = 1; + } } } + if (check_key(key_file, "section1", "key", "yes") != 0 || + check_key(key_file, "section1", "key1", "no") != 0 || + check_key(key_file, "section1", "key2", "yes") != 0 || + check_key(key_file, "section2", "key", "yes") != 0 || + check_key(key_file, "section3", "key", "yes")) + return 1; econf_free (groups); econf_free (key_file); From 9ad62288b3c83b1ceecaa7d9a5b10eef08c4b57c Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Tue, 17 Sep 2024 15:53:49 +0200 Subject: [PATCH 5/6] handling NULL for /etc and /usr/etc directory --- lib/libeconf.c | 44 +++++++++++++----- tests/meson.build | 3 ++ tests/tst-getconfdirs9.c | 97 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 tests/tst-getconfdirs9.c diff --git a/lib/libeconf.c b/lib/libeconf.c index 4f46c24..820ac22 100644 --- a/lib/libeconf.c +++ b/lib/libeconf.c @@ -428,12 +428,18 @@ econf_err econf_readDirsHistoryWithCallback(econf_file ***key_files, int count = 2; char **parse_dirs = calloc(count+1, sizeof(char *)); parse_dirs[count] = NULL; - parse_dirs[0] = strdup(dist_conf_dir); - parse_dirs[1] = strdup(etc_conf_dir); + if (dist_conf_dir) + parse_dirs[0] = strdup(dist_conf_dir); + else + parse_dirs[0] = strdup(""); + if (etc_conf_dir) + parse_dirs[1] = strdup(etc_conf_dir); + else + parse_dirs[1] = strdup(""); econf_err ret = readConfigHistoryWithCallback(key_files, size, - parse_dirs, 2, + parse_dirs, count, config_name, config_suffix, delim, @@ -458,11 +464,17 @@ econf_err econf_readDirsHistory(econf_file ***key_files, int count = 2; char **parse_dirs = calloc(count+1, sizeof(char *)); parse_dirs[count] = NULL; - parse_dirs[0] = strdup(dist_conf_dir); - parse_dirs[1] = strdup(etc_conf_dir); + if (dist_conf_dir) + parse_dirs[0] = strdup(dist_conf_dir); + else + parse_dirs[0] = strdup(""); + if (etc_conf_dir) + parse_dirs[1] = strdup(etc_conf_dir); + else + parse_dirs[1] = strdup(""); econf_err ret = readConfigHistoryWithCallback(key_files, size, - parse_dirs, 2, + parse_dirs, count, config_name, config_suffix, delim, comment, false, false, /*join_same_entries, python_style*/ @@ -489,8 +501,14 @@ econf_err econf_readDirsWithCallback(econf_file **result, (*result)->parse_dirs_count = 2; (*result)->parse_dirs = calloc((*result)->parse_dirs_count+1, sizeof(char *)); (*result)->parse_dirs[(*result)->parse_dirs_count] = NULL; - (*result)->parse_dirs[0] = strdup(dist_conf_dir); - (*result)->parse_dirs[1] = strdup(etc_conf_dir); + if (dist_conf_dir) + (*result)->parse_dirs[0] = strdup(dist_conf_dir); + else + (*result)->parse_dirs[0] = strdup(""); + if (etc_conf_dir) + (*result)->parse_dirs[1] = strdup(etc_conf_dir); + else + (*result)->parse_dirs[1] = strdup(""); return readConfigWithCallback(result, config_name, @@ -514,8 +532,14 @@ econf_err econf_readDirs(econf_file **result, (*result)->parse_dirs_count = 2; (*result)->parse_dirs = calloc((*result)->parse_dirs_count+1, sizeof(char *)); (*result)->parse_dirs[(*result)->parse_dirs_count] = NULL; - (*result)->parse_dirs[0] = strdup(dist_conf_dir); - (*result)->parse_dirs[1] = strdup(etc_conf_dir); + if (dist_conf_dir) + (*result)->parse_dirs[0] = strdup(dist_conf_dir); + else + (*result)->parse_dirs[0] = strdup(""); + if (etc_conf_dir) + (*result)->parse_dirs[1] = strdup(etc_conf_dir); + else + (*result)->parse_dirs[1] = strdup(""); return readConfigWithCallback(result, config_name, diff --git a/tests/meson.build b/tests/meson.build index 768a69d..8a48d5a 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -84,6 +84,9 @@ tst_getconfdirs7_exe = executable('tst-getconfdirs7', 'tst-getconfdirs7.c', c_ar test('tst-getconfdirs7', tst_getconfdirs7_exe) tst_getconfdirs8_exe = executable('tst-getconfdirs8', 'tst-getconfdirs8.c', c_args: ['-DSUFFIX="conf"', test_args], dependencies : libeconf_dep) test('tst-getconfdirs8', tst_getconfdirs8_exe) +tst_getconfdirs9_exe = executable('tst-getconfdirs9', 'tst-getconfdirs9.c', c_args: ['-DSUFFIX="conf"', test_args], dependencies : libeconf_dep) +test('tst-getconfdirs9', tst_getconfdirs9_exe) + tst_man_dir_exe = executable('tst-man-dir', 'tst-man-dir.c', c_args: test_args, dependencies : libeconf_dep) test('tst-man-dir', tst_man_dir_exe) diff --git a/tests/tst-getconfdirs9.c b/tests/tst-getconfdirs9.c new file mode 100644 index 0000000..d026349 --- /dev/null +++ b/tests/tst-getconfdirs9.c @@ -0,0 +1,97 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "libeconf.h" + +/* Test case: + Test if either /etc or /usr/etc directory has not been defined. + +*/ + +static int +check_key(econf_file *key_file, char *key, char *expected_val) +{ + char *val = NULL; + econf_err error = econf_getStringValue (key_file, "", key, &val); + if (expected_val == NULL) + { + if (val == NULL) + return 0; + + fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); + return 1; + } + if (val == NULL || strlen(val) == 0) + { + fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, + econf_errString(error)); + return 1; + } + if (strcmp (val, expected_val) != 0) + { + fprintf (stderr, "ERROR: %s is not \"%s\"\n", key, expected_val); + return 1; + } + + printf("Ok: %s=%s\n", key, val); + free (val); + return 0; +} + +int +main(void) +{ + econf_file *key_file = (econf_file *)-1; + int retval = 0; + econf_err error; + + error = econf_readDirs (&key_file, + NULL, + TESTSDIR"tst-getconfdirs1-data/etc", + "getconfdir", SUFFIX, "=", "#"); + if (error) + { + fprintf (stderr, "ERROR: econf_readDirs: %s\n", + econf_errString(error)); + return 1; + } + + if (check_key(key_file, "KEY1", "etcconfd") != 0) + retval = 1; + if (check_key(key_file, "USRETC", NULL) != 0) + retval = 1; + if (check_key(key_file, "ETC", "true") != 0) + retval = 1; + if (check_key(key_file, "OVERRIDE", "true") != 0) + retval = 1; + + econf_free (key_file); + + error = econf_readDirs (&key_file, + TESTSDIR"tst-getconfdirs1-data/usr/etc", + NULL, + "getconfdir", SUFFIX, "=", "#"); + if (error) + { + fprintf (stderr, "ERROR: econf_readDirs: %s\n", + econf_errString(error)); + return 1; + } + + if (check_key(key_file, "KEY1", "usretc") != 0) + retval = 1; + if (check_key(key_file, "USRETC", "true") != 0) + retval = 1; + if (check_key(key_file, "ETC", NULL) != 0) + retval = 1; + if (check_key(key_file, "OVERRIDE", NULL) != 0) + retval = 1; + + econf_free (key_file); + + return retval; +} From d6904e6305bead3550c0224bb811b973937ff149 Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Wed, 18 Sep 2024 09:27:53 +0200 Subject: [PATCH 6/6] added man links --- doc/man/econf_comment_tag.3 | 1 + doc/man/econf_delimiter_tag.3 | 1 + doc/man/econf_errLocation.3 | 1 + doc/man/econf_errString.3 | 1 + doc/man/econf_freeArray.3 | 1 + doc/man/econf_freeExtValue.3 | 1 + doc/man/econf_freeFile.3 | 1 + doc/man/econf_getBoolValue.3 | 1 + doc/man/econf_getExtValue.3 | 1 + doc/man/econf_getFloatValue.3 | 1 + doc/man/econf_getGroups.3 | 1 + doc/man/econf_getIntValue.3 | 1 + doc/man/econf_getKeys.3 | 1 + doc/man/econf_getPath.3 | 1 + doc/man/econf_getStringValue.3 | 1 + doc/man/econf_mergeFiles.3 | 1 + doc/man/econf_newIniFile.3 | 1 + doc/man/econf_newKeyFile.3 | 1 + doc/man/econf_readConfig.3 | 1 + doc/man/econf_readConfigWithCallback.3 | 1 + doc/man/econf_readFile.3 | 1 + doc/man/econf_readFileWithCallback.3 | 1 + doc/man/econf_setBoolValue.3 | 1 + doc/man/econf_setFloatValue.3 | 1 + doc/man/econf_setIntValue.3 | 1 + doc/man/econf_setStringValue.3 | 1 + doc/man/econf_set_comment_tag.3 | 1 + doc/man/econf_set_conf_dirs.3 | 1 + doc/man/econf_set_delimiter_tag.3 | 1 + doc/man/econf_writeFile.3 | 1 + 30 files changed, 30 insertions(+) create mode 100644 doc/man/econf_comment_tag.3 create mode 100644 doc/man/econf_delimiter_tag.3 create mode 100644 doc/man/econf_errLocation.3 create mode 100644 doc/man/econf_errString.3 create mode 100644 doc/man/econf_freeArray.3 create mode 100644 doc/man/econf_freeExtValue.3 create mode 100644 doc/man/econf_freeFile.3 create mode 100644 doc/man/econf_getBoolValue.3 create mode 100644 doc/man/econf_getExtValue.3 create mode 100644 doc/man/econf_getFloatValue.3 create mode 100644 doc/man/econf_getGroups.3 create mode 100644 doc/man/econf_getIntValue.3 create mode 100644 doc/man/econf_getKeys.3 create mode 100644 doc/man/econf_getPath.3 create mode 100644 doc/man/econf_getStringValue.3 create mode 100644 doc/man/econf_mergeFiles.3 create mode 100644 doc/man/econf_newIniFile.3 create mode 100644 doc/man/econf_newKeyFile.3 create mode 100644 doc/man/econf_readConfig.3 create mode 100644 doc/man/econf_readConfigWithCallback.3 create mode 100644 doc/man/econf_readFile.3 create mode 100644 doc/man/econf_readFileWithCallback.3 create mode 100644 doc/man/econf_setBoolValue.3 create mode 100644 doc/man/econf_setFloatValue.3 create mode 100644 doc/man/econf_setIntValue.3 create mode 100644 doc/man/econf_setStringValue.3 create mode 100644 doc/man/econf_set_comment_tag.3 create mode 100644 doc/man/econf_set_conf_dirs.3 create mode 100644 doc/man/econf_set_delimiter_tag.3 create mode 100644 doc/man/econf_writeFile.3 diff --git a/doc/man/econf_comment_tag.3 b/doc/man/econf_comment_tag.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_comment_tag.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_delimiter_tag.3 b/doc/man/econf_delimiter_tag.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_delimiter_tag.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_errLocation.3 b/doc/man/econf_errLocation.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_errLocation.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_errString.3 b/doc/man/econf_errString.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_errString.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_freeArray.3 b/doc/man/econf_freeArray.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_freeArray.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_freeExtValue.3 b/doc/man/econf_freeExtValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_freeExtValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_freeFile.3 b/doc/man/econf_freeFile.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_freeFile.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getBoolValue.3 b/doc/man/econf_getBoolValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getBoolValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getExtValue.3 b/doc/man/econf_getExtValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getExtValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getFloatValue.3 b/doc/man/econf_getFloatValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getFloatValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getGroups.3 b/doc/man/econf_getGroups.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getGroups.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getIntValue.3 b/doc/man/econf_getIntValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getIntValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getKeys.3 b/doc/man/econf_getKeys.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getKeys.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getPath.3 b/doc/man/econf_getPath.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getPath.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_getStringValue.3 b/doc/man/econf_getStringValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_getStringValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_mergeFiles.3 b/doc/man/econf_mergeFiles.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_mergeFiles.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_newIniFile.3 b/doc/man/econf_newIniFile.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_newIniFile.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_newKeyFile.3 b/doc/man/econf_newKeyFile.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_newKeyFile.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_readConfig.3 b/doc/man/econf_readConfig.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_readConfig.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_readConfigWithCallback.3 b/doc/man/econf_readConfigWithCallback.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_readConfigWithCallback.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_readFile.3 b/doc/man/econf_readFile.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_readFile.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_readFileWithCallback.3 b/doc/man/econf_readFileWithCallback.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_readFileWithCallback.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_setBoolValue.3 b/doc/man/econf_setBoolValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_setBoolValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_setFloatValue.3 b/doc/man/econf_setFloatValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_setFloatValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_setIntValue.3 b/doc/man/econf_setIntValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_setIntValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_setStringValue.3 b/doc/man/econf_setStringValue.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_setStringValue.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_set_comment_tag.3 b/doc/man/econf_set_comment_tag.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_set_comment_tag.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_set_conf_dirs.3 b/doc/man/econf_set_conf_dirs.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_set_conf_dirs.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_set_delimiter_tag.3 b/doc/man/econf_set_delimiter_tag.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_set_delimiter_tag.3 @@ -0,0 +1 @@ +.so man3/libeconf.3 diff --git a/doc/man/econf_writeFile.3 b/doc/man/econf_writeFile.3 new file mode 100644 index 0000000..8f00a7f --- /dev/null +++ b/doc/man/econf_writeFile.3 @@ -0,0 +1 @@ +.so man3/libeconf.3