Home | History | Annotate | Download | only in profile
      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, &section);
    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, &section);
    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, &section);
    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, &section);
    258 		if (retval == PROF_NO_SECTION)
    259 			retval = profile_add_node(section, *cpp, 0, &section);
    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