/external/e2fsprogs/e2fsck/profile_helpers.c
https://bitbucket.org/rlyspn/androidrr · C · 309 lines · 202 code · 45 blank · 62 comment · 47 complexity · 7d2c427826da14e7b7328b00fe16b096 MD5 · raw file
- /*
- * profile_helpers.c -- Helper functions for the profile library
- *
- * These functions are not part of the "core" profile library, and do
- * not require access to the internal functions and data structures of
- * the profile library. They are mainly convenience functions for
- * programs that want to do something unusual such as obtaining the
- * list of sections or relations, or accessing multiple values from a
- * relation that is listed more than once. This functionality can all
- * be done using the profile_iterator abstraction, but it is less
- * convenient.
- *
- * Copyright (C) 2006 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <et/com_err.h>
- #include "profile.h"
- #include "prof_err.h"
- /*
- * These functions --- init_list(), end_list(), and add_to_list() are
- * internal functions used to build up a null-terminated char ** list
- * of strings to be returned by functions like profile_get_values.
- *
- * The profile_string_list structure is used for internal booking
- * purposes to build up the list, which is returned in *ret_list by
- * the end_list() function.
- *
- * The publicly exported interface for freeing char** list is
- * profile_free_list().
- */
- struct profile_string_list {
- char **list;
- int num;
- int max;
- };
- /*
- * Initialize the string list abstraction.
- */
- static errcode_t init_list(struct profile_string_list *list)
- {
- list->num = 0;
- list->max = 10;
- list->list = malloc(list->max * sizeof(char *));
- if (list->list == 0)
- return ENOMEM;
- list->list[0] = 0;
- return 0;
- }
- /*
- * Free any memory left over in the string abstraction, returning the
- * built up list in *ret_list if it is non-null.
- */
- static void end_list(struct profile_string_list *list, char ***ret_list)
- {
- char **cp;
- if (list == 0)
- return;
- if (ret_list) {
- *ret_list = list->list;
- return;
- } else {
- for (cp = list->list; *cp; cp++)
- free(*cp);
- free(list->list);
- }
- list->num = list->max = 0;
- list->list = 0;
- }
- /*
- * Add a string to the list.
- */
- static errcode_t add_to_list(struct profile_string_list *list, char *str)
- {
- char **newlist;
- int newmax;
- if (list->num+1 >= list->max) {
- newmax = list->max + 10;
- newlist = realloc(list->list, newmax * sizeof(char *));
- if (newlist == 0)
- return ENOMEM;
- list->max = newmax;
- list->list = newlist;
- }
- list->list[list->num++] = str;
- list->list[list->num] = 0;
- return 0;
- }
- /*
- * Return TRUE if the string is already a member of the list.
- */
- static int is_list_member(struct profile_string_list *list, const char *str)
- {
- char **cpp;
- if (!list->list)
- return 0;
- for (cpp = list->list; *cpp; cpp++) {
- if (!strcmp(*cpp, str))
- return 1;
- }
- return 0;
- }
- /*
- * This function frees a null-terminated list as returned by
- * profile_get_values.
- */
- void profile_free_list(char **list)
- {
- char **cp;
- if (list == 0)
- return;
- for (cp = list; *cp; cp++)
- free(*cp);
- free(list);
- }
- errcode_t
- profile_get_values(profile_t profile, const char *const *names,
- char ***ret_values)
- {
- errcode_t retval;
- void *state;
- char *value;
- struct profile_string_list values;
- if ((retval = profile_iterator_create(profile, names,
- PROFILE_ITER_RELATIONS_ONLY,
- &state)))
- return retval;
- if ((retval = init_list(&values)))
- return retval;
- do {
- if ((retval = profile_iterator(&state, 0, &value)))
- goto cleanup;
- if (value)
- add_to_list(&values, value);
- } while (state);
- if (values.num == 0) {
- retval = PROF_NO_RELATION;
- goto cleanup;
- }
- end_list(&values, ret_values);
- return 0;
- cleanup:
- end_list(&values, 0);
- return retval;
- }
- /*
- * This function will return the list of the names of subections in the
- * under the specified section name.
- */
- errcode_t
- profile_get_subsection_names(profile_t profile, const char **names,
- char ***ret_names)
- {
- errcode_t retval;
- void *state;
- char *name;
- struct profile_string_list values;
- if ((retval = profile_iterator_create(profile, names,
- PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
- &state)))
- return retval;
- if ((retval = init_list(&values)))
- return retval;
- do {
- if ((retval = profile_iterator(&state, &name, 0)))
- goto cleanup;
- if (name)
- add_to_list(&values, name);
- } while (state);
- end_list(&values, ret_names);
- return 0;
- cleanup:
- end_list(&values, 0);
- return retval;
- }
- /*
- * This function will return the list of the names of relations in the
- * under the specified section name.
- */
- errcode_t
- profile_get_relation_names(profile_t profile, const char **names,
- char ***ret_names)
- {
- errcode_t retval;
- void *state;
- char *name;
- struct profile_string_list values;
- if ((retval = profile_iterator_create(profile, names,
- PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
- &state)))
- return retval;
- if ((retval = init_list(&values)))
- return retval;
- do {
- if ((retval = profile_iterator(&state, &name, 0)))
- goto cleanup;
- if (name) {
- if (is_list_member(&values, name))
- free(name);
- else
- add_to_list(&values, name);
- }
- } while (state);
- end_list(&values, ret_names);
- return 0;
- cleanup:
- end_list(&values, 0);
- return retval;
- }
- void
- profile_release_string(char *str)
- {
- free(str);
- }
- errcode_t
- profile_init_path(const char * filepath,
- profile_t *ret_profile)
- {
- int n_entries, i;
- unsigned int ent_len;
- const char *s, *t;
- char **filenames;
- errcode_t retval;
- /* count the distinct filename components */
- for(s = filepath, n_entries = 1; *s; s++) {
- if (*s == ':')
- n_entries++;
- }
- /* the array is NULL terminated */
- filenames = (char **) malloc((n_entries+1) * sizeof(char*));
- if (filenames == 0)
- return ENOMEM;
- /* measure, copy, and skip each one */
- for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
- ent_len = t-s;
- filenames[i] = (char*) malloc(ent_len + 1);
- if (filenames[i] == 0) {
- /* if malloc fails, free the ones that worked */
- while(--i >= 0) free(filenames[i]);
- free(filenames);
- return ENOMEM;
- }
- strncpy(filenames[i], s, ent_len);
- filenames[i][ent_len] = 0;
- if (*t == 0) {
- i++;
- break;
- }
- }
- /* cap the array */
- filenames[i] = 0;
- retval = profile_init((const char **) filenames,
- ret_profile);
- /* count back down and free the entries */
- while(--i >= 0) free(filenames[i]);
- free(filenames);
- return retval;
- }