~ubuntu-branches/ubuntu/edgy/e2fsprogs/edgy-updates

« back to all changes in this revision

Viewing changes to e2fsck/profile_helpers.c

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Y. Ts'o
  • Date: 2006-05-29 11:07:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060529110753-uvkuaxqr96y31kqy
Tags: 1.39-1
* New upstream version
* Fix debugfs's dump_unused command so it will not core dump on
  filesystems with a 64k blocksize
* Clarified and improved man pages, including spelling errors
  (Closes: #368392, #368393, #368394, #368179)
* New filesystems are now created with directory indexing and
  on-line resizing enabled by default
* Fix previously mangled wording in an older Debian changelog entry
* Fix doc-base pointer to the top-level html file (Closes: #362544, #362970)

Show diffs side-by-side

added added

removed removed

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