#include <stdio.h>
#include <ctype.h>
-/*
- * Clean up all extra memory used by the parser and exporter
- */
-static void uci_file_cleanup(struct uci_context *ctx)
-{
-}
-
+static struct uci_backend uci_file_backend;
/*
* verify that the end of the line or command is reached.
/* add the last config to main config file list */
if (pctx->package) {
+ pctx->package->backend = ctx->backend;
uci_list_add(&ctx->root, &pctx->package->e.list);
pctx->package = NULL;
UCI_HANDLE_ERR(ctx);
/* make sure no memory from previous parse attempts is leaked */
- uci_file_cleanup(ctx);
+ ctx->internal = true;
+ uci_cleanup(ctx);
uci_alloc_parse_context(ctx);
pctx = ctx->pctx;
uci_switch_config(ctx);
/* no error happened, we can get rid of the parser context now */
- uci_file_cleanup(ctx);
+ uci_cleanup(ctx);
return 0;
}
return filename;
}
-int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package)
-{
- char *filename;
- bool confdir;
- FILE *file = NULL;
-
- UCI_HANDLE_ERR(ctx);
-
- switch (name[0]) {
- case '.':
- /* relative path outside of /etc/config */
- if (name[1] != '/')
- UCI_THROW(ctx, UCI_ERR_NOTFOUND);
- /* fall through */
- case '/':
- /* absolute path outside of /etc/config */
- filename = uci_strdup(ctx, name);
- name = strrchr(name, '/') + 1;
- confdir = false;
- break;
- default:
- /* config in /etc/config */
- filename = uci_config_path(ctx, name);
- confdir = true;
- break;
- }
-
- file = uci_open_stream(ctx, filename, SEEK_SET, false, false);
- ctx->errno = 0;
- UCI_TRAP_SAVE(ctx, done);
- UCI_INTERNAL(uci_import, ctx, file, name, package, true);
- UCI_TRAP_RESTORE(ctx);
-
- if (*package) {
- (*package)->path = filename;
- (*package)->confdir = confdir;
- uci_load_history(ctx, *package, false);
- }
-
-done:
- uci_close_stream(file);
- return ctx->errno;
-}
-
-int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite)
+void uci_file_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite)
{
- struct uci_package *p;
+ struct uci_package *p = *package;
FILE *f = NULL;
char *name = NULL;
char *path = NULL;
- UCI_HANDLE_ERR(ctx);
- UCI_ASSERT(ctx, package != NULL);
- p = *package;
-
- UCI_ASSERT(ctx, p != NULL);
if (!p->path) {
if (overwrite)
p->path = uci_config_path(ctx, p->e.name);
UCI_THROW(ctx, UCI_ERR_INVAL);
}
-
/* open the config file for writing now, so that it is locked */
f = uci_open_stream(ctx, p->path, SEEK_SET, true, true);
* as well. dump and reload
*/
uci_free_package(&p);
- uci_file_cleanup(ctx);
+ uci_cleanup(ctx);
UCI_INTERNAL(uci_import, ctx, f, name, &p, true);
p->path = path;
uci_close_stream(f);
if (ctx->errno)
UCI_THROW(ctx, ctx->errno);
-
- return 0;
}
return 0;
}
+static struct uci_package *uci_file_load(struct uci_context *ctx, const char *name)
+{
+ struct uci_package *package = NULL;
+ char *filename;
+ bool confdir;
+ FILE *file = NULL;
+
+ switch (name[0]) {
+ case '.':
+ /* relative path outside of /etc/config */
+ if (name[1] != '/')
+ UCI_THROW(ctx, UCI_ERR_NOTFOUND);
+ /* fall through */
+ case '/':
+ /* absolute path outside of /etc/config */
+ filename = uci_strdup(ctx, name);
+ name = strrchr(name, '/') + 1;
+ confdir = false;
+ break;
+ default:
+ /* config in /etc/config */
+ filename = uci_config_path(ctx, name);
+ confdir = true;
+ break;
+ }
+
+ file = uci_open_stream(ctx, filename, SEEK_SET, false, false);
+ ctx->errno = 0;
+ UCI_TRAP_SAVE(ctx, done);
+ UCI_INTERNAL(uci_import, ctx, file, name, &package, true);
+ UCI_TRAP_RESTORE(ctx);
+
+ if (package) {
+ package->path = filename;
+ package->confdir = confdir;
+ uci_load_history(ctx, package, false);
+ }
+
+done:
+ uci_close_stream(file);
+ if (ctx->errno)
+ UCI_THROW(ctx, ctx->errno);
+ return package;
+}
+
+static struct uci_backend uci_file_backend = {
+ .name = "file",
+ .load = uci_file_load,
+ .commit = uci_file_commit,
+};
[UCI_ERR_UNKNOWN] = "Unknown error",
};
+static void uci_cleanup(struct uci_context *ctx);
+
#include "uci_internal.h"
#include "util.c"
#include "list.c"
ctx->confdir = (char *) uci_confdir;
ctx->savedir = (char *) uci_savedir;
+ ctx->backend = &uci_file_backend;
return ctx;
}
if (ctx->savedir != uci_savedir)
free(ctx->savedir);
- UCI_TRAP_SAVE(ctx, ignore);
- ctx->internal = true;
uci_cleanup(ctx);
+ UCI_TRAP_SAVE(ctx, ignore);
uci_foreach_element_safe(&ctx->root, tmp, e) {
struct uci_package *p = uci_to_package(e);
uci_free_package(&p);
return 0;
}
-int uci_cleanup(struct uci_context *ctx)
+static void uci_cleanup(struct uci_context *ctx)
{
struct uci_parse_context *pctx;
- UCI_HANDLE_ERR(ctx);
if (ctx->buf) {
free(ctx->buf);
pctx = ctx->pctx;
if (!pctx)
- goto done;
+ return;
ctx->pctx = NULL;
if (pctx->package)
free(pctx->buf);
free(pctx);
-done:
- return 0;
}
void uci_perror(struct uci_context *ctx, const char *prefix)
}
}
+int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite)
+{
+ UCI_HANDLE_ERR(ctx);
+ UCI_ASSERT(ctx, package != NULL);
+ UCI_ASSERT(ctx, *package != NULL);
+ UCI_ASSERT(ctx, ctx->backend && ctx->backend->commit);
+ ctx->backend->commit(ctx, package, overwrite);
+ return 0;
+}
+
+int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package)
+{
+ struct uci_package *p;
+ UCI_HANDLE_ERR(ctx);
+ UCI_ASSERT(ctx, ctx->backend && ctx->backend->load);
+ p = ctx->backend->load(ctx, name);
+ if (package)
+ *package = p;
+
+ return 0;
+}
+
struct uci_option;
struct uci_history;
struct uci_context;
+struct uci_backend;
struct uci_parse_context;
*/
extern int uci_unload(struct uci_context *ctx, struct uci_package *p);
-/**
- * uci_cleanup: Clean up after an error
- *
- * @ctx: uci context
- */
-extern int uci_cleanup(struct uci_context *ctx);
-
/**
* uci_lookup: Look up an uci element
*
char *name;
};
+struct uci_backend
+{
+ const char *name;
+ struct uci_package *(*load)(struct uci_context *ctx, const char *name);
+ void (*commit)(struct uci_context *ctx, struct uci_package **p, bool overwrite);
+};
+
+
struct uci_context
{
/* list of config packages */
/* parser context, use for error handling only */
struct uci_parse_context *pctx;
+ /* backend for import and export */
+ struct uci_backend *backend;
+
/* uci runtime flags */
enum uci_flags flags;
char *path;
/* private: */
+ struct uci_backend *backend;
int n_section;
struct uci_list history;
struct uci_list saved_history;