L4Re/departure

libext2fs/lib/libsupport/profile_helpers.c

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