17c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27c478bd9Sstevel@tonic-gate /* 37c478bd9Sstevel@tonic-gate * prof_set.c --- routines that expose the public interfaces for 47c478bd9Sstevel@tonic-gate * inserting, updating and deleting items from the profile. 57c478bd9Sstevel@tonic-gate * 67c478bd9Sstevel@tonic-gate * WARNING: These routines only look at the first file opened in the 77c478bd9Sstevel@tonic-gate * profile. It's not clear how to handle multiple files, actually. 87c478bd9Sstevel@tonic-gate * In the future it may be necessary to modify this public interface, 97c478bd9Sstevel@tonic-gate * or possibly add higher level functions to support this correctly. 107c478bd9Sstevel@tonic-gate * 117c478bd9Sstevel@tonic-gate * WARNING: We're not yet doing locking yet, either. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 15*505d05c7Sgtb #include "prof_int.h" 16*505d05c7Sgtb 177c478bd9Sstevel@tonic-gate #include <stdio.h> 187c478bd9Sstevel@tonic-gate #include <string.h> 197c478bd9Sstevel@tonic-gate #ifdef HAVE_STDLIB_H 207c478bd9Sstevel@tonic-gate #include <stdlib.h> 217c478bd9Sstevel@tonic-gate #endif 227c478bd9Sstevel@tonic-gate #include <errno.h> 237c478bd9Sstevel@tonic-gate 24*505d05c7Sgtb static errcode_t rw_setup(profile_t profile) 257c478bd9Sstevel@tonic-gate { 267c478bd9Sstevel@tonic-gate prf_file_t file; 27*505d05c7Sgtb errcode_t retval = 0; 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate if (!profile) 307c478bd9Sstevel@tonic-gate return PROF_NO_PROFILE; 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate if (profile->magic != PROF_MAGIC_PROFILE) 337c478bd9Sstevel@tonic-gate return PROF_MAGIC_PROFILE; 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate file = profile->first_file; 36*505d05c7Sgtb 37*505d05c7Sgtb retval = profile_lock_global(); 38*505d05c7Sgtb if (retval) 39*505d05c7Sgtb return retval; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* Don't update the file if we've already made modifications */ 42*505d05c7Sgtb if (file->data->flags & PROFILE_FILE_DIRTY) { 43*505d05c7Sgtb profile_unlock_global(); 44*505d05c7Sgtb return 0; 45*505d05c7Sgtb } 46*505d05c7Sgtb 47*505d05c7Sgtb if ((file->data->flags & PROFILE_FILE_SHARED) != 0) { 48*505d05c7Sgtb prf_data_t new_data; 49*505d05c7Sgtb new_data = profile_make_prf_data(file->data->filespec); 50*505d05c7Sgtb if (new_data == NULL) { 51*505d05c7Sgtb retval = ENOMEM; 52*505d05c7Sgtb } else { 53*505d05c7Sgtb retval = k5_mutex_init(&new_data->lock); 54*505d05c7Sgtb if (retval == 0) { 55*505d05c7Sgtb new_data->root = NULL; 56*505d05c7Sgtb new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED; 57*505d05c7Sgtb new_data->timestamp = 0; 58*505d05c7Sgtb new_data->upd_serial = file->data->upd_serial; 59*505d05c7Sgtb } 60*505d05c7Sgtb } 61*505d05c7Sgtb 62*505d05c7Sgtb if (retval != 0) { 63*505d05c7Sgtb profile_unlock_global(); 64*505d05c7Sgtb free(new_data); 65*505d05c7Sgtb return retval; 66*505d05c7Sgtb } 67*505d05c7Sgtb profile_dereference_data_locked(file->data); 68*505d05c7Sgtb file->data = new_data; 69*505d05c7Sgtb } 70*505d05c7Sgtb 71*505d05c7Sgtb profile_unlock_global(); 727c478bd9Sstevel@tonic-gate retval = profile_update_file(file); 73*505d05c7Sgtb 747c478bd9Sstevel@tonic-gate return retval; 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * Delete or update a particular child node 807c478bd9Sstevel@tonic-gate * 817c478bd9Sstevel@tonic-gate * ADL - 2/23/99, rewritten TYT 2/25/99 827c478bd9Sstevel@tonic-gate */ 83*505d05c7Sgtb errcode_t KRB5_CALLCONV 84*505d05c7Sgtb profile_update_relation(profile_t profile, const char **names, 85*505d05c7Sgtb const char *old_value, const char *new_value) 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate errcode_t retval; 887c478bd9Sstevel@tonic-gate struct profile_node *section, *node; 897c478bd9Sstevel@tonic-gate void *state; 907c478bd9Sstevel@tonic-gate const char **cpp; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate retval = rw_setup(profile); 937c478bd9Sstevel@tonic-gate if (retval) 947c478bd9Sstevel@tonic-gate return retval; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0) 977c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate if (!old_value || !*old_value) 1007c478bd9Sstevel@tonic-gate return PROF_EINVAL; 1017c478bd9Sstevel@tonic-gate 102*505d05c7Sgtb retval = k5_mutex_lock(&profile->first_file->data->lock); 103*505d05c7Sgtb if (retval) 104*505d05c7Sgtb return retval; 105*505d05c7Sgtb section = profile->first_file->data->root; 1067c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) { 1077c478bd9Sstevel@tonic-gate state = 0; 1087c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, 1097c478bd9Sstevel@tonic-gate &state, §ion); 110*505d05c7Sgtb if (retval) { 111*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 112*505d05c7Sgtb return retval; 113*505d05c7Sgtb } 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate state = 0; 1177c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, old_value, 0, &state, &node); 118*505d05c7Sgtb if (retval == 0) { 119*505d05c7Sgtb if (new_value) 1207c478bd9Sstevel@tonic-gate retval = profile_set_relation_value(node, new_value); 121*505d05c7Sgtb else 1227c478bd9Sstevel@tonic-gate retval = profile_remove_node(node); 123*505d05c7Sgtb } 124*505d05c7Sgtb if (retval == 0) 125*505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 126*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 1277c478bd9Sstevel@tonic-gate 128*505d05c7Sgtb return retval; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Clear a particular all of the relations with a specific name. 1337c478bd9Sstevel@tonic-gate * 1347c478bd9Sstevel@tonic-gate * TYT - 2/25/99 1357c478bd9Sstevel@tonic-gate */ 136*505d05c7Sgtb errcode_t KRB5_CALLCONV 137*505d05c7Sgtb profile_clear_relation(profile_t profile, const char **names) 1387c478bd9Sstevel@tonic-gate { 1397c478bd9Sstevel@tonic-gate errcode_t retval; 1407c478bd9Sstevel@tonic-gate struct profile_node *section, *node; 1417c478bd9Sstevel@tonic-gate void *state; 1427c478bd9Sstevel@tonic-gate const char **cpp; 143*505d05c7Sgtb 1447c478bd9Sstevel@tonic-gate retval = rw_setup(profile); 1457c478bd9Sstevel@tonic-gate if (retval) 1467c478bd9Sstevel@tonic-gate return retval; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0) 1497c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET; 1507c478bd9Sstevel@tonic-gate 151*505d05c7Sgtb section = profile->first_file->data->root; 1527c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) { 1537c478bd9Sstevel@tonic-gate state = 0; 1547c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, 1557c478bd9Sstevel@tonic-gate &state, §ion); 1567c478bd9Sstevel@tonic-gate if (retval) 1577c478bd9Sstevel@tonic-gate return retval; 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate state = 0; 1617c478bd9Sstevel@tonic-gate do { 1627c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 0, &state, &node); 1637c478bd9Sstevel@tonic-gate if (retval) 1647c478bd9Sstevel@tonic-gate return retval; 1657c478bd9Sstevel@tonic-gate retval = profile_remove_node(node); 1667c478bd9Sstevel@tonic-gate if (retval) 1677c478bd9Sstevel@tonic-gate return retval; 1687c478bd9Sstevel@tonic-gate } while (state); 1697c478bd9Sstevel@tonic-gate 170*505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate return 0; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Rename a particular section; if the new_section name is NULL, 1777c478bd9Sstevel@tonic-gate * delete it. 1787c478bd9Sstevel@tonic-gate * 1797c478bd9Sstevel@tonic-gate * ADL - 2/23/99, rewritten TYT 2/25/99 1807c478bd9Sstevel@tonic-gate */ 181*505d05c7Sgtb errcode_t KRB5_CALLCONV 182*505d05c7Sgtb profile_rename_section(profile_t profile, const char **names, 183*505d05c7Sgtb const char *new_name) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate errcode_t retval; 1867c478bd9Sstevel@tonic-gate struct profile_node *section, *node; 1877c478bd9Sstevel@tonic-gate void *state; 1887c478bd9Sstevel@tonic-gate const char **cpp; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate retval = rw_setup(profile); 1917c478bd9Sstevel@tonic-gate if (retval) 1927c478bd9Sstevel@tonic-gate return retval; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0) 1957c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET; 1967c478bd9Sstevel@tonic-gate 197*505d05c7Sgtb retval = k5_mutex_lock(&profile->first_file->data->lock); 198*505d05c7Sgtb if (retval) 199*505d05c7Sgtb return retval; 200*505d05c7Sgtb section = profile->first_file->data->root; 2017c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) { 2027c478bd9Sstevel@tonic-gate state = 0; 2037c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, 2047c478bd9Sstevel@tonic-gate &state, §ion); 205*505d05c7Sgtb if (retval) { 206*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 207*505d05c7Sgtb return retval; 208*505d05c7Sgtb } 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate state = 0; 2127c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, &state, &node); 213*505d05c7Sgtb if (retval == 0) { 214*505d05c7Sgtb if (new_name) 2157c478bd9Sstevel@tonic-gate retval = profile_rename_node(node, new_name); 216*505d05c7Sgtb else 2177c478bd9Sstevel@tonic-gate retval = profile_remove_node(node); 218*505d05c7Sgtb } 219*505d05c7Sgtb if (retval == 0) 220*505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 221*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 222*505d05c7Sgtb return retval; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * Insert a new relation. If the new_value argument is NULL, then 2277c478bd9Sstevel@tonic-gate * create a new section instead. 2287c478bd9Sstevel@tonic-gate * 2297c478bd9Sstevel@tonic-gate * Note: if the intermediate sections do not exist, this function will 2307c478bd9Sstevel@tonic-gate * automatically create them. 2317c478bd9Sstevel@tonic-gate * 2327c478bd9Sstevel@tonic-gate * ADL - 2/23/99, rewritten TYT 2/25/99 2337c478bd9Sstevel@tonic-gate */ 234*505d05c7Sgtb errcode_t KRB5_CALLCONV 235*505d05c7Sgtb profile_add_relation(profile_t profile, const char **names, 236*505d05c7Sgtb const char *new_value) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate errcode_t retval; 2397c478bd9Sstevel@tonic-gate struct profile_node *section; 2407c478bd9Sstevel@tonic-gate const char **cpp; 2417c478bd9Sstevel@tonic-gate void *state; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate retval = rw_setup(profile); 2447c478bd9Sstevel@tonic-gate if (retval) 2457c478bd9Sstevel@tonic-gate return retval; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0) 2487c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET; 2497c478bd9Sstevel@tonic-gate 250*505d05c7Sgtb retval = k5_mutex_lock(&profile->first_file->data->lock); 251*505d05c7Sgtb if (retval) 252*505d05c7Sgtb return retval; 253*505d05c7Sgtb section = profile->first_file->data->root; 2547c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) { 2557c478bd9Sstevel@tonic-gate state = 0; 2567c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, 2577c478bd9Sstevel@tonic-gate &state, §ion); 2587c478bd9Sstevel@tonic-gate if (retval == PROF_NO_SECTION) 2597c478bd9Sstevel@tonic-gate retval = profile_add_node(section, *cpp, 0, §ion); 260*505d05c7Sgtb if (retval) { 261*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 262*505d05c7Sgtb return retval; 263*505d05c7Sgtb } 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if (new_value == 0) { 2677c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, &state, 0); 268*505d05c7Sgtb if (retval == 0) { 269*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 270*505d05c7Sgtb return PROF_EXISTS; 271*505d05c7Sgtb } else if (retval != PROF_NO_SECTION) { 272*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 273*505d05c7Sgtb return retval; 274*505d05c7Sgtb } 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate retval = profile_add_node(section, *cpp, new_value, 0); 278*505d05c7Sgtb if (retval) { 279*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 280*505d05c7Sgtb return retval; 281*505d05c7Sgtb } 2827c478bd9Sstevel@tonic-gate 283*505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 284*505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock); 2857c478bd9Sstevel@tonic-gate return 0; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 288