Coverage Report

Created: 2023-09-23 07:09

/src/augeas/src/internal.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * internal.h: Useful definitions
3
 *
4
 * Copyright (C) 2007-2017 David Lutterkort
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19
 *
20
 * Author: David Lutterkort <dlutter@redhat.com>
21
 */
22
23
#ifndef INTERNAL_H_
24
#define INTERNAL_H_
25
26
#include "list.h"
27
#include "datadir.h"
28
#include "augeas.h"
29
30
#include <stdio.h>
31
#include <string.h>
32
#include <strings.h>
33
#include <stdlib.h>
34
#include <stdbool.h>
35
#include <unistd.h>
36
#include <errno.h>
37
#include <assert.h>
38
#include <locale.h>
39
#include <stdint.h>
40
41
/*
42
 * Various parameters about env vars, special tree nodes etc.
43
 */
44
45
/* Define: AUGEAS_LENS_DIR
46
 * The default location for lens definitions */
47
0
#define AUGEAS_LENS_DIR DATADIR "/augeas/lenses"
48
49
/* The directory where we install lenses distribute with Augeas */
50
0
#define AUGEAS_LENS_DIST_DIR DATADIR "/augeas/lenses/dist"
51
52
/* Define: AUGEAS_ROOT_ENV
53
 * The env var that points to the chroot holding files we may modify.
54
 * Mostly useful for testing */
55
0
#define AUGEAS_ROOT_ENV "AUGEAS_ROOT"
56
57
/* Define: AUGEAS_FILES_TREE
58
 * The root for actual file contents */
59
0
#define AUGEAS_FILES_TREE "/files"
60
61
/* Define: AUGEAS_META_TREE
62
 * Augeas reports some information in this subtree */
63
4.50k
#define AUGEAS_META_TREE "/augeas"
64
65
/* Define: AUGEAS_META_FILES
66
 * Information about files */
67
0
#define AUGEAS_META_FILES AUGEAS_META_TREE AUGEAS_FILES_TREE
68
69
/* Define: AUGEAS_META_TEXT
70
 * Information about text (see aug_text_store and aug_text_retrieve) */
71
11
#define AUGEAS_META_TEXT AUGEAS_META_TREE "/text"
72
73
/* Define: AUGEAS_META_ROOT
74
 * The root directory */
75
158
#define AUGEAS_META_ROOT AUGEAS_META_TREE "/root"
76
77
/* Define: AUGEAS_META_SAVE_MODE
78
 * How we save files. One of 'backup', 'overwrite' or 'newfile' */
79
158
#define AUGEAS_META_SAVE_MODE AUGEAS_META_TREE "/save"
80
81
/* Define: AUGEAS_CLONE_IF_RENAME_FAILS
82
 * Control what save does when renaming the temporary file to its final
83
 * destination fails with EXDEV or EBUSY: when this tree node exists, copy
84
 * the file contents. If it is not present, simply give up and report an
85
 * error.  */
86
#define AUGEAS_COPY_IF_RENAME_FAILS \
87
0
    AUGEAS_META_SAVE_MODE "/copy_if_rename_fails"
88
89
/* Define: AUGEAS_CONTEXT
90
 * Context prepended to all non-absolute paths */
91
4.02k
#define AUGEAS_CONTEXT AUGEAS_META_TREE "/context"
92
93
/* A hierarchy where we record certain 'events', e.g. which tree
94
 * nodes actually gotsaved into files */
95
0
#define AUGEAS_EVENTS AUGEAS_META_TREE "/events"
96
97
0
#define AUGEAS_EVENTS_SAVED AUGEAS_EVENTS "/saved"
98
99
/* Where to put information about parsing of path expressions */
100
#define AUGEAS_META_PATHX AUGEAS_META_TREE "/pathx"
101
102
/* Define: AUGEAS_SPAN_OPTION
103
 * Enable or disable node indexes */
104
158
#define AUGEAS_SPAN_OPTION AUGEAS_META_TREE "/span"
105
106
/* Define: AUGEAS_LENS_ENV
107
 * Name of env var that contains list of paths to search for additional
108
   spec files */
109
158
#define AUGEAS_LENS_ENV "AUGEAS_LENS_LIB"
110
111
/* Define: MAX_ENV_SIZE
112
 * Fairly arbitrary bound on the length of the path we
113
 *  accept from AUGEAS_SPEC_ENV */
114
#define MAX_ENV_SIZE 4096
115
116
/* Define: PATH_SEP_CHAR
117
 * Character separating paths in a list of paths */
118
0
#define PATH_SEP_CHAR ':'
119
120
/* Constants for setting the save mode via the augeas path at
121
 * AUGEAS_META_SAVE_MODE */
122
0
#define AUG_SAVE_BACKUP_TEXT "backup"
123
0
#define AUG_SAVE_NEWFILE_TEXT "newfile"
124
0
#define AUG_SAVE_NOOP_TEXT "noop"
125
158
#define AUG_SAVE_OVERWRITE_TEXT "overwrite"
126
127
/* constants for options in the tree */
128
0
#define AUG_ENABLE "enable"
129
158
#define AUG_DISABLE "disable"
130
131
/* default value for the relative path context */
132
158
#define AUG_CONTEXT_DEFAULT "/files"
133
134
#ifdef __GNUC__
135
136
#ifndef __GNUC_PREREQ
137
#define __GNUC_PREREQ(maj,min) 0
138
#endif
139
140
/**
141
* AUGEAS_LIKELY:
142
*
143
* Macro to flag a code branch as a likely branch
144
*
145
* AUGEAS_UNLIKELY:
146
*
147
* Macro to flag a code branch as an unlikely branch
148
*/
149
#ifndef __has_builtin
150
#   define __has_builtin(x) (0)
151
#endif
152
#if defined(__builtin_expect) || __has_builtin(__builtin_expect)
153
#   define AUGEAS_LIKELY(x)        (__builtin_expect(!!(x), 1))
154
65.1M
#   define AUGEAS_UNLIKELY(x)      (__builtin_expect(!!(x), 0))
155
#else
156
#   define AUGEAS_LIKELY(x)        (x)
157
#   define AUGEAS_UNLIKELY(x)      (x)
158
#endif
159
160
/**
161
 * ATTRIBUTE_UNUSED:
162
 *
163
 * Macro to flag conciously unused parameters to functions
164
 */
165
#ifndef ATTRIBUTE_UNUSED
166
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
167
#endif
168
169
/**
170
 * ATTRIBUTE_FORMAT
171
 *
172
 * Macro used to check printf/scanf-like functions, if compiling
173
 * with gcc.
174
 */
175
#ifndef ATTRIBUTE_FORMAT
176
#define ATTRIBUTE_FORMAT(args...) __attribute__((__format__ (args)))
177
#endif
178
179
#ifndef ATTRIBUTE_PURE
180
#define ATTRIBUTE_PURE __attribute__((pure))
181
#endif
182
183
#ifndef ATTRIBUTE_RETURN_CHECK
184
#if __GNUC_PREREQ (3, 4)
185
#define ATTRIBUTE_RETURN_CHECK __attribute__((__warn_unused_result__))
186
#else
187
#define ATTRIBUTE_RETURN_CHECK
188
#endif
189
#endif
190
191
/* Allow falling through in switch statements for the few cases where that
192
   is needed */
193
#ifndef ATTRIBUTE_FALLTHROUGH
194
#  if __GNUC_PREREQ (7, 0)
195
#    define ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough))
196
#  else
197
#    define ATTRIBUTE_FALLTHROUGH
198
#  endif
199
#endif
200
201
/* A poor man's macro to get some move semantics: return the value of P but
202
   set P itself to NULL. This has the effect that if you say 'x = move(y)'
203
   that there is still only one pointer pointing to the memory Y pointed to
204
   initially.
205
 */
206
0
#define move(p) ({ typeof(p) _tmp = (p); (p) = NULL; _tmp; })
207
208
#else
209
#define ATTRIBUTE_UNUSED
210
#define ATTRIBUTE_FORMAT(...)
211
#define ATTRIBUTE_PURE
212
#define ATTRIBUTE_RETURN_CHECK
213
#define ATTRIBUTE_FALLTHROUGH
214
#define move(p) p
215
#endif                                   /* __GNUC__ */
216
217
36.0M
#define ARRAY_CARDINALITY(array) (sizeof (array) / sizeof *(array))
218
219
/* String equality tests, suggested by Jim Meyering. */
220
10.2M
#define STREQ(a,b) (strcmp((a),(b)) == 0)
221
41
#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
222
#define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0)
223
17.0k
#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
224
#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
225
968M
#define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0)
226
0
#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
227
228
ATTRIBUTE_PURE
229
170k
static inline int streqv(const char *a, const char *b) {
230
170k
    if (a == NULL || b == NULL)
231
6.74k
        return a == b;
232
163k
    return STREQ(a,b);
233
170k
}
Unexecuted instantiation: augeas_api_fuzzer.cc:streqv(char const*, char const*)
augeas.c:streqv
Line
Count
Source
229
19.2k
static inline int streqv(const char *a, const char *b) {
230
19.2k
    if (a == NULL || b == NULL)
231
6.73k
        return a == b;
232
12.4k
    return STREQ(a,b);
233
19.2k
}
Unexecuted instantiation: pathx.c:streqv
internal.c:streqv
Line
Count
Source
229
150k
static inline int streqv(const char *a, const char *b) {
230
150k
    if (a == NULL || b == NULL)
231
0
        return a == b;
232
150k
    return STREQ(a,b);
233
150k
}
Unexecuted instantiation: memory.c:streqv
syntax.c:streqv
Line
Count
Source
229
10
static inline int streqv(const char *a, const char *b) {
230
10
    if (a == NULL || b == NULL)
231
10
        return a == b;
232
0
    return STREQ(a,b);
233
10
}
Unexecuted instantiation: parser.c:streqv
Unexecuted instantiation: builtin.c:streqv
Unexecuted instantiation: lens.c:streqv
Unexecuted instantiation: regexp.c:streqv
Unexecuted instantiation: transform.c:streqv
Unexecuted instantiation: get.c:streqv
Unexecuted instantiation: put.c:streqv
Unexecuted instantiation: info.c:streqv
Unexecuted instantiation: errcode.c:streqv
Unexecuted instantiation: jmt.c:streqv
Unexecuted instantiation: lexer.c:streqv
Unexecuted instantiation: ast.c:streqv
Unexecuted instantiation: fa.c:streqv
Unexecuted instantiation: hash.c:streqv
234
235
/* Path length and comparison */
236
237
3.88k
#define SEP '/'
238
239
/* Length of PATH without any trailing '/' */
240
ATTRIBUTE_PURE
241
0
static inline int pathlen(const char *path) {
242
0
    int len = strlen(path);
243
0
244
0
    if (len > 0 && path[len-1] == SEP)
245
0
        len--;
246
0
247
0
    return len;
248
0
}
Unexecuted instantiation: augeas_api_fuzzer.cc:pathlen(char const*)
Unexecuted instantiation: augeas.c:pathlen
Unexecuted instantiation: pathx.c:pathlen
Unexecuted instantiation: internal.c:pathlen
Unexecuted instantiation: memory.c:pathlen
Unexecuted instantiation: syntax.c:pathlen
Unexecuted instantiation: parser.c:pathlen
Unexecuted instantiation: builtin.c:pathlen
Unexecuted instantiation: lens.c:pathlen
Unexecuted instantiation: regexp.c:pathlen
Unexecuted instantiation: transform.c:pathlen
Unexecuted instantiation: get.c:pathlen
Unexecuted instantiation: put.c:pathlen
Unexecuted instantiation: info.c:pathlen
Unexecuted instantiation: errcode.c:pathlen
Unexecuted instantiation: jmt.c:pathlen
Unexecuted instantiation: lexer.c:pathlen
Unexecuted instantiation: ast.c:pathlen
Unexecuted instantiation: fa.c:pathlen
Unexecuted instantiation: hash.c:pathlen
249
250
/* Return 1 if P1 is a prefix of P2. P1 as a string must have length <= P2 */
251
ATTRIBUTE_PURE
252
0
static inline int pathprefix(const char *p1, const char *p2) {
253
0
    if (p1 == NULL || p2 == NULL)
254
0
        return 0;
255
0
    int l1 = pathlen(p1);
256
0
257
0
    return STREQLEN(p1, p2, l1) && (p2[l1] == '\0' || p2[l1] == SEP);
258
0
}
Unexecuted instantiation: augeas_api_fuzzer.cc:pathprefix(char const*, char const*)
Unexecuted instantiation: augeas.c:pathprefix
Unexecuted instantiation: pathx.c:pathprefix
Unexecuted instantiation: internal.c:pathprefix
Unexecuted instantiation: memory.c:pathprefix
Unexecuted instantiation: syntax.c:pathprefix
Unexecuted instantiation: parser.c:pathprefix
Unexecuted instantiation: builtin.c:pathprefix
Unexecuted instantiation: lens.c:pathprefix
Unexecuted instantiation: regexp.c:pathprefix
Unexecuted instantiation: transform.c:pathprefix
Unexecuted instantiation: get.c:pathprefix
Unexecuted instantiation: put.c:pathprefix
Unexecuted instantiation: info.c:pathprefix
Unexecuted instantiation: errcode.c:pathprefix
Unexecuted instantiation: jmt.c:pathprefix
Unexecuted instantiation: lexer.c:pathprefix
Unexecuted instantiation: ast.c:pathprefix
Unexecuted instantiation: fa.c:pathprefix
Unexecuted instantiation: hash.c:pathprefix
259
260
0
static inline int pathendswith(const char *path, const char *basenam) {
261
0
    const char *p = strrchr(path, SEP);
262
0
    if (p == NULL)
263
0
        return 0;
264
0
    return streqv(p+1, basenam);
265
0
}
Unexecuted instantiation: augeas_api_fuzzer.cc:pathendswith(char const*, char const*)
Unexecuted instantiation: augeas.c:pathendswith
Unexecuted instantiation: pathx.c:pathendswith
Unexecuted instantiation: internal.c:pathendswith
Unexecuted instantiation: memory.c:pathendswith
Unexecuted instantiation: syntax.c:pathendswith
Unexecuted instantiation: parser.c:pathendswith
Unexecuted instantiation: builtin.c:pathendswith
Unexecuted instantiation: lens.c:pathendswith
Unexecuted instantiation: regexp.c:pathendswith
Unexecuted instantiation: transform.c:pathendswith
Unexecuted instantiation: get.c:pathendswith
Unexecuted instantiation: put.c:pathendswith
Unexecuted instantiation: info.c:pathendswith
Unexecuted instantiation: errcode.c:pathendswith
Unexecuted instantiation: jmt.c:pathendswith
Unexecuted instantiation: lexer.c:pathendswith
Unexecuted instantiation: ast.c:pathendswith
Unexecuted instantiation: fa.c:pathendswith
Unexecuted instantiation: hash.c:pathendswith
266
267
/* Join NSEG path components (passed as const char *) into one PATH.
268
   Allocate as needed. Return 0 on success, -1 on failure */
269
int pathjoin(char **path, int nseg, ...);
270
271
3.31k
#define MEMZERO(ptr, n) memset((ptr), 0, (n) * sizeof(*(ptr)));
272
273
0
#define MEMMOVE(dest, src, n) memmove((dest), (src), (n) * sizeof(*(src)))
274
275
/**
276
 * TODO:
277
 *
278
 * macro to flag unimplemented blocks
279
 */
280
#define TODO                \
281
    fprintf(stderr, "%s:%d Unimplemented block\n",      \
282
            __FILE__, __LINE__);
283
284
#define FIXME(msg, args ...)                            \
285
    do {                                                \
286
        fprintf(stderr, "%s:%d Fixme: ",                \
287
                __FILE__, __LINE__);                    \
288
      fprintf(stderr, msg, ## args);                    \
289
      fputc('\n', stderr);                              \
290
    } while(0)
291
292
/*
293
 * Internal data structures
294
 */
295
296
// internal.c
297
298
/* Function: escape
299
 * Escape nonprintable characters within TEXT, similar to how it's done in
300
 * C string literals. Caller must free the returned string.
301
 */
302
char *escape(const char *text, int cnt, const char *extra);
303
304
/* Function: unescape */
305
char *unescape(const char *s, int len, const char *extra);
306
307
/* Extra characters to be escaped in strings and regexps respectively */
308
7.09k
#define STR_ESCAPES "\"\\"
309
0
#define RX_ESCAPES  "/\\"
310
311
/* Function: print_chars */
312
int print_chars(FILE *out, const char *text, int cnt);
313
314
/* Function: print_pos
315
 * Print a pretty representation of being at position POS within TEXT */
316
void print_pos(FILE *out, const char *text, int pos);
317
char *format_pos(const char *text, int pos);
318
319
/* Function: xread_file
320
 * Read the contents of file PATH and return them as one long string. The
321
 * caller must free the result. Return NULL if any error occurs.
322
 */
323
char* xread_file(const char *path);
324
325
/* Like xread_file, but caller supplies a file pointer */
326
char* xfread_file(FILE *fp);
327
328
/* Get the error message for ERRNUM in a threadsafe way. Based on libvirt's
329
 * virStrError
330
 */
331
const char *xstrerror(int errnum, char *buf, size_t len);
332
333
/* Like asprintf, but set *STRP to NULL on error */
334
int xasprintf(char **strp, const char *format, ...);
335
336
/* Convert S to RESULT with error checking */
337
int xstrtoint64(char const *s, int base, int64_t *result);
338
339
/* Calculate line and column number of character POS in TEXT */
340
void calc_line_ofs(const char *text, size_t pos, size_t *line, size_t *ofs);
341
342
/* Cleans path from user, removing trailing slashes and whitespace */
343
char *cleanpath(char *path);
344
345
/* Take the first LEN characters from the regexp *U and expand any
346
 * character ranges in it. The expanded regexp, if expansion is necessary,
347
 * is in U, and the old string is freed. If expansion is not needed or an
348
 * error happens, U will be unchanged.
349
 *
350
 * Return 0 if expansion is not necessary, -1 if an error occurs, and 1 if
351
 * expansion was needed.
352
 */
353
int regexp_c_locale(char **u, size_t *len);
354
355
/* Struct: augeas
356
 * The data structure representing a connection to Augeas. */
357
struct augeas {
358
    struct tree      *origin;     /* Actual tree root is origin->children */
359
    const char       *root;       /* Filesystem root for all files */
360
                                  /* always ends with '/' */
361
    unsigned int      flags;      /* Flags passed to AUG_INIT */
362
    struct module    *modules;    /* Loaded modules */
363
    size_t            nmodpath;
364
    char             *modpathz;   /* The search path for modules as a
365
                                     glibc argz vector */
366
    struct pathx_symtab *symtab;
367
    struct error        *error;
368
    uint                api_entries;  /* Number of entries through a public
369
                                       * API, 0 when called from outside */
370
#if HAVE_USELOCALE
371
    /* On systems that have a uselocale call, we switch to the C locale
372
     * on entry into API functions, and back to the old user locale
373
     * on exit.
374
     * FIXME: We need some solution for systems without uselocale, like
375
     * setlocale + critical section, though that is very heavy-handed
376
     */
377
    locale_t            c_locale;
378
    locale_t            user_locale;
379
#endif
380
};
381
382
11.5k
static inline struct error *err_of_aug(const struct augeas *aug) {
383
11.5k
    return ((struct augeas *) aug)->error;
384
11.5k
}
Unexecuted instantiation: augeas_api_fuzzer.cc:err_of_aug(augeas const*)
augeas.c:err_of_aug
Line
Count
Source
382
11.5k
static inline struct error *err_of_aug(const struct augeas *aug) {
383
11.5k
    return ((struct augeas *) aug)->error;
384
11.5k
}
Unexecuted instantiation: pathx.c:err_of_aug
Unexecuted instantiation: internal.c:err_of_aug
Unexecuted instantiation: memory.c:err_of_aug
Unexecuted instantiation: syntax.c:err_of_aug
Unexecuted instantiation: parser.c:err_of_aug
Unexecuted instantiation: builtin.c:err_of_aug
Unexecuted instantiation: lens.c:err_of_aug
Unexecuted instantiation: regexp.c:err_of_aug
Unexecuted instantiation: transform.c:err_of_aug
Unexecuted instantiation: get.c:err_of_aug
Unexecuted instantiation: put.c:err_of_aug
Unexecuted instantiation: info.c:err_of_aug
Unexecuted instantiation: errcode.c:err_of_aug
Unexecuted instantiation: jmt.c:err_of_aug
Unexecuted instantiation: lexer.c:err_of_aug
Unexecuted instantiation: ast.c:err_of_aug
Unexecuted instantiation: fa.c:err_of_aug
Unexecuted instantiation: hash.c:err_of_aug
385
386
/* Used by augparse for loading tests */
387
int __aug_load_module_file(struct augeas *aug, const char *filename);
388
389
/* Called at beginning and end of every _public_ API function */
390
void api_entry(const struct augeas *aug);
391
void api_exit(const struct augeas *aug);
392
393
/* Struct: tree
394
 * An entry in the global config tree. The data structure allows associating
395
 * values with interior nodes, but the API currently marks that as an error.
396
 *
397
 * To make dealing with parents uniform, even for the root, we create
398
 * standalone trees with a fake root, called origin. That root is generally
399
 * not referenced from anywhere. Standalone trees should be created with
400
 * MAKE_TREE_ORIGIN.
401
 *
402
 * The DIRTY flag is used to track which parts of the tree might need to be
403
 * saved. For any node that is marked dirty, all of its ancestors must be
404
 * marked dirty, too. Instead of setting this flag directly, the function
405
 * TREE_MARK_DIRTY in augeas.c should be used (and only functions in that
406
 * file should have a need to mark nodes as dirty)
407
 *
408
 * The FILE flag is set for entries underneath /augeas/files that hold the
409
 * metadata for a file by ADD_FILE_INFO. The FILE flag is set for entries
410
 * underneath /files for the toplevel node corresponding to a file by
411
 * TREE_FREPLACE and is used by AUG_SOURCE to find the file to which a node
412
 * belongs.
413
 */
414
struct tree {
415
    struct tree *next;
416
    struct tree *parent;     /* Points to self for root */
417
    char        *label;      /* Last component of PATH */
418
    struct tree *children;   /* List of children through NEXT */
419
    char        *value;
420
    struct span *span;
421
422
    /* Flags */
423
    bool         dirty;
424
    bool         file;
425
    bool         added;      /* only used by ns_add and tree_rm to dedupe
426
                                nodesets */
427
};
428
429
/* The opaque structure used to represent path expressions. API's
430
 * using STRUCT PATHX are declared farther below
431
 */
432
struct pathx;
433
434
21.0k
#define ROOT_P(t) ((t) != NULL && (t)->parent == (t)->parent->parent)
435
436
40.2k
#define TREE_HIDDEN(tree) ((tree)->label == NULL)
437
438
/* Function: make_tree
439
 * Allocate a new tree node with the given LABEL, VALUE, and CHILDREN,
440
 * which are not copied. The new tree is marked as dirty
441
 */
442
struct tree *make_tree(char *label, char *value,
443
                       struct tree *parent, struct tree *children);
444
445
/* Mark a tree as a standalone tree; this creates a fake parent for ROOT,
446
 * so that even ROOT has a parent. A new node with only child ROOT is
447
 * returned on success, and NULL on failure.
448
 */
449
struct tree  *make_tree_origin(struct tree *root);
450
451
/* Make a new tree node and append it to parent's children */
452
struct tree *tree_append(struct tree *parent, char *label, char *value);
453
454
int tree_rm(struct pathx *p);
455
int tree_unlink(struct augeas *aug, struct tree *tree);
456
struct tree *tree_set(struct pathx *p, const char *value);
457
int tree_insert(struct pathx *p, const char *label, int before);
458
int free_tree(struct tree *tree);
459
int dump_tree(FILE *out, struct tree *tree);
460
int tree_equal(const struct tree *t1, const struct tree *t2);
461
/* Return the 1-based index of TREE amongst its siblings with the same
462
 * label or 0 if none of TREE's siblings have the same label */
463
int tree_sibling_index(struct tree *tree);
464
char *path_expand(struct tree *tree, const char *ppath);
465
char *path_of_tree(struct tree *tree);
466
/* Clear the dirty flag in the whole TREE */
467
void tree_clean(struct tree *tree);
468
/* Return first child with label LABEL or NULL */
469
struct tree *tree_child(struct tree *tree, const char *label);
470
/* Return first existing child with label LABEL or create one. Return NULL
471
 * when allocation fails */
472
struct tree *tree_child_cr(struct tree *tree, const char *label);
473
/* Create a path in the tree; nodes along the path are looked up with
474
 * tree_child_cr */
475
struct tree *tree_path_cr(struct tree *tree, int n, ...);
476
/* Store VALUE directly as the value of TREE and set VALUE to NULL.
477
 * Update dirty flags */
478
void tree_store_value(struct tree *tree, char **value);
479
/* Set the value of TREE to a copy of VALUE and update dirty flags */
480
int tree_set_value(struct tree *tree, const char *value);
481
/* Cleanly remove all children of TREE, but leave TREE itself unchanged */
482
void tree_unlink_children(struct augeas *aug, struct tree *tree);
483
/* Find a node in the tree at path FPATH; FPATH is a file path, i.e.
484
 * not interpreted as a path expression. If no such node exists, return NULL
485
 */
486
struct tree *tree_fpath(struct augeas *aug, const char *fpath);
487
/* Find a node in the tree at path FPATH; FPATH is a file path, i.e.
488
 * not interpreted as a path expression. If no such node exists, create
489
 * it and all its missing ancestors.
490
 */
491
struct tree *tree_fpath_cr(struct augeas *aug, const char *fpath);
492
/* Find the node matching PATH.
493
 * Returns the node or NULL on error
494
 * Errors: EMMATCH - more than one node matches PATH
495
 *         ENOMEM  - allocation error
496
 */
497
struct tree *tree_find(struct augeas *aug, const char *path);
498
/* Find the node matching PATH. Expand the tree to contain such a node if
499
 * none exists.
500
 * Returns the node or NULL on error
501
 */
502
struct tree *tree_find_cr(struct augeas *aug, const char *path);
503
/* Find the node at the path stored in AUGEAS_CONTEXT, i.e. the root context
504
 * node for relative paths.
505
 * Errors: EMMATCH - more than one node matches PATH
506
 *         ENOMEM  - allocation error
507
 */
508
struct tree *tree_root_ctx(const struct augeas *aug);
509
510
/* Struct: memstream
511
 * Wrappers to simulate OPEN_MEMSTREAM where that's not available. The
512
 * STREAM member is opened by INIT_MEMSTREAM and closed by
513
 * CLOSE_MEMSTREAM. The BUF is allocated automatically, but can not be used
514
 * until after CLOSE_MEMSTREAM has been called. It is the callers
515
 * responsibility to free up BUF.
516
 */
517
struct memstream {
518
    FILE   *stream;
519
    char   *buf;
520
    size_t size;
521
};
522
523
/* Function: init_memstream
524
 * Initialize a memstream. On systems that have OPEN_MEMSTREAM, it is used
525
 * to open MS->STREAM. On systems without OPEN_MEMSTREAM, MS->STREAM is
526
 * backed by a temporary file.
527
 *
528
 * MS must be allocated in advance; INIT_MEMSTREAM initializes it.
529
 */
530
int __aug_init_memstream(struct memstream *ms);
531
0
#define init_memstream(ms) __aug_init_memstream(ms);
532
533
/* Function: close_memstream
534
 * Close a memstream. After calling this, MS->STREAM can not be used
535
 * anymore and a string representing whatever was written to it is
536
 * available in MS->BUF. The caller must free MS->BUF.
537
 *
538
 * The caller must free the MEMSTREAM structure.
539
 */
540
int __aug_close_memstream(struct memstream *ms);
541
0
#define close_memstream(ms) __aug_close_memstream(ms)
542
543
/*
544
 * Path expressions
545
 */
546
547
typedef enum {
548
    PATHX_NOERROR = 0,
549
    PATHX_ENAME,
550
    PATHX_ESTRING,
551
    PATHX_ENUMBER,
552
    PATHX_EDELIM,
553
    PATHX_ENOEQUAL,
554
    PATHX_ENOMEM,
555
    PATHX_EPRED,
556
    PATHX_EPAREN,
557
    PATHX_ESLASH,
558
    PATHX_EINTERNAL,
559
    PATHX_ETYPE,
560
    PATHX_ENOVAR,
561
    PATHX_EEND,
562
    PATHX_ENOMATCH,
563
    PATHX_EARITY,
564
    PATHX_EREGEXP,
565
    PATHX_EMMATCH,
566
    PATHX_EREGEXPFLAG
567
} pathx_errcode_t;
568
569
struct pathx;
570
struct pathx_symtab;
571
572
const char *pathx_error(struct pathx *pathx, const char **txt, int *pos);
573
574
/* Parse a path expression PATH rooted at TREE, which is a node somewhere
575
 * in AUG->ORIGIN. If TREE is NULL, AUG->ORIGIN is used. If ROOT_CTX is not
576
 * NULL and the PATH isn't absolute then it will be rooted at ROOT_CTX.
577
 *
578
 * Use this function rather than PATHX_PARSE for path expressions inside
579
 * the tree in AUG->ORIGIN.
580
 *
581
 * If NEED_NODESET is true, the resulting path expression must evaluate toa
582
 * nodeset, otherwise it can evaluate to a value of any type.
583
 *
584
 * Return the resulting path expression, or NULL on error. If an error
585
 * occurs, the error struct in AUG contains details.
586
 */
587
struct pathx *pathx_aug_parse(const struct augeas *aug,
588
                              struct tree *tree,
589
                              struct tree *root_ctx,
590
                              const char *path, bool need_nodeset);
591
592
/* Parse the string PATH into a path expression PX that will be evaluated
593
 * against the tree ORIGIN.
594
 *
595
 * If NEED_NODESET is true, the resulting path expression must evaluate toa
596
 * nodeset, otherwise it can evaluate to a value of any type.
597
 *
598
 * Returns 0 on success, and -1 on error
599
 */
600
int pathx_parse(const struct tree *origin,
601
                struct error *err,
602
                const char *path,
603
                bool need_nodeset,
604
                struct pathx_symtab *symtab,
605
                struct tree *root_ctx,
606
                struct pathx **px);
607
/* Return the error struct that was passed into pathx_parse */
608
struct error *err_of_pathx(struct pathx *px);
609
struct tree *pathx_first(struct pathx *path);
610
struct tree *pathx_next(struct pathx *path);
611
/* Return -1 if evaluating PATH runs into trouble, otherwise return the
612
 * number of nodes matching PATH and set MATCH to the first matching
613
 * node */
614
int pathx_find_one(struct pathx *path, struct tree **match);
615
int pathx_expand_tree(struct pathx *path, struct tree **tree);
616
void free_pathx(struct pathx *path);
617
618
struct pathx_symtab *pathx_get_symtab(struct pathx *pathx);
619
int pathx_symtab_define(struct pathx_symtab **symtab,
620
                        const char *name, struct pathx *px);
621
/* Returns 1 on success, and -1 when out of memory */
622
int pathx_symtab_assign_tree(struct pathx_symtab **symtab, const char *name,
623
                             struct tree *tree);
624
int pathx_symtab_undefine(struct pathx_symtab **symtab, const char *name);
625
void pathx_symtab_remove_descendants(struct pathx_symtab *symtab,
626
                                     const struct tree *tree);
627
628
/* Return the number of nodes in the nodeset NAME. If the variable NAME
629
 * does not exist, or is not a nodeset, return -1 */
630
int pathx_symtab_count(const struct pathx_symtab *symtab, const char *name);
631
632
/* Return the tree stored in the variable NAME at position I, which is the
633
   same as evaluating the path expression '$NAME[I]'. If the variable NAME
634
   does not exist, or does not contain a nodeset, or if I is bigger than
635
   the size of the nodeset, return NULL */
636
struct tree *pathx_symtab_get_tree(struct pathx_symtab *symtab,
637
                                   const char *name, int i);
638
void free_symtab(struct pathx_symtab *symtab);
639
640
/* Escape a name so that it is safe to pass to parse_name and have it
641
 * interpreted as the literal name of a path component.
642
 *
643
 * On return, *OUT will be NULL if IN does not need escaping, otherwise it
644
 * will contain an escaped copy of IN which the caller must free.
645
 *
646
 * Returns -1 if it failed to allocate memory for *OUT, 0 on success
647
 */
648
int pathx_escape_name(const char *in, char **out);
649
650
/* Debug helpers, all defined in internal.c. When ENABLE_DEBUG is not
651
 * set, they compile to nothing.
652
 */
653
#  if ENABLE_DEBUG
654
  /* Return true if debugging for CATEGORY is turned on */
655
  bool debugging(const char *category);
656
  /* Format the arguments into a file name, prepend it with the directory
657
   * from the environment variable AUGEAS_DEBUG_DIR, and open the file for
658
   * writing.
659
  */
660
  FILE *debug_fopen(const char *format, ...)
661
    ATTRIBUTE_FORMAT(printf, 1, 2);
662
#  else
663
#    define debugging(facility) (0)
664
#    define debug_fopen(format ...) (NULL)
665
#  endif
666
#endif
667
668
669
/*
670
 * Local variables:
671
 *  indent-tabs-mode: nil
672
 *  c-indent-level: 4
673
 *  c-basic-offset: 4
674
 *  tab-width: 4
675
 * End:
676
 */