1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * profile_helpers.c -- Helper functions for the profile library
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * These functions are not part of the "core" profile library, and do
5*6a54128fSAndroid Build Coastguard Worker * not require access to the internal functions and data structures of
6*6a54128fSAndroid Build Coastguard Worker * the profile library. They are mainly convenience functions for
7*6a54128fSAndroid Build Coastguard Worker * programs that want to do something unusual such as obtaining the
8*6a54128fSAndroid Build Coastguard Worker * list of sections or relations, or accessing multiple values from a
9*6a54128fSAndroid Build Coastguard Worker * relation that is listed more than once. This functionality can all
10*6a54128fSAndroid Build Coastguard Worker * be done using the profile_iterator abstraction, but it is less
11*6a54128fSAndroid Build Coastguard Worker * convenient.
12*6a54128fSAndroid Build Coastguard Worker *
13*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2006 by Theodore Ts'o.
14*6a54128fSAndroid Build Coastguard Worker *
15*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
16*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Public
17*6a54128fSAndroid Build Coastguard Worker * License.
18*6a54128fSAndroid Build Coastguard Worker * %End-Header%
19*6a54128fSAndroid Build Coastguard Worker */
20*6a54128fSAndroid Build Coastguard Worker
21*6a54128fSAndroid Build Coastguard Worker #include "config.h"
22*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
23*6a54128fSAndroid Build Coastguard Worker #include <string.h>
24*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
25*6a54128fSAndroid Build Coastguard Worker
26*6a54128fSAndroid Build Coastguard Worker #include <et/com_err.h>
27*6a54128fSAndroid Build Coastguard Worker #include "profile.h"
28*6a54128fSAndroid Build Coastguard Worker #include "profile_helpers.h"
29*6a54128fSAndroid Build Coastguard Worker #include "prof_err.h"
30*6a54128fSAndroid Build Coastguard Worker
31*6a54128fSAndroid Build Coastguard Worker /*
32*6a54128fSAndroid Build Coastguard Worker * These functions --- init_list(), end_list(), and add_to_list() are
33*6a54128fSAndroid Build Coastguard Worker * internal functions used to build up a null-terminated char ** list
34*6a54128fSAndroid Build Coastguard Worker * of strings to be returned by functions like profile_get_values.
35*6a54128fSAndroid Build Coastguard Worker *
36*6a54128fSAndroid Build Coastguard Worker * The profile_string_list structure is used for internal booking
37*6a54128fSAndroid Build Coastguard Worker * purposes to build up the list, which is returned in *ret_list by
38*6a54128fSAndroid Build Coastguard Worker * the end_list() function.
39*6a54128fSAndroid Build Coastguard Worker *
40*6a54128fSAndroid Build Coastguard Worker * The publicly exported interface for freeing char** list is
41*6a54128fSAndroid Build Coastguard Worker * profile_free_list().
42*6a54128fSAndroid Build Coastguard Worker */
43*6a54128fSAndroid Build Coastguard Worker
44*6a54128fSAndroid Build Coastguard Worker struct profile_string_list {
45*6a54128fSAndroid Build Coastguard Worker char **list;
46*6a54128fSAndroid Build Coastguard Worker int num;
47*6a54128fSAndroid Build Coastguard Worker int max;
48*6a54128fSAndroid Build Coastguard Worker };
49*6a54128fSAndroid Build Coastguard Worker
50*6a54128fSAndroid Build Coastguard Worker /*
51*6a54128fSAndroid Build Coastguard Worker * Initialize the string list abstraction.
52*6a54128fSAndroid Build Coastguard Worker */
init_list(struct profile_string_list * list)53*6a54128fSAndroid Build Coastguard Worker static errcode_t init_list(struct profile_string_list *list)
54*6a54128fSAndroid Build Coastguard Worker {
55*6a54128fSAndroid Build Coastguard Worker list->num = 0;
56*6a54128fSAndroid Build Coastguard Worker list->max = 10;
57*6a54128fSAndroid Build Coastguard Worker list->list = malloc(list->max * sizeof(char *));
58*6a54128fSAndroid Build Coastguard Worker if (list->list == 0)
59*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
60*6a54128fSAndroid Build Coastguard Worker list->list[0] = 0;
61*6a54128fSAndroid Build Coastguard Worker return 0;
62*6a54128fSAndroid Build Coastguard Worker }
63*6a54128fSAndroid Build Coastguard Worker
64*6a54128fSAndroid Build Coastguard Worker /*
65*6a54128fSAndroid Build Coastguard Worker * Free any memory left over in the string abstraction, returning the
66*6a54128fSAndroid Build Coastguard Worker * built up list in *ret_list if it is non-null.
67*6a54128fSAndroid Build Coastguard Worker */
end_list(struct profile_string_list * list,char *** ret_list)68*6a54128fSAndroid Build Coastguard Worker static void end_list(struct profile_string_list *list, char ***ret_list)
69*6a54128fSAndroid Build Coastguard Worker {
70*6a54128fSAndroid Build Coastguard Worker char **cp;
71*6a54128fSAndroid Build Coastguard Worker
72*6a54128fSAndroid Build Coastguard Worker if (list == 0)
73*6a54128fSAndroid Build Coastguard Worker return;
74*6a54128fSAndroid Build Coastguard Worker
75*6a54128fSAndroid Build Coastguard Worker if (ret_list) {
76*6a54128fSAndroid Build Coastguard Worker *ret_list = list->list;
77*6a54128fSAndroid Build Coastguard Worker return;
78*6a54128fSAndroid Build Coastguard Worker } else {
79*6a54128fSAndroid Build Coastguard Worker for (cp = list->list; *cp; cp++)
80*6a54128fSAndroid Build Coastguard Worker free(*cp);
81*6a54128fSAndroid Build Coastguard Worker free(list->list);
82*6a54128fSAndroid Build Coastguard Worker }
83*6a54128fSAndroid Build Coastguard Worker list->num = list->max = 0;
84*6a54128fSAndroid Build Coastguard Worker list->list = 0;
85*6a54128fSAndroid Build Coastguard Worker }
86*6a54128fSAndroid Build Coastguard Worker
87*6a54128fSAndroid Build Coastguard Worker /*
88*6a54128fSAndroid Build Coastguard Worker * Add a string to the list.
89*6a54128fSAndroid Build Coastguard Worker */
add_to_list(struct profile_string_list * list,char * str)90*6a54128fSAndroid Build Coastguard Worker static errcode_t add_to_list(struct profile_string_list *list, char *str)
91*6a54128fSAndroid Build Coastguard Worker {
92*6a54128fSAndroid Build Coastguard Worker char **newlist;
93*6a54128fSAndroid Build Coastguard Worker int newmax;
94*6a54128fSAndroid Build Coastguard Worker
95*6a54128fSAndroid Build Coastguard Worker if (list->num+1 >= list->max) {
96*6a54128fSAndroid Build Coastguard Worker newmax = list->max + 10;
97*6a54128fSAndroid Build Coastguard Worker newlist = realloc(list->list, newmax * sizeof(char *));
98*6a54128fSAndroid Build Coastguard Worker if (newlist == 0)
99*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
100*6a54128fSAndroid Build Coastguard Worker list->max = newmax;
101*6a54128fSAndroid Build Coastguard Worker list->list = newlist;
102*6a54128fSAndroid Build Coastguard Worker }
103*6a54128fSAndroid Build Coastguard Worker
104*6a54128fSAndroid Build Coastguard Worker list->list[list->num++] = str;
105*6a54128fSAndroid Build Coastguard Worker list->list[list->num] = 0;
106*6a54128fSAndroid Build Coastguard Worker return 0;
107*6a54128fSAndroid Build Coastguard Worker }
108*6a54128fSAndroid Build Coastguard Worker
109*6a54128fSAndroid Build Coastguard Worker /*
110*6a54128fSAndroid Build Coastguard Worker * Return TRUE if the string is already a member of the list.
111*6a54128fSAndroid Build Coastguard Worker */
is_list_member(struct profile_string_list * list,const char * str)112*6a54128fSAndroid Build Coastguard Worker static int is_list_member(struct profile_string_list *list, const char *str)
113*6a54128fSAndroid Build Coastguard Worker {
114*6a54128fSAndroid Build Coastguard Worker char **cpp;
115*6a54128fSAndroid Build Coastguard Worker
116*6a54128fSAndroid Build Coastguard Worker if (!list->list)
117*6a54128fSAndroid Build Coastguard Worker return 0;
118*6a54128fSAndroid Build Coastguard Worker
119*6a54128fSAndroid Build Coastguard Worker for (cpp = list->list; *cpp; cpp++) {
120*6a54128fSAndroid Build Coastguard Worker if (!strcmp(*cpp, str))
121*6a54128fSAndroid Build Coastguard Worker return 1;
122*6a54128fSAndroid Build Coastguard Worker }
123*6a54128fSAndroid Build Coastguard Worker return 0;
124*6a54128fSAndroid Build Coastguard Worker }
125*6a54128fSAndroid Build Coastguard Worker
126*6a54128fSAndroid Build Coastguard Worker /*
127*6a54128fSAndroid Build Coastguard Worker * This function frees a null-terminated list as returned by
128*6a54128fSAndroid Build Coastguard Worker * profile_get_values.
129*6a54128fSAndroid Build Coastguard Worker */
profile_free_list(char ** list)130*6a54128fSAndroid Build Coastguard Worker void profile_free_list(char **list)
131*6a54128fSAndroid Build Coastguard Worker {
132*6a54128fSAndroid Build Coastguard Worker char **cp;
133*6a54128fSAndroid Build Coastguard Worker
134*6a54128fSAndroid Build Coastguard Worker if (list == 0)
135*6a54128fSAndroid Build Coastguard Worker return;
136*6a54128fSAndroid Build Coastguard Worker
137*6a54128fSAndroid Build Coastguard Worker for (cp = list; *cp; cp++)
138*6a54128fSAndroid Build Coastguard Worker free(*cp);
139*6a54128fSAndroid Build Coastguard Worker free(list);
140*6a54128fSAndroid Build Coastguard Worker }
141*6a54128fSAndroid Build Coastguard Worker
142*6a54128fSAndroid Build Coastguard Worker errcode_t
profile_get_values(profile_t profile,const char * const * names,char *** ret_values)143*6a54128fSAndroid Build Coastguard Worker profile_get_values(profile_t profile, const char *const *names,
144*6a54128fSAndroid Build Coastguard Worker char ***ret_values)
145*6a54128fSAndroid Build Coastguard Worker {
146*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
147*6a54128fSAndroid Build Coastguard Worker void *state;
148*6a54128fSAndroid Build Coastguard Worker char *value;
149*6a54128fSAndroid Build Coastguard Worker struct profile_string_list values;
150*6a54128fSAndroid Build Coastguard Worker
151*6a54128fSAndroid Build Coastguard Worker if ((retval = profile_iterator_create(profile, names,
152*6a54128fSAndroid Build Coastguard Worker PROFILE_ITER_RELATIONS_ONLY,
153*6a54128fSAndroid Build Coastguard Worker &state)))
154*6a54128fSAndroid Build Coastguard Worker return retval;
155*6a54128fSAndroid Build Coastguard Worker
156*6a54128fSAndroid Build Coastguard Worker if ((retval = init_list(&values)))
157*6a54128fSAndroid Build Coastguard Worker goto cleanup_iterator;
158*6a54128fSAndroid Build Coastguard Worker
159*6a54128fSAndroid Build Coastguard Worker do {
160*6a54128fSAndroid Build Coastguard Worker if ((retval = profile_iterator(&state, 0, &value)))
161*6a54128fSAndroid Build Coastguard Worker goto cleanup;
162*6a54128fSAndroid Build Coastguard Worker if (value)
163*6a54128fSAndroid Build Coastguard Worker add_to_list(&values, value);
164*6a54128fSAndroid Build Coastguard Worker } while (state);
165*6a54128fSAndroid Build Coastguard Worker
166*6a54128fSAndroid Build Coastguard Worker if (values.num == 0) {
167*6a54128fSAndroid Build Coastguard Worker retval = PROF_NO_RELATION;
168*6a54128fSAndroid Build Coastguard Worker goto cleanup;
169*6a54128fSAndroid Build Coastguard Worker }
170*6a54128fSAndroid Build Coastguard Worker
171*6a54128fSAndroid Build Coastguard Worker end_list(&values, ret_values);
172*6a54128fSAndroid Build Coastguard Worker return 0;
173*6a54128fSAndroid Build Coastguard Worker
174*6a54128fSAndroid Build Coastguard Worker cleanup:
175*6a54128fSAndroid Build Coastguard Worker end_list(&values, 0);
176*6a54128fSAndroid Build Coastguard Worker cleanup_iterator:
177*6a54128fSAndroid Build Coastguard Worker profile_iterator_free(&state);
178*6a54128fSAndroid Build Coastguard Worker return retval;
179*6a54128fSAndroid Build Coastguard Worker }
180*6a54128fSAndroid Build Coastguard Worker
181*6a54128fSAndroid Build Coastguard Worker /*
182*6a54128fSAndroid Build Coastguard Worker * This function will return the list of the names of subsections in the
183*6a54128fSAndroid Build Coastguard Worker * under the specified section name.
184*6a54128fSAndroid Build Coastguard Worker */
185*6a54128fSAndroid Build Coastguard Worker errcode_t
profile_get_subsection_names(profile_t profile,const char ** names,char *** ret_names)186*6a54128fSAndroid Build Coastguard Worker profile_get_subsection_names(profile_t profile, const char **names,
187*6a54128fSAndroid Build Coastguard Worker char ***ret_names)
188*6a54128fSAndroid Build Coastguard Worker {
189*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
190*6a54128fSAndroid Build Coastguard Worker void *state;
191*6a54128fSAndroid Build Coastguard Worker char *name;
192*6a54128fSAndroid Build Coastguard Worker struct profile_string_list values;
193*6a54128fSAndroid Build Coastguard Worker
194*6a54128fSAndroid Build Coastguard Worker if ((retval = profile_iterator_create(profile, names,
195*6a54128fSAndroid Build Coastguard Worker PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
196*6a54128fSAndroid Build Coastguard Worker &state)))
197*6a54128fSAndroid Build Coastguard Worker return retval;
198*6a54128fSAndroid Build Coastguard Worker
199*6a54128fSAndroid Build Coastguard Worker if ((retval = init_list(&values)))
200*6a54128fSAndroid Build Coastguard Worker goto cleanup_iterator;
201*6a54128fSAndroid Build Coastguard Worker
202*6a54128fSAndroid Build Coastguard Worker do {
203*6a54128fSAndroid Build Coastguard Worker if ((retval = profile_iterator(&state, &name, 0)))
204*6a54128fSAndroid Build Coastguard Worker goto cleanup;
205*6a54128fSAndroid Build Coastguard Worker if (name)
206*6a54128fSAndroid Build Coastguard Worker add_to_list(&values, name);
207*6a54128fSAndroid Build Coastguard Worker } while (state);
208*6a54128fSAndroid Build Coastguard Worker
209*6a54128fSAndroid Build Coastguard Worker end_list(&values, ret_names);
210*6a54128fSAndroid Build Coastguard Worker return 0;
211*6a54128fSAndroid Build Coastguard Worker
212*6a54128fSAndroid Build Coastguard Worker cleanup:
213*6a54128fSAndroid Build Coastguard Worker end_list(&values, 0);
214*6a54128fSAndroid Build Coastguard Worker cleanup_iterator:
215*6a54128fSAndroid Build Coastguard Worker profile_iterator_free(&state);
216*6a54128fSAndroid Build Coastguard Worker return retval;
217*6a54128fSAndroid Build Coastguard Worker }
218*6a54128fSAndroid Build Coastguard Worker
219*6a54128fSAndroid Build Coastguard Worker /*
220*6a54128fSAndroid Build Coastguard Worker * This function will return the list of the names of relations in the
221*6a54128fSAndroid Build Coastguard Worker * under the specified section name.
222*6a54128fSAndroid Build Coastguard Worker */
223*6a54128fSAndroid Build Coastguard Worker errcode_t
profile_get_relation_names(profile_t profile,const char ** names,char *** ret_names)224*6a54128fSAndroid Build Coastguard Worker profile_get_relation_names(profile_t profile, const char **names,
225*6a54128fSAndroid Build Coastguard Worker char ***ret_names)
226*6a54128fSAndroid Build Coastguard Worker {
227*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
228*6a54128fSAndroid Build Coastguard Worker void *state;
229*6a54128fSAndroid Build Coastguard Worker char *name;
230*6a54128fSAndroid Build Coastguard Worker struct profile_string_list values;
231*6a54128fSAndroid Build Coastguard Worker
232*6a54128fSAndroid Build Coastguard Worker if ((retval = profile_iterator_create(profile, names,
233*6a54128fSAndroid Build Coastguard Worker PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
234*6a54128fSAndroid Build Coastguard Worker &state)))
235*6a54128fSAndroid Build Coastguard Worker return retval;
236*6a54128fSAndroid Build Coastguard Worker
237*6a54128fSAndroid Build Coastguard Worker if ((retval = init_list(&values)))
238*6a54128fSAndroid Build Coastguard Worker goto cleanup_iterator;
239*6a54128fSAndroid Build Coastguard Worker
240*6a54128fSAndroid Build Coastguard Worker do {
241*6a54128fSAndroid Build Coastguard Worker if ((retval = profile_iterator(&state, &name, 0)))
242*6a54128fSAndroid Build Coastguard Worker goto cleanup;
243*6a54128fSAndroid Build Coastguard Worker if (name) {
244*6a54128fSAndroid Build Coastguard Worker if (is_list_member(&values, name))
245*6a54128fSAndroid Build Coastguard Worker free(name);
246*6a54128fSAndroid Build Coastguard Worker else
247*6a54128fSAndroid Build Coastguard Worker add_to_list(&values, name);
248*6a54128fSAndroid Build Coastguard Worker }
249*6a54128fSAndroid Build Coastguard Worker } while (state);
250*6a54128fSAndroid Build Coastguard Worker
251*6a54128fSAndroid Build Coastguard Worker end_list(&values, ret_names);
252*6a54128fSAndroid Build Coastguard Worker return 0;
253*6a54128fSAndroid Build Coastguard Worker
254*6a54128fSAndroid Build Coastguard Worker cleanup:
255*6a54128fSAndroid Build Coastguard Worker end_list(&values, 0);
256*6a54128fSAndroid Build Coastguard Worker cleanup_iterator:
257*6a54128fSAndroid Build Coastguard Worker profile_iterator_free(&state);
258*6a54128fSAndroid Build Coastguard Worker return retval;
259*6a54128fSAndroid Build Coastguard Worker }
260*6a54128fSAndroid Build Coastguard Worker
261*6a54128fSAndroid Build Coastguard Worker
262*6a54128fSAndroid Build Coastguard Worker void
profile_release_string(char * str)263*6a54128fSAndroid Build Coastguard Worker profile_release_string(char *str)
264*6a54128fSAndroid Build Coastguard Worker {
265*6a54128fSAndroid Build Coastguard Worker free(str);
266*6a54128fSAndroid Build Coastguard Worker }
267*6a54128fSAndroid Build Coastguard Worker
268*6a54128fSAndroid Build Coastguard Worker errcode_t
profile_init_path(const char * filepath,profile_t * ret_profile)269*6a54128fSAndroid Build Coastguard Worker profile_init_path(const char * filepath,
270*6a54128fSAndroid Build Coastguard Worker profile_t *ret_profile)
271*6a54128fSAndroid Build Coastguard Worker {
272*6a54128fSAndroid Build Coastguard Worker int n_entries, i;
273*6a54128fSAndroid Build Coastguard Worker unsigned int ent_len;
274*6a54128fSAndroid Build Coastguard Worker const char *s, *t;
275*6a54128fSAndroid Build Coastguard Worker char **filenames;
276*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
277*6a54128fSAndroid Build Coastguard Worker
278*6a54128fSAndroid Build Coastguard Worker /* count the distinct filename components */
279*6a54128fSAndroid Build Coastguard Worker for(s = filepath, n_entries = 1; *s; s++) {
280*6a54128fSAndroid Build Coastguard Worker if (*s == ':')
281*6a54128fSAndroid Build Coastguard Worker n_entries++;
282*6a54128fSAndroid Build Coastguard Worker }
283*6a54128fSAndroid Build Coastguard Worker
284*6a54128fSAndroid Build Coastguard Worker /* the array is NULL terminated */
285*6a54128fSAndroid Build Coastguard Worker filenames = (char **) malloc((n_entries+1) * sizeof(char*));
286*6a54128fSAndroid Build Coastguard Worker if (filenames == 0)
287*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
288*6a54128fSAndroid Build Coastguard Worker
289*6a54128fSAndroid Build Coastguard Worker /* measure, copy, and skip each one */
290*6a54128fSAndroid Build Coastguard Worker for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
291*6a54128fSAndroid Build Coastguard Worker ent_len = t-s;
292*6a54128fSAndroid Build Coastguard Worker filenames[i] = (char*) malloc(ent_len + 1);
293*6a54128fSAndroid Build Coastguard Worker if (filenames[i] == 0) {
294*6a54128fSAndroid Build Coastguard Worker /* if malloc fails, free the ones that worked */
295*6a54128fSAndroid Build Coastguard Worker while(--i >= 0) free(filenames[i]);
296*6a54128fSAndroid Build Coastguard Worker free(filenames);
297*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
298*6a54128fSAndroid Build Coastguard Worker }
299*6a54128fSAndroid Build Coastguard Worker strncpy(filenames[i], s, ent_len);
300*6a54128fSAndroid Build Coastguard Worker filenames[i][ent_len] = 0;
301*6a54128fSAndroid Build Coastguard Worker if (*t == 0) {
302*6a54128fSAndroid Build Coastguard Worker i++;
303*6a54128fSAndroid Build Coastguard Worker break;
304*6a54128fSAndroid Build Coastguard Worker }
305*6a54128fSAndroid Build Coastguard Worker }
306*6a54128fSAndroid Build Coastguard Worker /* cap the array */
307*6a54128fSAndroid Build Coastguard Worker filenames[i] = 0;
308*6a54128fSAndroid Build Coastguard Worker
309*6a54128fSAndroid Build Coastguard Worker retval = profile_init((const char * const *) filenames,
310*6a54128fSAndroid Build Coastguard Worker ret_profile);
311*6a54128fSAndroid Build Coastguard Worker
312*6a54128fSAndroid Build Coastguard Worker /* count back down and free the entries */
313*6a54128fSAndroid Build Coastguard Worker while(--i >= 0) free(filenames[i]);
314*6a54128fSAndroid Build Coastguard Worker free(filenames);
315*6a54128fSAndroid Build Coastguard Worker
316*6a54128fSAndroid Build Coastguard Worker return retval;
317*6a54128fSAndroid Build Coastguard Worker }
318