/* * prof_set.c --- routines that expose the public interfaces for * inserting, updating and deleting items from the profile. * * WARNING: These routines only look at the first file opened in the * profile. It's not clear how to handle multiple files, actually. * In the future it may be necessary to modify this public interface, * or possibly add higher level functions to support this correctly. * * WARNING: We're not yet doing locking yet, either. * */ #include "prof_int.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include static errcode_t rw_setup(profile_t profile) { prf_file_t file; errcode_t retval = 0; if (!profile) return PROF_NO_PROFILE; if (profile->magic != PROF_MAGIC_PROFILE) return PROF_MAGIC_PROFILE; file = profile->first_file; retval = profile_lock_global(); if (retval) return retval; /* Don't update the file if we've already made modifications */ if (file->data->flags & PROFILE_FILE_DIRTY) { profile_unlock_global(); return 0; } if ((file->data->flags & PROFILE_FILE_SHARED) != 0) { prf_data_t new_data; new_data = profile_make_prf_data(file->data->filespec); if (new_data == NULL) { retval = ENOMEM; } else { retval = k5_mutex_init(&new_data->lock); if (retval == 0) { new_data->root = NULL; new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED; new_data->timestamp = 0; new_data->upd_serial = file->data->upd_serial; } } if (retval != 0) { profile_unlock_global(); free(new_data); return retval; } profile_dereference_data_locked(file->data); file->data = new_data; } profile_unlock_global(); retval = profile_update_file(file); return retval; } /* * Delete or update a particular child node * * ADL - 2/23/99, rewritten TYT 2/25/99 */ errcode_t KRB5_CALLCONV profile_update_relation(profile_t profile, const char **names, const char *old_value, const char *new_value) { errcode_t retval; struct profile_node *section, *node; void *state; const char **cpp; retval = rw_setup(profile); if (retval) return retval; if (names == 0 || names[0] == 0 || names[1] == 0) return PROF_BAD_NAMESET; if (!old_value || !*old_value) return PROF_EINVAL; retval = k5_mutex_lock(&profile->first_file->data->lock); if (retval) return retval; section = profile->first_file->data->root; for (cpp = names; cpp[1]; cpp++) { state = 0; retval = profile_find_node(section, *cpp, 0, 1, &state, §ion); if (retval) { k5_mutex_unlock(&profile->first_file->data->lock); return retval; } } state = 0; retval = profile_find_node(section, *cpp, old_value, 0, &state, &node); if (retval == 0) { if (new_value) retval = profile_set_relation_value(node, new_value); else retval = profile_remove_node(node); } if (retval == 0) profile->first_file->data->flags |= PROFILE_FILE_DIRTY; k5_mutex_unlock(&profile->first_file->data->lock); return retval; } /* * Clear a particular all of the relations with a specific name. * * TYT - 2/25/99 */ errcode_t KRB5_CALLCONV profile_clear_relation(profile_t profile, const char **names) { errcode_t retval; struct profile_node *section, *node; void *state; const char **cpp; retval = rw_setup(profile); if (retval) return retval; if (names == 0 || names[0] == 0 || names[1] == 0) return PROF_BAD_NAMESET; section = profile->first_file->data->root; for (cpp = names; cpp[1]; cpp++) { state = 0; retval = profile_find_node(section, *cpp, 0, 1, &state, §ion); if (retval) return retval; } state = 0; do { retval = profile_find_node(section, *cpp, 0, 0, &state, &node); if (retval) return retval; retval = profile_remove_node(node); if (retval) return retval; } while (state); profile->first_file->data->flags |= PROFILE_FILE_DIRTY; return 0; } /* * Rename a particular section; if the new_section name is NULL, * delete it. * * ADL - 2/23/99, rewritten TYT 2/25/99 */ errcode_t KRB5_CALLCONV profile_rename_section(profile_t profile, const char **names, const char *new_name) { errcode_t retval; struct profile_node *section, *node; void *state; const char **cpp; retval = rw_setup(profile); if (retval) return retval; if (names == 0 || names[0] == 0 || names[1] == 0) return PROF_BAD_NAMESET; retval = k5_mutex_lock(&profile->first_file->data->lock); if (retval) return retval; section = profile->first_file->data->root; for (cpp = names; cpp[1]; cpp++) { state = 0; retval = profile_find_node(section, *cpp, 0, 1, &state, §ion); if (retval) { k5_mutex_unlock(&profile->first_file->data->lock); return retval; } } state = 0; retval = profile_find_node(section, *cpp, 0, 1, &state, &node); if (retval == 0) { if (new_name) retval = profile_rename_node(node, new_name); else retval = profile_remove_node(node); } if (retval == 0) profile->first_file->data->flags |= PROFILE_FILE_DIRTY; k5_mutex_unlock(&profile->first_file->data->lock); return retval; } /* * Insert a new relation. If the new_value argument is NULL, then * create a new section instead. * * Note: if the intermediate sections do not exist, this function will * automatically create them. * * ADL - 2/23/99, rewritten TYT 2/25/99 */ errcode_t KRB5_CALLCONV profile_add_relation(profile_t profile, const char **names, const char *new_value) { errcode_t retval; struct profile_node *section; const char **cpp; void *state; retval = rw_setup(profile); if (retval) return retval; if (names == 0 || names[0] == 0 || names[1] == 0) return PROF_BAD_NAMESET; retval = k5_mutex_lock(&profile->first_file->data->lock); if (retval) return retval; section = profile->first_file->data->root; for (cpp = names; cpp[1]; cpp++) { state = 0; retval = profile_find_node(section, *cpp, 0, 1, &state, §ion); if (retval == PROF_NO_SECTION) retval = profile_add_node(section, *cpp, 0, §ion); if (retval) { k5_mutex_unlock(&profile->first_file->data->lock); return retval; } } if (new_value == 0) { retval = profile_find_node(section, *cpp, 0, 1, &state, 0); if (retval == 0) { k5_mutex_unlock(&profile->first_file->data->lock); return PROF_EXISTS; } else if (retval != PROF_NO_SECTION) { k5_mutex_unlock(&profile->first_file->data->lock); return retval; } } retval = profile_add_node(section, *cpp, new_value, 0); if (retval) { k5_mutex_unlock(&profile->first_file->data->lock); return retval; } profile->first_file->data->flags |= PROFILE_FILE_DIRTY; k5_mutex_unlock(&profile->first_file->data->lock); return 0; }