• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uci/uci.h

  1 /*
  2  * libuci - Library for the Unified Configuration Interface
  3  * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU Lesser General Public License version 2.1
  7  * as published by the Free Software Foundation
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU Lesser General Public License for more details.
 13  */
 14 
 15 #ifndef __LIBUCI_H
 16 #define __LIBUCI_H
 17 
 18 #ifdef __cplusplus
 19 extern "C" {
 20 #endif
 21 
 22 #include "uci_config.h"
 23 
 24 /*
 25  * you can use these defines to enable debugging behavior for
 26  * apps compiled against libuci:
 27  *
 28  * #define UCI_DEBUG_TYPECAST:
 29  *   enable uci_element typecast checking at run time
 30  *
 31  */
 32 
 33 #include <stdbool.h>
 34 #include <setjmp.h>
 35 #include <stdio.h>
 36 #include <stdint.h>
 37 #include <stddef.h>
 38 
 39 #define UCI_CONFDIR "/etc/config"
 40 #define UCI_SAVEDIR "/tmp/.uci"
 41 #define UCI_CONF2DIR "/var/run/uci"
 42 #define UCI_DIRMODE 0700
 43 #define UCI_FILEMODE 0600
 44 
 45 enum
 46 {
 47         UCI_OK = 0,
 48         UCI_ERR_MEM,
 49         UCI_ERR_INVAL,
 50         UCI_ERR_NOTFOUND,
 51         UCI_ERR_IO,
 52         UCI_ERR_PARSE,
 53         UCI_ERR_DUPLICATE,
 54         UCI_ERR_UNKNOWN,
 55         UCI_ERR_LAST
 56 };
 57 
 58 struct uci_list;
 59 struct uci_list
 60 {
 61         struct uci_list *next;
 62         struct uci_list *prev;
 63 };
 64 
 65 struct uci_ptr;
 66 struct uci_element;
 67 struct uci_package;
 68 struct uci_section;
 69 struct uci_option;
 70 struct uci_delta;
 71 struct uci_context;
 72 struct uci_backend;
 73 struct uci_parse_option;
 74 struct uci_parse_context;
 75 
 76 
 77 /**
 78  * uci_alloc_context: Allocate a new uci context
 79  */
 80 extern struct uci_context *uci_alloc_context(void);
 81 
 82 /**
 83  * uci_free_context: Free the uci context including all of its data
 84  */
 85 extern void uci_free_context(struct uci_context *ctx);
 86 
 87 /**
 88  * uci_perror: Print the last uci error that occured
 89  * @ctx: uci context
 90  * @str: string to print before the error message
 91  */
 92 extern void uci_perror(struct uci_context *ctx, const char *str);
 93 
 94 /**
 95  * uci_geterror: Get an error string for the last uci error
 96  * @ctx: uci context
 97  * @dest: target pointer for the string
 98  * @str: prefix for the error message
 99  *
100  * Note: string must be freed by the caller
101  */
102 extern void uci_get_errorstr(struct uci_context *ctx, char **dest, const char *str);
103 
104 /**
105  * uci_import: Import uci config data from a stream
106  * @ctx: uci context
107  * @stream: file stream to import from
108  * @name: (optional) assume the config has the given name
109  * @package: (optional) store the last parsed config package in this variable
110  * @single: ignore the 'package' keyword and parse everything into a single package
111  *
112  * the name parameter is for config files that don't explicitly use the 'package <...>' keyword
113  * if 'package' points to a non-null struct pointer, enable delta tracking and merge
114  */
115 extern int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct uci_package **package, bool single);
116 
117 /**
118  * uci_export: Export one or all uci config packages
119  * @ctx: uci context
120  * @stream: output stream
121  * @package: (optional) uci config package to export
122  * @header: include the package header
123  */
124 extern int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *package, bool header);
125 
126 /**
127  * uci_load: Parse an uci config file and store it in the uci context
128  *
129  * @ctx: uci context
130  * @name: name of the config file (relative to the config directory)
131  * @package: store the loaded config package in this variable
132  */
133 extern int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package);
134 
135 /**
136  * uci_unload: Unload a config file from the uci context
137  *
138  * @ctx: uci context
139  * @package: pointer to the uci_package struct
140  */
141 extern int uci_unload(struct uci_context *ctx, struct uci_package *p);
142 
143 /**
144  * uci_lookup_ptr: Split an uci tuple string and look up an element tree
145  * @ctx: uci context
146  * @ptr: lookup result struct
147  * @str: uci tuple string to look up
148  * @extended: allow extended syntax lookup
149  *
150  * if extended is set to true, uci_lookup_ptr supports the following
151  * extended syntax:
152  *
153  * Examples:
154  *   network.@interface[0].ifname ('ifname' option of the first interface section)
155  *   network.@interface[-1]       (last interface section)
156  * Note: uci_lookup_ptr will automatically load a config package if necessary
157  * @str must not be constant, as it will be modified and used for the strings inside @ptr,
158  * thus it must also be available as long as @ptr is in use.
159  *
160  * This function returns UCI_ERR_NOTFOUND if the package specified in the tuple
161  * string cannot be found.  Otherwise it will return UCI_OK.
162  *
163  * Note that failures in looking up other parts, if they are also specfied,
164  * including section and option, will also have a return value UCI_OK but with
165  * ptr->flags * UCI_LOOKUP_COMPLETE not set.
166  */
167 extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended);
168 
169 /**
170  * uci_add_section: Add an unnamed section
171  * @ctx: uci context
172  * @p: package to add the section to
173  * @type: section type
174  * @res: pointer to store a reference to the new section in
175  */
176 extern int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char *type, struct uci_section **res);
177 
178 /**
179  * uci_set: Set an element's value; create the element if necessary
180  * @ctx: uci context
181  * @ptr: uci pointer
182  *
183  * The updated/created element is stored in ptr->last
184  */
185 extern int uci_set(struct uci_context *ctx, struct uci_ptr *ptr);
186 
187 /**
188  * uci_add_list: Append a string to an element list
189  * @ctx: uci context
190  * @ptr: uci pointer (with value)
191  *
192  * Note: if the given option already contains a string value,
193  * it will be converted to an 1-element-list before appending the next element
194  */
195 extern int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr);
196 
197 /**
198  * uci_del_list: Remove a string from an element list
199  * @ctx: uci context
200  * @ptr: uci pointer (with value)
201  *
202  */
203 extern int uci_del_list(struct uci_context *ctx, struct uci_ptr *ptr);
204 
205 /**
206  * uci_reorder: Reposition a section
207  * @ctx: uci context
208  * @s: uci section to reposition
209  * @pos: new position in the section list
210  */
211 extern int uci_reorder_section(struct uci_context *ctx, struct uci_section *s, int pos);
212 
213 /**
214  * uci_rename: Rename an element
215  * @ctx: uci context
216  * @ptr: uci pointer (with value)
217  */
218 extern int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr);
219 
220 /**
221  * uci_delete: Delete a section or option
222  * @ctx: uci context
223  * @ptr: uci pointer
224  */
225 extern int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr);
226 
227 /**
228  * uci_save: save change delta for a package
229  * @ctx: uci context
230  * @p: uci_package struct
231  */
232 extern int uci_save(struct uci_context *ctx, struct uci_package *p);
233 
234 /**
235  * uci_commit: commit changes to a package
236  * @ctx: uci context
237  * @p: uci_package struct pointer
238  * @overwrite: overwrite existing config data and flush delta
239  *
240  * committing may reload the whole uci_package data,
241  * the supplied pointer is updated accordingly
242  */
243 extern int uci_commit(struct uci_context *ctx, struct uci_package **p, bool overwrite);
244 
245 /**
246  * uci_list_configs: List available uci config files
247  * @ctx: uci context
248  *
249  * caller is responsible for freeing the allocated memory behind list
250  */
251 extern int uci_list_configs(struct uci_context *ctx, char ***list);
252 
253 /**
254  * uci_set_savedir: override the default delta save directory
255  * @ctx: uci context
256  * @dir: directory name
257  *
258  * This will also try adding the specified dir to the end of delta pathes.
259  */
260 extern int uci_set_savedir(struct uci_context *ctx, const char *dir);
261 
262 /**
263  * uci_set_savedir: override the default config storage directory
264  * @ctx: uci context
265  * @dir: directory name
266  */
267 extern int uci_set_confdir(struct uci_context *ctx, const char *dir);
268 
269 /**
270  * uci_set_conf2dir: change the override config storage directory
271  * @ctx: uci context
272  * @dir: directory name (can be NULL to disable config override)
273  */
274 extern int uci_set_conf2dir(struct uci_context *ctx, const char *dir);
275 
276 /**
277  * uci_add_delta_path: add a directory to the search path for change delta files
278  * @ctx: uci context
279  * @dir: directory name
280  *
281  * This function allows you to add directories, which contain 'overlays'
282  * for the active config, that will never be committed.
283  *
284  * Adding a duplicate directory will cause UCI_ERR_DUPLICATE be returned.
285  */
286 extern int uci_add_delta_path(struct uci_context *ctx, const char *dir);
287 
288 /**
289  * uci_revert: revert all changes to a config item
290  * @ctx: uci context
291  * @ptr: uci pointer
292  */
293 extern int uci_revert(struct uci_context *ctx, struct uci_ptr *ptr);
294 
295 /**
296  * uci_parse_argument: parse a shell-style argument, with an arbitrary quoting style
297  * @ctx: uci context
298  * @stream: input stream
299  * @str: pointer to the current line (use NULL for parsing the next line)
300  * @result: pointer for the result
301  */
302 extern int uci_parse_argument(struct uci_context *ctx, FILE *stream, char **str, char **result);
303 
304 /**
305  * uci_set_backend: change the default backend
306  * @ctx: uci context
307  * @name: name of the backend
308  *
309  * The default backend is "file", which uses /etc/config for config storage
310  */
311 extern int uci_set_backend(struct uci_context *ctx, const char *name);
312 
313 /**
314  * uci_validate_text: validate a value string for uci options
315  * @str: value
316  *
317  * this function checks whether a given string is acceptable as value
318  * for uci options
319  */
320 extern bool uci_validate_text(const char *str);
321 
322 /**
323  * uci_parse_ptr: parse a uci string into a uci_ptr
324  * @ctx: uci context
325  * @ptr: target data structure
326  * @str: string to parse
327  *
328  * str is modified by this function
329  */
330 int uci_parse_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str);
331 
332 /**
333  * uci_lookup_next: lookup a child element
334  * @ctx: uci context
335  * @e: target element pointer
336  * @list: list of elements
337  * @name: name of the child element
338  *
339  * if parent is NULL, the function looks up the package with the given name
340  */
341 int uci_lookup_next(struct uci_context *ctx, struct uci_element **e, struct uci_list *list, const char *name);
342 
343 /**
344  * uci_parse_section: look up a set of options
345  * @s: uci section
346  * @opts: list of options to look up
347  * @n_opts: number of options to look up
348  * @tb: array of pointers to found options
349  */
350 void uci_parse_section(struct uci_section *s, const struct uci_parse_option *opts,
351                        int n_opts, struct uci_option **tb);
352 
353 /**
354  * uci_hash_options: build a hash over a list of options
355  * @tb: list of option pointers
356  * @n_opts: number of options
357  */
358 uint32_t uci_hash_options(struct uci_option **tb, int n_opts);
359 
360 
361 /* UCI data structures */
362 enum uci_type {
363         UCI_TYPE_UNSPEC = 0,
364         UCI_TYPE_DELTA = 1,
365         UCI_TYPE_PACKAGE = 2,
366         UCI_TYPE_SECTION = 3,
367         UCI_TYPE_OPTION = 4,
368         UCI_TYPE_PATH = 5,
369         UCI_TYPE_BACKEND = 6,
370         UCI_TYPE_ITEM = 7,
371         UCI_TYPE_HOOK = 8,
372 };
373 
374 enum uci_option_type {
375         UCI_TYPE_STRING = 0,
376         UCI_TYPE_LIST = 1,
377 };
378 
379 enum uci_flags {
380         UCI_FLAG_STRICT =        (1 << 0), /* strict mode for the parser */
381         UCI_FLAG_PERROR =        (1 << 1), /* print parser error messages */
382         UCI_FLAG_EXPORT_NAME =   (1 << 2), /* when exporting, name unnamed sections */
383         UCI_FLAG_SAVED_DELTA = (1 << 3), /* store the saved delta in memory as well */
384 };
385 
386 struct uci_element
387 {
388         struct uci_list list;
389         enum uci_type type;
390         char *name;
391 };
392 
393 struct uci_backend
394 {
395         struct uci_element e;
396         char **(*list_configs)(struct uci_context *ctx);
397         struct uci_package *(*load)(struct uci_context *ctx, const char *name);
398         void (*commit)(struct uci_context *ctx, struct uci_package **p, bool overwrite);
399 
400         /* private: */
401         const void *ptr;
402         void *priv;
403 };
404 
405 struct uci_context
406 {
407         /* list of config packages */
408         struct uci_list root;
409 
410         /* parser context, use for error handling only */
411         struct uci_parse_context *pctx;
412 
413         /* backend for import and export */
414         struct uci_backend *backend;
415         struct uci_list backends;
416 
417         /* uci runtime flags */
418         enum uci_flags flags;
419 
420         char *confdir;
421         char *savedir;
422         char *conf2dir;
423 
424         /* search path for delta files */
425         struct uci_list delta_path;
426 
427         /* private: */
428         int err;
429         const char *func;
430         jmp_buf trap;
431         bool internal, nested;
432         char *buf;
433         int bufsz;
434 };
435 
436 struct uci_package
437 {
438         struct uci_element e;
439         struct uci_list sections;
440         struct uci_context *ctx;
441         bool has_delta, uses_conf2;
442         char *path;
443 
444         /* private: */
445         struct uci_backend *backend;
446         void *priv;
447         int n_section;
448         struct uci_list delta;
449         struct uci_list saved_delta;
450 };
451 
452 struct uci_section
453 {
454         struct uci_element e;
455         struct uci_list options;
456         struct uci_package *package;
457         bool anonymous;
458         char *type;
459 };
460 
461 struct uci_option
462 {
463         struct uci_element e;
464         struct uci_section *section;
465         enum uci_option_type type;
466         union {
467                 struct uci_list list;
468                 char *string;
469         } v;
470 };
471 
472 /*
473  * UCI_CMD_ADD is used for anonymous sections or list values
474  */
475 enum uci_command {
476         UCI_CMD_ADD,
477         UCI_CMD_REMOVE,
478         UCI_CMD_CHANGE,
479         UCI_CMD_RENAME,
480         UCI_CMD_REORDER,
481         UCI_CMD_LIST_ADD,
482         UCI_CMD_LIST_DEL,
483         __UCI_CMD_MAX,
484         __UCI_CMD_LAST = __UCI_CMD_MAX - 1
485 };
486 extern char const uci_command_char[];
487 
488 struct uci_delta
489 {
490         struct uci_element e;
491         enum uci_command cmd;
492         char *section;
493         char *value;
494 };
495 
496 struct uci_ptr
497 {
498         enum uci_type target;
499         enum {
500                 UCI_LOOKUP_DONE =     (1 << 0),
501                 UCI_LOOKUP_COMPLETE = (1 << 1),
502                 UCI_LOOKUP_EXTENDED = (1 << 2),
503         } flags;
504 
505         struct uci_package *p;
506         struct uci_section *s;
507         struct uci_option *o;
508         struct uci_element *last;
509 
510         const char *package;
511         const char *section;
512         const char *option;
513         const char *value;
514 };
515 
516 struct uci_parse_option {
517         const char *name;
518         enum uci_option_type type;
519 };
520 
521 
522 /**
523  * container_of - cast a member of a structure out to the containing structure
524  * @ptr:    the pointer to the member.
525  * @type:   the type of the container struct this is embedded in.
526  * @member: the name of the member within the struct.
527  */
528 #ifndef container_of
529 #define container_of(ptr, type, member) \
530         ((type *) ((char *)ptr - offsetof(type,member)))
531 #endif
532 
533 
534 /**
535  * uci_list_entry: casts an uci_list pointer to the containing struct.
536  * @_type: config, section or option
537  * @_ptr: pointer to the uci_list struct
538  */
539 #define list_to_element(ptr) \
540         container_of(ptr, struct uci_element, list)
541 
542 /**
543  * uci_foreach_entry: loop through a list of uci elements
544  * @_list: pointer to the uci_list struct
545  * @_ptr: iteration variable, struct uci_element
546  *
547  * use like a for loop, e.g:
548  *   uci_foreach(&list, p) {
549  *      ...
550  *   }
551  */
552 #define uci_foreach_element(_list, _ptr)                \
553         for(_ptr = list_to_element((_list)->next);      \
554                 &_ptr->list != (_list);                 \
555                 _ptr = list_to_element(_ptr->list.next))
556 
557 /**
558  * uci_foreach_entry_safe: like uci_foreach_safe, but safe for deletion
559  * @_list: pointer to the uci_list struct
560  * @_tmp: temporary variable, struct uci_element *
561  * @_ptr: iteration variable, struct uci_element *
562  *
563  * use like a for loop, e.g:
564  *   uci_foreach(&list, p) {
565  *      ...
566  *   }
567  */
568 #define uci_foreach_element_safe(_list, _tmp, _ptr)             \
569         for(_ptr = list_to_element((_list)->next),              \
570                 _tmp = list_to_element(_ptr->list.next);        \
571                 &_ptr->list != (_list);                 \
572                 _ptr = _tmp, _tmp = list_to_element(_ptr->list.next))
573 
574 /**
575  * uci_list_empty: returns true if a list is empty
576  * @list: list head
577  */
578 #define uci_list_empty(list) ((list)->next == (list))
579 
580 /* wrappers for dynamic type handling */
581 #define uci_type_backend UCI_TYPE_BACKEND
582 #define uci_type_delta UCI_TYPE_DELTA
583 #define uci_type_package UCI_TYPE_PACKAGE
584 #define uci_type_section UCI_TYPE_SECTION
585 #define uci_type_option UCI_TYPE_OPTION
586 
587 /* element typecasting */
588 #ifdef UCI_DEBUG_TYPECAST
589 static const char *uci_typestr[] = {
590         [uci_type_backend] = "backend",
591         [uci_type_delta] = "delta",
592         [uci_type_package] = "package",
593         [uci_type_section] = "section",
594         [uci_type_option] = "option",
595 };
596 
597 static void uci_typecast_error(int from, int to)
598 {
599         fprintf(stderr, "Invalid typecast from '%s' to '%s'\n", uci_typestr[from], uci_typestr[to]);
600 }
601 
602 #define BUILD_CAST(_type) \
603         static inline struct uci_ ## _type *uci_to_ ## _type (struct uci_element *e) \
604         { \
605                 if (e->type != uci_type_ ## _type) { \
606                         uci_typecast_error(e->type, uci_type_ ## _type); \
607                 } \
608                 return (struct uci_ ## _type *) e; \
609         }
610 
611 BUILD_CAST(backend)
612 BUILD_CAST(delta)
613 BUILD_CAST(package)
614 BUILD_CAST(section)
615 BUILD_CAST(option)
616 
617 #else
618 #define uci_to_backend(ptr) container_of(ptr, struct uci_backend, e)
619 #define uci_to_delta(ptr) container_of(ptr, struct uci_delta, e)
620 #define uci_to_package(ptr) container_of(ptr, struct uci_package, e)
621 #define uci_to_section(ptr) container_of(ptr, struct uci_section, e)
622 #define uci_to_option(ptr)  container_of(ptr, struct uci_option, e)
623 #endif
624 
625 #define uci_dataptr(ptr) \
626         (((char *) ptr) + sizeof(*ptr))
627 
628 /**
629  * uci_lookup_package: look up a package
630  * @ctx: uci context
631  * @name: name of the package
632  */
633 static inline struct uci_package *
634 uci_lookup_package(struct uci_context *ctx, const char *name)
635 {
636         struct uci_element *e = NULL;
637         if (uci_lookup_next(ctx, &e, &ctx->root, name) == 0)
638                 return uci_to_package(e);
639         else
640                 return NULL;
641 }
642 
643 /**
644  * uci_lookup_section: look up a section
645  * @ctx: uci context
646  * @p: package that the section belongs to
647  * @name: name of the section
648  */
649 static inline struct uci_section *
650 uci_lookup_section(struct uci_context *ctx, struct uci_package *p, const char *name)
651 {
652         struct uci_element *e = NULL;
653         if (uci_lookup_next(ctx, &e, &p->sections, name) == 0)
654                 return uci_to_section(e);
655         else
656                 return NULL;
657 }
658 
659 /**
660  * uci_lookup_option: look up an option
661  * @ctx: uci context
662  * @section: section that the option belongs to
663  * @name: name of the option
664  */
665 static inline struct uci_option *
666 uci_lookup_option(struct uci_context *ctx, struct uci_section *s, const char *name)
667 {
668         struct uci_element *e = NULL;
669         if (uci_lookup_next(ctx, &e, &s->options, name) == 0)
670                 return uci_to_option(e);
671         else
672                 return NULL;
673 }
674 
675 static inline const char *
676 uci_lookup_option_string(struct uci_context *ctx, struct uci_section *s, const char *name)
677 {
678         struct uci_option *o;
679 
680         o = uci_lookup_option(ctx, s, name);
681         if (!o || o->type != UCI_TYPE_STRING)
682                 return NULL;
683 
684         return o->v.string;
685 }
686 
687 #ifndef BITS_PER_LONG
688 #define BITS_PER_LONG (8 * sizeof(unsigned long))
689 #endif
690 
691 static inline void uci_bitfield_set(unsigned long *bits, int bit)
692 {
693         bits[bit / BITS_PER_LONG] |= (1UL << (bit % BITS_PER_LONG));
694 }
695 
696 #ifdef __cplusplus
697 }
698 #endif
699 
700 #endif
701 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt