/* Push a bool property. */ int col_push_bool_property(struct collection_item *stack, const char *property, unsigned char logical) { int error = EOK; TRACE_FLOW_STRING("col_push_bool_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_bool_property(stack, NULL, property, logical); TRACE_FLOW_STRING("push_double_property", "Exit."); return error; }
/* Pop_item */ int col_pop_item(struct collection_item *stack, struct collection_item **item) { int error = EOK; TRACE_FLOW_STRING("col_pop_item", "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_extract_item_from_current(stack, COL_DSP_END, NULL, 0, 0, item); TRACE_FLOW_STRING("col_pop_item", "Exit."); return error; }
/* Push a binary property to stack. */ int col_push_binary_property(struct collection_item *stack, const char *property, void *binary_data, int length) { int error = EOK; TRACE_FLOW_STRING("col_push_binary_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_binary_property(stack, NULL, property, binary_data, length); TRACE_FLOW_STRING("col_push_binary_property", "Exit."); return error; }
/* 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; }
/* Pins down the iterator to loop around this point */ void col_pin_iterator(struct collection_iterator *iterator) { TRACE_FLOW_STRING("col_iterator_add_pin", "Entry"); if ((!iterator) || (!iterator->stack)) { TRACE_FLOW_STRING("Invalid itertor", "Ingoring"); return; } while ((iterator->stack_depth) && (iterator->stack[iterator->stack_depth - 1] == NULL)) { iterator->stack_depth--; } if (iterator->stack_depth == 0) { iterator->pin = iterator->top; iterator->pin_level = 0; } else { iterator->pin = iterator->stack[iterator->stack_depth - 1]; iterator->pin_level = iterator->stack_depth - 1; } iterator->can_break = 0; TRACE_FLOW_STRING("col_iterator_add_pin", "Exit"); }
/* Function that destroys a stack object */ void col_destroy_stack(struct collection_item *stack) { TRACE_FLOW_STRING("col_destroy_stack", "Entry point."); col_destroy_collection(stack); TRACE_FLOW_STRING("col_destroy_stack", "Exit"); }
/* Unbind the iterator from the collection */ void col_unbind_iterator(struct collection_iterator *iterator) { TRACE_FLOW_STRING("col_unbind_iterator", "Entry."); if (iterator != NULL) { col_destroy_collection(iterator->top); col_delete_item(iterator->end_item); free(iterator->stack); free(iterator); } TRACE_FLOW_STRING("col_unbind_iterator", "Exit"); }
/* Function that creates a stack object */ int col_create_stack(struct collection_item **stack) { int error = EOK; TRACE_FLOW_STRING("col_create_stack", "Entry point."); error = col_create_collection(stack, COL_NAME_STACK, COL_CLASS_STACK); TRACE_FLOW_STRING("col_create_stack", "Exit."); return error; }
/* Prepare metadata */ int prepare_metadata(uint32_t metaflags, struct collection_item **metadata, int *save_error) { int error = EOK; struct collection_item *metasec = NULL; TRACE_FLOW_STRING("prepare_metadata", "Entry"); /* Are we supposed to collect or process meta data ? */ if (!metadata) { TRACE_FLOW_STRING("No meta data", "Exit"); return EOK; } /* Allocate metadata */ error = col_create_collection(metadata, INI_METADATA, COL_CLASS_INI_META); if (error) { TRACE_ERROR_NUMBER("Failed to create meta data", error); return error; } /* Check and create section for file error if needed */ if (metaflags & INI_META_SEC_ERROR_FLAG) { /* Create ERROR collection */ if ((error = col_create_collection(&metasec, INI_META_SEC_ERROR, COL_CLASS_INI_SECTION)) || (error = col_add_collection_to_collection( *metadata, NULL, NULL, metasec, COL_ADD_MODE_REFERENCE))) { TRACE_ERROR_NUMBER("Failed to create error section", error); col_destroy_collection(metasec); col_destroy_collection(*metadata); *metadata = NULL; return error; } /* If we are here we would have to save file open error */ *save_error = 1; col_destroy_collection(metasec); } TRACE_FLOW_STRING("prepare_metadata", "Exit"); return error; }
/* 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; }
/* Function to free the list of properties. */ void col_free_property_list(char **str_list) { int current = 0; TRACE_FLOW_STRING("col_free_property_list","Entry"); if (str_list != NULL) { while(str_list[current]) { free(str_list[current]); current++; } free(str_list); } TRACE_FLOW_STRING("col_free_property_list","Exit"); }
/* Print the collection using default serialization */ int col_print_collection(struct collection_item *handle) { struct col_serial_data buf_data; int error = EOK; TRACE_FLOW_STRING("col_print_collection", "Entry"); printf("COLLECTION:\n"); 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_serialize, (void *)(&buf_data)); if (error) printf("Error traversing collection %d\n", error); else printf("%s\n", buf_data.buffer); free(buf_data.buffer); TRACE_FLOW_NUMBER("col_print_collection returning", error); return error; }
/* 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; }
/* Find and print one item using default serialization */ int col_print_item(struct collection_item *handle, const char *name) { struct col_serial_data buf_data; int error = EOK; TRACE_FLOW_STRING("col_print_item", "Entry"); printf("PRINT ITEM:\n"); buf_data.buffer = NULL; buf_data.length = 0; buf_data.size = 0; buf_data.nest_level = 0; error = col_get_item_and_do(handle, name, COL_TYPE_ANY, COL_TRAVERSE_DEFAULT, col_serialize, &buf_data); if(error) printf("Error searching collection %d\n", error); else { if (buf_data.buffer != NULL) { if (buf_data.length > 0) buf_data.length--; buf_data.buffer[buf_data.length] = '\0', printf("%s\n", buf_data.buffer); free(buf_data.buffer); } else { printf("Name %s is not found in the collection %s.\n", name, handle->property); } } TRACE_FLOW_NUMBER("col_print_item returning", error); return error; }
/* Swap two elements in the array */ int ref_array_swap(struct ref_array *ra, uint32_t idx1, uint32_t idx2) { int error = EOK; void *temp = NULL; TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } if ((idx1 >= ra->len) || (idx2 >= ra->len)) { TRACE_ERROR_NUMBER("Index is out of range", ERANGE); return ERANGE; } if (idx1 == idx2) { TRACE_FLOW_STRING("ref_array_swap", "Noop return"); return EOK; } temp = malloc(ra->elsize); if (!temp) { TRACE_FLOW_STRING("Failed to allocate memory for temp storage.", ""); return ENOMEM; } memcpy(temp, (unsigned char *)(ra->storage) + idx2 * ra->elsize, ra->elsize); memcpy((unsigned char *)(ra->storage) + idx2 * ra->elsize, (unsigned char *)(ra->storage) + idx1 * ra->elsize, ra->elsize); memcpy((unsigned char *)(ra->storage) + idx1 * ra->elsize, temp, ra->elsize); free(temp); TRACE_FLOW_EXIT(); return error; }
/* Function to check whether the configuration is different */ int config_changed(struct collection_item *metadata, struct collection_item *saved_metadata, int *changed) { int error = EOK; struct collection_item *md[2]; unsigned long value[3][2]; const char *key[] = { INI_META_KEY_MODIFIED, INI_META_KEY_DEV, INI_META_KEY_INODE }; int i, j; TRACE_FLOW_STRING("config_changed", "Entry"); if ((!metadata) || (!saved_metadata) || (!changed) || (!col_is_of_class(metadata, COL_CLASS_INI_META)) || (!col_is_of_class(saved_metadata, COL_CLASS_INI_META))) { TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); return EINVAL; } md[0] = metadata; md[1] = saved_metadata; /* Get three values from each collection and compare them */ for (i = 0; i < 3; i++) { for (j = 0; j < 2; j++) { value[i][j] = get_checked_value(md[j], key[i] , &error); if (error) { TRACE_ERROR_NUMBER("Failed to get section.", error); return error; } } if (value[i][0] != value[i][1]) { *changed = 1; break; } } TRACE_FLOW_STRING("config_changed", "Exit"); return error; }
/* 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; }
/* Rewinds iterator to the beginning */ void col_rewind_iterator(struct collection_iterator *iterator) { TRACE_FLOW_STRING("col_rewind_iterator", "Entry"); if ((!iterator) || (!iterator->stack)) { TRACE_FLOW_STRING("Invalid itertor", "Ingoring"); return; } iterator->pin = iterator->top; iterator->stack[0] = iterator->top; iterator->stack_depth = 1; iterator->item_level = 0; iterator->pin_level = 0; iterator->can_break = 0; TRACE_FLOW_STRING("col_rewind_iterator", "Exit"); }
/* Function to check uid or gid */ static int check_id(struct collection_item *metadata, unsigned long id, const char *key) { int error = EOK; struct collection_item *item = NULL; unsigned long fid; TRACE_FLOW_STRING("check_id", "Entry"); TRACE_INFO_STRING("Key", key); error = get_config_item(INI_META_SEC_ACCESS, key, 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; } fid = get_ulong_config_value(item, 1, -1, &error); if ((error) || (fid == -1)) { TRACE_ERROR_NUMBER("Conversion failed", EINVAL); return EINVAL; } if (id != fid) { TRACE_ERROR_NUMBER("File ID:", fid); TRACE_ERROR_NUMBER("ID passed in.", id); TRACE_ERROR_NUMBER("Access denied.", EACCES); return EACCES; } TRACE_FLOW_STRING("check_id", "Exit"); return EOK; }
/* 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; }
/* Grow iteration stack */ static int col_grow_stack(struct collection_iterator *iterator, unsigned desired) { int grow_by = 0; struct collection_item **temp; TRACE_FLOW_STRING("col_grow_stack", "Entry."); if (desired > iterator->stack_size) { grow_by = (((desired - iterator->stack_size) / STACK_DEPTH_BLOCK) + 1) * STACK_DEPTH_BLOCK; temp = (struct collection_item **)realloc(iterator->stack, grow_by * sizeof(struct collection_item *)); if (temp == NULL) { TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM); return ENOMEM; } iterator->stack = temp; iterator->stack_size += grow_by; } TRACE_FLOW_STRING("col_grow_stack", "Exit."); return EOK; }
/* 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; }
/* Print collection for debugging purposes */ int col_debug_collection(struct collection_item *handle, int flag) { int error = EOK; int nest_level = 0; TRACE_FLOW_STRING("col_debug_collection", "Entry."); printf("DEBUG COLLECTION %s\n", handle->property); flag |= COL_TRAVERSE_END; printf("Traverse flags %d\n", flag); /* Traverse collection */ error = col_traverse_collection(handle, flag, col_debug_handle, (void *)(&nest_level)); if (error) printf("Error debuging collection %d\n", error); TRACE_FLOW_STRING("col_debug_collection", "Exit."); return error; }
/* Calculate the potential size of the item */ int col_get_data_len(int type, int length) { int len = 0; TRACE_FLOW_STRING("col_get_data_len", "Entry point"); switch (type) { case COL_TYPE_INTEGER: case COL_TYPE_UNSIGNED: len = 11; break; case COL_TYPE_LONG: case COL_TYPE_ULONG: len = 20; break; case COL_TYPE_STRING: case COL_TYPE_BINARY: len = length * 2 + 2; break; case COL_TYPE_DOUBLE: len = 64; break; case COL_TYPE_BOOL: len = 6; break; default: len = 0; break; } TRACE_FLOW_STRING("col_get_data_len","Exit point"); return len; }
static unsigned long get_checked_value(struct collection_item *metadata, const char *key, int *err) { int error = EOK; struct collection_item *item = NULL; unsigned long value; TRACE_FLOW_STRING("get_checked_value", "Entry"); TRACE_INFO_STRING("Key", key); error = get_config_item(INI_META_SEC_ACCESS, key, metadata, &item); if (error) { TRACE_ERROR_NUMBER("Internal collection error.", error); *err = error; return 0; } /* 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); *err = ENOENT; return 0; } value = get_ulong_config_value(item, 1, -1, &error); if ((error) || (value == -1)) { TRACE_ERROR_NUMBER("Conversion failed", EINVAL); *err = EINVAL; return 0; } *err = 0; TRACE_FLOW_NUMBER("get_checked_value Returning", value); return value; }
/* Function to print errors from the list */ void ini_print_errors(FILE *file, char **error_list) { unsigned count = 0; TRACE_FLOW_ENTRY(); if (!error_list) { TRACE_FLOW_STRING("List is empty.", ""); return; } while (error_list[count]) { fprintf(file, "%s\n", error_list[count]); count++; } TRACE_FLOW_EXIT(); return; }
/* 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; }
/* 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; }
/* 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; }
/* 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; }