예제 #1
0
/* Destroy parser object */
static void parser_destroy(struct parser_obj *po)
{
    TRACE_FLOW_ENTRY();

    if(po) {
        col_destroy_queue(po->queue);
        col_destroy_collection_with_cb(po->sec, ini_cleanup_cb, NULL);
        ini_comment_destroy(po->ic);
        value_destroy_arrays(po->raw_lines,
                             po->raw_lengths);
        if (po->last_read) free(po->last_read);
        if (po->key) free(po->key);
        col_destroy_collection_with_cb(po->top, ini_cleanup_cb, NULL);
        free(po);
    }

    TRACE_FLOW_EXIT();
}
예제 #2
0
/* Traverse the collection and clean the object */
void ini_config_destroy(struct ini_cfgobj *ini_config)
{
    TRACE_FLOW_ENTRY();

    if (ini_config) {
        if(ini_config->cfg) {

            col_destroy_collection_with_cb(ini_config->cfg,
                                           ini_cleanup_cb,
                                           NULL);
        }
        free(ini_config);
    }

    TRACE_FLOW_EXIT();
}
예제 #3
0
/* Function to read next line from the file */
static int parser_save_section(struct parser_obj *po)
{
    int error = EOK;
    uint32_t mergemode;
    int merge = 0;

    TRACE_FLOW_ENTRY();

    if (po->sec) {

        TRACE_INFO_STRING("Section exists.", "");

        /* First detect if we have collision */
        error = check_section_collision(po);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to check for collision", error);
            return error;
        }

        if (po->merge_sec) {

            TRACE_INFO_STRING("Merge collision detected", "");

            mergemode = po->collision_flags & INI_MS_MASK;

            switch (mergemode) {
            case INI_MS_ERROR:
                /* Report error and return */
                TRACE_INFO_STRING("Reporting error", "duplicate section");
                error = save_error(po->el,
                                   po->seclinenum,
                                   ERR_DUPSECTION,
                                   ERROR_TXT);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to "
                                       "save error",
                                        error);
                    return error;
                }
                /* Return error */
                TRACE_FLOW_RETURN(EEXIST);
                return EEXIST;

            case INI_MS_PRESERVE:
                /* Delete new section */
                TRACE_INFO_STRING("Preserve mode", "");
                col_destroy_collection_with_cb(
                                        po->sec,
                                        ini_cleanup_cb,
                                        NULL);
                po->sec = NULL;
                break;

            case INI_MS_OVERWRITE:
                /* Empty existing section */
                TRACE_INFO_STRING("Ovewrite mode", "");
                error = empty_section(po->merge_sec);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to "
                                       "empty section",
                                        error);
                    return error;
                }
                merge = 1;
                break;

            case INI_MS_DETECT:
                /* Detect mode */
                TRACE_INFO_STRING("Detect mode", "");
                po->merge_error = EEXIST;
                error = save_error(po->el,
                                   po->seclinenum,
                                   ERR_DUPSECTION,
                                   ERROR_TXT);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to "
                                       "save error",
                                        error);
                    return error;
                }
                merge = 1;
                break;

            case INI_MS_MERGE:
                /* Merge */
            default:
                TRACE_INFO_STRING("Merge mode", "");
                merge = 1;
                break;
            }

            if (merge) {
                error = merge_section(po);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to merge section", error);
                    return error;
                }
            }

            po->merge_sec = NULL;
        }
        else {
            /* Add section to configuration */
            TRACE_INFO_STRING("Now adding collection", "");
            error = col_add_collection_to_collection(po->top,
                                                     NULL, NULL,
                                                     po->sec,
                                                     COL_ADD_MODE_EMBED);

            if (error) {
                TRACE_ERROR_NUMBER("Failed to embed section", error);
                return error;
            }

            po->sec = NULL;
        }
    }

    TRACE_FLOW_EXIT();
    return EOK;

}
예제 #4
0
/* Merge contents of the section */
static int merge_section(struct parser_obj *po)
{
    int error = EOK;
    struct collection_item *item = NULL;
    struct value_obj *vo = NULL;
    int work_to_do = 1;
    const char *key;

    TRACE_FLOW_ENTRY();

    do {
        TRACE_INFO_STRING("Top of the merge loop", "");

        item = NULL;
        error = col_extract_item_from_current(po->sec,
                                              COL_DSP_FRONT,
                                              NULL,
                                              0,
                                              COL_TYPE_ANY,
                                              &item);
        if ((error) && (error != ENOENT)) {
            TRACE_ERROR_NUMBER("Failed to extract item.", error);
            return error;
        }

        if (item) {

            TRACE_INFO_STRING("Item found:", col_get_item_property(item, NULL));

            if (strncmp(col_get_item_property(item, NULL),
                        INI_SECTION_KEY, 1) == 0) {
                /* Just ignore the first item */
                vo = *((struct value_obj **)(col_get_item_data(item)));
                value_destroy(vo);
                col_delete_item(item);
                continue;
            }

            po->merge_vo = *((struct value_obj **)(col_get_item_data(item)));
            key = col_get_item_property(item, NULL);
            /* To be able to use po->merge_key in the loop
             * we have to overcome constraints imposed by
             * the "const" declaration.
             */
            memcpy(&(po->merge_key), &key, sizeof(char *));

            /* Use the value processing function to inser the value */
            error = complete_value_processing(po);

            /* In case of error value is already cleaned */
            po->merge_vo = NULL;
            po->merge_key = NULL;
            col_delete_item(item);
            /* Now we can check the error */
            if (error) {
                TRACE_ERROR_NUMBER("Failed to merge item.", error);
                return error;
            }
        }
        else {
            TRACE_INFO_STRING("No more items:", "");
            work_to_do = 0;
        }
    }
    while (work_to_do);

    /* If we reached this place the incoming section is empty.
     * but just to be safe clean with callback. */
    col_destroy_collection_with_cb(po->sec, ini_cleanup_cb, NULL);
    po->sec = NULL;

    TRACE_FLOW_EXIT();
    return EOK;
}
예제 #5
0
/* Top level wrapper around the parser */
int ini_config_parse(struct ini_cfgfile *file_ctx,
                     int error_level,
                     uint32_t collision_flags,
                     uint32_t parse_flags,
                     struct ini_cfgobj *ini_config)
{
    int error = EOK;
    struct parser_obj *po = NULL;
    uint32_t fl1, fl2, fl3;

    TRACE_FLOW_ENTRY();

    if ((!ini_config) || (!(ini_config->cfg))) {
        TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
        return EINVAL;
    }

    if (!file_ctx) {
        TRACE_ERROR_NUMBER("Invalid file context", EINVAL);
        return EINVAL;
    }

    if (!valid_collision_flags(collision_flags)) {
        TRACE_ERROR_NUMBER("Invalid flags.", EINVAL);
        return EINVAL;
    }

    if ((error_level != INI_STOP_ON_ANY) &&
        (error_level != INI_STOP_ON_NONE) &&
        (error_level != INI_STOP_ON_ERROR)) {
        TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
        return EINVAL;
    }

    error = parser_create(ini_config,
                          file_ctx->file,
                          file_ctx->filename,
                          error_level,
                          collision_flags,
                          parse_flags,
                          &po);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to perform an action", error);
        return error;
    }

    error = parser_run(po);
    if (error) {
        fl1 = collision_flags & INI_MS_MASK;
        fl2 = collision_flags & INI_MV1S_MASK;
        fl3 = collision_flags & INI_MV2S_MASK;
        if ((error == EEXIST) &&
            (((fl1 == INI_MS_DETECT) &&
              (fl2 != INI_MV1S_ERROR) &&
              (fl3 != INI_MV2S_ERROR)) ||
             ((fl2 == INI_MV1S_DETECT) &&
              (fl1 != INI_MS_ERROR) &&
              (fl3 != INI_MV2S_ERROR)) ||
             ((fl3 == INI_MV2S_DETECT) &&
              (fl1 != INI_MS_ERROR) &&
              (fl2 != INI_MV1S_ERROR)))) {
            TRACE_ERROR_NUMBER("No error in detect mode", error);
            /* Fall through */
        }
        else {
            TRACE_ERROR_NUMBER("Failed to parse file", error);
            TRACE_ERROR_NUMBER("Mode", collision_flags);
            col_get_collection_count(ini_config->error_list, &(ini_config->count));
            if(ini_config->count) (ini_config->count)--;
            parser_destroy(po);
            return error;
        }
    }

    /* If should be empty anyways */
    col_destroy_collection_with_cb(ini_config->cfg, ini_cleanup_cb, NULL);
    ini_config->cfg = po->top;
    po->top = NULL;

    parser_destroy(po);

    TRACE_FLOW_EXIT();
    return error;
}