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