e2fsprogs/e2fsck/profile_helpers.c
Theodore Ts'o d1154eb460 Shorten compile commands run by the build system
The DEFS line in MCONFIG had gotten so long that it exceeded 4k, and
this was starting to cause some tools heartburn.  It also made "make
V=1" almost useless, since trying to following the individual commands
run by make was lost in the noise of all of the defines.

So fix this by putting the configure-generated defines in lib/config.h
and the directory pathnames to lib/dirpaths.h.

In addition, clean up some vestigal defines in configure.in and in the
Makefiles to further shorten the cc command lines.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2011-09-18 17:34:37 -04:00

311 lines
6.4 KiB
C

/*
* 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 "config.h"
#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;
}