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