From: Felix Fietkau Date: Tue, 12 Feb 2008 10:31:41 +0000 (+0100) Subject: some backend abstraction X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=85125c59e696827c43065676c4fbf1a98953ecac;p=uci.git some backend abstraction --- diff --git a/cli.c b/cli.c index be479c4..287ef96 100644 --- a/cli.c +++ b/cli.c @@ -403,7 +403,6 @@ static int uci_batch(void) fprintf(stderr, "Unknown command\n"); /* clean up */ - uci_cleanup(ctx); uci_foreach_element_safe(&ctx->root, tmp, e) { uci_unload(ctx, uci_to_package(e)); } diff --git a/file.c b/file.c index 7049b33..62ab1a8 100644 --- a/file.c +++ b/file.c @@ -25,13 +25,7 @@ #include #include -/* - * 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. @@ -61,6 +55,7 @@ static void uci_switch_config(struct uci_context *ctx) /* 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; @@ -298,7 +293,8 @@ int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct u 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; @@ -343,7 +339,7 @@ error: 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; } @@ -360,62 +356,13 @@ static char *uci_config_path(struct uci_context *ctx, const char *name) 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); @@ -423,7 +370,6 @@ int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overw 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); @@ -442,7 +388,7 @@ int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overw * 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; @@ -476,8 +422,6 @@ done: uci_close_stream(f); if (ctx->errno) UCI_THROW(ctx, ctx->errno); - - return 0; } @@ -543,3 +487,53 @@ int uci_list_configs(struct uci_context *ctx, char ***list) 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, +}; diff --git a/history.c b/history.c index 75e3f40..089bcef 100644 --- a/history.c +++ b/history.c @@ -162,7 +162,6 @@ static int uci_parse_history(struct uci_context *ctx, FILE *stream, struct uci_p int changes = 0; /* make sure no memory from previous parse attempts is leaked */ - ctx->internal = true; uci_cleanup(ctx); pctx = (struct uci_parse_context *) uci_malloc(ctx, sizeof(struct uci_parse_context)); @@ -187,7 +186,6 @@ error: } /* no error happened, we can get rid of the parser context now */ - ctx->internal = true; uci_cleanup(ctx); return changes; } @@ -311,7 +309,6 @@ done: uci_foreach_element_safe(&list, tmp, e) { uci_free_element(e); } - ctx->internal = true; uci_cleanup(ctx); } diff --git a/libuci.c b/libuci.c index 118289b..4985a33 100644 --- a/libuci.c +++ b/libuci.c @@ -39,6 +39,8 @@ static const char *uci_errstr[] = { [UCI_ERR_UNKNOWN] = "Unknown error", }; +static void uci_cleanup(struct uci_context *ctx); + #include "uci_internal.h" #include "util.c" #include "list.c" @@ -58,6 +60,7 @@ struct uci_context *uci_alloc_context(void) ctx->confdir = (char *) uci_confdir; ctx->savedir = (char *) uci_savedir; + ctx->backend = &uci_file_backend; return ctx; } @@ -71,9 +74,8 @@ void uci_free_context(struct uci_context *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); @@ -102,10 +104,9 @@ int uci_set_confdir(struct uci_context *ctx, const char *dir) 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); @@ -115,7 +116,7 @@ int uci_cleanup(struct uci_context *ctx) pctx = ctx->pctx; if (!pctx) - goto done; + return; ctx->pctx = NULL; if (pctx->package) @@ -125,8 +126,6 @@ int uci_cleanup(struct uci_context *ctx) free(pctx->buf); free(pctx); -done: - return 0; } void uci_perror(struct uci_context *ctx, const char *prefix) @@ -159,4 +158,26 @@ 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; +} + diff --git a/uci.h b/uci.h index 8f4fa71..2fbcb80 100644 --- a/uci.h +++ b/uci.h @@ -63,6 +63,7 @@ struct uci_section; struct uci_option; struct uci_history; struct uci_context; +struct uci_backend; struct uci_parse_context; @@ -135,13 +136,6 @@ 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_cleanup: Clean up after an error - * - * @ctx: uci context - */ -extern int uci_cleanup(struct uci_context *ctx); - /** * uci_lookup: Look up an uci element * @@ -302,6 +296,14 @@ struct 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 */ @@ -310,6 +312,9 @@ struct uci_context /* 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; @@ -337,6 +342,7 @@ struct uci_package char *path; /* private: */ + struct uci_backend *backend; int n_section; struct uci_list history; struct uci_list saved_history;