17c478bd9Sstevel@tonic-gate /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * prof_init.c --- routines that manipulate the user-visible profile_t
97c478bd9Sstevel@tonic-gate  * 	object.
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
12505d05c7Sgtb #include "prof_int.h"
13505d05c7Sgtb 
147c478bd9Sstevel@tonic-gate #include <stdio.h>
157c478bd9Sstevel@tonic-gate #include <string.h>
167c478bd9Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
177c478bd9Sstevel@tonic-gate #include <stdlib.h>
187c478bd9Sstevel@tonic-gate #endif
197c478bd9Sstevel@tonic-gate #include <errno.h>
207c478bd9Sstevel@tonic-gate 
21*159d09a2SMark Phalan #ifdef HAVE_STDINT_H
22*159d09a2SMark Phalan # include <stdint.h>
23*159d09a2SMark Phalan #endif
24*159d09a2SMark Phalan #ifdef HAVE_INTTYPES_H
25*159d09a2SMark Phalan # include <inttypes.h>
26*159d09a2SMark Phalan #endif
27*159d09a2SMark Phalan typedef int32_t prof_int32;
287c478bd9Sstevel@tonic-gate 
29505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_init(const_profile_filespec_t * files,profile_t * ret_profile)30505d05c7Sgtb profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
317c478bd9Sstevel@tonic-gate {
327c478bd9Sstevel@tonic-gate 	const_profile_filespec_t *fs;
337c478bd9Sstevel@tonic-gate 	profile_t profile;
347c478bd9Sstevel@tonic-gate 	prf_file_t  new_file, last = 0;
357c478bd9Sstevel@tonic-gate 	errcode_t retval = 0;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate 	profile = malloc(sizeof(struct _profile_t));
387c478bd9Sstevel@tonic-gate 	if (!profile)
397c478bd9Sstevel@tonic-gate 		return ENOMEM;
407c478bd9Sstevel@tonic-gate 	memset(profile, 0, sizeof(struct _profile_t));
417c478bd9Sstevel@tonic-gate 	profile->magic = PROF_MAGIC_PROFILE;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate         /* if the filenames list is not specified return an empty profile */
447c478bd9Sstevel@tonic-gate         if ( files ) {
457c478bd9Sstevel@tonic-gate 	    for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
467c478bd9Sstevel@tonic-gate 		retval = profile_open_file(*fs, &new_file);
477c478bd9Sstevel@tonic-gate 		/* if this file is missing, skip to the next */
48505d05c7Sgtb 		if (retval == ENOENT || retval == EACCES) {
497c478bd9Sstevel@tonic-gate 			continue;
507c478bd9Sstevel@tonic-gate 		}
517c478bd9Sstevel@tonic-gate 		if (retval) {
527c478bd9Sstevel@tonic-gate 			profile_release(profile);
537c478bd9Sstevel@tonic-gate 			return retval;
547c478bd9Sstevel@tonic-gate 		}
557c478bd9Sstevel@tonic-gate 		if (last)
567c478bd9Sstevel@tonic-gate 			last->next = new_file;
577c478bd9Sstevel@tonic-gate 		else
587c478bd9Sstevel@tonic-gate 			profile->first_file = new_file;
597c478bd9Sstevel@tonic-gate 		last = new_file;
607c478bd9Sstevel@tonic-gate 	    }
617c478bd9Sstevel@tonic-gate 	    /*
627c478bd9Sstevel@tonic-gate 	     * If last is still null after the loop, then all the files were
637c478bd9Sstevel@tonic-gate 	     * missing, so return the appropriate error.
647c478bd9Sstevel@tonic-gate 	     */
657c478bd9Sstevel@tonic-gate 	    if (!last) {
667c478bd9Sstevel@tonic-gate 		profile_release(profile);
677c478bd9Sstevel@tonic-gate 		return ENOENT;
687c478bd9Sstevel@tonic-gate 	    }
697c478bd9Sstevel@tonic-gate 	}
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate         *ret_profile = profile;
727c478bd9Sstevel@tonic-gate         return 0;
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
75*159d09a2SMark Phalan #define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD)	\
76*159d09a2SMark Phalan 	{						\
77*159d09a2SMark Phalan 	    int cll_counter = 0;			\
78*159d09a2SMark Phalan 	    PTYPE cll_ptr = (START);			\
79*159d09a2SMark Phalan 	    while (cll_ptr != NULL) {			\
80*159d09a2SMark Phalan 		cll_counter++;				\
81*159d09a2SMark Phalan 		cll_ptr = cll_ptr->FIELD;		\
82*159d09a2SMark Phalan 	    }						\
83*159d09a2SMark Phalan 	    (COUNT) = cll_counter;			\
84*159d09a2SMark Phalan 	}
85*159d09a2SMark Phalan 
86*159d09a2SMark Phalan errcode_t KRB5_CALLCONV
profile_copy(profile_t old_profile,profile_t * new_profile)87*159d09a2SMark Phalan profile_copy(profile_t old_profile, profile_t *new_profile)
88*159d09a2SMark Phalan {
89*159d09a2SMark Phalan     size_t size, i;
90*159d09a2SMark Phalan     const_profile_filespec_t *files;
91*159d09a2SMark Phalan     prf_file_t file;
92*159d09a2SMark Phalan     errcode_t err;
93*159d09a2SMark Phalan 
94*159d09a2SMark Phalan     /* The fields we care about are read-only after creation, so
95*159d09a2SMark Phalan        no locking is needed.  */
96*159d09a2SMark Phalan     COUNT_LINKED_LIST (size, prf_file_t, old_profile->first_file, next);
97*159d09a2SMark Phalan     files = malloc ((size+1) * sizeof(*files));
98*159d09a2SMark Phalan     if (files == NULL)
99*159d09a2SMark Phalan 	return errno;
100*159d09a2SMark Phalan     for (i = 0, file = old_profile->first_file; i < size; i++, file = file->next)
101*159d09a2SMark Phalan 	files[i] = file->data->filespec;
102*159d09a2SMark Phalan     files[size] = NULL;
103*159d09a2SMark Phalan     err = profile_init (files, new_profile);
104*159d09a2SMark Phalan     free (files);
105*159d09a2SMark Phalan     return err;
106*159d09a2SMark Phalan }
107*159d09a2SMark Phalan 
108505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_init_path(const_profile_filespec_list_t filepath,profile_t * ret_profile)109505d05c7Sgtb profile_init_path(const_profile_filespec_list_t filepath,
110505d05c7Sgtb 		  profile_t *ret_profile)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	int n_entries, i;
113505d05c7Sgtb 	unsigned int ent_len;
1147c478bd9Sstevel@tonic-gate 	const char *s, *t;
115505d05c7Sgtb 	profile_filespec_t *filenames;
1167c478bd9Sstevel@tonic-gate 	errcode_t retval;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* count the distinct filename components */
1197c478bd9Sstevel@tonic-gate 	for(s = filepath, n_entries = 1; *s; s++) {
1207c478bd9Sstevel@tonic-gate 		if (*s == ':')
1217c478bd9Sstevel@tonic-gate 			n_entries++;
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/* the array is NULL terminated */
125505d05c7Sgtb 	filenames = (profile_filespec_t*) malloc((n_entries+1) * sizeof(char*));
1267c478bd9Sstevel@tonic-gate 	if (filenames == 0)
1277c478bd9Sstevel@tonic-gate 		return ENOMEM;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	/* measure, copy, and skip each one */
130*159d09a2SMark Phalan 	/* Solaris Kerberos */
1317c478bd9Sstevel@tonic-gate 	for(s = filepath, i=0; ((t = strchr(s, ':')) != NULL) ||
132505d05c7Sgtb 			((t=s+strlen(s)) != NULL); s=t+1, i++) {
1337c478bd9Sstevel@tonic-gate 		ent_len = t-s;
1347c478bd9Sstevel@tonic-gate 		filenames[i] = (char*) malloc(ent_len + 1);
1357c478bd9Sstevel@tonic-gate 		if (filenames[i] == 0) {
1367c478bd9Sstevel@tonic-gate 			/* if malloc fails, free the ones that worked */
1377c478bd9Sstevel@tonic-gate 			while(--i >= 0) free(filenames[i]);
1387c478bd9Sstevel@tonic-gate                         free(filenames);
1397c478bd9Sstevel@tonic-gate 			return ENOMEM;
1407c478bd9Sstevel@tonic-gate 		}
1417c478bd9Sstevel@tonic-gate 		strncpy(filenames[i], s, ent_len);
1427c478bd9Sstevel@tonic-gate 		filenames[i][ent_len] = 0;
1437c478bd9Sstevel@tonic-gate 		if (*t == 0) {
1447c478bd9Sstevel@tonic-gate 			i++;
1457c478bd9Sstevel@tonic-gate 			break;
1467c478bd9Sstevel@tonic-gate 		}
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	/* cap the array */
1497c478bd9Sstevel@tonic-gate 	filenames[i] = 0;
1507c478bd9Sstevel@tonic-gate 
151505d05c7Sgtb 	retval = profile_init((const_profile_filespec_t *) filenames,
152505d05c7Sgtb 			      ret_profile);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* count back down and free the entries */
1557c478bd9Sstevel@tonic-gate 	while(--i >= 0) free(filenames[i]);
1567c478bd9Sstevel@tonic-gate 	free(filenames);
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	return retval;
1597c478bd9Sstevel@tonic-gate }
160505d05c7Sgtb 
161505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_is_writable(profile_t profile,int * writable)162505d05c7Sgtb profile_is_writable(profile_t profile, int *writable)
1637c478bd9Sstevel@tonic-gate {
164*159d09a2SMark Phalan     if (!profile || profile->magic != PROF_MAGIC_PROFILE)
165*159d09a2SMark Phalan         return PROF_MAGIC_PROFILE;
166*159d09a2SMark Phalan 
167*159d09a2SMark Phalan     if (!writable)
168*159d09a2SMark Phalan         return EINVAL;
169*159d09a2SMark Phalan 
170*159d09a2SMark Phalan     if (profile->first_file)
171*159d09a2SMark Phalan         *writable = (profile->first_file->data->flags & PROFILE_FILE_RW);
172*159d09a2SMark Phalan 
173*159d09a2SMark Phalan     return 0;
174505d05c7Sgtb }
175505d05c7Sgtb 
176505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_is_modified(profile_t profile,int * modified)177505d05c7Sgtb profile_is_modified(profile_t profile, int *modified)
178505d05c7Sgtb {
179*159d09a2SMark Phalan     if (!profile || profile->magic != PROF_MAGIC_PROFILE)
180*159d09a2SMark Phalan         return PROF_MAGIC_PROFILE;
181*159d09a2SMark Phalan 
182*159d09a2SMark Phalan     if (!modified)
183*159d09a2SMark Phalan         return EINVAL;
184*159d09a2SMark Phalan 
185*159d09a2SMark Phalan     if (profile->first_file)
186*159d09a2SMark Phalan         *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
187*159d09a2SMark Phalan 
188*159d09a2SMark Phalan     return 0;
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
191505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_flush(profile_t profile)192505d05c7Sgtb profile_flush(profile_t profile)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
1957c478bd9Sstevel@tonic-gate 		return PROF_MAGIC_PROFILE;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (profile->first_file)
1987c478bd9Sstevel@tonic-gate 		return profile_flush_file(profile->first_file);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	return 0;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
203505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_flush_to_file(profile_t profile,const_profile_filespec_t outfile)204505d05c7Sgtb profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile)
205505d05c7Sgtb {
206505d05c7Sgtb 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
207505d05c7Sgtb 		return PROF_MAGIC_PROFILE;
208505d05c7Sgtb 
209505d05c7Sgtb 	if (profile->first_file)
210505d05c7Sgtb 		return profile_flush_file_to_file(profile->first_file,
211505d05c7Sgtb 						  outfile);
212505d05c7Sgtb 
213505d05c7Sgtb 	return 0;
214505d05c7Sgtb }
215505d05c7Sgtb 
216505d05c7Sgtb errcode_t KRB5_CALLCONV
profile_flush_to_buffer(profile_t profile,char ** buf)217505d05c7Sgtb profile_flush_to_buffer(profile_t profile, char **buf)
218505d05c7Sgtb {
219505d05c7Sgtb     return profile_flush_file_data_to_buffer(profile->first_file->data, buf);
220505d05c7Sgtb }
221505d05c7Sgtb 
222505d05c7Sgtb void KRB5_CALLCONV
profile_free_buffer(profile_t profile,char * buf)223505d05c7Sgtb profile_free_buffer(profile_t profile, char *buf)
224505d05c7Sgtb {
225505d05c7Sgtb     free(buf);
226505d05c7Sgtb }
227505d05c7Sgtb 
228505d05c7Sgtb void KRB5_CALLCONV
profile_abandon(profile_t profile)229505d05c7Sgtb profile_abandon(profile_t profile)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	prf_file_t	p, next;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
2347c478bd9Sstevel@tonic-gate 		return;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	for (p = profile->first_file; p; p = next) {
2377c478bd9Sstevel@tonic-gate 		next = p->next;
2387c478bd9Sstevel@tonic-gate 		profile_free_file(p);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	profile->magic = 0;
2417c478bd9Sstevel@tonic-gate 	free(profile);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
244