| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "inicfg_internals.h" |
| 4 | |
| 5 | // ---------------------------------------------------------------------------- |
| 6 | // config sections index |
| 7 | |
| 8 | int inicfg_section_compare(void *a, void *b) { |
| 9 | if(((struct config_section *)a)->name < ((struct config_section *)b)->name) return -1; |
| 10 | else if(((struct config_section *)a)->name > ((struct config_section *)b)->name) return 1; |
| 11 | else return string_cmp(((struct config_section *)a)->name, ((struct config_section *)b)->name); |
| 12 | } |
| 13 | |
| 14 | struct config_section *inicfg_section_find(struct config *root, const char *name) { |
| 15 | struct config_section sect_tmp = { |
| 16 | .name = string_strdupz(name), |
| 17 | }; |
| 18 | |
| 19 | struct config_section *rc = (struct config_section *)avl_search_lock(&root->index, (avl_t *) §_tmp); |
| 20 | string_freez(sect_tmp.name); |
| 21 | return rc; |
| 22 | } |
| 23 | |
| 24 | // ---------------------------------------------------------------------------- |
| 25 | // config section methods |
| 26 | |
| 27 | void inicfg_section_free(struct config_section *sect) { |
| 28 | avl_destroy_lock(§->values_index); |
| 29 | string_freez(sect->name); |
| 30 | freez(sect); |
| 31 | } |
| 32 | |
| 33 | void inicfg_section_remove_and_delete(struct config *root, struct config_section *sect, bool have_root_lock, bool have_sect_lock) { |
| 34 | struct config_section *sect_found = inicfg_section_del(root, sect); |
| 35 | if(sect_found != sect) { |
| 36 | nd_log(NDLS_DAEMON, NDLP_ERR, |
| 37 | "INTERNAL ERROR: Cannot remove section '%s', it was not inserted before.", |
| 38 | string2str(sect->name)); |
| 39 | return; |
| 40 | } |
| 41 | |
| 42 | inicfg_option_remove_and_delete_all(sect, have_sect_lock); |
| 43 | |
| 44 | if(!have_root_lock) |
| 45 | APPCONFIG_LOCK(root); |
| 46 | |
| 47 | DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(root->sections, sect, prev, next); |
| 48 | |
| 49 | if(!have_root_lock) |
| 50 | APPCONFIG_UNLOCK(root); |
| 51 | |
| 52 | // if the caller has the section lock, we will unlock it, to cleanup |
| 53 | if(have_sect_lock) |
| 54 | SECTION_UNLOCK(sect); |
| 55 | |
| 56 | inicfg_section_free(sect); |
| 57 | } |
| 58 | |
| 59 | struct config_section *inicfg_section_create(struct config *root, const char *section) { |
| 60 | struct config_section *sect = callocz(1, sizeof(struct config_section)); |
| 61 | sect->name = string_strdupz(section); |
| 62 | spinlock_init(§->spinlock); |
| 63 | |
| 64 | avl_init_lock(§->values_index, inicfg_option_compare); |
| 65 | |
| 66 | struct config_section *sect_found = inicfg_section_add(root, sect); |
| 67 | if(sect_found != sect) { |
| 68 | nd_log(NDLS_DAEMON, NDLP_ERR, |
| 69 | "CONFIG: section '%s', already exists, using existing.", |
| 70 | string2str(sect->name)); |
| 71 | inicfg_section_free(sect); |
| 72 | return sect_found; |
| 73 | } |
| 74 | |
| 75 | APPCONFIG_LOCK(root); |
| 76 | DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(root->sections, sect, prev, next); |
| 77 | APPCONFIG_UNLOCK(root); |
| 78 | |
| 79 | return sect; |
| 80 | } |
| 81 | |
| 82 |