/
githubmirror
/
ding-libs
Обзор
Документация
Войти
/
githubmirror
/
ding-libs
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
ini/ini_configmod.c
1 606 строк
53 KB
Alexey Tikhonov
INI: fix check for error code
10 авг 2021, 14:12
10 авг 2021, 14:12
ec68177
Код
Авторство
О чём код?
/* INI LIBRARY Implementation of the modification interface. Copyright (C) Dmitri Pal <dpal@redhat.com> 2014 INI Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. INI Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with INI Library. If not, see <http://www.gnu.org/licenses/>. */ #include "config.h" #include <errno.h> #include <string.h> #include <stdio.h> #include <inttypes.h> #include "trace.h" #include "ref_array.h" #include "simplebuffer.h" #include "collection.h" #include "ini_comment.h" #include "ini_defines.h" #include "ini_valueobj.h" #include "ini_configobj.h" #include "ini_config_priv.h" #include "ini_configmod.h" /* Which kind of search we should use? */ #define EXACT(a) ((a == INI_VA_MOD_E) || (a == INI_VA_MODADD_E)) ? 1 : 0 static void cb(const char *property, int property_len, int type, void *data, int length, void *ext_data); /* Delete value by key or position */ int ini_config_delete_value(struct ini_cfgobj *ini_config, const char *section, int position, const char *key, int idx) { int error = EOK; struct value_obj *vo = NULL; struct collection_item *item = NULL; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } if (!key) { TRACE_ERROR_STRING("Invalid argument","key"); return EINVAL; } if (idx < 0) { TRACE_ERROR_STRING("Invalid argument","idx"); return EINVAL; } error = col_extract_item(ini_config->cfg, section, position, key, idx, COL_TYPE_ANY, &item); if (error) { TRACE_ERROR_NUMBER("Item not found or error", error); return error; } vo = *((struct value_obj **)(col_get_item_data(item))); value_destroy(vo); col_delete_item(item); TRACE_FLOW_EXIT(); return error; } /* Updates a comment for value that is found by seaching for a specific key */ int ini_config_update_comment(struct ini_cfgobj *ini_config, const char *section, const char *key, const char *comments[], size_t count_comment, int idx) { int error = EOK; struct ini_comment *ic = NULL; struct value_obj *vo = NULL; struct collection_item *item = NULL; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } if (!key) { TRACE_ERROR_STRING("Invalid argument","key"); return EINVAL; } if (idx < 0) { TRACE_ERROR_STRING("Invalid argument","idx"); return EINVAL; } /* Look for the exact item */ error = col_get_dup_item(ini_config->cfg, section, key, COL_TYPE_ANY, idx, 1, &item); if (error) { TRACE_ERROR_NUMBER("Item not found or error", error); return error; } /* If item not found return error */ if (!item) { TRACE_ERROR_NUMBER("Item not found.", ENOENT); return ENOENT; } /* Build comment */ if (comments) { error = ini_comment_construct(comments, count_comment, &ic); if (error) { TRACE_ERROR_NUMBER("Failed to construct comment", error); return error; } } vo = *((struct value_obj **)(col_get_item_data(item))); /* Replace comment with the new one. Old one is freed by the function */ error = value_put_comment(vo, ic); if (error) { TRACE_ERROR_NUMBER("Faile to update comment.", error); ini_comment_destroy(ic); return error; } TRACE_FLOW_EXIT(); return EOK; } /* Add or modify a value that stores array of integers */ int ini_config_add_int_arr_value(struct ini_cfgobj *ini_config, const char *section, const char *key, int *value_int_arr, size_t count_int, char sep, const char *comments[], size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char **str_arr = NULL; size_t i = 0; size_t j = 0; TRACE_FLOW_ENTRY(); if (!count_int) { TRACE_ERROR_STRING("Invalid argument","count_int"); return EINVAL; } str_arr = calloc(count_int, sizeof(char *)); if (!str_arr) { TRACE_ERROR_STRING("Failed to allocate memory for string array", ENOMEM); return ENOMEM; } for (i = 0; i < count_int; i++) { ret = asprintf(&str_arr[i], "%d", value_int_arr[i]); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ for (j = 0; j < i; j++) free(str_arr[j]); free(str_arr); return ENOMEM; } } error = ini_config_add_str_arr_value(ini_config, section, key, str_arr, count_int, sep, comments, count_comment, border, position, other_key, idx, flags); for (i = 0; i < count_int; i++) free(str_arr[i]); free(str_arr); TRACE_FLOW_RETURN(error); return error; } /* Add or modify a value that stores array of long ints */ int ini_config_add_long_arr_value(struct ini_cfgobj *ini_config, const char *section, const char *key, long *value_long_arr, size_t count_long, char sep, const char *comments[], size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char **str_arr = NULL; size_t i = 0; size_t j = 0; TRACE_FLOW_ENTRY(); if (!count_long) { TRACE_ERROR_STRING("Invalid argument","count_long"); return EINVAL; } str_arr = calloc(count_long, sizeof(char *)); if (!str_arr) { TRACE_ERROR_STRING("Failed to allocate memory for string array", ENOMEM); return ENOMEM; } for (i = 0; i < count_long; i++) { ret = asprintf(&str_arr[i], "%ld", value_long_arr[i]); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ for (j = 0; j < i; j++) free(str_arr[j]); free(str_arr); return ENOMEM; } } error = ini_config_add_str_arr_value(ini_config, section, key, str_arr, count_long, sep, comments, count_comment, border, position, other_key, idx, flags); for (i = 0; i < count_long; i++) free(str_arr[i]); free(str_arr); TRACE_FLOW_RETURN(error); return error; } /* Add or modify a value that stores array of doubles */ int ini_config_add_double_arr_value(struct ini_cfgobj *ini_config, const char *section, const char *key, double *value_double_arr, size_t count_double, char sep, const char *comments[], size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char **str_arr = NULL; size_t i = 0; size_t j = 0; TRACE_FLOW_ENTRY(); if (!count_double) { TRACE_ERROR_STRING("Invalid argument","count_double"); return EINVAL; } str_arr = calloc(count_double, sizeof(char *)); if (!str_arr) { TRACE_ERROR_STRING("Failed to allocate memory for string array", ENOMEM); return ENOMEM; } for (i = 0; i < count_double; i++) { ret = asprintf(&str_arr[i], "%f", value_double_arr[i]); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ for (j = 0; j < i; j++) free(str_arr[j]); free(str_arr); return ENOMEM; } } error = ini_config_add_str_arr_value(ini_config, section, key, str_arr, count_double, sep, comments, count_comment, border, position, other_key, idx, flags); for (i = 0; i < count_double; i++) free(str_arr[i]); free(str_arr); TRACE_FLOW_RETURN(error); return error; } /* Add or modify a value that stores array of strings */ int ini_config_add_const_str_arr_value(struct ini_cfgobj *ini_config, const char *section, const char *key, const char *value_str_arr[], size_t count_str, char sep, const char *comments[], size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; size_t len = 0; size_t i = 0; struct simplebuffer *sbobj = NULL; char sp[3] = " "; TRACE_FLOW_ENTRY(); if (!count_str) { TRACE_ERROR_STRING("Invalid argument","count_str"); return EINVAL; } error = simplebuffer_alloc(&sbobj); if (error) { TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error); return error; } sp[0] = sep; for (i = 0; i < count_str - 1; i++) { len = strlen(value_str_arr[i]); if ((error = simplebuffer_add_str(sbobj, value_str_arr[i], len, INI_VALUE_BLOCK)) || (error = simplebuffer_add_str(sbobj, sp, 2, INI_VALUE_BLOCK))) { TRACE_ERROR_NUMBER("String append failed.", error); simplebuffer_free(sbobj); return error; } } len = strlen(value_str_arr[count_str - 1]); error = simplebuffer_add_str(sbobj, value_str_arr[count_str - 1], len, INI_VALUE_BLOCK); if (error) { TRACE_ERROR_NUMBER("String append failed.", error); simplebuffer_free(sbobj); return error; } error = ini_config_add_str_value(ini_config, section, key, (const char *)simplebuffer_get_buf(sbobj), comments, count_comment, border, position, other_key, idx, flags); simplebuffer_free(sbobj); TRACE_FLOW_RETURN(error); return error; } /* Add or modify a value that stores array of strings */ int ini_config_add_str_arr_value(struct ini_cfgobj *ini_config, const char *section, const char *key, char *value_str_arr[], size_t count_str, char sep, const char *comments[], size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { const char **const_str_arr = (const char **)(intptr_t)value_str_arr; return ini_config_add_const_str_arr_value(ini_config, section, key, const_str_arr, count_str, sep, comments, count_comment, border, position, other_key, idx, flags); } /* Function to add integer value */ int ini_config_add_int_value(struct ini_cfgobj *ini_config, const char *section, const char *key, int value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%d", value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add long value */ int ini_config_add_long_value(struct ini_cfgobj *ini_config, const char *section, const char *key, long value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%ld", value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add ulong value */ int ini_config_add_ulong_value(struct ini_cfgobj *ini_config, const char *section, const char *key, unsigned long value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%lu", value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add unsigned value */ int ini_config_add_unsigned_value(struct ini_cfgobj *ini_config, const char *section, const char *key, unsigned value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%u", value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add int32 value */ int ini_config_add_int32_value(struct ini_cfgobj *ini_config, const char *section, const char *key, int32_t value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%"PRId32, value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add uint32 value */ int ini_config_add_uint32_value(struct ini_cfgobj *ini_config, const char *section, const char *key, uint32_t value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%"PRIu32, value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add int64 value */ int ini_config_add_int64_value(struct ini_cfgobj *ini_config, const char *section, const char *key, int64_t value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%"PRId64, value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add uint64 value */ int ini_config_add_uint64_value(struct ini_cfgobj *ini_config, const char *section, const char *key, uint64_t value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%"PRIu64, value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add double value */ int ini_config_add_double_value(struct ini_cfgobj *ini_config, const char *section, const char *key, double value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; int ret = 0; char *strval = NULL; TRACE_FLOW_ENTRY(); ret = asprintf(&strval, "%f", value); if (ret == -1) { TRACE_ERROR_NUMBER("Asprintf failed.", ret); /* The main reason is propbaly memory allocation */ return ENOMEM; } /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); TRACE_FLOW_RETURN(error); free(strval); return error; } /* Function to add binary value */ int ini_config_add_bin_value(struct ini_cfgobj *ini_config, const char *section, const char *key, void *value, size_t value_len, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; size_t i; char *strval = NULL; char *ptr = NULL; TRACE_FLOW_ENTRY(); /* Do we have the vo ? */ if ((!value) && (value_len)) { TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); return EINVAL; } /* The value is good so we can allocate memory for it */ strval = malloc(value_len * 2 + 3); if (strval == NULL) { TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); return ENOMEM; } strval[0] = '\''; /* Convert the value */ ptr = strval + 1; for (i = 0; i < value_len; i++) { sprintf(ptr, "%02x", *((unsigned char *)(value) + i)); ptr += 2; } strval[value_len * 2 + 1] = '\''; strval[value_len * 2 + 2] = '\0'; /* Call string function */ error = ini_config_add_str_value(ini_config, section, key, strval, comments, count_comment, border, position, other_key, idx, flags); free(strval); TRACE_FLOW_RETURN(error); return error; } /* Function to add string value */ int ini_config_add_str_value(struct ini_cfgobj *ini_config, const char *section, const char *key, const char *value, const char **comments, size_t count_comment, int border, int position, const char *other_key, int idx, enum INI_VA flags) { int error = EOK; struct ini_comment *ic = NULL; struct value_obj *vo = NULL; struct value_obj *old_vo = NULL; struct collection_item *item = NULL; const char sp_key[] = INI_SECTION_KEY; const char *key_ptr; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } if (!key) { TRACE_ERROR_STRING("Invalid argument","key"); return EINVAL; } if (!value) { TRACE_ERROR_STRING("Invalid argument","value"); return EINVAL; } if (idx < 0) { TRACE_ERROR_STRING("Invalid argument","idx"); return EINVAL; } switch (flags) { case INI_VA_NOCHECK: /* Just fall through */ break; case INI_VA_MOD: case INI_VA_MOD_E: /* Find the value by index. * If value is not found return error. */ error = col_get_dup_item(ini_config->cfg, section, key, COL_TYPE_ANY, idx, EXACT(flags), &item); if (error) { TRACE_ERROR_NUMBER("Error " "looking for item.", error); return error; } break; case INI_VA_MODADD: error = col_get_dup_item(ini_config->cfg, section, key, COL_TYPE_ANY, idx, 0, /* no exact */ &item); if ((error) && (error != ENOENT)) { TRACE_ERROR_NUMBER("Unexpected error " "looking for item.", error); return error; } break; case INI_VA_MODADD_E: /* Find the value by index. * If value is not found it is OK. */ error = col_get_dup_item(ini_config->cfg, section, key, COL_TYPE_ANY, idx, 1, /* use exact */ &item); switch (error) { case EOK: /* we matched entry even with exact * just return it. */ break; case ENOENT: /* Entry can be missing or index was * to big. Try one more time without * exact flag */ error = col_get_dup_item(ini_config->cfg, section, key, COL_TYPE_ANY, idx, 0, &item); if (error == EOK) { /* index was to big */ return ENOENT; } else if (error != EOK && error != ENOENT) { TRACE_ERROR_NUMBER("Unexpected error " "looking for item.", error); return error; } break; default: TRACE_ERROR_NUMBER("Unexpected error " "looking for item.", error); return error; } break; case INI_VA_DUPERROR: /* Find any instance */ error = col_get_dup_item(ini_config->cfg, section, key, COL_TYPE_ANY, 0, 0, &item); if ((error) && (error != ENOENT)) { TRACE_ERROR_NUMBER("Unexpected error " "looking for item.", error); return error; } if (!error) { TRACE_ERROR_NUMBER("Key exists " "this is error.", error); return EEXIST; } break; case INI_VA_CLEAN: /* Delete all instaces of the key first */ while (!error) { error = col_remove_item_with_cb( ini_config->cfg, section, COL_DSP_FIRSTDUP, key, 0, COL_TYPE_ANY, cb, NULL); if (error) { if (error != ENOENT) { TRACE_ERROR_NUMBER("Failed to clean " "the section.", error); return error; } else break; } } break; default: /* The new ones should be added here */ TRACE_ERROR_NUMBER("Flag is not implemented", ENOSYS); return ENOSYS; } /* Start with the comment */ if (comments) { error = ini_comment_construct(comments, count_comment, &ic); if (error) { TRACE_ERROR_NUMBER("Failed to construct comment", error); return error; } } /* Create value object */ error = value_create_new(value, strnlen(value, MAX_VALUE -1), INI_VALUE_CREATED, strnlen(key, MAX_KEY -1), border, ic, &vo); if (error) { TRACE_ERROR_NUMBER("Failed to construct value object.", error); ini_comment_destroy(ic); return error; } if (item) { /* If we have selected item remove old value */ old_vo = *((struct value_obj **)(col_get_item_data(item))); value_destroy(old_vo); /* Update the item with the new value */ error = col_modify_binary_item(item, NULL, &vo, sizeof(struct value_obj *)); if (error) { TRACE_ERROR_NUMBER("Failed to update item.", error); value_destroy(vo); return error; } } else { if (position == COL_DSP_FRONT) { key_ptr = sp_key; position = COL_DSP_AFTER; } else { key_ptr = other_key; } /* Add value to collection */ error = col_insert_binary_property(ini_config->cfg, section, position, key_ptr, idx, flags, key, &vo, sizeof(struct value_obj *)); } if (error) { TRACE_ERROR_NUMBER("Failed to insert value.", error); value_destroy(vo); return error; } TRACE_FLOW_EXIT(); return EOK; } /* Function to add section */ int ini_config_add_section(struct ini_cfgobj *ini_config, const char *section, const char *comments[], size_t count_comment, int position, const char *other_section, int idx) { int error = EOK; struct ini_comment *ic = NULL; struct value_obj *vo = NULL; struct collection_item *item = NULL; struct collection_item *sec = NULL; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } if (position > COL_DSP_INDEX) { TRACE_ERROR_STRING("Invalid argument","position"); return EINVAL; } if (idx < 0) { TRACE_ERROR_STRING("Invalid argument","idx"); return EINVAL; } /* Check if section exists */ error = col_get_item(ini_config->cfg, section, COL_TYPE_COLLECTIONREF, COL_TRAVERSE_ONELEVEL, &item); if (error) { TRACE_ERROR_NUMBER("Search for section failed.", error); return error; } if (item) { TRACE_ERROR_STRING("Section already exists.", section); return EEXIST; } /* Create a new section */ error = col_create_collection(&sec, section, COL_CLASS_INI_SECTION); if (error) { TRACE_ERROR_NUMBER("Failed to create a section", error); return error; } /* Process comment */ if (comments) { error = ini_comment_construct(comments, count_comment, &ic); if (error) { TRACE_ERROR_NUMBER("Failed to construct comment", error); col_destroy_collection(sec); return error; } } /* Create value object */ error = value_create_new(section, strnlen(section, MAX_VALUE -1), INI_VALUE_CREATED, strlen(INI_SECTION_KEY), INI_WRAP_BOUNDARY, ic, &vo); if (error) { TRACE_ERROR_NUMBER("Failed to construct value object.", error); ini_comment_destroy(ic); col_destroy_collection(sec); return error; } /* Comment is now a part of value - no need to clean it seprately. */ /* Add value to section collection */ error = col_insert_binary_property(sec, NULL, COL_DSP_END, NULL, 0, COL_INSERT_NOCHECK, INI_SECTION_KEY, &vo, sizeof(struct value_obj *)); if (error) { TRACE_ERROR_NUMBER("Failed to add value object to section.", error); value_destroy(vo); col_destroy_collection(sec); return error; } /* Embed section collection */ /* Since there is no function to do addition of collection to * collection with disposition we will use a workaround. */ error = col_insert_property_with_ref(ini_config->cfg, NULL, position, other_section, idx, COL_INSERT_NOCHECK, section, COL_TYPE_COLLECTIONREF, (void *)(&sec), sizeof(struct collection_item **), NULL); if (error) { TRACE_ERROR_NUMBER("Failed to embed section", error); value_destroy(vo); col_destroy_collection(sec); return error; } TRACE_FLOW_EXIT(); return EOK; } /* Function to add or remove comments for a section */ int ini_config_comment_section(struct ini_cfgobj *ini_config, const char *section, const char *comments[], size_t count_comment) { int error = EOK; struct ini_comment *ic = NULL; struct value_obj *vo = NULL; struct collection_item *item = NULL; struct collection_item *sec = NULL; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } /* Get the section */ error = col_get_item(ini_config->cfg, section, COL_TYPE_COLLECTIONREF, COL_TRAVERSE_ONELEVEL, &item); if (error) { TRACE_ERROR_NUMBER("Search for section failed.", error); return error; } /* If item not found return error */ if (!item) { TRACE_ERROR_NUMBER("Item not found.", ENOENT); return ENOENT; } /* Item is actually a section reference */ sec = *((struct collection_item **)col_get_item_data(item)); item = NULL; /* Now get the special item from the section collection */ error = col_get_item(sec, INI_SECTION_KEY, COL_TYPE_ANY, COL_TRAVERSE_ONELEVEL, &item); if (error) { TRACE_ERROR_NUMBER("Search for section failed.", error); return error; } /* If item not found return error */ if (!item) { /* Something is really broken with the internal implementation * if we can't find the item, thus EINVAL. */ TRACE_ERROR_NUMBER("Item not found.", EINVAL); return EINVAL; } /* Item is actually a value object. */ vo = *((struct value_obj **)(col_get_item_data(item))); /* Build comment */ if (comments) { error = ini_comment_construct(comments, count_comment, &ic); if (error) { TRACE_ERROR_NUMBER("Failed to construct comment", error); return error; } } /* Replace comment with the new one. Old one is freed by the function */ error = value_put_comment(vo, ic); if (error) { TRACE_ERROR_NUMBER("Faile to update comment.", error); ini_comment_destroy(ic); return error; } TRACE_FLOW_EXIT(); return EOK; } /* Function to rename section */ int ini_config_rename_section(struct ini_cfgobj *ini_config, const char *section, const char *newname) { int error = EOK; struct collection_item *item = NULL; struct collection_item *sec = NULL; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } if (!newname) { TRACE_ERROR_STRING("Invalid argument","newname"); return EINVAL; } /* Get the section */ error = col_get_item(ini_config->cfg, section, COL_TYPE_COLLECTIONREF, COL_TRAVERSE_ONELEVEL, &item); if (error) { TRACE_ERROR_NUMBER("Search for section failed.", error); return error; } /* If item not found return error */ if (!item) { TRACE_ERROR_NUMBER("Item not found.", ENOENT); return ENOENT; } /* Item is actually a section reference */ sec = *((struct collection_item **)col_get_item_data(item)); /* Change name only */ error = col_modify_item(item, newname, 0, NULL, 0); if (error) { TRACE_ERROR_NUMBER("Failed to change section name.", error); return error; } /* Change name of the embedded collection (for consistency) */ error = col_modify_item(sec, newname, 0, NULL, 0); if (error) { TRACE_ERROR_NUMBER("Failed to change section name " "inside the embedded collection.", error); return error; } TRACE_FLOW_EXIT(); return EOK; } /* Cleanup collback */ static void cb(const char *property, int property_len, int type, void *data, int length, void *ext_data) { struct value_obj *vo; TRACE_FLOW_ENTRY(); if ((type == COL_TYPE_COLLECTIONREF) || (type == COL_TYPE_COLLECTION)) return; vo = *((struct value_obj **)(data)); value_destroy(vo); TRACE_FLOW_EXIT(); } /* Function to delete section by name */ int ini_config_delete_section_by_name(struct ini_cfgobj *ini_config, const char *section) { int error = EOK; TRACE_FLOW_ENTRY(); error = ini_config_delete_section_by_position(ini_config, COL_DSP_FIRSTDUP, section, 0); if (error) { TRACE_ERROR_NUMBER("Search for section failed.", error); return error; } TRACE_FLOW_EXIT(); return EOK; } /* Function to delete section by relative postion */ int ini_config_delete_section_by_position(struct ini_cfgobj *ini_config, int position, const char *section, int idx) { int error = EOK; struct collection_item *item = NULL; TRACE_FLOW_ENTRY(); /* Check arguments */ if (!ini_config) { TRACE_ERROR_STRING("Invalid argument","ini_config"); return EINVAL; } if (!section) { TRACE_ERROR_STRING("Invalid argument","section"); return EINVAL; } if (idx < 0) { TRACE_ERROR_STRING("Invalid argument","idx"); return EINVAL; } /* Extract section */ error = col_extract_item(ini_config->cfg, NULL, position, section, idx, COL_TYPE_ANY, &item); if (error) { TRACE_ERROR_NUMBER("Search for section failed.", error); return error; } /* If item not found return error */ if (!item) { TRACE_ERROR_NUMBER("Item not found.", ENOENT); return ENOENT; } /* Delete item and subcollection */ col_delete_item_with_cb(item, cb, NULL); TRACE_FLOW_EXIT(); return EOK; }