summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ini/ini_parse.c165
1 files changed, 116 insertions, 49 deletions
diff --git a/ini/ini_parse.c b/ini/ini_parse.c
index 4dab4b6..5fa5b2e 100644
--- a/ini/ini_parse.c
+++ b/ini/ini_parse.c
@@ -529,6 +529,7 @@ static int parser_save_section(struct parser_obj *po)
static int complete_value_processing(struct parser_obj *po)
{
int error = EOK;
+ int error2 = EOK;
struct value_obj *vo = NULL;
struct value_obj *vo_old = NULL;
unsigned insertmode;
@@ -536,12 +537,19 @@ static int complete_value_processing(struct parser_obj *po)
int suppress = 0;
int doinsert = 0;
struct collection_item *item = NULL;
+ struct collection_item *section = NULL;
+ int merging = 0;
TRACE_FLOW_ENTRY();
- /* If there is not open section create a default one */
- if(!(po->sec)) {
- /* Create a new section */
+ if (po->merge_sec) {
+ TRACE_INFO_STRING("Processing value in merge mode", "");
+ section = po->merge_sec;
+ merging = 1;
+ }
+ else if(!(po->sec)) {
+ TRACE_INFO_STRING("Creating default section", "");
+ /* If there is not open section create a default one */
error = col_create_collection(&po->sec,
INI_DEFAULT_SECTION,
COL_CLASS_INI_SECTION);
@@ -549,29 +557,44 @@ static int complete_value_processing(struct parser_obj *po)
TRACE_ERROR_NUMBER("Failed to create default section", error);
return error;
}
+ section = po->sec;
}
-
- /* Construct value object from what we have */
- error = value_create_from_refarray(po->raw_lines,
- po->raw_lengths,
- po->keylinenum,
- INI_VALUE_READ,
- po->key_len,
- po->boundary,
- po->ic,
- &vo);
-
- if (error) {
- TRACE_ERROR_NUMBER("Failed to create value object", error);
- return error;
+ else {
+ TRACE_INFO_STRING("Processing value in normal mode", "");
+ section = po->sec;
}
- /* Forget about the arrays. They are now owned by the value object */
- po->ic = NULL;
- po->raw_lines = NULL;
- po->raw_lengths = NULL;
+ if (merging) {
+ TRACE_INFO_STRING("Using merge key:", po->merge_key);
+ vo = po->merge_vo;
+ /* We are adding to the merge section so use MV2S flags.
+ * But flags are done in such a way that deviding MV2S by MV1S mask
+ * will translate MV2S flags into MV1S so we can use
+ * MV1S constants. */
+ TRACE_INFO_NUMBER("Collisions flags:", po->collision_flags);
+ mergemode = (po->collision_flags & INI_MV2S_MASK) / INI_MV1S_MASK;
+ }
+ else {
+ /* Construct value object from what we have */
+ error = value_create_from_refarray(po->raw_lines,
+ po->raw_lengths,
+ po->keylinenum,
+ INI_VALUE_READ,
+ po->key_len,
+ po->boundary,
+ po->ic,
+ &vo);
- mergemode = po->collision_flags & INI_MV1S_MASK;
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create value object", error);
+ return error;
+ }
+ /* Forget about the arrays. They are now owned by the value object */
+ po->ic = NULL;
+ po->raw_lines = NULL;
+ po->raw_lengths = NULL;
+ mergemode = po->collision_flags & INI_MV1S_MASK;
+ }
switch (mergemode) {
case INI_MV1S_ERROR: insertmode = COL_INSERT_DUPERROR;
@@ -585,16 +608,18 @@ static int complete_value_processing(struct parser_obj *po)
doinsert = 1;
break;
case INI_MV1S_OVERWRITE: /* Special handling */
+ case INI_MV1S_DETECT:
default:
break;
}
/* Do not insert but search for dups first */
if (!doinsert) {
- TRACE_INFO_STRING("Ovewrite mode. Lokking for:", po->key);
+ TRACE_INFO_STRING("Overwrite mode. Looking for:",
+ (char *)(merging ? po->merge_key : po->key));
- error = col_get_item(po->sec,
- po->key,
+ error = col_get_item(section,
+ merging ? po->merge_key : po->key,
COL_TYPE_BINARY,
COL_TRAVERSE_DEFAULT,
&item);
@@ -607,21 +632,42 @@ static int complete_value_processing(struct parser_obj *po)
/* Check if there is a dup */
if (item) {
- /* Dup exists - update it */
- vo_old = *((struct value_obj **)(col_get_item_data(item)));
- error = col_modify_binary_item(item,
- NULL,
- &vo,
- sizeof(struct value_obj *));
- if (error) {
- TRACE_ERROR_NUMBER("Failed updating the value", error);
- value_destroy(vo);
- return error;
+ /* Check if we are in the detect mode */
+ if (mergemode == INI_MV1S_DETECT) {
+ po->merge_error = EEXIST;
+ /* There is a dup - inform user about it and continue */
+ error = save_error(po->el,
+ merging ? po->seclinenum : po->keylinenum,
+ merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
+ ERROR_TXT);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to save error", error);
+ value_destroy(vo);
+ return error;
+ }
+ doinsert = 1;
+ insertmode = COL_INSERT_NOCHECK;
+
+ }
+ else {
+
+ /* Dup exists - update it */
+ vo_old = *((struct value_obj **)(col_get_item_data(item)));
+ error = col_modify_binary_item(item,
+ NULL,
+ &vo,
+ sizeof(struct value_obj *));
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed updating the value", error);
+ value_destroy(vo);
+ return error;
+ }
+
+ /* If we failed to update it is better to leak then crash,
+ * so destroy original value only on the successful update.
+ */
+ value_destroy(vo_old);
}
- /* If we failed to update it is better to leak then crash,
- * so desctroy original value only on the successful update.
- */
- value_destroy(vo_old);
}
else {
/* No dup found so we can insert with no check */
@@ -632,31 +678,52 @@ static int complete_value_processing(struct parser_obj *po)
if (doinsert) {
/* Add value to collection */
- error = col_insert_binary_property(po->sec,
+ error = col_insert_binary_property(section,
NULL,
COL_DSP_END,
NULL,
0,
insertmode,
- po->key,
+ merging ? po->merge_key : po->key,
&vo,
sizeof(struct value_obj *));
if (error) {
+ value_destroy(vo);
+
if ((suppress) && (error == EEXIST)) {
- TRACE_INFO_STRING("Preseved exisitng value", po->key);
- value_destroy(vo);
+ TRACE_INFO_STRING("Preseved exisitng value",
+ (char *)(merging ? po->merge_key : po->key));
}
else {
- TRACE_ERROR_NUMBER("Failed to add value object to the section", error);
- value_destroy(vo);
- return error;
+ /* Check if this is a critical error or not */
+ if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
+ TRACE_ERROR_NUMBER("Failed to add value object "
+ "to the section", error);
+ error2 = save_error(po->el,
+ merging ? po->seclinenum : po->keylinenum,
+ merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
+ ERROR_TXT);
+ if (error2) {
+ TRACE_ERROR_NUMBER("Failed to save error", error2);
+ return error2;
+ }
+ return error;
+ }
+ else {
+ TRACE_ERROR_NUMBER("Failed to add value object"
+ " to the section", error);
+ return error;
+ }
}
}
}
- free(po->key);
- po->key = NULL;
- po->key_len = 0;
+ if (!merging) {
+ free(po->key);
+ po->key = NULL;
+ po->key_len = 0;
+ }
+
TRACE_FLOW_EXIT();
return EOK;
}