ucimap: free memory allocated for fixups
[project/uci.git] / uci.h
diff --git a/uci.h b/uci.h
index fe05bb3..74bbdff 100644 (file)
--- a/uci.h
+++ b/uci.h
@@ -56,6 +56,8 @@ struct uci_list
 };
 
 struct uci_ptr;
+struct uci_plugin;
+struct uci_hook_ops;
 struct uci_element;
 struct uci_package;
 struct uci_section;
@@ -84,6 +86,16 @@ extern void uci_free_context(struct uci_context *ctx);
 extern void uci_perror(struct uci_context *ctx, const char *str);
 
 /**
+ * uci_geterror: Get an error string for the last uci error
+ * @ctx: uci context
+ * @dest: target pointer for the string
+ * @str: prefix for the error message
+ *
+ * Note: string must be freed by the caller
+ */
+extern void uci_get_errorstr(struct uci_context *ctx, char **dest, const char *str);
+
+/**
  * uci_import: Import uci config data from a stream
  * @ctx: uci context
  * @stream: file stream to import from
@@ -123,44 +135,21 @@ extern int uci_load(struct uci_context *ctx, const char *name, struct uci_packag
 extern int uci_unload(struct uci_context *ctx, struct uci_package *p);
 
 /**
- * uci_lookup: Look up an uci element
- *
- * @ctx: uci context
- * @res: where to store the result
- * @package: uci_package struct 
- * @section: config section (optional)
- * @option: option to search for (optional)
- *
- * If section is omitted, then a pointer to the config package is returned
- * If option is omitted, then a pointer to the config section is returned
- */
-extern int uci_lookup(struct uci_context *ctx, struct uci_element **res, struct uci_package *package, const char *section, const char *option);
-
-/**
- * uci_lookup_ptr: Split an uci tuple string and look up elements
+ * uci_lookup_ptr: Split an uci tuple string and look up an element tree
  * @ctx: uci context
  * @ptr: lookup result struct
  * @str: uci tuple string to look up
  * @extended: allow extended syntax lookup
- */
-extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended);
-
-/**
- * uci_lookup_ext: Extended lookup for an uci element
- *
- * @ctx: uci context
- * @res: where to store the result
- * @ptr: uci pointer tuple
  *
- * Looks up an element using the extended syntax.
- * It can look up sections by an index with an optional type.
+ * if extended is set to true, uci_lookup_ptr supports the following 
+ * extended syntax:
  *
  * Examples:
  *   network.@interface[0].ifname ('ifname' option of the first interface section)
  *   network.@interface[-1]       (last interface section)
  * Note: uci_lookup_ext will automatically load a config package if necessary
  */
-extern int uci_lookup_ext(struct uci_context *ctx, struct uci_element **res, char *ptr);
+extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended);
 
 /**
  * uci_add_section: Add an unnamed section
@@ -172,74 +161,45 @@ extern int uci_lookup_ext(struct uci_context *ctx, struct uci_element **res, cha
 extern int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char *type, struct uci_section **res);
 
 /**
- * uci_set_element_value: Replace an element's value with a new one
- * @ctx: uci context
- * @element: pointer to an uci_element struct pointer
- * @value: new value
- * 
- * Only valid for uci_option and uci_section. Will replace the type string
- * when used with an uci_section
- */
-extern int uci_set_element_value(struct uci_context *ctx, struct uci_element **element, const char *value);
-
-/**
- * uci_add_element_list: Append a string to a list option
- * @ctx: uci context
- * @option: pointer to the uci option element
- * @value: string to append
- */
-extern int uci_add_element_list(struct uci_context *ctx, struct uci_option *o, const char *value);
-
-/**
  * uci_set: Set an element's value; create the element if necessary
  * @ctx: uci context
- * @package: package name
- * @section: section name
- * @option: option name
- * @value: value (option) or type (section)
- * @result: store the updated element in this variable (optional)
+ * @ptr: uci pointer 
+ *
+ * The updated/created element is stored in ptr->last
  */
-extern int uci_set(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option, const char *value, struct uci_element **result);
+extern int uci_set(struct uci_context *ctx, struct uci_ptr *ptr);
 
 /**
  * uci_add_list: Append a string to an element list
  * @ctx: uci context
- * @package: package name
- * @section: section name
- * @option: option name
- * @value: string value
- * @result: store the updated element in this variable (optional)
+ * @ptr: uci pointer (with value)
  *
- * Note: if the given option already contains a string, convert it to an 1-element-list
- * before appending the next element
+ * Note: if the given option already contains a string value,
+ * it will be converted to an 1-element-list before appending the next element
  */
-extern int uci_add_list(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option, const char *value, struct uci_option **result);
+extern int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr);
 
 /**
- * uci_rename: Rename an element
+ * uci_reorder: Reposition a section
  * @ctx: uci context
- * @package: package name
- * @section: section name
- * @option: option name
- * @name: new name
+ * @s: uci section to reposition
+ * @pos: new position in the section list
  */
-extern int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name);
+extern int uci_reorder_section(struct uci_context *ctx, struct uci_section *s, int pos);
 
 /**
- * uci_delete_element: Delete a section or option
+ * uci_rename: Rename an element
  * @ctx: uci context
- * @e: element (section or option)
+ * @ptr: uci pointer (with value)
  */
-extern int uci_delete_element(struct uci_context *ctx, struct uci_element *e);
+extern int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr);
 
 /**
  * uci_delete: Delete a section or option
  * @ctx: uci context
- * @p: uci package
- * @section: section name
- * @option: option name (optional)
+ * @ptr: uci pointer 
  */
-extern int uci_delete(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option);
+extern int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr);
 
 /**
  * uci_save: save change history for a package
@@ -294,11 +254,9 @@ extern int uci_add_history_path(struct uci_context *ctx, const char *dir);
 /**
  * uci_revert: revert all changes to a config item
  * @ctx: uci context
- * @p: pointer to a uci_package struct ptr (will be replaced by the revert)
- * @section: section name (optional)
- * @option option name (optional)
+ * @ptr: uci pointer
  */
-extern int uci_revert(struct uci_context *ctx, struct uci_package **p, const char *section, const char *option);
+extern int uci_revert(struct uci_context *ctx, struct uci_ptr *ptr);
 
 /**
  * uci_parse_argument: parse a shell-style argument, with an arbitrary quoting style
@@ -327,6 +285,43 @@ extern int uci_set_backend(struct uci_context *ctx, const char *name);
  */
 extern bool uci_validate_text(const char *str);
 
+
+/**
+ * uci_add_hook: add a uci hook
+ * @ctx: uci context
+ * @ops: uci hook ops
+ *
+ * NB: allocated and freed by the caller
+ */
+extern int uci_add_hook(struct uci_context *ctx, const struct uci_hook_ops *ops);
+
+/**
+ * uci_remove_hook: remove a uci hook
+ * @ctx: uci context
+ * @ops: uci hook ops
+ */
+extern int uci_remove_hook(struct uci_context *ctx, const struct uci_hook_ops *ops);
+
+/**
+ * uci_load_plugin: load an uci plugin
+ * @ctx: uci context
+ * @filename: path to the uci plugin
+ *
+ * NB: plugin will be unloaded automatically when the context is freed
+ */
+int uci_load_plugin(struct uci_context *ctx, const char *filename);
+
+/**
+ * uci_load_plugins: load all uci plugins from a directory
+ * @ctx: uci context
+ * @pattern: pattern of uci plugin files (optional)
+ *
+ * if pattern is NULL, then uci_load_plugins will call uci_load_plugin
+ * for uci_*.so in <prefix>/lib/
+ */
+int uci_load_plugins(struct uci_context *ctx, const char *pattern);
+
+
 /* UCI data structures */
 enum uci_type {
        UCI_TYPE_UNSPEC = 0,
@@ -337,6 +332,8 @@ enum uci_type {
        UCI_TYPE_PATH = 5,
        UCI_TYPE_BACKEND = 6,
        UCI_TYPE_ITEM = 7,
+       UCI_TYPE_HOOK = 8,
+       UCI_TYPE_PLUGIN = 9,
 };
 
 enum uci_option_type {
@@ -395,9 +392,12 @@ struct uci_context
        int err;
        const char *func;
        jmp_buf trap;
-       bool internal;
+       bool internal, nested;
        char *buf;
        int bufsz;
+
+       struct uci_list hooks;
+       struct uci_list plugins;
 };
 
 struct uci_package
@@ -441,6 +441,7 @@ enum uci_command {
        UCI_CMD_REMOVE,
        UCI_CMD_CHANGE,
        UCI_CMD_RENAME,
+       UCI_CMD_REORDER,
        UCI_CMD_LIST_ADD,
 };
 
@@ -464,11 +465,37 @@ struct uci_ptr
        struct uci_package *p;
        struct uci_section *s;
        struct uci_option *o;
+       struct uci_element *last;
 
-       char *package;
-       char *section;
-       char *option;
-       char *value;
+       const char *package;
+       const char *section;
+       const char *option;
+       const char *value;
+};
+
+struct uci_hook_ops
+{
+       void (*load)(const struct uci_hook_ops *ops, struct uci_package *p);
+       void (*set)(const struct uci_hook_ops *ops, struct uci_package *p, struct uci_history *e);
+};
+
+struct uci_hook
+{
+       struct uci_element e;
+       const struct uci_hook_ops *ops;
+};
+
+struct uci_plugin_ops
+{
+       int (*attach)(struct uci_context *ctx);
+       void (*detach)(struct uci_context *ctx);
+};
+
+struct uci_plugin
+{
+       struct uci_element e;
+       const struct uci_plugin_ops *ops;
+       void *dlh;
 };
 
 
@@ -483,8 +510,10 @@ struct uci_ptr
  * @type:   the type of the container struct this is embedded in.
  * @member: the name of the member within the struct.
  */
+#ifndef container_of
 #define container_of(ptr, type, member) \
        ((type *) ((char *)ptr - offsetof(type,member)))
+#endif
 
 
 /**
@@ -539,6 +568,8 @@ struct uci_ptr
 #define uci_type_package UCI_TYPE_PACKAGE
 #define uci_type_section UCI_TYPE_SECTION
 #define uci_type_option UCI_TYPE_OPTION
+#define uci_type_hook UCI_TYPE_HOOK
+#define uci_type_plugin UCI_TYPE_PLUGIN
 
 /* element typecasting */
 #ifdef UCI_DEBUG_TYPECAST
@@ -548,6 +579,8 @@ static const char *uci_typestr[] = {
        [uci_type_package] = "package",
        [uci_type_section] = "section",
        [uci_type_option] = "option",
+       [uci_type_hook] = "hook",
+       [uci_type_plugin] = "plugin",
 };
 
 static void uci_typecast_error(int from, int to)
@@ -569,6 +602,8 @@ BUILD_CAST(history)
 BUILD_CAST(package)
 BUILD_CAST(section)
 BUILD_CAST(option)
+BUILD_CAST(hook)
+BUILD_CAST(plugin)
 
 #else
 #define uci_to_backend(ptr) container_of(ptr, struct uci_backend, e)
@@ -576,6 +611,8 @@ BUILD_CAST(option)
 #define uci_to_package(ptr) container_of(ptr, struct uci_package, e)
 #define uci_to_section(ptr) container_of(ptr, struct uci_section, e)
 #define uci_to_option(ptr)  container_of(ptr, struct uci_option, e)
+#define uci_to_hook(ptr)    container_of(ptr, struct uci_hook, e)
+#define uci_to_plugin(ptr)  container_of(ptr, struct uci_plugin, e)
 #endif
 
 /**