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, &section);
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, &section);
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, &section);
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, &section);
257 		if (retval == PROF_NO_SECTION)
258 			retval = profile_add_node(section, *cpp, 0, &section);
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