uci_file_cleanup(ctx);
}
+static void uci_load_history_file(struct uci_context *ctx, struct uci_package *p, char *filename, FILE **f, bool flush)
+{
+ FILE *stream = NULL;
+
+ UCI_TRAP_SAVE(ctx, done);
+ stream = uci_open_stream(ctx, filename, SEEK_SET, flush, false);
+ if (p)
+ uci_parse_history(ctx, stream, p);
+ UCI_TRAP_RESTORE(ctx);
+done:
+ if (f)
+ *f = stream;
+ else if (stream)
+ uci_close_stream(stream);
+}
+
static void uci_load_history(struct uci_context *ctx, struct uci_package *p, bool flush)
{
+ struct uci_element *e;
char *filename = NULL;
FILE *f = NULL;
if (!p->confdir)
return;
+ uci_foreach_element(&ctx->history_path, e) {
+ if ((asprintf(&filename, "%s/%s", e->name, p->e.name) < 0) || !filename)
+ UCI_THROW(ctx, UCI_ERR_MEM);
+
+ uci_load_history_file(ctx, p, filename, NULL, false);
+ free(filename);
+ }
+
if ((asprintf(&filename, "%s/%s", ctx->savedir, p->e.name) < 0) || !filename)
UCI_THROW(ctx, UCI_ERR_MEM);
- UCI_TRAP_SAVE(ctx, done);
- f = uci_open_stream(ctx, filename, SEEK_SET, flush, false);
- if (p)
- uci_parse_history(ctx, f, p);
- UCI_TRAP_RESTORE(ctx);
-
-done:
+ uci_load_history_file(ctx, p, filename, &f, flush);
if (flush && f) {
rewind(f);
ftruncate(fileno(f), 0);
ctx = (struct uci_context *) malloc(sizeof(struct uci_context));
memset(ctx, 0, sizeof(struct uci_context));
uci_list_init(&ctx->root);
+ uci_list_init(&ctx->history_path);
ctx->flags = UCI_FLAG_STRICT;
ctx->confdir = (char *) uci_confdir;
struct uci_package *p = uci_to_package(e);
uci_free_package(&p);
}
+ uci_foreach_element_safe(&ctx->history_path, tmp, e) {
+ uci_free_element(e);
+ }
free(ctx);
UCI_TRAP_RESTORE(ctx);
return;
}
-int uci_set_confdir(struct uci_context *ctx, char *dir)
+int uci_add_history_path(struct uci_context *ctx, const char *dir)
+{
+ struct uci_element *e;
+
+ UCI_HANDLE_ERR(ctx);
+ UCI_ASSERT(ctx, dir != NULL);
+ e = uci_alloc_generic(ctx, UCI_TYPE_PATH, dir, sizeof(struct uci_element));
+ uci_list_add(&ctx->history_path, &e->list);
+
+ return 0;
+}
+
+int uci_set_confdir(struct uci_context *ctx, const char *dir)
{
- dir = uci_strdup(ctx, dir);
+ char *cdir;
+
+ UCI_HANDLE_ERR(ctx);
+ UCI_ASSERT(ctx, dir != NULL);
+
+ cdir = uci_strdup(ctx, dir);
if (ctx->confdir != uci_confdir)
free(ctx->confdir);
- ctx->confdir = dir;
+ ctx->confdir = cdir;
return 0;
}
-int uci_set_savedir(struct uci_context *ctx, char *dir)
+int uci_set_savedir(struct uci_context *ctx, const char *dir)
{
- dir = uci_strdup(ctx, dir);
+ char *sdir;
+
+ UCI_HANDLE_ERR(ctx);
+ UCI_ASSERT(ctx, dir != NULL);
+
+ sdir = uci_strdup(ctx, dir);
if (ctx->savedir != uci_savedir)
free(ctx->savedir);
- ctx->savedir = dir;
+ ctx->savedir = sdir;
return 0;
}
* @ctx: uci context
* @dir: directory name
*/
-extern int uci_set_savedir(struct uci_context *ctx, char *dir);
+extern int uci_set_savedir(struct uci_context *ctx, const char *dir);
/**
* uci_set_savedir: override the default config storage directory
* @ctx: uci context
* @dir: directory name
*/
-extern int uci_set_confdir(struct uci_context *ctx, char *dir);
+extern int uci_set_confdir(struct uci_context *ctx, const char *dir);
+/**
+ * uci_add_history_path: add a directory to the search path for change history files
+ * @ctx: uci context
+ * @dir: directory name
+ */
+extern int uci_add_history_path(struct uci_context *ctx, const char *dir);
/* UCI data structures */
enum uci_type {
UCI_TYPE_HISTORY = 0,
UCI_TYPE_PACKAGE = 1,
UCI_TYPE_SECTION = 2,
- UCI_TYPE_OPTION = 3
+ UCI_TYPE_OPTION = 3,
+ UCI_TYPE_PATH = 4
};
enum uci_flags {
char *confdir;
char *savedir;
+ /* search path for history files */
+ struct uci_list history_path;
+
/* private: */
int errno;
const char *func;