/* 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; }
/* 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; }
/* 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 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"); }
/* 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"); }
/* 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; }