From b9ce9b7ecd1db5afbfc1a51def601ec03e657f32 Mon Sep 17 00:00:00 2001 From: Alexander Scheel Date: Wed, 12 Jul 2017 15:14:52 -0400 Subject: [PATCH] INI: Extend INI_MS_DETECT to be non-exclusive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates the INI_MS_DETECT flag such that it can be used in combination with INI_MS_MERGE, INI_MS_OVERWRITE, and INI_MS_PRESERVE. With the previous behavior, to detect that duplicate sections exist in a config directory, two separate calls to ini_augment would need to be made: one with a copy baes_obj and INI_MS_DETECT, and one with INI_MS_PRESERVE. Resolves: https://pagure.io/SSSD/ding-libs/issue/3167 Signed-off-by: Alexander Scheel Reviewed-by: Michal Židek Merges: https://pagure.io/SSSD/ding-libs/issue/3167 (cherry picked from commit 3163a969bbcd10c4d9e48e191f978c6991ac01cd) --- ini/ini_augment.c | 4 +-- ini/ini_configobj.c | 71 ++++++++++++++++++++++++++++++++--------------------- ini/ini_configobj.h | 3 ++- ini/ini_defines.h | 5 ++++ ini/ini_parse.c | 32 +++++++++++------------- 5 files changed, 67 insertions(+), 48 deletions(-) diff --git a/ini/ini_augment.c b/ini/ini_augment.c index 0855381..e4ac94b 100644 --- a/ini/ini_augment.c +++ b/ini/ini_augment.c @@ -808,9 +808,9 @@ static int ini_aug_apply(struct ini_cfgobj *cfg, } else if ((error == EEXIST) && - ((((merge_flags & INI_MS_MASK) == INI_MS_DETECT) && + ((ini_flags_have(INI_MS_DETECT, merge_flags) && ((merge_flags & INI_MV2S_MASK) != INI_MV2S_ERROR)) || - (((merge_flags & INI_MS_MASK) != INI_MS_ERROR) && + ((!ini_flags_have(INI_MS_ERROR, merge_flags)) && ((merge_flags & INI_MV2S_MASK) == INI_MV2S_DETECT)))) { TRACE_ERROR_NUMBER("Got error in detect mode", error); /* Fall through! */ diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 04e81ba..09bedc4 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -270,6 +270,23 @@ static int ini_copy_cb(struct collection_item *item, return error; } +/* Check flags for flag */ +int ini_flags_have(uint32_t flag, uint32_t flags) +{ + switch (flag) { + case INI_MS_MERGE: + case INI_MS_ERROR: + case INI_MS_OVERWRITE: + case INI_MS_PRESERVE: + return flag == (flags & INI_MS_MODE_MASK); + case INI_MS_DETECT: + return flag == (flags & INI_MS_DETECT); + default: + TRACE_ERROR_NUMBER("Unsupported flag", flag); + } + return 0; +} + /* Copy configuration */ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new) @@ -547,7 +564,12 @@ static int acceptor_handler(const char *property, donor = passed_data->ci; acceptor = *((struct collection_item **)(data)); - mergemode = passed_data->flags & INI_MS_MASK; + mergemode = passed_data->flags & INI_MS_MODE_MASK; + + if (passed_data->flags & INI_MS_DETECT) { + TRACE_INFO_STRING("Detect mode", ""); + passed_data->error = EEXIST; + } switch (mergemode) { case INI_MS_ERROR: /* Report error and return */ @@ -582,21 +604,6 @@ static int acceptor_handler(const char *property, } break; - case INI_MS_DETECT: /* Detect mode */ - TRACE_INFO_STRING("Detect mode", ""); - passed_data->error = EEXIST; - error = merge_two_sections(donor, - acceptor, - passed_data->flags); - if (error) { - if (error != EEXIST) { - TRACE_ERROR_NUMBER("Failed to merge " - "sections", error); - return error; - } - } - break; - case INI_MS_MERGE: /* Merge */ default: TRACE_INFO_STRING("Merge mode", ""); error = merge_two_sections(donor, @@ -608,14 +615,22 @@ static int acceptor_handler(const char *property, "sections", error); return error; } - passed_data->error = error; + + if (!(passed_data->flags & INI_MS_DETECT)) { + passed_data->error = error; + } + + error = EOK; } break; } - *dummy = 1; + if (error == EOK) { + *dummy = 1; + } + TRACE_FLOW_EXIT(); - return EOK; + return error; } /* Callback to process the donating config */ @@ -671,8 +686,8 @@ static int donor_handler(const char *property, /* Save error anyway */ passed_data->error = acceptor_data.error; /* If it is section DETECT or MERGE+DETECT */ - if (((passed_data->flags & INI_MS_MASK) == INI_MS_DETECT) || - (((passed_data->flags & INI_MS_MASK) != INI_MS_ERROR) && + if (ini_flags_have(INI_MS_DETECT, passed_data->flags) || + (!ini_flags_have(INI_MS_ERROR, passed_data->flags) && ((passed_data->flags & INI_MV2S_MASK) == INI_MV2S_DETECT))) { TRACE_INFO_NUMBER("Non-critical error", @@ -782,7 +797,7 @@ static int merge_configs(struct ini_cfgobj *donor, /* Check if we got error */ if ((data.error) && - (((collision_flags & INI_MS_MASK) == INI_MS_ERROR) || + (ini_flags_have(INI_MS_ERROR, collision_flags) || ((collision_flags & INI_MV2S_MASK) == INI_MV2S_ERROR))) { TRACE_ERROR_NUMBER("Got error in error mode", data.error); return data.error; @@ -806,7 +821,7 @@ static int merge_configs(struct ini_cfgobj *donor, /* Check if we got error */ if ((data.error) && - (((collision_flags & INI_MS_MASK) == INI_MS_DETECT) || + (ini_flags_have(INI_MS_DETECT, collision_flags) || ((collision_flags & INI_MV2S_MASK) == INI_MV2S_DETECT))) { TRACE_ERROR_NUMBER("Got error in error or detect mode", data.error); error = data.error; @@ -843,12 +858,12 @@ int valid_collision_flags(uint32_t collision_flags) return 0; } - flag = collision_flags & INI_MS_MASK; + /* Any combination of DETECT and a MODE flag is valid. */ + flag = collision_flags & INI_MS_MODE_MASK; if ((flag != INI_MS_MERGE) && (flag != INI_MS_OVERWRITE) && (flag != INI_MS_ERROR) && - (flag != INI_MS_PRESERVE) && - (flag != INI_MS_DETECT)) { + (flag != INI_MS_PRESERVE)) { TRACE_ERROR_STRING("Invalid section collision flag",""); return 0; } @@ -906,9 +921,9 @@ int ini_config_merge(struct ini_cfgobj *first, if (error) { TRACE_ERROR_NUMBER("Failed to merge configuration", error); if ((error == EEXIST) && - ((((collision_flags & INI_MS_MASK) == INI_MS_DETECT) && + ((ini_flags_have(INI_MS_DETECT, collision_flags) && ((collision_flags & INI_MV2S_MASK) != INI_MV2S_ERROR)) || - (((collision_flags & INI_MS_MASK) != INI_MS_ERROR) && + (!ini_flags_have(INI_MS_ERROR, collision_flags) && ((collision_flags & INI_MV2S_MASK) == INI_MV2S_DETECT)))) { TRACE_ERROR_NUMBER("Got error in detect mode", error); /* Fall through! */ diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 093916a..ca1e5ff 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -344,7 +344,8 @@ enum ERR_PARSE { #define INI_MS_OVERWRITE 0x0200 /** @brief Second section is discarded */ #define INI_MS_PRESERVE 0x0300 -/** @brief Merge but log errors if duplicate sections are detected */ +/** @brief Log errors if duplicate sections are detected; non-exclusive */ +/** This defaults to MERGE, but can be used with OVERWRITE and PRESERVE **/ #define INI_MS_DETECT 0x0400 /** diff --git a/ini/ini_defines.h b/ini/ini_defines.h index bb34510..d79019b 100644 --- a/ini/ini_defines.h +++ b/ini/ini_defines.h @@ -22,6 +22,8 @@ #ifndef INI_DEFINES_H #define INI_DEFINES_H +#include + #define NAME_OVERHEAD 10 #define SLASH "/" @@ -115,9 +117,12 @@ #define INI_MV2S_MASK 0x00F0 /* Merge values options mask * for two sections. */ #define INI_MS_MASK 0x0F00 /* Merge section options mask */ +#define INI_MS_MODE_MASK 0x0300 /* Merge section merge mode mask */ /* Different error string functions can be passed as callbacks */ typedef const char * (*error_fn)(int error); +int ini_flags_have(uint32_t flag, uint32_t flags); + #endif diff --git a/ini/ini_parse.c b/ini/ini_parse.c index e5baeca..3050223 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -580,7 +580,7 @@ static int parser_save_section(struct parser_obj *po) TRACE_INFO_STRING("Merge collision detected", ""); - mergemode = po->collision_flags & INI_MS_MASK; + mergemode = po->collision_flags & INI_MS_MODE_MASK; switch (mergemode) { case INI_MS_ERROR: @@ -623,9 +623,15 @@ static int parser_save_section(struct parser_obj *po) merge = 1; break; - case INI_MS_DETECT: - /* Detect mode */ - TRACE_INFO_STRING("Detect mode", ""); + case INI_MS_MERGE: + /* Merge */ + default: + TRACE_INFO_STRING("Merge mode", ""); + merge = 1; + break; + } + + if (po->collision_flags & INI_MS_DETECT) { po->merge_error = EEXIST; error = save_error(po->el, po->seclinenum, @@ -637,15 +643,6 @@ static int parser_save_section(struct parser_obj *po) error); return error; } - merge = 1; - break; - - case INI_MS_MERGE: - /* Merge */ - default: - TRACE_INFO_STRING("Merge mode", ""); - merge = 1; - break; } if (merge) { @@ -1599,9 +1596,9 @@ static int parser_error(struct parser_obj *po) * We check for reverse condition and return error, * otherwise fall through. */ - if (!((((po->collision_flags & INI_MS_MASK) == INI_MS_ERROR) && + if (!(((ini_flags_have(INI_MS_ERROR, po->collision_flags)) && (error == EEXIST)) || - (((po->collision_flags & INI_MS_MASK) == INI_MS_MERGE) && + (ini_flags_have(INI_MS_ERROR, po->collision_flags) && ((po->collision_flags & INI_MV2S_MASK) == INI_MV2S_ERROR) && (error == EEXIST)))) { return error; @@ -1728,11 +1725,12 @@ int ini_config_parse(struct ini_cfgfile *file_ctx, error = parser_run(po); if (error) { - fl1 = collision_flags & INI_MS_MASK; + fl1 = collision_flags & INI_MS_MODE_MASK; fl2 = collision_flags & INI_MV1S_MASK; fl3 = collision_flags & INI_MV2S_MASK; if ((error == EEXIST) && - (((fl1 == INI_MS_DETECT) && + ((ini_flags_have(INI_MS_DETECT, collision_flags) && + (fl1 != INI_MS_ERROR) && (fl2 != INI_MV1S_ERROR) && (fl3 != INI_MV2S_ERROR)) || ((fl2 == INI_MV1S_DETECT) && -- 2.13.2