/* Create a buffer containg JSON serialization */
int col_json_collection(struct collection_item *handle, char **storage)
{
    struct col_serial_data buf_data;
    int error = EOK;

    TRACE_FLOW_STRING("col_json_collection", "Entry");

    if (storage == NULL) {
        TRACE_ERROR_STRING("Error.", "Storage data is not passed in!");
        return EINVAL;
    }

    *storage = NULL;

    buf_data.buffer = NULL;
    buf_data.length = 0;
    buf_data.size = 0;
    buf_data.nest_level = 0;

    /* Traverse collection */
    error = col_traverse_collection(handle,
                                    COL_TRAVERSE_DEFAULT | COL_TRAVERSE_END ,
                                    col_json, (void *)(&buf_data));
    if (error)
        TRACE_ERROR_NUMBER("Error traversing collection ", error);
    else
        *storage = buf_data.buffer;

    TRACE_FLOW_NUMBER("col_json_collection returning", error);
    return error;
}
Exemple #2
0
/* Reset array */
void ref_array_reset(struct ref_array *ra)
{
    int idx;

    TRACE_FLOW_ENTRY();

    /* Check if array is not NULL */
    if (!ra) {
        TRACE_ERROR_STRING("Uninitialized array.", "Coding error???");
        return;
    }

    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);
    ra->storage = NULL;
    ra->size = 0;
    ra->len = 0;

    TRACE_FLOW_EXIT();
}
Exemple #3
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;
}
/* Print the collection using iterator */
int col_print_collection2(struct collection_item *handle)
{
    struct collection_iterator *iterator = NULL;
    int error = EOK;
    struct collection_item *item = NULL;
    int nest_level = 0;
    int dummy = 0;
    int line = 1;

    TRACE_FLOW_STRING("col_print_collection2", "Entry");

    /* If we have something to print print it */
    if (handle == NULL) {
        TRACE_ERROR_STRING("No error list", "");
        return EINVAL;
    }

    /* Bind iterator */
    error = col_bind_iterator(&iterator, handle,
                              COL_TRAVERSE_DEFAULT |
                              COL_TRAVERSE_END |
                              COL_TRAVERSE_SHOWSUB);
    if (error) {
        TRACE_ERROR_NUMBER("Error (bind):", error);
        return error;
    }

    do {
        /* Loop through a collection */
        error = col_iterate_collection(iterator, &item);
        if (error) {
            TRACE_ERROR_NUMBER("Error (iterate):", error);
            col_unbind_iterator(iterator);
            return error;
        }

        /* Are we done ? */
        if (item == NULL) break;

        if (item->type != COL_TYPE_END) printf("%05d", line);

        col_debug_handle(item->property,
                         item->property_len,
                         item->type,
                         item->data,
                         item->length,
                         (void *)(&nest_level),
                         &dummy);
        line++;
    }
    while(1);

    /* Do not forget to unbind iterator - otherwise there will be a leak */
    col_unbind_iterator(iterator);

    TRACE_INFO_STRING("col_print_collection2", "Exit");
    return EOK;
}
Exemple #5
0
/* Alternative function to get length */
uint32_t ref_array_len(struct ref_array *ra)
{
    TRACE_FLOW_ENTRY();

    if (!ra) {
        TRACE_ERROR_STRING("Uninitialized argument.", "");
        errno = EINVAL;
        return 0;
    }

    TRACE_FLOW_EXIT();
    return ra->len;
}
Exemple #6
0
/* Allocate buffer structure */
int simplebuffer_alloc(struct simplebuffer **data)
{
    int error = EOK;

    TRACE_FLOW_ENTRY();

    if (!data) {
        TRACE_ERROR_STRING("Invalid argument", "");
        error = EINVAL;
    }
    else {
        *data = (struct simplebuffer *)calloc(1,
                                              sizeof(struct simplebuffer));
        if (*data == NULL) {
            TRACE_ERROR_STRING("Failed to allocate memory", "");
            error = ENOMEM;
        }
        else error = EOK;
    }

    TRACE_FLOW_RETURN(error);
    return error;
}
Exemple #7
0
/* Get length */
int ref_array_getlen(struct ref_array *ra, uint32_t *len)
{
    TRACE_FLOW_ENTRY();

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

    *len = ra->len;

    TRACE_FLOW_EXIT();
    return EOK;
}
int col_push_str_property(struct collection_item *stack,
                          const char *property, const char *string, int length)
{
    int error = EOK;

    TRACE_FLOW_STRING("col_push_str_property", "Entry point.");

    /* Check that stack is not empty */
    if (stack == NULL) {
        TRACE_ERROR_STRING("Stack can't be NULL", "");
        return EINVAL;
    }

    /* Make sure it is a stack */
    if (!col_is_of_class(stack, COL_CLASS_STACK)) {
        TRACE_ERROR_STRING("Wrong class", "");
        return EINVAL;
    }

    error = col_add_str_property(stack, NULL, property, string, length);

    TRACE_FLOW_STRING("col_push_str_property", "Exit.");
    return error;
}
Exemple #9
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;
}
Exemple #10
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();
}
/* 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;

}
Exemple #12
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;
}
Exemple #13
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;
}
Exemple #14
0
/* Print errors and warnings that were detected while parsing
 * the whole configuration */
void print_config_parsing_errors(FILE *file,
                                 struct collection_item *error_list)
{
    struct collection_iterator *iterator;
    int error;
    struct collection_item *item = NULL;
    struct collection_item *file_errors = NULL;

    TRACE_FLOW_STRING("print_config_parsing_errors", "Entry");

    /* If we have something to print print it */
    if (error_list == NULL) {
        TRACE_ERROR_STRING("No error list", "");
        return;
    }

    /* Make sure we go the right collection */
    if (!col_is_of_class(error_list, COL_CLASS_INI_PESET)) {
        TRACE_ERROR_STRING("Wrong collection class:", WRONG_COLLECTION);
        fprintf(file, "%s\n", WRONG_COLLECTION);
        return;
    }

    /* Bind iterator */
    error =  col_bind_iterator(&iterator, error_list, COL_TRAVERSE_DEFAULT);
    if (error) {
        TRACE_ERROR_STRING("Error (bind):", FAILED_TO_PROCCESS);
        fprintf(file,"%s\n", FAILED_TO_PROCCESS);
        return;
    }

    while(1) {
        /* Loop through a collection */
        error = col_iterate_collection(iterator, &item);
        if (error) {
            TRACE_ERROR_STRING("Error (iterate):", FAILED_TO_PROCCESS);
            fprintf(file, "%s\n", FAILED_TO_PROCCESS);
            col_unbind_iterator(iterator);
            return;
        }

        /* Are we done ? */
        if (item == NULL) break;

        /* Print per file sets of errors */
        if (col_get_item_type(item) == COL_TYPE_COLLECTIONREF) {
            /* Extract a sub collection */
            error = col_get_reference_from_item(item, &file_errors);
            if (error) {
                TRACE_ERROR_STRING("Error (extract):", FAILED_TO_PROCCESS);
                fprintf(file, "%s\n", FAILED_TO_PROCCESS);
                col_unbind_iterator(iterator);
                return;
            }
            print_file_parsing_errors(file, file_errors);
            col_destroy_collection(file_errors);
        }
    }

    /* Do not forget to unbind iterator - otherwise there will be a leak */
    col_unbind_iterator(iterator);

    TRACE_FLOW_STRING("print_config_parsing_errors", "Exit");
}
Exemple #15
0
/* Internal function that prints errors */
static void print_error_list(FILE *file,
                             struct collection_item *error_list,
                             int cclass,
                             char *wrong_col_error,
                             char *failed_to_process,
                             char *error_header,
                             char *line_format,
                             int family)
{
    struct collection_iterator *iterator;
    int error;
    struct collection_item *item = NULL;
    struct parse_error *pe;
    unsigned int count;

    TRACE_FLOW_STRING("print_error_list", "Entry");

    /* If we have something to print print it */
    if (error_list == NULL) {
        TRACE_ERROR_STRING("No error list","");
        return;
    }

    /* Make sure we go the right collection */
    if (!col_is_of_class(error_list, cclass)) {
        TRACE_ERROR_STRING("Wrong collection class:", wrong_col_error);
        fprintf(file,"%s\n", wrong_col_error);
        return;
    }

    /* Bind iterator */
    error =  col_bind_iterator(&iterator, error_list, COL_TRAVERSE_DEFAULT);
    if (error) {
        TRACE_ERROR_STRING("Error (bind):", failed_to_process);
        fprintf(file, "%s\n", failed_to_process);
        return;
    }

    while(1) {
        /* Loop through a collection */
        error = col_iterate_collection(iterator, &item);
        if (error) {
            TRACE_ERROR_STRING("Error (iterate):", failed_to_process);
            fprintf(file, "%s\n", failed_to_process);
            col_unbind_iterator(iterator);
            return;
        }

        /* Are we done ? */
        if (item == NULL) break;

        /* Process collection header */
        if (col_get_item_type(item) == COL_TYPE_COLLECTION) {
            col_get_collection_count(item, &count);
            if (count <= 2) break;
        } else if (col_get_item_type(item) == COL_TYPE_STRING) {
            fprintf(file, error_header, (char *)col_get_item_data(item));
        }
        else {
            /* Put error into provided format */
            pe = (struct parse_error *)(col_get_item_data(item));
            fprintf(file, line_format,
                    col_get_item_property(item, NULL), /* Error or warning */
                    pe->error,                         /* Error */
                    pe->line,                          /* Line */
                    ini_get_error_str(pe->error,
                                      family));        /* Error str */
        }

    }

    /* Do not forget to unbind iterator - otherwise there will be a leak */
    col_unbind_iterator(iterator);

    TRACE_FLOW_STRING("print_error_list", "Exit");
}