2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * prof_init.c --- routines that manipulate the user-visible profile_t
24 #ifdef HAVE_INTTYPES_H
25 # include <inttypes.h>
27 typedef int32_t prof_int32
;
29 errcode_t KRB5_CALLCONV
30 profile_init(const_profile_filespec_t
*files
, profile_t
*ret_profile
)
32 const_profile_filespec_t
*fs
;
34 prf_file_t new_file
, last
= 0;
37 profile
= malloc(sizeof(struct _profile_t
));
40 memset(profile
, 0, sizeof(struct _profile_t
));
41 profile
->magic
= PROF_MAGIC_PROFILE
;
43 /* if the filenames list is not specified return an empty profile */
45 for (fs
= files
; !PROFILE_LAST_FILESPEC(*fs
); fs
++) {
46 retval
= profile_open_file(*fs
, &new_file
);
47 /* if this file is missing, skip to the next */
48 if (retval
== ENOENT
|| retval
== EACCES
) {
52 profile_release(profile
);
56 last
->next
= new_file
;
58 profile
->first_file
= new_file
;
62 * If last is still null after the loop, then all the files were
63 * missing, so return the appropriate error.
66 profile_release(profile
);
71 *ret_profile
= profile
;
75 #define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD) \
77 int cll_counter = 0; \
78 PTYPE cll_ptr = (START); \
79 while (cll_ptr != NULL) { \
81 cll_ptr = cll_ptr->FIELD; \
83 (COUNT) = cll_counter; \
86 errcode_t KRB5_CALLCONV
87 profile_copy(profile_t old_profile
, profile_t
*new_profile
)
90 const_profile_filespec_t
*files
;
94 /* The fields we care about are read-only after creation, so
95 no locking is needed. */
96 COUNT_LINKED_LIST (size
, prf_file_t
, old_profile
->first_file
, next
);
97 files
= malloc ((size
+1) * sizeof(*files
));
100 for (i
= 0, file
= old_profile
->first_file
; i
< size
; i
++, file
= file
->next
)
101 files
[i
] = file
->data
->filespec
;
103 err
= profile_init (files
, new_profile
);
108 errcode_t KRB5_CALLCONV
109 profile_init_path(const_profile_filespec_list_t filepath
,
110 profile_t
*ret_profile
)
113 unsigned int ent_len
;
115 profile_filespec_t
*filenames
;
118 /* count the distinct filename components */
119 for(s
= filepath
, n_entries
= 1; *s
; s
++) {
124 /* the array is NULL terminated */
125 filenames
= (profile_filespec_t
*) malloc((n_entries
+1) * sizeof(char*));
129 /* measure, copy, and skip each one */
130 /* Solaris Kerberos */
131 for(s
= filepath
, i
=0; ((t
= strchr(s
, ':')) != NULL
) ||
132 ((t
=s
+strlen(s
)) != NULL
); s
=t
+1, i
++) {
134 filenames
[i
] = (char*) malloc(ent_len
+ 1);
135 if (filenames
[i
] == 0) {
136 /* if malloc fails, free the ones that worked */
137 while(--i
>= 0) free(filenames
[i
]);
141 strncpy(filenames
[i
], s
, ent_len
);
142 filenames
[i
][ent_len
] = 0;
151 retval
= profile_init((const_profile_filespec_t
*) filenames
,
154 /* count back down and free the entries */
155 while(--i
>= 0) free(filenames
[i
]);
161 errcode_t KRB5_CALLCONV
162 profile_is_writable(profile_t profile
, int *writable
)
164 if (!profile
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
165 return PROF_MAGIC_PROFILE
;
170 if (profile
->first_file
)
171 *writable
= (profile
->first_file
->data
->flags
& PROFILE_FILE_RW
);
176 errcode_t KRB5_CALLCONV
177 profile_is_modified(profile_t profile
, int *modified
)
179 if (!profile
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
180 return PROF_MAGIC_PROFILE
;
185 if (profile
->first_file
)
186 *modified
= (profile
->first_file
->data
->flags
& PROFILE_FILE_DIRTY
);
191 errcode_t KRB5_CALLCONV
192 profile_flush(profile_t profile
)
194 if (!profile
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
195 return PROF_MAGIC_PROFILE
;
197 if (profile
->first_file
)
198 return profile_flush_file(profile
->first_file
);
203 errcode_t KRB5_CALLCONV
204 profile_flush_to_file(profile_t profile
, const_profile_filespec_t outfile
)
206 if (!profile
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
207 return PROF_MAGIC_PROFILE
;
209 if (profile
->first_file
)
210 return profile_flush_file_to_file(profile
->first_file
,
216 errcode_t KRB5_CALLCONV
217 profile_flush_to_buffer(profile_t profile
, char **buf
)
219 return profile_flush_file_data_to_buffer(profile
->first_file
->data
, buf
);
223 profile_free_buffer(profile_t profile
, char *buf
)
229 profile_abandon(profile_t profile
)
233 if (!profile
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
236 for (p
= profile
->first_file
; p
; p
= next
) {
238 profile_free_file(p
);
245 profile_release(profile_t profile
)
249 if (!profile
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
252 for (p
= profile
->first_file
; p
; p
= next
) {
254 profile_close_file(p
);
261 * Here begins the profile serialization functions.
264 errcode_t
profile_ser_size(const char *unused
, profile_t profile
,
270 required
= 3*sizeof(prof_int32
);
271 for (pfp
= profile
->first_file
; pfp
; pfp
= pfp
->next
) {
272 required
+= sizeof(prof_int32
);
273 required
+= strlen(pfp
->data
->filespec
);
279 static void pack_int32(prof_int32 oval
, unsigned char **bufpp
, size_t *remainp
)
281 (*bufpp
)[0] = (unsigned char) ((oval
>> 24) & 0xff);
282 (*bufpp
)[1] = (unsigned char) ((oval
>> 16) & 0xff);
283 (*bufpp
)[2] = (unsigned char) ((oval
>> 8) & 0xff);
284 (*bufpp
)[3] = (unsigned char) (oval
& 0xff);
285 *bufpp
+= sizeof(prof_int32
);
286 *remainp
-= sizeof(prof_int32
);
289 errcode_t
profile_ser_externalize(const char *unused
, profile_t profile
,
290 unsigned char **bufpp
, size_t *remainp
)
297 prof_int32 fcount
, slen
;
305 (void) profile_ser_size(unused
, profile
, &required
);
306 if (required
<= remain
) {
308 for (pfp
= profile
->first_file
; pfp
; pfp
= pfp
->next
)
310 pack_int32(PROF_MAGIC_PROFILE
, &bp
, &remain
);
311 pack_int32(fcount
, &bp
, &remain
);
312 for (pfp
= profile
->first_file
; pfp
; pfp
= pfp
->next
) {
313 slen
= (prof_int32
) strlen(pfp
->data
->filespec
);
314 pack_int32(slen
, &bp
, &remain
);
316 memcpy(bp
, pfp
->data
->filespec
, (size_t) slen
);
318 remain
-= (size_t) slen
;
321 pack_int32(PROF_MAGIC_PROFILE
, &bp
, &remain
);
330 static int unpack_int32(prof_int32
*intp
, unsigned char **bufpp
,
333 if (*remainp
>= sizeof(prof_int32
)) {
334 *intp
= (((prof_int32
) (*bufpp
)[0] << 24) |
335 ((prof_int32
) (*bufpp
)[1] << 16) |
336 ((prof_int32
) (*bufpp
)[2] << 8) |
337 ((prof_int32
) (*bufpp
)[3]));
338 *bufpp
+= sizeof(prof_int32
);
339 *remainp
-= sizeof(prof_int32
);
347 errcode_t
profile_ser_internalize(const char *unused
, profile_t
*profilep
,
348 unsigned char **bufpp
, size_t *remainp
)
354 prof_int32 fcount
, tmp
;
355 profile_filespec_t
*flist
= 0;
361 (void) unpack_int32(&tmp
, &bp
, &remain
);
365 if (tmp
!= PROF_MAGIC_PROFILE
) {
370 (void) unpack_int32(&fcount
, &bp
, &remain
);
373 flist
= (profile_filespec_t
*) malloc(sizeof(profile_filespec_t
) * (fcount
+ 1));
377 memset(flist
, 0, sizeof(char *) * (fcount
+1));
378 for (i
=0; i
<fcount
; i
++) {
379 if (!unpack_int32(&tmp
, &bp
, &remain
)) {
380 flist
[i
] = (char *) malloc((size_t) (tmp
+1));
383 memcpy(flist
[i
], bp
, (size_t) tmp
);
384 flist
[i
][tmp
] = '\0';
386 remain
-= (size_t) tmp
;
390 if (unpack_int32(&tmp
, &bp
, &remain
) ||
391 (tmp
!= PROF_MAGIC_PROFILE
)) {
396 if ((retval
= profile_init((const_profile_filespec_t
*) flist
,
405 for (i
=0; i
<fcount
; i
++) {
416 profile_get_options_boolean(profile
, section
, options
)
419 profile_options_boolean
*options
;
421 char ** actual_section
;
423 errcode_t retval
= 0;
426 for (max_i
= 0; section
[max_i
]; max_i
++);
427 if (actual_section
= (char **)malloc((max_i
+ 2) * sizeof(char *))) {
428 for (actual_section
[max_i
+ 1] = NULL
, i
= 0; section
[i
]; i
++)
429 actual_section
[i
] = section
[i
];
431 for (i
= 0; options
[i
].name
; i
++) {
432 if (options
[i
].found
) continue;
433 actual_section
[max_i
] = options
[i
].name
;
434 retval
= profile_get_value(profile
, (const char **) actual_section
,
435 (const char **)&value
);
436 if (retval
&& (retval
!= PROF_NO_RELATION
) &&
437 (retval
!= PROF_NO_SECTION
)) {
438 free(actual_section
);
441 if ((retval
== 0) && value
) {
443 * Any string other than true will turn off the
446 if (strncmp(value
,"true",4) == 0)
447 *(options
[i
].value
) = 1;
449 *(options
[i
].value
) = 0;
450 options
[i
].found
= 1;
454 free(actual_section
);
462 profile_get_options_string(profile
, section
, options
)
465 profile_option_strings
*options
;
467 char ** actual_section
;
469 errcode_t retval
= 0;
472 for (max_i
= 0; section
[max_i
]; max_i
++);
473 if (actual_section
= (char **)malloc((max_i
+ 2) * sizeof(char *))) {
474 for (actual_section
[max_i
+ 1] = NULL
, i
= 0; section
[i
]; i
++)
475 actual_section
[i
] = section
[i
];
477 for (i
= 0; options
[i
].name
; i
++) {
478 if (options
[i
].found
) continue;
479 actual_section
[max_i
] = options
[i
].name
;
480 retval
= profile_get_value(profile
, (const char **) actual_section
,
481 (const char **)&value
);
482 if (retval
&& (retval
!= PROF_NO_RELATION
) &&
483 (retval
!= PROF_NO_SECTION
)) {
484 free(actual_section
);
487 if ((retval
== 0) && value
) {
488 *options
[i
].value
= malloc(strlen(value
)+1);
489 if (*options
[i
].value
== 0)
491 strcpy(*options
[i
].value
, value
);
492 options
[i
].found
= 1;
494 *options
[i
].value
= 0;
496 free(actual_section
);