/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 | 1.52k | #define AUGEAS_LENS_DIR DATADIR "/augeas/lenses" |
48 | | |
49 | | /* The directory where we install lenses distribute with Augeas */ |
50 | 1.52k | #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 | 1.52k | #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 | 38.1k | #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 | 0 | #define AUGEAS_META_TEXT AUGEAS_META_TREE "/text" |
72 | | |
73 | | /* Define: AUGEAS_META_ROOT |
74 | | * The root directory */ |
75 | 1.52k | #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 | 1.52k | #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 | 32.0k | #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 | 3.04k | #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 | 1.52k | #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 | 19.8k | #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 | 1.52k | #define AUG_SAVE_OVERWRITE_TEXT "overwrite" |
126 | | |
127 | | /* constants for options in the tree */ |
128 | 1.52k | #define AUG_ENABLE "enable" |
129 | 1.52k | #define AUG_DISABLE "disable" |
130 | | |
131 | | /* default value for the relative path context */ |
132 | 1.52k | #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 | 24.5M | # 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 | 11.2M | #define ARRAY_CARDINALITY(array) (sizeof (array) / sizeof *(array)) |
218 | | |
219 | | /* String equality tests, suggested by Jim Meyering. */ |
220 | 1.20M | #define STREQ(a,b) (strcmp((a),(b)) == 0) |
221 | 0 | #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0) |
222 | | #define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0) |
223 | 77.7k | #define STRNEQ(a,b) (strcmp((a),(b)) != 0) |
224 | | #define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0) |
225 | 45.0M | #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 | 87.0k | static inline int streqv(const char *a, const char *b) { |
230 | 87.0k | if (a == NULL || b == NULL) |
231 | 48.4k | return a == b; |
232 | 38.5k | return STREQ(a,b); |
233 | 87.0k | } Line | Count | Source | 229 | 87.0k | static inline int streqv(const char *a, const char *b) { | 230 | 87.0k | if (a == NULL || b == NULL) | 231 | 48.4k | return a == b; | 232 | 38.5k | return STREQ(a,b); | 233 | 87.0k | } |
Unexecuted instantiation: pathx.c:streqv Unexecuted instantiation: internal.c:streqv Unexecuted instantiation: memory.c:streqv Unexecuted instantiation: syntax.c:streqv 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 | 30.4k | #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.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.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.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 | 32.0k | #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 | 0 | #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 | 91.4k | static inline struct error *err_of_aug(const struct augeas *aug) { |
383 | 91.4k | return ((struct augeas *) aug)->error; |
384 | 91.4k | } Line | Count | Source | 382 | 91.4k | static inline struct error *err_of_aug(const struct augeas *aug) { | 383 | 91.4k | return ((struct augeas *) aug)->error; | 384 | 91.4k | } |
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 | 0 | #define ROOT_P(t) ((t) != NULL && (t)->parent == (t)->parent->parent) |
435 | | |
436 | 177 | #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 | | */ |