1 #pragma ident "%Z%%M% %I% %E% SMI" 2 /* 3 * prof_set.c --- routines that expose the public interfaces for 4 * inserting, updating and deleting items from the profile. 5 * 6 * WARNING: These routines only look at the first file opened in the 7 * profile. It's not clear how to handle multiple files, actually. 8 * In the future it may be necessary to modify this public interface, 9 * or possibly add higher level functions to support this correctly. 10 * 11 * WARNING: We're not yet doing locking yet, either. 12 * 13 */ 14 15 #include "prof_int.h" 16 17 #include <stdio.h> 18 #include <string.h> 19 #ifdef HAVE_STDLIB_H 20 #include <stdlib.h> 21 #endif 22 #include <errno.h> 23 24 static errcode_t rw_setup(profile_t profile) 25 { 26 prf_file_t file; 27 errcode_t retval = 0; 28 29 if (!profile) 30 return PROF_NO_PROFILE; 31 32 if (profile->magic != PROF_MAGIC_PROFILE) 33 return PROF_MAGIC_PROFILE; 34 35 file = profile->first_file; 36 37 retval = profile_lock_global(); 38 if (retval) 39 return retval; 40 41 /* Don't update the file if we've already made modifications */ 42 if (file->data->flags & PROFILE_FILE_DIRTY) { 43 profile_unlock_global(); 44 return 0; 45 } 46 47 if ((file->data->flags & PROFILE_FILE_SHARED) != 0) { 48 prf_data_t new_data; 49 new_data = profile_make_prf_data(file->data->filespec); 50 if (new_data == NULL) { 51 retval = ENOMEM; 52 } else { 53 retval = k5_mutex_init(&new_data->lock); 54 if (retval == 0) { 55 new_data->root = NULL; 56 new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED; 57 new_data->timestamp = 0; 58 new_data->upd_serial = file->data->upd_serial; 59 } 60 } 61 62 if (retval != 0) { 63 profile_unlock_global(); 64 free(new_data); 65 return retval; 66 } 67 profile_dereference_data_locked(file->data); 68 file->data = new_data; 69 } 70 71 profile_unlock_global(); 72 retval = profile_update_file(file); 73 74 return retval; 75 } 76 77 78 /* 79 * Delete or update a particular child node 80 * 81 * ADL - 2/23/99, rewritten TYT 2/25/99 82 */ 83 errcode_t KRB5_CALLCONV 84 profile_update_relation(profile_t profile, const char **names, 85 const char *old_value, const char *new_value) 86 { 87 errcode_t retval; 88 struct profile_node *section, *node; 89 void *state; 90 const char **cpp; 91 92 retval = rw_setup(profile); 93 if (retval) 94 return retval; 95 96 if (names == 0 || names[0] == 0 || names[1] == 0) 97 return PROF_BAD_NAMESET; 98 99 if (!old_value || !*old_value) 100 return PROF_EINVAL; 101 102 retval = k5_mutex_lock(&profile->first_file->data->lock); 103 if (retval) 104 return retval; 105 section = profile->first_file->data->root; 106 for (cpp = names; cpp[1]; cpp++) { 107 state = 0; 108 retval = profile_find_node(section, *cpp, 0, 1, 109 &state, §ion); 110 if (retval) { 111 k5_mutex_unlock(&profile->first_file->data->lock); 112 return retval; 113 } 114 } 115 116 state = 0; 117 retval = profile_find_node(section, *cpp, old_value, 0, &state, &node); 118 if (retval == 0) { 119 if (new_value) 120 retval = profile_set_relation_value(node, new_value); 121 else 122 retval = profile_remove_node(node); 123 } 124 if (retval == 0) 125 profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 126 k5_mutex_unlock(&profile->first_file->data->lock); 127 128 return retval; 129 } 130 131 /* 132 * Clear a particular all of the relations with a specific name. 133 * 134 * TYT - 2/25/99 135 */ 136 errcode_t KRB5_CALLCONV 137 profile_clear_relation(profile_t profile, const char **names) 138 { 139 errcode_t retval; 140 struct profile_node *section, *node; 141 void *state; 142 const char **cpp; 143 144 retval = rw_setup(profile); 145 if (retval) 146 return retval; 147 148 if (names == 0 || names[0] == 0 || names[1] == 0) 149 return PROF_BAD_NAMESET; 150 151 section = profile->first_file->data->root; 152 for (cpp = names; cpp[1]; cpp++) { 153 state = 0; 154 retval = profile_find_node(section, *cpp, 0, 1, 155 &state, §ion); 156 if (retval) 157 return retval; 158 } 159 160 state = 0; 161 do { 162 retval = profile_find_node(section, *cpp, 0, 0, &state, &node); 163 if (retval) 164 return retval; 165 retval = profile_remove_node(node); 166 if (retval) 167 return retval; 168 } while (state); 169 170 profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 171 172 return 0; 173 } 174 175 /* 176 * Rename a particular section; if the new_section name is NULL, 177 * delete it. 178 * 179 * ADL - 2/23/99, rewritten TYT 2/25/99 180 */ 181 errcode_t KRB5_CALLCONV 182 profile_rename_section(profile_t profile, const char **names, 183 const char *new_name) 184 { 185 errcode_t retval; 186 struct profile_node *section, *node; 187 void *state; 188 const char **cpp; 189 190 retval = rw_setup(profile); 191 if (retval) 192 return retval; 193 194 if (names == 0 || names[0] == 0 || names[1] == 0) 195 return PROF_BAD_NAMESET; 196 197 retval = k5_mutex_lock(&profile->first_file->data->lock); 198 if (retval) 199 return retval; 200 section = profile->first_file->data->root; 201 for (cpp = names; cpp[1]; cpp++) { 202 state = 0; 203 retval = profile_find_node(section, *cpp, 0, 1, 204 &state, §ion); 205 if (retval) { 206 k5_mutex_unlock(&profile->first_file->data->lock); 207 return retval; 208 } 209 } 210 211 state = 0; 212 retval = profile_find_node(section, *cpp, 0, 1, &state, &node); 213 if (retval == 0) { 214 if (new_name) 215 retval = profile_rename_node(node, new_name); 216 else 217 retval = profile_remove_node(node); 218 } 219 if (retval == 0) 220 profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 221 k5_mutex_unlock(&profile->first_file->data->lock); 222 return retval; 223 } 224 225 /* 226 * Insert a new relation. If the new_value argument is NULL, then 227 * create a new section instead. 228 * 229 * Note: if the intermediate sections do not exist, this function will 230 * automatically create them. 231 * 232 * ADL - 2/23/99, rewritten TYT 2/25/99 233 */ 234 errcode_t KRB5_CALLCONV 235 profile_add_relation(profile_t profile, const char **names, 236 const char *new_value) 237 { 238 errcode_t retval; 239 struct profile_node *section; 240 const char **cpp; 241 void *state; 242 243 retval = rw_setup(profile); 244 if (retval) 245 return retval; 246 247 if (names == 0 || names[0] == 0 || names[1] == 0) 248 return PROF_BAD_NAMESET; 249 250 retval = k5_mutex_lock(&profile->first_file->data->lock); 251 if (retval) 252 return retval; 253 section = profile->first_file->data->root; 254 for (cpp = names; cpp[1]; cpp++) { 255 state = 0; 256 retval = profile_find_node(section, *cpp, 0, 1, 257 &state, §ion); 258 if (retval == PROF_NO_SECTION) 259 retval = profile_add_node(section, *cpp, 0, §ion); 260 if (retval) { 261 k5_mutex_unlock(&profile->first_file->data->lock); 262 return retval; 263 } 264 } 265 266 if (new_value == 0) { 267 retval = profile_find_node(section, *cpp, 0, 1, &state, 0); 268 if (retval == 0) { 269 k5_mutex_unlock(&profile->first_file->data->lock); 270 return PROF_EXISTS; 271 } else if (retval != PROF_NO_SECTION) { 272 k5_mutex_unlock(&profile->first_file->data->lock); 273 return retval; 274 } 275 } 276 277 retval = profile_add_node(section, *cpp, new_value, 0); 278 if (retval) { 279 k5_mutex_unlock(&profile->first_file->data->lock); 280 return retval; 281 } 282 283 profile->first_file->data->flags |= PROFILE_FILE_DIRTY; 284 k5_mutex_unlock(&profile->first_file->data->lock); 285 return 0; 286 } 287 288