/src/augeas/src/internal.h
Line | Count | Source |
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 | 3.11k | #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 | 4 | #define AUGEAS_META_TEXT AUGEAS_META_TREE "/text" |
72 | | |
73 | | /* Define: AUGEAS_META_ROOT |
74 | | * The root directory */ |
75 | 109 | #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 | 109 | #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 | 2.78k | #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 | 109 | #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 | 109 | #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 | 109 | #define AUG_SAVE_OVERWRITE_TEXT "overwrite" |
126 | | |
127 | | /* constants for options in the tree */ |
128 | 0 | #define AUG_ENABLE "enable" |
129 | 109 | #define AUG_DISABLE "disable" |
130 | | |
131 | | /* default value for the relative path context */ |
132 | 109 | #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 | 35.0M | # 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 defined __has_attribute |
195 | | # if __has_attribute (fallthrough) |
196 | | # define ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough)) |
197 | | # else |
198 | | # define ATTRIBUTE_FALLTHROUGH |
199 | | # endif |
200 | | # else |
201 | | # define ATTRIBUTE_FALLTHROUGH |
202 | | # endif |
203 | | #endif |
204 | | |
205 | | /* A poor man's macro to get some move semantics: return the value of P but |
206 | | set P itself to NULL. This has the effect that if you say 'x = move(y)' |
207 | | that there is still only one pointer pointing to the memory Y pointed to |
208 | | initially. |
209 | | */ |
210 | 0 | #define move(p) ({ typeof(p) _tmp = (p); (p) = NULL; _tmp; }) |
211 | | |
212 | | #else |
213 | | #define ATTRIBUTE_UNUSED |
214 | | #define ATTRIBUTE_FORMAT(...) |
215 | | #define ATTRIBUTE_PURE |
216 | | #define ATTRIBUTE_RETURN_CHECK |
217 | | #define ATTRIBUTE_FALLTHROUGH |
218 | | #define move(p) p |
219 | | #endif /* __GNUC__ */ |
220 | | |
221 | 24.2M | #define ARRAY_CARDINALITY(array) (sizeof (array) / sizeof *(array)) |
222 | | |
223 | | /* String equality tests, suggested by Jim Meyering. */ |
224 | 12.9M | #define STREQ(a,b) (strcmp((a),(b)) == 0) |
225 | 13 | #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0) |
226 | | #define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0) |
227 | 165k | #define STRNEQ(a,b) (strcmp((a),(b)) != 0) |
228 | | #define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0) |
229 | 345M | #define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0) |
230 | 0 | #define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0) |
231 | | |
232 | | ATTRIBUTE_PURE |
233 | 208k | static inline int streqv(const char *a, const char *b) { |
234 | 208k | if (a == NULL || b == NULL) |
235 | 4.73k | return a == b; |
236 | 203k | return STREQ(a,b); |
237 | 208k | } Unexecuted instantiation: augeas_api_fuzzer.cc:streqv(char const*, char const*) Line | Count | Source | 233 | 16.6k | static inline int streqv(const char *a, const char *b) { | 234 | 16.6k | if (a == NULL || b == NULL) | 235 | 4.72k | return a == b; | 236 | 11.9k | return STREQ(a,b); | 237 | 16.6k | } |
Unexecuted instantiation: pathx.c:streqv Line | Count | Source | 233 | 191k | static inline int streqv(const char *a, const char *b) { | 234 | 191k | if (a == NULL || b == NULL) | 235 | 0 | return a == b; | 236 | 191k | return STREQ(a,b); | 237 | 191k | } |
Unexecuted instantiation: memory.c:streqv Line | Count | Source | 233 | 3 | static inline int streqv(const char *a, const char *b) { | 234 | 3 | if (a == NULL || b == NULL) | 235 | 3 | return a == b; | 236 | 0 | return STREQ(a,b); | 237 | 3 | } |
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 |
238 | | |
239 | | /* Path length and comparison */ |
240 | | |
241 | 2.68k | #define SEP '/' |
242 | | |
243 | | /* Length of PATH without any trailing '/' */ |
244 | | ATTRIBUTE_PURE |
245 | 0 | static inline int pathlen(const char *path) { |
246 | 0 | int len = strlen(path); |
247 | 0 |
|
248 | 0 | if (len > 0 && path[len-1] == SEP) |
249 | 0 | len--; |
250 | 0 |
|
251 | 0 | return len; |
252 | 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 |
253 | | |
254 | | /* Return 1 if P1 is a prefix of P2. P1 as a string must have length <= P2 */ |
255 | | ATTRIBUTE_PURE |
256 | 0 | static inline int pathprefix(const char *p1, const char *p2) { |
257 | 0 | if (p1 == NULL || p2 == NULL) |
258 | 0 | return 0; |
259 | 0 | int l1 = pathlen(p1); |
260 | 0 |
|
261 | 0 | return STREQLEN(p1, p2, l1) && (p2[l1] == '\0' || p2[l1] == SEP); |
262 | 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 |
263 | | |
264 | 0 | static inline int pathendswith(const char *path, const char *basenam) { |
265 | 0 | const char *p = strrchr(path, SEP); |
266 | 0 | if (p == NULL) |
267 | 0 | return 0; |
268 | 0 | return streqv(p+1, basenam); |
269 | 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 |
270 | | |
271 | | /* Join NSEG path components (passed as const char *) into one PATH. |
272 | | Allocate as needed. Return 0 on success, -1 on failure */ |
273 | | int pathjoin(char **path, int nseg, ...); |
274 | | |
275 | 2.28k | #define MEMZERO(ptr, n) memset((ptr), 0, (n) * sizeof(*(ptr))); |
276 | | |
277 | 0 | #define MEMMOVE(dest, src, n) memmove((dest), (src), (n) * sizeof(*(src))) |
278 | | |
279 | | /** |
280 | | * TODO: |
281 | | * |
282 | | * macro to flag unimplemented blocks |
283 | | */ |
284 | | #define TODO \ |
285 | | fprintf(stderr, "%s:%d Unimplemented block\n", \ |
286 | | __FILE__, __LINE__); |
287 | | |
288 | | #define FIXME(msg, args ...) \ |
289 | | do { \ |
290 | | fprintf(stderr, "%s:%d Fixme: ", \ |
291 | | __FILE__, __LINE__); \ |
292 | | fprintf(stderr, msg, ## args); \ |
293 | | fputc('\n', stderr); \ |
294 | | } while(0) |
295 | | |
296 | | /* |
297 | | * Internal data structures |
298 | | */ |
299 | | |
300 | | // internal.c |
301 | | |
302 | | /* Function: escape |
303 | | * Escape nonprintable characters within TEXT, similar to how it's done in |
304 | | * C string literals. Caller must free the returned string. |
305 | | */ |
306 | | char *escape(const char *text, int cnt, const char *extra); |
307 | | |
308 | | /* Function: unescape */ |
309 | | char *unescape(const char *s, int len, const char *extra); |
310 | | |
311 | | /* Extra characters to be escaped in strings and regexps respectively */ |
312 | 8.13k | #define STR_ESCAPES "\"\\" |
313 | 0 | #define RX_ESCAPES "/\\" |
314 | | |
315 | | /* Function: print_chars */ |
316 | | int print_chars(FILE *out, const char *text, int cnt); |
317 | | |
318 | | /* Function: print_pos |
319 | | * Print a pretty representation of being at position POS within TEXT */ |
320 | | void print_pos(FILE *out, const char *text, int pos); |
321 | | char *format_pos(const char *text, int pos); |
322 | | |
323 | | /* Function: xread_file |
324 | | * Read the contents of file PATH and return them as one long string. The |
325 | | * caller must free the result. Return NULL if any error occurs. |
326 | | */ |
327 | | char* xread_file(const char *path); |
328 | | |
329 | | /* Like xread_file, but caller supplies a file pointer */ |
330 | | char* xfread_file(FILE *fp); |
331 | | |
332 | | /* Get the error message for ERRNUM in a threadsafe way. Based on libvirt's |
333 | | * virStrError |
334 | | */ |
335 | | const char *xstrerror(int errnum, char *buf, size_t len); |
336 | | |
337 | | /* Like asprintf, but set *STRP to NULL on error */ |
338 | | int xasprintf(char **strp, const char *format, ...); |
339 | | |
340 | | /* Convert S to RESULT with error checking */ |
341 | | int xstrtoint64(char const *s, int base, int64_t *result); |
342 | | |
343 | | /* Calculate line and column number of character POS in TEXT */ |
344 | | void calc_line_ofs(const char *text, size_t pos, size_t *line, size_t *ofs); |
345 | | |
346 | | /* Cleans path from user, removing trailing slashes and whitespace */ |
347 | | char *cleanpath(char *path); |
348 | | |
349 | | /* Take the first LEN characters from the regexp *U and expand any |
350 | | * character ranges in it. The expanded regexp, if expansion is necessary, |
351 | | * is in U, and the old string is freed. If expansion is not needed or an |
352 | | * error happens, U will be unchanged. |
353 | | * |
354 | | * Return 0 if expansion is not necessary, -1 if an error occurs, and 1 if |
355 | | * expansion was needed. |
356 | | */ |
357 | | int regexp_c_locale(char **u, size_t *len); |
358 | | |
359 | | /* Struct: augeas |
360 | | * The data structure representing a connection to Augeas. */ |
361 | | struct augeas { |
362 | | struct tree *origin; /* Actual tree root is origin->children */ |
363 | | const char *root; /* Filesystem root for all files */ |
364 | | /* always ends with '/' */ |
365 | | unsigned int flags; /* Flags passed to AUG_INIT */ |
366 | | struct module *modules; /* Loaded modules */ |
367 | | size_t nmodpath; |
368 | | char *modpathz; /* The search path for modules as a |
369 | | glibc argz vector */ |
370 | | struct pathx_symtab *symtab; |
371 | | struct error *error; |
372 | | uint api_entries; /* Number of entries through a public |
373 | | * API, 0 when called from outside */ |
374 | | #if HAVE_USELOCALE |
375 | | /* On systems that have a uselocale call, we switch to the C locale |
376 | | * on entry into API functions, and back to the old user locale |
377 | | * on exit. |
378 | | * FIXME: We need some solution for systems without uselocale, like |
379 | | * setlocale + critical section, though that is very heavy-handed |
380 | | */ |
381 | | locale_t c_locale; |
382 | | locale_t user_locale; |
383 | | #endif |
384 | | }; |
385 | | |
386 | 8.03k | static inline struct error *err_of_aug(const struct augeas *aug) { |
387 | 8.03k | return ((struct augeas *) aug)->error; |
388 | 8.03k | } Unexecuted instantiation: augeas_api_fuzzer.cc:err_of_aug(augeas const*) Line | Count | Source | 386 | 8.03k | static inline struct error *err_of_aug(const struct augeas *aug) { | 387 | 8.03k | return ((struct augeas *) aug)->error; | 388 | 8.03k | } |
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 |
389 | | |
390 | | /* Used by augparse for loading tests */ |
391 | | int __aug_load_module_file(struct augeas *aug, const char *filename); |
392 | | |
393 | | /* Called at beginning and end of every _public_ API function */ |
394 | | void api_entry(const struct augeas *aug); |
395 | | void api_exit(const struct augeas *aug); |
396 | | |
397 | | /* Struct: tree |
398 | | * An entry in the global config tree. The data structure allows associating |
399 | | * values with interior nodes, but the API currently marks that as an error. |
400 | | * |
401 | | * To make dealing with parents uniform, even for the root, we create |
402 | | * standalone trees with a fake root, called origin. That root is generally |
403 | | * not referenced from anywhere. Standalone trees should be created with |
404 | | * MAKE_TREE_ORIGIN. |
405 | | * |
406 | | * The DIRTY flag is used to track which parts of the tree might need to be |
407 | | * saved. For any node that is marked dirty, all of its ancestors must be |
408 | | * marked dirty, too. Instead of setting this flag directly, the function |
409 | | * TREE_MARK_DIRTY in augeas.c should be used (and only functions in that |
410 | | * file should have a need to mark nodes as dirty) |
411 | | * |
412 | | * The FILE flag is set for entries underneath /augeas/files that hold the |
413 | | * metadata for a file by ADD_FILE_INFO. The FILE flag is set for entries |
414 | | * underneath /files for the toplevel node corresponding to a file by |
415 | | * TREE_FREPLACE and is used by AUG_SOURCE to find the file to which a node |
416 | | * belongs. |
417 | | */ |
418 | | struct tree { |
419 | | struct tree *next; |
420 | | struct tree *parent; /* Points to self for root */ |
421 | | char *label; /* Last component of PATH */ |
422 | | struct tree *children; /* List of children through NEXT */ |
423 | | char *value; |
424 | | struct span *span; |
425 | | |
426 | | /* Flags */ |
427 | | bool dirty; |
428 | | bool file; |
429 | | bool added; /* only used by ns_add and tree_rm to dedupe |
430 | | nodesets */ |
431 | | }; |
432 | | |
433 | | /* The opaque structure used to represent path expressions. API's |
434 | | * using STRUCT PATHX are declared farther below |
435 | | */ |
436 | | struct pathx; |
437 | | |
438 | 40.3k | #define ROOT_P(t) ((t) != NULL && (t)->parent == (t)->parent->parent) |
439 | | |
440 | 49.2k | #define TREE_HIDDEN(tree) ((tree)->label == NULL) |
441 | | |
442 | | /* Function: make_tree |
443 | | * Allocate a new tree node with the given LABEL, VALUE, and CHILDREN, |
444 | | * which are not copied. The new tree is marked as dirty |
445 | | */ |
446 | | struct tree *make_tree(char *label, char *value, |
447 | | struct tree *parent, struct tree *children); |
448 | | |
449 | | /* Mark a tree as a standalone tree; this creates a fake parent for ROOT, |
450 | | * so that even ROOT has a parent. A new node with only child ROOT is |
451 | | * returned on success, and NULL on failure. |
452 | | */ |
453 | | struct tree *make_tree_origin(struct tree *root); |
454 | | |
455 | | /* Make a new tree node and append it to parent's children */ |
456 | | struct tree *tree_append(struct tree *parent, char *label, char *value); |
457 | | |
458 | | int tree_rm(struct pathx *p); |
459 | | int tree_unlink(struct augeas *aug, struct tree *tree); |
460 | | struct tree *tree_set(struct pathx *p, const char *value); |
461 | | int tree_insert(struct pathx *p, const char *label, int before); |
462 | | int free_tree(struct tree *tree); |
463 | | int dump_tree(FILE *out, struct tree *tree); |
464 | | int tree_equal(const struct tree *t1, const struct tree *t2); |
465 | | /* Return the 1-based index of TREE amongst its siblings with the same |
466 | | * label or 0 if none of TREE's siblings have the same label */ |
467 | | int tree_sibling_index(struct tree *tree); |
468 | | char *path_expand(struct tree *tree, const char *ppath); |
469 | | char *path_of_tree(struct tree *tree); |
470 | | /* Clear the dirty flag in the whole TREE */ |
471 | | void tree_clean(struct tree *tree); |
472 | | /* Return first child with label LABEL or NULL */ |
473 | | struct tree *tree_child(struct tree *tree, const char *label); |
474 | | /* Return first existing child with label LABEL or create one. Return NULL |
475 | | * when allocation fails */ |
476 | | struct tree *tree_child_cr(struct tree *tree, const char *label); |
477 | | /* Create a path in the tree; nodes along the path are looked up with |
478 | | * tree_child_cr */ |
479 | | struct tree *tree_path_cr(struct tree *tree, int n, ...); |
480 | | /* Store VALUE directly as the value of TREE and set VALUE to NULL. |
481 | | * Update dirty flags */ |
482 | | void tree_store_value(struct tree *tree, char **value); |
483 | | /* Set the value of TREE to a copy of VALUE and update dirty flags */ |
484 | | int tree_set_value(struct tree *tree, const char *value); |
485 | | /* Cleanly remove all children of TREE, but leave TREE itself unchanged */ |
486 | | void tree_unlink_children(struct augeas *aug, struct tree *tree); |
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, return NULL |
489 | | */ |
490 | | struct tree *tree_fpath(struct augeas *aug, const char *fpath); |
491 | | /* Find a node in the tree at path FPATH; FPATH is a file path, i.e. |
492 | | * not interpreted as a path expression. If no such node exists, create |
493 | | * it and all its missing ancestors. |
494 | | */ |
495 | | struct tree *tree_fpath_cr(struct augeas *aug, const char *fpath); |
496 | | /* Find the node matching PATH. |
497 | | * Returns the node or NULL on error |
498 | | * Errors: EMMATCH - more than one node matches PATH |
499 | | * ENOMEM - allocation error |
500 | | */ |
501 | | struct tree *tree_find(struct augeas *aug, const char *path); |
502 | | /* Find the node matching PATH. Expand the tree to contain such a node if |
503 | | * none exists. |
504 | | * Returns the node or NULL on error |
505 | | */ |
506 | | struct tree *tree_find_cr(struct augeas *aug, const char *path); |
507 | | /* Find the node at the path stored in AUGEAS_CONTEXT, i.e. the root context |
508 | | * node for relative paths. |
509 | | * Errors: EMMATCH - more than one node matches PATH |
510 | | * ENOMEM - allocation error |
511 | | */ |
512 | | struct tree *tree_root_ctx(const struct augeas *aug); |
513 | | |
514 | | /* Struct: memstream |
515 | | * Wrappers to simulate OPEN_MEMSTREAM where that's not available. The |
516 | | * STREAM member is opened by INIT_MEMSTREAM and closed by |
517 | | * CLOSE_MEMSTREAM. The BUF is allocated automatically, but can not be used |
518 | | * until after CLOSE_MEMSTREAM has been called. It is the callers |
519 | | * responsibility to free up BUF. |
520 | | */ |
521 | | struct memstream { |
522 | | FILE *stream; |
523 | | char *buf; |
524 | | size_t size; |
525 | | }; |
526 | | |
527 | | /* Function: init_memstream |
528 | | * Initialize a memstream. On systems that have OPEN_MEMSTREAM, it is used |
529 | | * to open MS->STREAM. On systems without OPEN_MEMSTREAM, MS->STREAM is |
530 | | * backed by a temporary file. |
531 | | * |
532 | | * MS must be allocated in advance; INIT_MEMSTREAM initializes it. |
533 | | */ |
534 | | int __aug_init_memstream(struct memstream *ms); |
535 | 0 | #define init_memstream(ms) __aug_init_memstream(ms); |
536 | | |
537 | | /* Function: close_memstream |
538 | | * Close a memstream. After calling this, MS->STREAM can not be used |
539 | | * anymore and a string representing whatever was written to it is |
540 | | * available in MS->BUF. The caller must free MS->BUF. |
541 | | * |
542 | | * The caller must free the MEMSTREAM structure. |
543 | | */ |
544 | | int __aug_close_memstream(struct memstream *ms); |
545 | 0 | #define close_memstream(ms) __aug_close_memstream(ms) |
546 | | |
547 | | /* |
548 | | * Path expressions |
549 | | */ |
550 | | |
551 | | typedef enum { |
552 | | PATHX_NOERROR = 0, |
553 | | PATHX_ENAME, |
554 | | PATHX_ESTRING, |
555 | | PATHX_ENUMBER, |
556 | | PATHX_EDELIM, |
557 | | PATHX_ENOEQUAL, |
558 | | PATHX_ENOMEM, |
559 | | PATHX_EPRED, |
560 | | PATHX_EPAREN, |
561 | | PATHX_ESLASH, |
562 | | PATHX_EINTERNAL, |
563 | | PATHX_ETYPE, |
564 | | PATHX_ENOVAR, |
565 | | PATHX_EEND, |
566 | | PATHX_ENOMATCH, |
567 | | PATHX_EARITY, |
568 | | PATHX_EREGEXP, |
569 | | PATHX_EMMATCH, |
570 | | PATHX_EREGEXPFLAG |
571 | | } pathx_errcode_t; |
572 | | |
573 | | struct pathx; |
574 | | struct pathx_symtab; |
575 | | |
576 | | const char *pathx_error(struct pathx *pathx, const char **txt, int *pos); |
577 | | |
578 | | /* Parse a path expression PATH rooted at TREE, which is a node somewhere |
579 | | * in AUG->ORIGIN. If TREE is NULL, AUG->ORIGIN is used. If ROOT_CTX is not |
580 | | * NULL and the PATH isn't absolute then it will be rooted at ROOT_CTX. |
581 | | * |
582 | | * Use this function rather than PATHX_PARSE for path expressions inside |
583 | | * the tree in AUG->ORIGIN. |
584 | | * |
585 | | * If NEED_NODESET is true, the resulting path expression must evaluate toa |
586 | | * nodeset, otherwise it can evaluate to a value of any type. |
587 | | * |
588 | | * Return the resulting path expression, or NULL on error. If an error |
589 | | * occurs, the error struct in AUG contains details. |
590 | | */ |
591 | | struct pathx *pathx_aug_parse(const struct augeas *aug, |
592 | | struct tree *tree, |
593 | | struct tree *root_ctx, |
594 | | const char *path, bool need_nodeset); |
595 | | |
596 | | /* Parse the string PATH into a path expression PX that will be evaluated |
597 | | * against the tree ORIGIN. |
598 | | * |
599 | | * If NEED_NODESET is true, the resulting path expression must evaluate toa |
600 | | * nodeset, otherwise it can evaluate to a value of any type. |
601 | | * |
602 | | * Returns 0 on success, and -1 on error |
603 | | */ |
604 | | int pathx_parse(const struct tree *origin, |
605 | | struct error *err, |
606 | | const char *path, |
607 | | bool need_nodeset, |
608 | | struct pathx_symtab *symtab, |
609 | | struct tree *root_ctx, |
610 | | struct pathx **px); |
611 | | /* Return the error struct that was passed into pathx_parse */ |
612 | | struct error *err_of_pathx(struct pathx *px); |
613 | | struct tree *pathx_first(struct pathx *path); |
614 | | struct tree *pathx_next(struct pathx *path); |
615 | | /* Return -1 if evaluating PATH runs into trouble, otherwise return the |
616 | | * number of nodes matching PATH and set MATCH to the first matching |
617 | | * node */ |
618 | | int pathx_find_one(struct pathx *path, struct tree **match); |
619 | | int pathx_expand_tree(struct pathx *path, struct tree **tree); |
620 | | void free_pathx(struct pathx *path); |
621 | | |
622 | | struct pathx_symtab *pathx_get_symtab(struct pathx *pathx); |
623 | | int pathx_symtab_define(struct pathx_symtab **symtab, |
624 | | const char *name, struct pathx *px); |
625 | | /* Returns 1 on success, and -1 when out of memory */ |
626 | | int pathx_symtab_assign_tree(struct pathx_symtab **symtab, const char *name, |
627 | | struct tree *tree); |
628 | | int pathx_symtab_undefine(struct pathx_symtab **symtab, const char *name); |
629 | | void pathx_symtab_remove_descendants(struct pathx_symtab *symtab, |
630 | | const struct tree *tree); |
631 | | |
632 | | /* Return the number of nodes in the nodeset NAME. If the variable NAME |
633 | | * does not exist, or is not a nodeset, return -1 */ |
634 | | int pathx_symtab_count(const struct pathx_symtab *symtab, const char *name); |
635 | | |
636 | | /* Return the tree stored in the variable NAME at position I, which is the |
637 | | same as evaluating the path expression '$NAME[I]'. If the variable NAME |
638 | | does not exist, or does not contain a nodeset, or if I is bigger than |
639 | | the size of the nodeset, return NULL */ |
640 | | struct tree *pathx_symtab_get_tree(struct pathx_symtab *symtab, |
641 | | const char *name, int i); |
642 | | void free_symtab(struct pathx_symtab *symtab); |
643 | | |
644 | | /* Escape a name so that it is safe to pass to parse_name and have it |
645 | | * interpreted as the literal name of a path component. |
646 | | * |
647 | | * On return, *OUT will be NULL if IN does not need escaping, otherwise it |
648 | | * will contain an escaped copy of IN which the caller must free. |
649 | | * |
650 | | * Returns -1 if it failed to allocate memory for *OUT, 0 on success |
651 | | */ |
652 | | int pathx_escape_name(const char *in, char **out); |
653 | | |
654 | | /* Debug helpers, all defined in internal.c. When ENABLE_DEBUG is not |
655 | | * set, they compile to nothing. |
656 | | */ |
657 | | # if ENABLE_DEBUG |
658 | | /* Return true if debugging for CATEGORY is turned on */ |
659 | | bool debugging(const char *category); |
660 | | /* Format the arguments into a file name, prepend it with the directory |
661 | | * from the environment variable AUGEAS_DEBUG_DIR, and open the file for |
662 | | * writing. |
663 | | */ |
664 | | FILE *debug_fopen(const char *format, ...) |
665 | | ATTRIBUTE_FORMAT(printf, 1, 2); |
666 | | # else |
667 | | # define debugging(facility) (0) |
668 | | # define debug_fopen(format ...) (NULL) |
669 | | # endif |
670 | | #endif |
671 | | |
672 | | |
673 | | /* |
674 | | * Local variables: |
675 | | * indent-tabs-mode: nil |
676 | | * c-indent-level: 4 |
677 | | * c-basic-offset: 4 |
678 | | * tab-width: 4 |
679 | | * End: |
680 | | */ |