示例#1
0
static int ref_array_grow(struct ref_array *ra)
{
    int error = EOK;
    void *newbuf = NULL;

    TRACE_FLOW_ENTRY();

    TRACE_INFO_NUMBER("Current length: ", ra->len);
    TRACE_INFO_NUMBER("Current size: ", ra->size);

    /* Grow buffer if needed */
    newbuf = realloc(ra->storage, (ra->size + ra->grow_by) * ra->elsize);
    if (newbuf == NULL) {
        TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
        return ENOMEM;
    }

    ra->storage = newbuf;
    ra->size += ra->grow_by;

    TRACE_INFO_NUMBER("Final size: ", ra->size);
    TRACE_FLOW_RETURN(error);
    return error;

}
示例#2
0
/* Get element */
void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr)
{
    TRACE_FLOW_ENTRY();

    if (!ra) {
        TRACE_ERROR_STRING("Uninitialized argument.", "");
        return NULL;
    }

    if (idx >= ra->len) {
        TRACE_INFO_NUMBER("Invalid idx.", idx);
        return NULL;
    }

    TRACE_INFO_NUMBER("Index: ", idx);

    if (acptr) {

        TRACE_INFO_STRING("Copying data.", "");
        memcpy(acptr,
               (unsigned char *)(ra->storage) + idx * ra->elsize,
               ra->elsize);

    }

    TRACE_FLOW_EXIT();
    return (unsigned char *)(ra->storage) + idx * ra->elsize;
}
示例#3
0
/* Add new element to the array */
int ref_array_append(struct ref_array *ra, void *element)
{
    int error = EOK;

    TRACE_FLOW_ENTRY();

    if ((!ra) || (!element)) {
        TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
        return EINVAL;
    }

    /* Do we have enough room for a new element? */
    if (ra->size == ra->len) {
        error = ref_array_grow(ra);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to grow array.", error);
            return error;
        }
    }

    /* Copy element */
    memcpy((unsigned char *)(ra->storage) + ra->len * ra->elsize,
           element,
           ra->elsize);

    ra->len++;

    TRACE_INFO_NUMBER("Length after append: ", ra->len);

    TRACE_FLOW_EXIT();
    return error;
}
示例#4
0
static int save_portion(struct ref_array *raw_lines,
                        struct ref_array *raw_lengths,
                        const char* buf,
                        uint32_t len)
{
    int error = EOK;
    char *copy = NULL;
    uint32_t adj = 0;

    TRACE_FLOW_ENTRY();

    /* Add leading space only if there is
     * a) no space
     * b) it is not an empty line
     * c) it is now a first line
     */

    if ((buf[0] != ' ') &&
        (buf[0] != '\t') &&
        (len != 0) &&
        (ref_array_len(raw_lines) != 0)) adj = 1;

    copy = malloc(len + adj + 1);
    if (!copy) {
        TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM);
        return ENOMEM;
    }

    memcpy(copy + adj, buf, len);
    len += adj;
    copy[len] = 0;

    /* If the section being saved is not starting
     * with space add a space.
     */
    if (adj) copy[0] = ' ';

    error = ref_array_append(raw_lines, (void *)(&copy));
    if (error) {
        TRACE_ERROR_NUMBER("Failed to append line",
                            error);
        free(copy);
        return error;
    }

    error = ref_array_append(raw_lengths, (void *)(&len));
    if (error) {
        TRACE_ERROR_NUMBER("Failed to append length",
                            error);
        return error;
    }

    TRACE_INFO_STRING("Added string:", (char *)copy);
    TRACE_INFO_NUMBER("Added number:", len);


    TRACE_FLOW_EXIT();
    return EOK;
}
示例#5
0
/* Inspect the line */
static int parser_inspect(struct parser_obj *po)
{
    int error = EOK;
    uint32_t action = PARSE_DONE;

    TRACE_FLOW_ENTRY();

    TRACE_INFO_STRING("Buffer:", po->last_read);
    TRACE_INFO_NUMBER("In comment:", po->inside_comment);

    if (check_for_comment(po->last_read,
                          po->last_read_len,
                          !(po->parse_flags & INI_PARSE_NO_C_COMMENTS),
                          &(po->inside_comment))) {

        error = handle_comment(po, &action);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to process comment", error);
            return error;
        }
    }
    else if (isspace(*(po->last_read))) {

        error = handle_space(po, &action);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to process line wrapping", error);
            return error;
        }
    }
    else if (*(po->last_read) == '[') {

        error = handle_section(po, &action);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to save section", error);
            return error;
        }
    }
    else {

        error = handle_kvp(po, &action);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to save kvp", error);
            return error;
        }
    }

    /* Move to the next action */
    error = col_enqueue_unsigned_property(po->queue,
                                          PARSE_ACTION,
                                          action);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to schedule an action", error);
        return error;
    }

    TRACE_FLOW_EXIT();
    return error;
}
示例#6
0
/* Get new reference to an array */
struct ref_array *ref_array_getref(struct ref_array *ra)
{
    TRACE_FLOW_ENTRY();

    /* Check if array is not NULL */
    if (ra) {
        TRACE_INFO_NUMBER("Increasing reference count. Current: ", ra->refcount);
        /* Increase reference count */
        ra->refcount++;
        TRACE_INFO_NUMBER("Increased reference count. New: ", ra->refcount);

    }
    else {
        TRACE_ERROR_STRING("Uninitialized array.", "Returning NULL");
    }

    TRACE_FLOW_EXIT();
    return ra;
}
示例#7
0
/* Run parser */
static int parser_run(struct parser_obj *po)
{
    int error = EOK;
    struct collection_item *item = NULL;
    uint32_t action = 0;
    action_fn operations[] = { parser_read,
                               parser_inspect,
                               parser_post,
                               parser_error,
                               NULL };

    TRACE_FLOW_ENTRY();

    while(1) {
        /* Get next action */
        item = NULL;
        error = col_dequeue_item(po->queue, &item);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to get action", error);
            return error;
        }

        /* Get action, run operation */
        action = *((uint32_t *)(col_get_item_data(item)));
        col_delete_item(item);

        if (action == PARSE_DONE) {

            TRACE_INFO_NUMBER("We are done", error);

            /* Report merge error in detect mode
             * if no other error was detected. */
            if ((po->ret == 0) &&
                (po->merge_error != 0) &&
                ((po->collision_flags & INI_MV1S_DETECT) ||
                 (po->collision_flags & INI_MV2S_DETECT) ||
                 (po->collision_flags & INI_MS_DETECT)))
                po->ret = po->merge_error;

            error = po->ret;
            break;
        }

        error = operations[action](po);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to perform an action", error);
            return error;
        }

    }

    TRACE_FLOW_EXIT();
    return error;
}
示例#8
0
/* Grow buffer */
int simplebuffer_grow(struct simplebuffer *data,
                      uint32_t len,
                      uint32_t block)
{
    int error = EOK;
    unsigned char *newbuf = NULL;

    TRACE_FLOW_ENTRY();

    TRACE_INFO_NUMBER("Current length: ", data->length);
    TRACE_INFO_NUMBER("Current size: ", data->size);
    TRACE_INFO_NUMBER("Length to have: ", len);
    TRACE_INFO_NUMBER("Increment length: ", block);

    /* Grow buffer if needed */
    while (data->length + len >= data->size) {
        newbuf = realloc(data->buffer, data->size + block);
        if (newbuf == NULL) {
            TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
            return ENOMEM;
        }
        data->buffer = newbuf;
        data->size += block;
        TRACE_INFO_NUMBER("New size: ", data->size);
    }

    TRACE_INFO_NUMBER("Final size: ", data->size);
    TRACE_FLOW_RETURN(error);
    return error;
}
示例#9
0
/* Grow buffer to accomodate more space */
int col_grow_buffer(struct col_serial_data *buf_data, int len)
{
    char *tmp;

    TRACE_FLOW_STRING("col_grow_buffer", "Entry point");
    TRACE_INFO_NUMBER("Current length: ", buf_data->length);
    TRACE_INFO_NUMBER("Increment length: ", len);
    TRACE_INFO_NUMBER("Expected length: ", buf_data->length+len);
    TRACE_INFO_NUMBER("Current size: ", buf_data->size);

    /* Grow buffer if needed */
    while (buf_data->length+len >= buf_data->size) {
        tmp = realloc(buf_data->buffer, buf_data->size + BLOCK_SIZE);
        if (tmp == NULL) {
            TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
            return ENOMEM;
        }
        buf_data->buffer = tmp;
        buf_data->size += BLOCK_SIZE;
        TRACE_INFO_NUMBER("New size: ", buf_data->size);

    }

    TRACE_INFO_NUMBER("Final size: ", buf_data->size);
    TRACE_FLOW_STRING("col_grow_buffer", "Success Exit.");
    return EOK;
}
示例#10
0
/* Stop processing this subcollection and move to the next item in the
 * collection 'level' levels up.*/
int col_iterate_up(struct collection_iterator *iterator, unsigned level)
{
    TRACE_FLOW_STRING("iterate_up", "Entry");

    if (iterator == NULL) {
        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
        return EINVAL;
    }

    TRACE_INFO_NUMBER("Going up:", level);
    TRACE_INFO_NUMBER("Current stack depth:", iterator->stack_depth);

    /* If level is big just move to the top,
     * that will end the iteration process.
     */
    if (level >= iterator->stack_depth) iterator->stack_depth = 0;
    else iterator->stack_depth -= level;

    TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
    TRACE_FLOW_STRING("col_iterate_up", "Exit");
    return EOK;
}
示例#11
0
/* Unfold the value represented by the array */
static int value_unfold(struct ref_array *raw_lines,
                        struct ref_array *raw_lengths,
                        struct simplebuffer **unfolded)
{
    int error;
    struct simplebuffer *oneline = NULL;
    uint32_t len = 0;
    char *ptr = NULL;
    uint32_t i = 0;
    char *part = NULL;

    TRACE_FLOW_ENTRY();

    error = simplebuffer_alloc(&oneline);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
        return error;
    }

    for (;;) {
        /* Get line */
        ptr = ref_array_get(raw_lines, i, NULL);
        if (ptr) {
            /* Get its length */
            ref_array_get(raw_lengths, i, (void *)&len);

            part = *((char **)(ptr));

            TRACE_INFO_STRING("Value:", part);
            TRACE_INFO_NUMBER("Lenght:", len);

            error = simplebuffer_add_raw(oneline,
                                         part,
                                         len,
                                         INI_VALUE_BLOCK);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add string", error);
                simplebuffer_free(oneline);
                return error;
            }

            i++;
        }
        else break;
    }

    *unfolded = oneline;

    TRACE_FLOW_EXIT();
    return error;
}
示例#12
0
/* Delete the array */
void ref_array_destroy(struct ref_array *ra)
{
    int idx;

    TRACE_FLOW_ENTRY();

    /* Check if array is not NULL */
    if (!ra) {
        TRACE_INFO_STRING("Uninitialized array.", "Might be Ok...");
        return;
    }

    TRACE_INFO_NUMBER("Current reference count: ", ra->refcount);
    if (ra->refcount) {
        /* Decrease reference count */
        ra->refcount--;
        if (ra->refcount == 0) {
            TRACE_INFO_NUMBER("It is time to delete array. Count:", ra->refcount);
            if (ra->cb) {
                for (idx = 0; idx < ra->len; idx++) {
                    ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize,
                            REF_ARRAY_DESTROY, ra->cb_data);
                }
            }
            free(ra->storage);
            free(ra);
        }
    }
    else {
        /* Should never be here...
         * This can happen if the caller by mistake would try to
         * destroy the object from within the callback. Brrr....
         */
        TRACE_ERROR_STRING("Reference count is 0.", "Coding error???");
    }

    TRACE_FLOW_EXIT();
}
示例#13
0
/* What was the level of the last item we got? */
int col_get_item_depth(struct collection_iterator *iterator, int *depth)
{
    TRACE_FLOW_STRING("col_get_item_depth", "Entry");

    if ((iterator == NULL) || (depth == NULL)) {
        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
        return EINVAL;
    }

    *depth = iterator->item_level;

    TRACE_INFO_NUMBER("Item level at the end:", iterator->item_level);
    TRACE_FLOW_STRING("col_get_item_depth","Exit");
    return EOK;
}
示例#14
0
/* Specail function to add different formatting symbols to the output */
int col_put_marker(struct col_serial_data *buf_data, const void *data, int len)
{
    int error = EOK;

    TRACE_FLOW_STRING("col_put_marker", "Entry point");
    TRACE_INFO_NUMBER("Marker length: ", len);

    error = col_grow_buffer(buf_data, len);
    if (error) {
        TRACE_ERROR_NUMBER("col_grow_buffer failed with: ", error);
        return error;
    }
    memcpy(buf_data->buffer + buf_data->length, data, len);
    buf_data->length += len;
    buf_data->buffer[buf_data->length] = '\0';

    TRACE_FLOW_STRING("col_put_marker","Success exit");
    return error;
}
示例#15
0
/* Use JSON formal for serialization */
int col_json(const char *property_in,
             int property_len_in,
             int type,
             void *data_in,
             int length_in,
             void *custom_data,
             int *dummy)
{
    int len;
    struct col_serial_data *buf_data;
    const char *property;
    const void *data;
    int  property_len;
    int length;
    int error = EOK;
    int i;

    TRACE_FLOW_STRING("col_json","Entry point");

    *dummy = 0;

    /* Check is there is buffer. If not allocate */
    buf_data = (struct col_serial_data *)custom_data;
    if (buf_data == NULL) {
        TRACE_ERROR_STRING("Error.", "Storage data is not passed in!");
        return EINVAL;
    }
    if (buf_data->buffer == NULL) {
        TRACE_INFO_STRING("First time use.", "Allocating buffer.");
        buf_data->buffer = malloc(BLOCK_SIZE);
        if (buf_data->buffer == NULL) {
            TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
            return ENOMEM;
        }
        buf_data->buffer[0] = '\0';
        buf_data->length = 0;
        buf_data->size = BLOCK_SIZE;
    }

    TRACE_INFO_NUMBER("Buffer len: ", buf_data->length);
    TRACE_INFO_NUMBER("Buffer size: ", buf_data->size);
    TRACE_INFO_STRING("Buffer: ", buf_data->buffer);

    /* Check the beginning of the collection */
    if (type == COL_TYPE_COLLECTION) {
        TRACE_INFO_STRING("Serializing collection: ", property_in);
        TRACE_INFO_STRING("First header. ", "");
        error = col_put_marker(buf_data, "{", 1);
        if (error != EOK) return error;
        property = TEXT_EVENT;
        property_len = TEXT_EVENTLEN;
        data = property_in;
        length = property_len_in + 1;
        type = COL_TYPE_STRING;
        buf_data->nest_level++;
    }
    /* Check for subcollections */
    else if (type == COL_TYPE_COLLECTIONREF) {
        /* Skip */
        TRACE_FLOW_STRING("col_serialize", "skip reference return");
        return EOK;
    }
    /* Check for the end of the collection */
    else if (type == COL_TYPE_END) {
        if ((buf_data->length > 0) &&
                (buf_data->buffer[buf_data->length-1] == ',')) {
            buf_data->length--;
            buf_data->buffer[buf_data->length] = '\0';
        }
        if (buf_data->nest_level > 0) {
            buf_data->nest_level--;
            error = col_put_marker(buf_data, "}", 1);
            if (error != EOK) return error;
        }
        TRACE_FLOW_STRING("col_serialize", "end collection item processed returning");
        return EOK;
    }
    else {
        property = property_in;
        property_len = property_len_in;
        data = data_in;
        length = length_in;
    }

    TRACE_INFO_STRING("Property: ", property);
    TRACE_INFO_NUMBER("Property length: ", property_len);

    /* Start with property and ":" */
    if ((error = col_put_marker(buf_data, "\"", 1)) ||
            (error = col_put_marker(buf_data, property, property_len)) ||
            (error = col_put_marker(buf_data, "\":", 2))) {
        TRACE_ERROR_NUMBER("put_marker returned error: ", error);
        return error;
    }
    /* Get projected length of the item */
    len = col_get_data_len(type,length);
    TRACE_INFO_NUMBER("Expected data length: ",len);
    TRACE_INFO_STRING("Buffer so far: ", buf_data->buffer);

    /* Make sure we have enough space */
    if ((error = col_grow_buffer(buf_data, len))) {
        TRACE_ERROR_NUMBER("grow_buffer returned error: ", error);
        return error;
    }

    /* Add the value */
    switch (type) {
    case COL_TYPE_STRING:
        /* Escape double quotes */
        len = col_copy_esc(&buf_data->buffer[buf_data->length],
                           (const char *)(data), '"');
        break;

    case COL_TYPE_BINARY:
        buf_data->buffer[buf_data->length] = '\'';
        for (i = 0; i < length; i++)
            sprintf(&buf_data->buffer[buf_data->length + i *2] + 1,
                    "%02X", (unsigned int)(((const unsigned char *)(data))[i]));
        len = length * 2 + 1;
        buf_data->buffer[buf_data->length + len] = '\'';
        len++;
        break;

    case COL_TYPE_INTEGER:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%d", *((const int32_t *)(data)));
        break;

    case COL_TYPE_UNSIGNED:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%u", *((const uint32_t *)(data)));
        break;

    case COL_TYPE_LONG:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%lld",
                      (long long int)(*((const int64_t *)(data))));
        break;

    case COL_TYPE_ULONG:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%llu",
                      (long long unsigned)(*((const uint64_t *)(data))));
        break;

    case COL_TYPE_DOUBLE:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%.4f", *((const double *)(data)));
        break;

    case COL_TYPE_BOOL:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%s", (*((const unsigned char *)(data))) ? "true" : "false");
        break;

    default:
        buf_data->buffer[buf_data->length] = '\0';
        len = 0;
        break;
    }

    /* Adjust length */
    buf_data->length += len;
    buf_data->buffer[buf_data->length] = '\0';

    /* Always put a comma at the end */
    error = col_put_marker(buf_data, ",", 1);
    if (error != EOK) {
        TRACE_ERROR_NUMBER("put_marker returned error: ", error);
        return error;
    }

    TRACE_INFO_STRING("Data: ", buf_data->buffer);
    TRACE_FLOW_STRING("col_json", "Exit point");
    return EOK;

}
示例#16
0
/* Debug handle */
int col_debug_handle(const char *property,
                     int property_len,
                     int type,
                     void *data,
                     int length,
                     void *custom_data,
                     int *dummy)
{
    int i;
    int nest_level;
    int ignore = 0;

    TRACE_FLOW_STRING("col_debug_handle", "Entry.");


    nest_level = *(int *)(custom_data);
    if (nest_level == -1) {
        ignore = 1;
        nest_level = 1;
    }

    TRACE_INFO_NUMBER("We are getting this pointer:", custom_data);
    TRACE_INFO_NUMBER("Nest level:", nest_level);

    switch (type) {
    case COL_TYPE_STRING:
        printf(">%*s%s[%d] str: %s (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               (char *)(data),
               nest_level);
        break;
    case COL_TYPE_BINARY:
        printf(">%*s%s[%d] bin: ",
               (nest_level -1) * 4, "",
               property,
               length);
        for (i = 0; i < length; i++)
            printf("%02X", ((unsigned char *)(data))[i]);
        printf(" (%d)\n", nest_level);
        break;
    case COL_TYPE_INTEGER:
        printf(">%*s%s[%d] int: %d (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               *((int32_t *)(data)),
               nest_level);
        break;
    case COL_TYPE_UNSIGNED:
        printf(">%*s%s[%d] uint: %u (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               *((uint32_t *)(data)),
               nest_level);
        break;
    case COL_TYPE_LONG:
        printf(">%*s%s[%d] long: %lld (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               (long long int)(*((int64_t *)(data))),
               nest_level);
        break;
    case COL_TYPE_ULONG:
        printf(">%*s%s[%d] ulong: %llu (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               (long long unsigned)(*((uint64_t *)(data))),
               nest_level);
        break;
    case COL_TYPE_DOUBLE:
        printf(">%*s%s[%d] double: %.4f (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               *((double *)(data)),
               nest_level);
        break;
    case COL_TYPE_BOOL:
        printf(">%*s%s[%d] bool: %s (%d)\n",
               (nest_level -1) * 4, "",
               property,
               length,
               (*((unsigned char *)(data)) == '\0') ? "false" : "true",
               nest_level);
        break;
    case COL_TYPE_COLLECTION:
        if (!ignore) nest_level++;
        printf(">%*s%s[%d] header: count %d, ref_count %d class %d data: ",
               (nest_level -1) * 4, "",
               property,
               length,
               ((struct collection_header *)(data))->count,
               ((struct collection_header *)(data))->reference_count,
               ((struct collection_header *)(data))->cclass);
        for (i = 0; i < length; i++)
            printf("%02X", ((unsigned char *)(data))[i]);
        printf(" (%d)\n", nest_level);
        break;
    case COL_TYPE_COLLECTIONREF:
        printf(">%*s%s[%d] external link: ",
               (nest_level -1) * 4, "",
               property,
               length);
        for (i = 0; i < length; i++)
            printf("%02X", ((unsigned char *)(data))[i]);
        printf(" (%d)\n", nest_level);
        break;
    case COL_TYPE_END:
        printf(">%*sEND[N/A] (%d)\n",
               (nest_level -1) * 4, "",
               nest_level);
        if (!ignore) nest_level--;
        break;
    default:
        printf("Not implemented yet.\n");
        break;
    }
    *(int *)(custom_data) = nest_level;
    TRACE_INFO_NUMBER("Nest level at the end:", nest_level);
    TRACE_FLOW_STRING("col_debug_handle", "Success exit.");
    return EOK;
}
示例#17
0
/* Handle key-value pair */
static int handle_kvp(struct parser_obj *po, uint32_t *action)
{
    int error = EOK;
    char *eq = NULL;
    uint32_t len = 0;
    char *dupval = NULL;
    char *str;
    uint32_t full_len;

    TRACE_FLOW_ENTRY();

    str = po->last_read;
    full_len = po->last_read_len;

    TRACE_INFO_STRING("Last read:", str);

    /* Trim spaces at the beginning */
    while ((full_len > 0) && (isspace(*(str)))) {
        str++;
        full_len--;
    }

    /* Check if we have the key */
    if (*(str) == '=') {
        TRACE_ERROR_STRING("No key", str);
        po->last_error = ERR_NOKEY;
        *action = PARSE_ERROR;
        return EOK;
    }

    /* Find "=" */
    eq = strchr(str, '=');
    if (eq == NULL) {
        TRACE_ERROR_STRING("No equal sign", str);
        po->last_error = ERR_NOEQUAL;
        *action = PARSE_ERROR;
        return EOK;
    }

    /* Strip spaces around "=" */
    /* Since eq > str we can substract 1 */
    len = eq - str - 1;
    while ((len > 0) && (isspace(*(str + len)))) len--;
    /* Adjust length properly */
    len++;

    /* Check the key length */
    if(len >= MAX_KEY) {
        TRACE_ERROR_STRING("Key name is too long", str);
        po->last_error = ERR_LONGKEY;
        *action = PARSE_ERROR;
        return EOK;
    }

    if (po->key) {
        /* Complete processing of the previous value */
        error = complete_value_processing(po);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to complete value processing", error);
            return error;
        }
    }

    /* Dup the key name */
    po->key = malloc(len + 1);
    if (!(po->key)) {
        TRACE_ERROR_NUMBER("Failed to dup key", ENOMEM);
        return ENOMEM;
    }

    memcpy(po->key, str, len);
    *(po->key + len) = '\0';
    po->key_len = len;

    TRACE_INFO_STRING("Key:", po->key);
    TRACE_INFO_NUMBER("Keylen:", po->key_len);

    len = full_len - (eq - str) - 1;

    /* Trim spaces after equal sign */
    eq++;
    while (isspace(*eq)) {
        eq++;
        len--;
    }

    TRACE_INFO_STRING("VALUE:", eq);
    TRACE_INFO_NUMBER("LENGTH:", len);

    /* Dup the part of the value */
    dupval = malloc(len + 1);
    if (!dupval) {
        TRACE_ERROR_NUMBER("Failed to dup value", ENOMEM);
        return ENOMEM;
    }

    memcpy(dupval, eq, len);
    *(dupval + len) = '\0';

    /* Create new arrays */
    error = value_create_arrays(&(po->raw_lines),
                                &(po->raw_lengths));
    if (error) {
        TRACE_ERROR_NUMBER("Failed to create arrays", error);
        free(dupval);
        return error;
    }

    /* Save a duplicated part in the value */
    error = value_add_to_arrays(dupval,
                                len,
                                po->raw_lines,
                                po->raw_lengths);

    if (error) {
        TRACE_ERROR_NUMBER("Failed to add value to arrays", error);
        free(dupval);
        return error;
    }

    /* Save the line number of the last found key */
    po->keylinenum = po->linenum;

    /* Prepare for reading */
    free(po->last_read);
    po->last_read = NULL;
    po->last_read_len = 0;

    *action = PARSE_READ;

    TRACE_FLOW_EXIT();
    return EOK;
}
示例#18
0
/* Complete value processing */
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;
    uint32_t mergemode;
    int suppress = 0;
    int doinsert = 0;
    struct collection_item *item = NULL;
    struct collection_item *section = NULL;
    int merging = 0;

    TRACE_FLOW_ENTRY();

    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);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to create default section", error);
            return error;
        }
        section = po->sec;
    }
    else {
        TRACE_INFO_STRING("Processing value in normal mode", "");
        section = po->sec;
    }

    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);

        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;
        doinsert = 1;
        break;

    case INI_MV1S_PRESERVE:

        insertmode = COL_INSERT_DUPERROR;
        doinsert = 1;
        suppress = 1;
        break;

    case INI_MV1S_ALLOW:

        insertmode = COL_INSERT_NOCHECK;
        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("Overwrite mode. Looking for:",
                          (char *)(merging ? po->merge_key : po->key));

        error = col_get_item(section,
                             merging ? po->merge_key : po->key,
                             COL_TYPE_BINARY,
                             COL_TRAVERSE_DEFAULT,
                             &item);

        if (error) {
            TRACE_ERROR_NUMBER("Failed searching for dup", error);
            value_destroy(vo);
            return error;
        }

        /* Check if there is a dup */
        if (item) {
            /* 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);
            }
        }
        else {
            /* No dup found so we can insert with no check */
            doinsert = 1;
            insertmode = COL_INSERT_NOCHECK;
        }
    }

    if (doinsert) {
        /* Add value to collection */
        error = col_insert_binary_property(section,
                                           NULL,
                                           COL_DSP_END,
                                           NULL,
                                           0,
                                           insertmode,
                                           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",
                                  (char *)(merging ? po->merge_key : po->key));
            }
            else {
                /* 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;
                }
            }
        }
    }

    if (!merging) {
        free(po->key);
        po->key = NULL;
        po->key_len = 0;
    }

    TRACE_FLOW_EXIT();
    return EOK;
}
示例#19
0
/* Function to read next line from the file */
static int parser_read(struct parser_obj *po)
{
    int error = EOK;
    char *buffer = NULL;
    ssize_t res = 0;
    size_t len = 0;
    int32_t i = 0;
    uint32_t action;

    TRACE_FLOW_ENTRY();

    /* Adjust line number */
    (po->linenum)++;

    /* Get line from the file */
    res = getline(&buffer, &len, po->file);
    if (res == -1) {
        if (feof(po->file)) {
            TRACE_FLOW_STRING("Read nothing", "");
            if (po->inside_comment) {
                action = PARSE_ERROR;
                po->last_error = ERR_BADCOMMENT;
            }
            else action = PARSE_POST;
        }
        else {
            TRACE_ERROR_STRING("Error reading", "");
            action = PARSE_ERROR;
            po->last_error = ERR_READ;
        }
        if(buffer) free(buffer);
    }
    else {
        /* Read Ok */
        len = res;
        TRACE_INFO_STRING("Read line ok:", buffer);
        TRACE_INFO_NUMBER("Length:", len);
        TRACE_INFO_NUMBER("Strlen:", strlen(buffer));

        if (buffer[0] == '\0') {
            /* Empty line - read again (should not ever happen) */
            action = PARSE_READ;
            free(buffer);
        }
        else {
            /* Check length */
            if (len >= BUFFER_SIZE) {
                TRACE_ERROR_STRING("Too long", "");
                action = PARSE_ERROR;
                po->last_error = ERR_LONGDATA;
                free(buffer);
            }
            else {
                /* Trim end line */
                i = len - 1;
                while ((i >= 0) &&
                       ((buffer[i] == '\r') ||
                        (buffer[i] == '\n'))) {
                    TRACE_INFO_NUMBER("Offset:", i);
                    TRACE_INFO_NUMBER("Code:", buffer[i]);
                    buffer[i] = '\0';
                    i--;
                }

                po->last_read = buffer;
                po->last_read_len = i + 1;
                action = PARSE_INSPECT;
                TRACE_INFO_STRING("Line:", po->last_read);
                TRACE_INFO_NUMBER("Linelen:", po->last_read_len);
            }
        }
    }

    /* Move to the next action */
    error = col_enqueue_unsigned_property(po->queue,
                                          PARSE_ACTION,
                                          action);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to schedule an action", error);
        return error;
    }

    TRACE_FLOW_EXIT();
    return EOK;
}
示例#20
0
/* Create a copy of the value */
int value_copy(struct value_obj *vo,
               struct value_obj **copy_vo)
{

    int error = EOK;
    struct value_obj *new_vo = NULL;
    struct simplebuffer *oneline = NULL;

    TRACE_FLOW_ENTRY();

    if ((!copy_vo) || (!vo)) {
        TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
        return EINVAL;
    }

    /* Create buffer to hold the value */
    error = simplebuffer_alloc(&oneline);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
        return error;
    }

    /* Put value into the buffer */
    error = simplebuffer_add_str(oneline,
                                 (const char *)simplebuffer_get_buf(vo->unfolded),
                                 simplebuffer_get_len(vo->unfolded),
                                 INI_VALUE_BLOCK);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to add string", error);
        simplebuffer_free(oneline);
        return error;
    }

    /* Acllocate new INI value structure */
    new_vo = malloc(sizeof(struct value_obj));
    if (!new_vo) {
        TRACE_ERROR_NUMBER("No memory", ENOMEM);
        simplebuffer_free(oneline);
        return ENOMEM;
    }

    new_vo->origin = vo->origin;
    new_vo->line = vo->line;
    new_vo->unfolded = oneline;
    new_vo->keylen = vo->keylen;
    new_vo->boundary = vo->boundary;
    new_vo->raw_lines = NULL;
    new_vo->raw_lengths = NULL;

    error = value_create_arrays(&(new_vo->raw_lines),
                                &(new_vo->raw_lengths));

    if (error) {
        TRACE_ERROR_NUMBER("Failed to fold", error);
        value_destroy(new_vo);
        return error;
    }

    /* Create arrays by folding the value */
    error = value_fold(new_vo->unfolded,
                       new_vo->keylen,
                       new_vo->boundary,
                       new_vo->raw_lines,
                       new_vo->raw_lengths);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to fold", error);
        value_destroy(new_vo);
        return error;
    }

    /* Copy comment */
    if (vo->ic) {
        error = ini_comment_copy(vo->ic, &new_vo->ic);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to copy comment", error);
            value_destroy(new_vo);
            return error;
        }
    }
    else new_vo->ic = NULL;

    *copy_vo = new_vo;

    TRACE_INFO_STRING("Orig value:",
                      (const char *)simplebuffer_get_buf(vo->unfolded));
    TRACE_INFO_STRING("Copy value:",
                      (const char *)simplebuffer_get_buf(new_vo->unfolded));

    TRACE_INFO_NUMBER("Orig value num lines:",
                      ref_array_len(vo->raw_lengths));
    TRACE_INFO_NUMBER("Copy value num lines:",
                      ref_array_len(new_vo->raw_lengths));

    TRACE_FLOW_EXIT();
    return error;
}
示例#21
0
/* Serialize value */
int value_serialize(struct value_obj *vo,
                    const char *key,
                    struct simplebuffer *sbobj)
{
    int error = EOK;
    uint32_t num = 0;
    uint32_t i = 0;
    uint32_t len = 0;
    char *commentline = NULL;
    char *ptr = NULL;
    char *part = NULL;
    int sec = 0;
    uint32_t vln = 0;

    TRACE_FLOW_ENTRY();
    TRACE_INFO_STRING("Serializing key:", key);

    if (!vo) {
        TRACE_ERROR_NUMBER("Invalid input parameter", EINVAL);
        return EINVAL;
    }

    /* Put comment first */
    if (vo->ic) {

        /* Get number of lines in the comment */
        error = ini_comment_get_numlines(vo->ic, &num);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to get number of lines", errno);
            return error;
        }

        for (i = 0; i < num; i++) {

            len = 0;
            commentline = NULL;

            error = ini_comment_get_line(vo->ic, i, &commentline, &len);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to get number of lines", errno);
                return error;
            }

            error = simplebuffer_add_raw(sbobj,
                                         commentline,
                                         len,
                                         INI_VALUE_BLOCK);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add comment", error);
                return error;
            }

            error = simplebuffer_add_cr(sbobj);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add CR", error);
                return error;
            }
        }
    }

    if (strncmp(key, INI_SPECIAL_KEY, sizeof(INI_SPECIAL_KEY)) == 0) {
        /* Special key carries only a comment */
        TRACE_FLOW_EXIT();
        return EOK;
    }

    /* Handle the case it is a section key */
    if (strncmp(key,
                INI_SECTION_KEY,
                sizeof(INI_SECTION_KEY)) == 0) sec = 1;

    if (sec) {
        error = simplebuffer_add_str(sbobj,
                                     INI_OPEN_BR,
                                     sizeof(INI_OPEN_BR) - 1,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add opening section bracket", error);
            return error;

        }
    }
    else {

        error = simplebuffer_add_str(sbobj,
                                     key,
                                     vo->keylen,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add key", error);
            return error;
        }

        error = simplebuffer_add_str(sbobj,
                                     INI_EQUAL_SIGN,
                                     sizeof(INI_EQUAL_SIGN) - 1,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add equal sign", error);
            return error;
        }

    }

    if (vo->raw_lines) {

        vln = ref_array_len(vo->raw_lines);
        TRACE_INFO_NUMBER("Number of lines:", vln);

#ifdef HAVE_TRACE

extern void ref_array_debug(struct ref_array *ra, int num);

        ref_array_debug(vo->raw_lines, 0);
        ref_array_debug(vo->raw_lengths, 1);
#endif

        for (i = 0; i < vln; i++) {
            /* Get line */
            ptr = ref_array_get(vo->raw_lines, i, NULL);

            if (ptr) {
                /* Get its length */
                len = 0;
                ref_array_get(vo->raw_lengths, i, (void *)&len);

                part = *((char **)(ptr));

                TRACE_INFO_STRING("Value:", part);
                TRACE_INFO_NUMBER("Lenght:", len);

                error = simplebuffer_add_raw(sbobj,
                                             part,
                                             len,
                                             INI_VALUE_BLOCK);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to add value", error);
                    return error;
                }

            }
            if (!sec) {
                error = simplebuffer_add_cr(sbobj);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to add CR", error);
                    return error;
                }
            }
        }

        if ((!vln) && (!sec)) {
            error = simplebuffer_add_cr(sbobj);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add CR", error);
                return error;
            }
        }
    }

    if (sec) {
        error = simplebuffer_add_str(sbobj,
                                     INI_CLOSE_BR,
                                     sizeof(INI_CLOSE_BR) - 1,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add closing bracket", error);
            return error;

        }

        error = simplebuffer_add_cr(sbobj);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add CR", error);
            return error;
        }
    }

    TRACE_INFO_STRING("Buffer:", (const char *)simplebuffer_get_buf(sbobj));
    TRACE_FLOW_EXIT();
    return error;
}
示例#22
0
/* Bind iterator to a collection */
int col_bind_iterator(struct collection_iterator **iterator,
                      struct collection_item *ci,
                      int mode_flags)
{
    int error;
    struct collection_header *header;
    struct collection_iterator *iter = NULL;

    TRACE_FLOW_STRING("col_bind_iterator", "Entry.");

    /* Do some argument checking first */
    if ((iterator == NULL) || (ci == NULL)) {
        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
        return EINVAL;
    }

    iter = (struct collection_iterator *)malloc(sizeof(struct collection_iterator));
    if (iter == NULL) {
        TRACE_ERROR_NUMBER("Error allocating memory for the iterator.", ENOMEM);
        return ENOMEM;
    }

    /* Allocate memory for the stack */
    iter->stack = NULL;
    iter->stack_size = 0;
    iter->stack_depth = 0;
    iter->item_level = 0;
    iter->flags = mode_flags;
    iter->pin_level = 0;
    iter->can_break = 0;

    TRACE_INFO_NUMBER("Iterator flags", iter->flags);

    /* Allocate memory for stack */
    error = col_grow_stack(iter, 1);
    if(error) {
        free(iter);
        TRACE_ERROR_NUMBER("Error growing stack.", error);
        return error;
    }

    /* Create a special end item */
    error = col_allocate_item(&(iter->end_item), "", NULL, 0, COL_TYPE_END);
    if(error) {
        free(iter);
        TRACE_ERROR_NUMBER("Error allocating end item.", error);
        return error;
    }

    /* Make sure that we tie iterator to the collection */
    header = (struct collection_header *)ci->data;
    header->reference_count++;
    iter->top = ci;
    iter->pin = ci;
    *(iter->stack) = ci;
    iter->stack_depth++;

    *iterator = iter;

    TRACE_FLOW_STRING("col_bind_iterator", "Exit");
    return EOK;
}
示例#23
0
/* Get items from the collection one by one following the tree */
int col_iterate_collection(struct collection_iterator *iterator,
                           struct collection_item **item)
{
    int error;
    struct collection_item *current;
    struct collection_item *other;

    TRACE_FLOW_STRING("col_iterate_collection", "Entry.");

    /* Check if we have storage for item */
    if (item == NULL) {
        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
        return EINVAL;
    }

    while (1) {

        TRACE_INFO_NUMBER("Stack depth:", iterator->stack_depth);

        if (iterator->stack_depth == 0) {
            /* Re-init so if we continue looping we start over */
            iterator->stack[0] = iterator->top;
            iterator->stack_depth++;
            iterator->item_level = 0;
        }

        /* Is current item available */
        current = iterator->stack[iterator->stack_depth - 1];
        iterator->item_level = iterator->stack_depth - 1;

        /* Are we done? */
        if (((iterator->stack_depth - 1) == iterator->pin_level) &&
            (iterator->pin == current)) {
            if (iterator->can_break) {
                TRACE_FLOW_STRING("We are done.", "");
                *item = NULL;
                iterator->can_break = 0;
                return EOK;
            }
            else iterator->can_break = 1;
        }

        /* We are not done so check if we have an item  */
        if (current != NULL) {

            TRACE_INFO_STRING("Current item:", current->property);
            TRACE_INFO_NUMBER("Current item type:", current->type);

            /* Is this a collection reference */
            if (current->type == COL_TYPE_COLLECTIONREF) {
                /* We do follow references? */
                TRACE_INFO_STRING("Current item:", "collection reference");
                if ((iterator->flags & COL_TRAVERSE_IGNORE) == 0) {
                    /* We should not ignore - then move on */
                    TRACE_INFO_STRING("Collection references are not ignored", "");
                    error = col_grow_stack(iterator, iterator->stack_depth + 1);
                    if (error) {
                        TRACE_ERROR_NUMBER("Error growing stack.", error);
                        return error;
                    }
                    /* Do we need to go deeper than one level ? */
                    if ((iterator->flags & COL_TRAVERSE_ONELEVEL) == 0) {
                        TRACE_INFO_STRING("Need to go deeper", "");
                        /* We need to go deeper... */
                        /* Do we need to show headers but not reference? */
                        if ((iterator->flags & COL_TRAVERSE_ONLYSUB) != 0) {
                            TRACE_INFO_STRING("Instructed to show header not reference", "");
                            other = *((struct collection_item **)current->data);
                            iterator->stack[iterator->stack_depth] = other->next;
                            iterator->item_level = iterator->stack_depth;
                            *item = other;
                        }
                        /* Do we need to show both? */
                        else if ((iterator->flags & COL_TRAVERSE_SHOWSUB) != 0) {
                            TRACE_INFO_STRING("Instructed to show header and reference","");
                            iterator->stack[iterator->stack_depth] = *((struct collection_item **)(current->data));
                            *item = current;
                            /* Do not need to adjust level here */
                        }
                        /* Do not show either */
                        else if ((iterator->flags & COL_TRAVERSE_FLAT) != 0) {
                            TRACE_INFO_STRING("Instructed not to show header and reference","");
                            other = *((struct collection_item **)current->data);
                            iterator->stack[iterator->stack_depth] = other->next;
                            iterator->stack[iterator->stack_depth - 1] = current->next;
                            iterator->stack_depth++;
                            /* Do not need to adjust level here */
                            continue;
                        }
                        /* We need to show reference only */
                        else {
                            TRACE_INFO_STRING("Instructed to show reference only", "");
                            other = *((struct collection_item **)current->data);
                            TRACE_INFO_STRING("Sub collection:", other->property);
                            TRACE_INFO_NUMBER("Sub collection type:", other->type);
                            iterator->stack[iterator->stack_depth] = other->next;
                            if (other->next != NULL) {
                                TRACE_INFO_STRING("Will show this item next time:", other->next->property);
                                TRACE_INFO_NUMBER("Will show this item next time type:", other->next->type);
                            }
                            *item = current;
                            TRACE_INFO_NUMBER("Level of the reference:", iterator->item_level);
                            /* Do not need to adjust level here */
                        }

                        TRACE_INFO_STRING("We return item:", (*item)->property);
                        TRACE_INFO_NUMBER("We return item type:", (*item)->type);
                        TRACE_INFO_STRING("Moving to the next item on the previous item in stack", "");
                        iterator->stack[iterator->stack_depth - 1] = current->next;
                        iterator->stack_depth++;

                    }
                    else {
                        TRACE_INFO_STRING("Instructed to parse just one level", "");
                        /* On one level - just return current */
                        *item = current;
                        TRACE_INFO_STRING("Moving to the next item on one level", "");
                        iterator->stack[iterator->stack_depth - 1] = current->next;
                    }
                    break;
                }
                else {
                    /* We need to ignore references so move to the next item */
                    TRACE_INFO_STRING("Stepping over the reference", "");
                    iterator->stack[iterator->stack_depth - 1] = current->next;
                    continue;
                }
            }
            else {
                /* Got a normal item - return it and move to the next one */
                if ((current->type == COL_TYPE_COLLECTION) &&
                    ((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
                    (iterator->stack_depth > 1)) {
                    TRACE_INFO_STRING("Header of the sub collection in flat case ", "");
                    iterator->stack[iterator->stack_depth - 1] = current->next;
                    continue;
                }
                else {
                    TRACE_INFO_STRING("Simple item", "");
                    *item = current;
                    iterator->stack[iterator->stack_depth - 1] = current->next;
                }
                break;
            }
        }
        else {
            /* Item is NULL */
            TRACE_INFO_STRING("Finished level", "moving to upper level");
            iterator->stack_depth--;
            /* Remember that item_level is zero based while depth is size
             * so we decrease and then assign. */
            TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
            if ((iterator->flags & COL_TRAVERSE_END) != 0) {

                /* Show end element
                 * a) If we are flattening but at the top
                 * b) We are not flattening
                 */
                if ((((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
                     (iterator->stack_depth == 0)) ||
                    ((iterator->flags & COL_TRAVERSE_FLAT) == 0)) {

                    /* Return dummy entry to indicate the end of the collection */
                    TRACE_INFO_STRING("Finished level", "told to return END");
                    *item = iterator->end_item;
                    break;
                }
            }
            else {
                /* Move to next level */
                continue;
            }
        }
    }

    TRACE_FLOW_STRING("col_iterate_collection", "Exit");
    return EOK;
}
示例#24
0
/* Function to create a folded value out of the unfolded string */
static int value_fold(struct simplebuffer *unfolded,
                      uint32_t key_len,
                      uint32_t fold_bound,
                      struct ref_array *raw_lines,
                      struct ref_array *raw_lengths)
{
    int error = EOK;
    const char *buf;
    uint32_t len = 0;          /* Full length of the buffer          */
    uint32_t fold_place = 0;   /* Potential folding place            */
    uint32_t best_place = 0;   /* Dynamic folding boundary           */
    uint32_t next_place = 0;   /* Position of the found space        */
    uint32_t fold_len = 0;     /* Determined length of the substring */
    uint32_t idx = 0;          /* Counter of lines                   */
    uint32_t i = 0;            /* Internal counter                   */
    uint32_t resume_place = 0; /* Place we resume parsing            */
    uint32_t start_place = 0;  /* Start of the string                */
    int done = 0;              /* Are we done?                       */

    TRACE_FLOW_ENTRY();

    /* Reset arrays */
    ref_array_reset(raw_lines);
    ref_array_reset(raw_lengths);

    /* Get the buffer info */
    len = simplebuffer_get_len(unfolded);
    if (!len) {
        /* Nothing to fold */
        TRACE_FLOW_EXIT();
        return EOK;
    }

    buf = (const char *)simplebuffer_get_buf(unfolded);

    TRACE_INFO_STRING("Unfolded value:", buf);

    /* Make sure that we have at least one character to fold */
    if (fold_bound == 0) fold_bound++;

    while (!done) {
        /* Determine the max length of the line */
        if (idx == 0) {
             if (fold_bound > (key_len + INI_FOLDING_OVERHEAD)) {
                 best_place = fold_bound - key_len - INI_FOLDING_OVERHEAD;
             }
             else best_place = 0;
        }
        else {
             best_place = fold_bound;

             /* Starting with the second line if we plan
              * to add space ourselves factor it into folding
              * boadary
              */
             if ((buf[start_place] != ' ') &&
                 (buf[start_place] != '\t')) best_place--;
        }

        TRACE_INFO_NUMBER("Best place", best_place);

        fold_place = start_place;
        next_place = start_place;
        best_place += start_place;


        /* Parse the buffer from the right place */
        for (i = resume_place; i <= len; i++) {

            /* Check for folding opportunity */
            if (i == len) {
                next_place = i;
                done = 1;
            }
            /*
             * Fold if we found the separator or the first line
             * is too long right away
             */
            else if (((buf[i] == ' ') || (buf[i] == '\t')) ||
                     ((best_place == 0) && (i == 0))) {
                next_place = i;
                TRACE_INFO_NUMBER("Next place:", next_place);
            }
            else continue;

            if ((next_place > best_place) || (next_place == 0)) {
                if ((fold_place == start_place) &&
                    (next_place != 0)) {
                    /* Our first found folding place
                     * is already after the preferred
                     * folding place. Time to fold then...
                     */
                    fold_len = next_place - start_place;

                }
                else {
                    /* We will use the previous
                     * folding place.
                     */
                    fold_len = fold_place - start_place;

                }

                TRACE_INFO_NUMBER("Fold len:", fold_len);

                error = save_portion(raw_lines,
                                     raw_lengths,
                                     buf + start_place,
                                     fold_len);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to save", error);
                    return error;
                }

                start_place += fold_len;

                /*
                 * This will force the re-processing
                 * of the same space but it is
                 * helpful in case the middle portion
                 * of the value is beyond our folding limit.
                 */
                resume_place = next_place;
                if (fold_len == 0) resume_place++;
                idx++;
                break;
            }
            else { /* Case when next_place <= best_place */
                fold_place = next_place;
            }
        }

        /* Save last portion */
        if (done) {
            if (next_place - start_place) {
                error = save_portion(raw_lines,
                                     raw_lengths,
                                     buf + start_place,
                                     next_place - start_place);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to save last chunk", error);
                    return error;
                }
                idx++;
            }
        }
    }

    TRACE_FLOW_EXIT();
    return error;
}
示例#25
0
/* Function to check access */
int config_access_check(struct collection_item *metadata,
                        uint32_t flags,
                        uid_t uid,
                        gid_t gid,
                        mode_t mode,
                        mode_t mask)
{
    int error = EOK;
    struct collection_item *item = NULL;
    mode_t f_mode;

    TRACE_FLOW_STRING("config_access_check", "Entry");

    flags &= INI_ACCESS_CHECK_MODE |
             INI_ACCESS_CHECK_GID |
             INI_ACCESS_CHECK_UID;

    if ((metadata == NULL) || (flags == 0)) {
        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
        return EINVAL;

    }

    /* Check that metadata is actually metadata */
    if(!col_is_of_class(metadata, COL_CLASS_INI_META)) {
        TRACE_ERROR_NUMBER("Invalid collection.", EINVAL);
        return EINVAL;
    }

    /* Check mode */
    if (flags & INI_ACCESS_CHECK_MODE) {

        error = get_config_item(INI_META_SEC_ACCESS,
                                INI_META_KEY_PERM,
                                metadata,
                                &item);
        if (error) {
            TRACE_ERROR_NUMBER("Internal collection error.", error);
            return error;
        }

        /* Entry is supposed to be there so it is an error
            * is the item is not found.
            */
        if (item == NULL) {
            TRACE_ERROR_NUMBER("Expected item is not found.", ENOENT);
            return ENOENT;
        }

        f_mode = (mode_t)get_ulong_config_value(item, 1, WRONG_FMODE, &error);
        if ((error) || (f_mode == WRONG_FMODE)) {
            TRACE_ERROR_NUMBER("Conversion failed", error);
            return ENOENT;
        }

        TRACE_INFO_NUMBER("File mode as saved.", f_mode);
        f_mode &= S_IRWXU | S_IRWXG | S_IRWXO;
        TRACE_INFO_NUMBER("File mode adjusted.", f_mode);

        TRACE_INFO_NUMBER("Mode as provided.", mode);
        mode &= S_IRWXU | S_IRWXG | S_IRWXO;
        TRACE_INFO_NUMBER("Mode adjusted.", mode);

        /* Adjust mask */
        if (mask == 0) mask = S_IRWXU | S_IRWXG | S_IRWXO;
        else mask &= S_IRWXU | S_IRWXG | S_IRWXO;

        if ((mode & mask) != (f_mode & mask)) {
            TRACE_INFO_NUMBER("File mode:", (mode & mask));
            TRACE_INFO_NUMBER("Mode adjusted.", (f_mode & mask));
            TRACE_ERROR_NUMBER("Access denied.", EACCES);
            return EACCES;
        }
    }

    /* Check uid */
    if (flags & INI_ACCESS_CHECK_UID) {

        error = check_id(metadata, (unsigned long)uid, INI_META_KEY_UID);
        if (error) {
            TRACE_ERROR_NUMBER("Check for UID failed.", error);
            return error;
        }
    }

    /* Check gid */
    if (flags & INI_ACCESS_CHECK_GID) {

        error = check_id(metadata, (unsigned long)gid, INI_META_KEY_GID);
        if (error) {
            TRACE_ERROR_NUMBER("Check for UID failed.", error);
            return error;
        }
    }

    TRACE_FLOW_STRING("config_access_check", "Exit");
    return error;

}