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
rw_setup(profile_t profile)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
profile_update_relation(profile_t profile,const char ** names,const char * old_value,const char * new_value)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
profile_clear_relation(profile_t profile,const char ** names)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
profile_rename_section(profile_t profile,const char ** names,const char * new_name)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
profile_add_relation(profile_t profile,const char ** names,const char * new_value)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