17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * prof_set.c --- routines that expose the public interfaces for
37c478bd9Sstevel@tonic-gate * inserting, updating and deleting items from the profile.
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * WARNING: These routines only look at the first file opened in the
67c478bd9Sstevel@tonic-gate * profile. It's not clear how to handle multiple files, actually.
77c478bd9Sstevel@tonic-gate * In the future it may be necessary to modify this public interface,
87c478bd9Sstevel@tonic-gate * or possibly add higher level functions to support this correctly.
97c478bd9Sstevel@tonic-gate *
10*1da57d55SToomas Soome * WARNING: We're not yet doing locking yet, either.
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate */
137c478bd9Sstevel@tonic-gate
14505d05c7Sgtb #include "prof_int.h"
15505d05c7Sgtb
167c478bd9Sstevel@tonic-gate #include <stdio.h>
177c478bd9Sstevel@tonic-gate #include <string.h>
187c478bd9Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
197c478bd9Sstevel@tonic-gate #include <stdlib.h>
207c478bd9Sstevel@tonic-gate #endif
217c478bd9Sstevel@tonic-gate #include <errno.h>
227c478bd9Sstevel@tonic-gate
rw_setup(profile_t profile)23505d05c7Sgtb static errcode_t rw_setup(profile_t profile)
247c478bd9Sstevel@tonic-gate {
257c478bd9Sstevel@tonic-gate prf_file_t file;
26505d05c7Sgtb errcode_t retval = 0;
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate if (!profile)
297c478bd9Sstevel@tonic-gate return PROF_NO_PROFILE;
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate if (profile->magic != PROF_MAGIC_PROFILE)
327c478bd9Sstevel@tonic-gate return PROF_MAGIC_PROFILE;
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate file = profile->first_file;
35505d05c7Sgtb
36505d05c7Sgtb retval = profile_lock_global();
37505d05c7Sgtb if (retval)
38505d05c7Sgtb return retval;
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate /* Don't update the file if we've already made modifications */
41505d05c7Sgtb if (file->data->flags & PROFILE_FILE_DIRTY) {
42505d05c7Sgtb profile_unlock_global();
43505d05c7Sgtb return 0;
44505d05c7Sgtb }
45505d05c7Sgtb
46505d05c7Sgtb if ((file->data->flags & PROFILE_FILE_SHARED) != 0) {
47505d05c7Sgtb prf_data_t new_data;
48505d05c7Sgtb new_data = profile_make_prf_data(file->data->filespec);
49505d05c7Sgtb if (new_data == NULL) {
50505d05c7Sgtb retval = ENOMEM;
51505d05c7Sgtb } else {
52505d05c7Sgtb retval = k5_mutex_init(&new_data->lock);
53505d05c7Sgtb if (retval == 0) {
54505d05c7Sgtb new_data->root = NULL;
55505d05c7Sgtb new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED;
56505d05c7Sgtb new_data->timestamp = 0;
57505d05c7Sgtb new_data->upd_serial = file->data->upd_serial;
58505d05c7Sgtb }
59505d05c7Sgtb }
60505d05c7Sgtb
61505d05c7Sgtb if (retval != 0) {
62505d05c7Sgtb profile_unlock_global();
63505d05c7Sgtb free(new_data);
64505d05c7Sgtb return retval;
65505d05c7Sgtb }
66505d05c7Sgtb profile_dereference_data_locked(file->data);
67505d05c7Sgtb file->data = new_data;
68505d05c7Sgtb }
69505d05c7Sgtb
70505d05c7Sgtb profile_unlock_global();
717c478bd9Sstevel@tonic-gate retval = profile_update_file(file);
72505d05c7Sgtb
737c478bd9Sstevel@tonic-gate return retval;
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate
77*1da57d55SToomas Soome /*
78*1da57d55SToomas Soome * Delete or update a particular child node
79*1da57d55SToomas Soome *
807c478bd9Sstevel@tonic-gate * ADL - 2/23/99, rewritten TYT 2/25/99
817c478bd9Sstevel@tonic-gate */
82505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_update_relation(profile_t profile,const char ** names,const char * old_value,const char * new_value)83505d05c7Sgtb profile_update_relation(profile_t profile, const char **names,
84505d05c7Sgtb const char *old_value, const char *new_value)
85*1da57d55SToomas Soome {
867c478bd9Sstevel@tonic-gate errcode_t retval;
877c478bd9Sstevel@tonic-gate struct profile_node *section, *node;
887c478bd9Sstevel@tonic-gate void *state;
897c478bd9Sstevel@tonic-gate const char **cpp;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate retval = rw_setup(profile);
927c478bd9Sstevel@tonic-gate if (retval)
937c478bd9Sstevel@tonic-gate return retval;
94*1da57d55SToomas Soome
957c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0)
967c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET;
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate if (!old_value || !*old_value)
997c478bd9Sstevel@tonic-gate return PROF_EINVAL;
1007c478bd9Sstevel@tonic-gate
101505d05c7Sgtb retval = k5_mutex_lock(&profile->first_file->data->lock);
102505d05c7Sgtb if (retval)
103505d05c7Sgtb return retval;
104505d05c7Sgtb section = profile->first_file->data->root;
1057c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) {
1067c478bd9Sstevel@tonic-gate state = 0;
1077c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1,
1087c478bd9Sstevel@tonic-gate &state, §ion);
109505d05c7Sgtb if (retval) {
110505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
111505d05c7Sgtb return retval;
112505d05c7Sgtb }
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate state = 0;
1167c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, old_value, 0, &state, &node);
117505d05c7Sgtb if (retval == 0) {
118505d05c7Sgtb if (new_value)
1197c478bd9Sstevel@tonic-gate retval = profile_set_relation_value(node, new_value);
120505d05c7Sgtb else
1217c478bd9Sstevel@tonic-gate retval = profile_remove_node(node);
122505d05c7Sgtb }
123505d05c7Sgtb if (retval == 0)
124505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
125505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
126*1da57d55SToomas Soome
127505d05c7Sgtb return retval;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
130*1da57d55SToomas Soome /*
1317c478bd9Sstevel@tonic-gate * Clear a particular all of the relations with a specific name.
132*1da57d55SToomas Soome *
1337c478bd9Sstevel@tonic-gate * TYT - 2/25/99
1347c478bd9Sstevel@tonic-gate */
135505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_clear_relation(profile_t profile,const char ** names)136505d05c7Sgtb profile_clear_relation(profile_t profile, const char **names)
137*1da57d55SToomas Soome {
1387c478bd9Sstevel@tonic-gate errcode_t retval;
1397c478bd9Sstevel@tonic-gate struct profile_node *section, *node;
1407c478bd9Sstevel@tonic-gate void *state;
1417c478bd9Sstevel@tonic-gate const char **cpp;
142505d05c7Sgtb
1437c478bd9Sstevel@tonic-gate retval = rw_setup(profile);
1447c478bd9Sstevel@tonic-gate if (retval)
1457c478bd9Sstevel@tonic-gate return retval;
146*1da57d55SToomas Soome
1477c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0)
1487c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET;
1497c478bd9Sstevel@tonic-gate
150505d05c7Sgtb section = profile->first_file->data->root;
1517c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) {
1527c478bd9Sstevel@tonic-gate state = 0;
1537c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1,
1547c478bd9Sstevel@tonic-gate &state, §ion);
1557c478bd9Sstevel@tonic-gate if (retval)
1567c478bd9Sstevel@tonic-gate return retval;
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate state = 0;
1607c478bd9Sstevel@tonic-gate do {
1617c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 0, &state, &node);
1627c478bd9Sstevel@tonic-gate if (retval)
1637c478bd9Sstevel@tonic-gate return retval;
1647c478bd9Sstevel@tonic-gate retval = profile_remove_node(node);
1657c478bd9Sstevel@tonic-gate if (retval)
1667c478bd9Sstevel@tonic-gate return retval;
1677c478bd9Sstevel@tonic-gate } while (state);
1687c478bd9Sstevel@tonic-gate
169505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
170*1da57d55SToomas Soome
1717c478bd9Sstevel@tonic-gate return 0;
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
174*1da57d55SToomas Soome /*
1757c478bd9Sstevel@tonic-gate * Rename a particular section; if the new_section name is NULL,
1767c478bd9Sstevel@tonic-gate * delete it.
177*1da57d55SToomas Soome *
1787c478bd9Sstevel@tonic-gate * ADL - 2/23/99, rewritten TYT 2/25/99
1797c478bd9Sstevel@tonic-gate */
180505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_rename_section(profile_t profile,const char ** names,const char * new_name)181505d05c7Sgtb profile_rename_section(profile_t profile, const char **names,
182505d05c7Sgtb const char *new_name)
183*1da57d55SToomas Soome {
1847c478bd9Sstevel@tonic-gate errcode_t retval;
1857c478bd9Sstevel@tonic-gate struct profile_node *section, *node;
1867c478bd9Sstevel@tonic-gate void *state;
1877c478bd9Sstevel@tonic-gate const char **cpp;
188*1da57d55SToomas Soome
1897c478bd9Sstevel@tonic-gate retval = rw_setup(profile);
1907c478bd9Sstevel@tonic-gate if (retval)
1917c478bd9Sstevel@tonic-gate return retval;
192*1da57d55SToomas Soome
1937c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0)
1947c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET;
1957c478bd9Sstevel@tonic-gate
196505d05c7Sgtb retval = k5_mutex_lock(&profile->first_file->data->lock);
197505d05c7Sgtb if (retval)
198505d05c7Sgtb return retval;
199505d05c7Sgtb section = profile->first_file->data->root;
2007c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) {
2017c478bd9Sstevel@tonic-gate state = 0;
2027c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1,
2037c478bd9Sstevel@tonic-gate &state, §ion);
204505d05c7Sgtb if (retval) {
205505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
206505d05c7Sgtb return retval;
207505d05c7Sgtb }
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate state = 0;
2117c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, &state, &node);
212505d05c7Sgtb if (retval == 0) {
213505d05c7Sgtb if (new_name)
2147c478bd9Sstevel@tonic-gate retval = profile_rename_node(node, new_name);
215505d05c7Sgtb else
2167c478bd9Sstevel@tonic-gate retval = profile_remove_node(node);
217505d05c7Sgtb }
218505d05c7Sgtb if (retval == 0)
219505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
220505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
221505d05c7Sgtb return retval;
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate /*
2257c478bd9Sstevel@tonic-gate * Insert a new relation. If the new_value argument is NULL, then
2267c478bd9Sstevel@tonic-gate * create a new section instead.
2277c478bd9Sstevel@tonic-gate *
2287c478bd9Sstevel@tonic-gate * Note: if the intermediate sections do not exist, this function will
2297c478bd9Sstevel@tonic-gate * automatically create them.
2307c478bd9Sstevel@tonic-gate *
2317c478bd9Sstevel@tonic-gate * ADL - 2/23/99, rewritten TYT 2/25/99
2327c478bd9Sstevel@tonic-gate */
233505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_add_relation(profile_t profile,const char ** names,const char * new_value)234505d05c7Sgtb profile_add_relation(profile_t profile, const char **names,
235505d05c7Sgtb const char *new_value)
2367c478bd9Sstevel@tonic-gate {
2377c478bd9Sstevel@tonic-gate errcode_t retval;
2387c478bd9Sstevel@tonic-gate struct profile_node *section;
2397c478bd9Sstevel@tonic-gate const char **cpp;
2407c478bd9Sstevel@tonic-gate void *state;
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate retval = rw_setup(profile);
2437c478bd9Sstevel@tonic-gate if (retval)
2447c478bd9Sstevel@tonic-gate return retval;
245*1da57d55SToomas Soome
2467c478bd9Sstevel@tonic-gate if (names == 0 || names[0] == 0 || names[1] == 0)
2477c478bd9Sstevel@tonic-gate return PROF_BAD_NAMESET;
2487c478bd9Sstevel@tonic-gate
249505d05c7Sgtb retval = k5_mutex_lock(&profile->first_file->data->lock);
250505d05c7Sgtb if (retval)
251505d05c7Sgtb return retval;
252505d05c7Sgtb section = profile->first_file->data->root;
2537c478bd9Sstevel@tonic-gate for (cpp = names; cpp[1]; cpp++) {
2547c478bd9Sstevel@tonic-gate state = 0;
2557c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1,
2567c478bd9Sstevel@tonic-gate &state, §ion);
2577c478bd9Sstevel@tonic-gate if (retval == PROF_NO_SECTION)
2587c478bd9Sstevel@tonic-gate retval = profile_add_node(section, *cpp, 0, §ion);
259505d05c7Sgtb if (retval) {
260505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
261505d05c7Sgtb return retval;
262505d05c7Sgtb }
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate if (new_value == 0) {
2667c478bd9Sstevel@tonic-gate retval = profile_find_node(section, *cpp, 0, 1, &state, 0);
267505d05c7Sgtb if (retval == 0) {
268505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
269505d05c7Sgtb return PROF_EXISTS;
270505d05c7Sgtb } else if (retval != PROF_NO_SECTION) {
271505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
272505d05c7Sgtb return retval;
273505d05c7Sgtb }
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate retval = profile_add_node(section, *cpp, new_value, 0);
277505d05c7Sgtb if (retval) {
278505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
279505d05c7Sgtb return retval;
280505d05c7Sgtb }
2817c478bd9Sstevel@tonic-gate
282505d05c7Sgtb profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
283505d05c7Sgtb k5_mutex_unlock(&profile->first_file->data->lock);
2847c478bd9Sstevel@tonic-gate return 0;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
287