Path: blob/main/crypto/krb5/src/util/profile/prof_set.c
34878 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/*2* prof_set.c --- routines that expose the public interfaces for3* inserting, updating and deleting items from the profile.4*5* WARNING: These routines only look at the first file opened in the6* profile. It's not clear how to handle multiple files, actually.7* In the future it may be necessary to modify this public interface,8* or possibly add higher level functions to support this correctly.9*10* WARNING: We're not yet doing locking yet, either.11*12*/1314#include "prof_int.h"1516#include <stdio.h>17#include <string.h>18#ifdef HAVE_STDLIB_H19#include <stdlib.h>20#endif21#include <errno.h>2223static errcode_t rw_setup(profile_t profile)24{25prf_file_t file;26prf_data_t new_data;2728if (!profile)29return PROF_NO_PROFILE;3031if (profile->magic != PROF_MAGIC_PROFILE)32return PROF_MAGIC_PROFILE;3334/* If the profile has no files, create a memory-only data object. */35if (profile->first_file == NULL) {36profile->first_file = profile_open_memory();37return (profile->first_file == NULL) ? ENOMEM : 0;38}3940file = profile->first_file;4142profile_lock_global();4344/* Don't update the file if we've already made modifications */45if (file->data->flags & PROFILE_FILE_DIRTY) {46profile_unlock_global();47return 0;48}4950if ((file->data->flags & PROFILE_FILE_SHARED) != 0) {51new_data = profile_make_prf_data(file->data->filespec);52if (new_data == NULL) {53profile_unlock_global();54return ENOMEM;55}56new_data->root = NULL;57new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED;58new_data->timestamp = 0;59new_data->upd_serial = file->data->upd_serial;6061profile_dereference_data_locked(file->data);62file->data = new_data;63}6465profile_unlock_global();66return profile_update_file(file, NULL);67}686970/*71* Delete or update a particular child node72*73* ADL - 2/23/99, rewritten TYT 2/25/9974*/75errcode_t KRB5_CALLCONV76profile_update_relation(profile_t profile, const char **names,77const char *old_value, const char *new_value)78{79errcode_t retval;80struct profile_node *section, *node;81void *state;82const char **cpp;8384if (profile->vt) {85if (!profile->vt->update_relation)86return PROF_UNSUPPORTED;87return profile->vt->update_relation(profile->cbdata, names, old_value,88new_value);89}9091retval = rw_setup(profile);92if (retval)93return retval;9495if (names == 0 || names[0] == 0 || names[1] == 0)96return PROF_BAD_NAMESET;9798if (!old_value || !*old_value)99return PROF_EINVAL;100101k5_mutex_lock(&profile->first_file->data->lock);102section = profile->first_file->data->root;103for (cpp = names; cpp[1]; cpp++) {104state = 0;105retval = profile_find_node(section, *cpp, 0, 1,106&state, §ion);107if (retval) {108k5_mutex_unlock(&profile->first_file->data->lock);109return retval;110}111}112113state = 0;114retval = profile_find_node(section, *cpp, old_value, 0, &state, &node);115if (retval == 0) {116if (new_value)117retval = profile_set_relation_value(node, new_value);118else119retval = profile_remove_node(node);120}121if (retval == 0)122profile->first_file->data->flags |= PROFILE_FILE_DIRTY;123k5_mutex_unlock(&profile->first_file->data->lock);124125return retval;126}127128/*129* Clear a particular all of the relations with a specific name.130*131* TYT - 2/25/99132*/133errcode_t KRB5_CALLCONV134profile_clear_relation(profile_t profile, const char **names)135{136errcode_t retval;137struct profile_node *section, *node;138void *state;139const char **cpp;140141if (profile->vt) {142if (!profile->vt->update_relation)143return PROF_UNSUPPORTED;144return profile->vt->update_relation(profile->cbdata, names, NULL,145NULL);146}147148retval = rw_setup(profile);149if (retval)150return retval;151152if (names == 0 || names[0] == 0 || names[1] == 0)153return PROF_BAD_NAMESET;154155section = profile->first_file->data->root;156for (cpp = names; cpp[1]; cpp++) {157state = 0;158retval = profile_find_node(section, *cpp, 0, 1,159&state, §ion);160if (retval)161return retval;162}163164state = 0;165do {166retval = profile_find_node(section, *cpp, 0, 0, &state, &node);167if (retval)168return retval;169retval = profile_remove_node(node);170if (retval)171return retval;172} while (state);173174profile->first_file->data->flags |= PROFILE_FILE_DIRTY;175176return 0;177}178179/*180* Rename a particular section; if the new_section name is NULL,181* delete it.182*183* ADL - 2/23/99, rewritten TYT 2/25/99184*/185errcode_t KRB5_CALLCONV186profile_rename_section(profile_t profile, const char **names,187const char *new_name)188{189errcode_t retval;190struct profile_node *section, *node;191void *state;192const char **cpp;193194if (profile->vt) {195if (!profile->vt->rename_section)196return PROF_UNSUPPORTED;197return profile->vt->rename_section(profile->cbdata, names, new_name);198}199200retval = rw_setup(profile);201if (retval)202return retval;203204if (names == 0 || names[0] == 0)205return PROF_BAD_NAMESET;206207k5_mutex_lock(&profile->first_file->data->lock);208section = profile->first_file->data->root;209for (cpp = names; cpp[1]; cpp++) {210state = 0;211retval = profile_find_node(section, *cpp, 0, 1,212&state, §ion);213if (retval) {214k5_mutex_unlock(&profile->first_file->data->lock);215return retval;216}217}218219state = 0;220retval = profile_find_node(section, *cpp, 0, 1, &state, &node);221if (retval == 0) {222if (new_name)223retval = profile_rename_node(node, new_name);224else225retval = profile_remove_node(node);226}227if (retval == 0)228profile->first_file->data->flags |= PROFILE_FILE_DIRTY;229k5_mutex_unlock(&profile->first_file->data->lock);230return retval;231}232233/*234* Insert a new relation. If the new_value argument is NULL, then235* create a new section instead.236*237* Note: if the intermediate sections do not exist, this function will238* automatically create them.239*240* ADL - 2/23/99, rewritten TYT 2/25/99241*/242errcode_t KRB5_CALLCONV243profile_add_relation(profile_t profile, const char **names,244const char *new_value)245{246errcode_t retval;247struct profile_node *section;248const char **cpp;249void *state;250251if (profile->vt) {252if (!profile->vt->add_relation)253return PROF_UNSUPPORTED;254return profile->vt->add_relation(profile->cbdata, names, new_value);255}256257retval = rw_setup(profile);258if (retval)259return retval;260261/* Require at least two names for a new relation, one for a new section. */262if (names == 0 || names[0] == 0 || (names[1] == 0 && new_value))263return PROF_BAD_NAMESET;264265k5_mutex_lock(&profile->first_file->data->lock);266section = profile->first_file->data->root;267for (cpp = names; cpp[1]; cpp++) {268state = 0;269retval = profile_find_node(section, *cpp, 0, 1,270&state, §ion);271if (retval == PROF_NO_SECTION)272retval = profile_add_node(section, *cpp, NULL, 0, §ion);273if (retval) {274k5_mutex_unlock(&profile->first_file->data->lock);275return retval;276}277}278279if (new_value == 0) {280state = 0;281retval = profile_find_node(section, *cpp, 0, 1, &state, 0);282if (retval == 0) {283k5_mutex_unlock(&profile->first_file->data->lock);284return PROF_EXISTS;285} else if (retval != PROF_NO_SECTION) {286k5_mutex_unlock(&profile->first_file->data->lock);287return retval;288}289}290291retval = profile_add_node(section, *cpp, new_value, 0, NULL);292if (retval) {293k5_mutex_unlock(&profile->first_file->data->lock);294return retval;295}296297profile->first_file->data->flags |= PROFILE_FILE_DIRTY;298k5_mutex_unlock(&profile->first_file->data->lock);299return 0;300}301302303