summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--uci.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/uci.c b/uci.c
index 2d7d430..35332d8 100644
--- a/uci.c
+++ b/uci.c
@@ -1292,17 +1292,53 @@ rpc_uci_copy_file(const char *src, const char *target, const char *file)
fclose(out);
}
+static int
+rpc_uci_apply_access(const char *sid, glob_t *gl)
+{
+ struct stat s;
+ int i, c = 0;
+
+ if (gl->gl_pathc < 3)
+ return UBUS_STATUS_NO_DATA;
+
+ for (i = 0; i < gl->gl_pathc; i++) {
+ char *config = basename(gl->gl_pathv[i]);
+
+ if (*config == '.')
+ continue;
+ if (stat(gl->gl_pathv[i], &s) || !s.st_size)
+ continue;
+ if (!rpc_session_access(sid, "uci", config, "write"))
+ return UBUS_STATUS_PERMISSION_DENIED;
+ c++;
+ }
+
+ if (!c)
+ return UBUS_STATUS_NO_DATA;
+
+ return 0;
+}
+
static void
-rpc_uci_do_rollback(struct ubus_context *ctx, const char *sid, glob_t *gl)
+rpc_uci_do_rollback(struct ubus_context *ctx, glob_t *gl)
{
- int i;
+ int i, deny;
char tmp[PATH_MAX];
- if (sid) {
- snprintf(tmp, sizeof(tmp), RPC_UCI_SAVEDIR_PREFIX "%s/", sid);
+ /* Test apply permission to see if the initiator session still exists.
+ * If it does, restore the delta files as well, else just restore the
+ * main configuration files. */
+ deny = apply_sid[0]
+ ? rpc_uci_apply_access(apply_sid, gl) : UBUS_STATUS_NOT_FOUND;
+
+ if (!deny) {
+ snprintf(tmp, sizeof(tmp), RPC_UCI_SAVEDIR_PREFIX "%s/", apply_sid);
mkdir(tmp, 0700);
}
+ /* avoid merging unrelated uci changes when restoring old configs */
+ rpc_uci_replace_savedir("/dev/null");
+
for (i = 0; i < gl->gl_pathc; i++) {
char *config = basename(gl->gl_pathv[i]);
@@ -1311,8 +1347,11 @@ rpc_uci_do_rollback(struct ubus_context *ctx, const char *sid, glob_t *gl)
rpc_uci_copy_file(RPC_SNAPSHOT_FILES, RPC_UCI_DIR, config);
rpc_uci_apply_config(ctx, config);
- if (sid)
- rpc_uci_copy_file(RPC_SNAPSHOT_DELTA, tmp, config);
+
+ if (deny)
+ continue;
+
+ rpc_uci_copy_file(RPC_SNAPSHOT_DELTA, tmp, config);
}
rpc_uci_purge_dir(RPC_SNAPSHOT_FILES);
@@ -1333,34 +1372,7 @@ rpc_uci_apply_timeout(struct uloop_timeout *t)
if (glob(tmp, GLOB_PERIOD, NULL, &gl) < 0)
return;
- rpc_uci_do_rollback(apply_ctx, NULL, &gl);
-}
-
-static int
-rpc_uci_apply_access(const char *sid, glob_t *gl)
-{
- struct stat s;
- int i, c = 0;
-
- if (gl->gl_pathc < 3)
- return UBUS_STATUS_NO_DATA;
-
- for (i = 0; i < gl->gl_pathc; i++) {
- char *config = basename(gl->gl_pathv[i]);
-
- if (*config == '.')
- continue;
- if (stat(gl->gl_pathv[i], &s) || !s.st_size)
- continue;
- if (!rpc_session_access(sid, "uci", config, "write"))
- return UBUS_STATUS_PERMISSION_DENIED;
- c++;
- }
-
- if (!c)
- return UBUS_STATUS_NO_DATA;
-
- return 0;
+ rpc_uci_do_rollback(apply_ctx, &gl);
}
static int
@@ -1397,6 +1409,8 @@ rpc_uci_apply(struct ubus_context *ctx, struct ubus_object *obj,
rpc_uci_purge_dir(RPC_SNAPSHOT_DELTA);
if (!apply_sid[0]) {
+ rpc_uci_set_savedir(tb[RPC_T_SESSION]);
+
mkdir(RPC_SNAPSHOT_FILES, 0700);
mkdir(RPC_SNAPSHOT_DELTA, 0700);
@@ -1503,7 +1517,7 @@ rpc_uci_rollback(struct ubus_context *ctx, struct ubus_object *obj,
if (glob(tmp, GLOB_PERIOD, NULL, &gl) < 0)
return UBUS_STATUS_NOT_FOUND;
- rpc_uci_do_rollback(ctx, sid, &gl);
+ rpc_uci_do_rollback(ctx, &gl);
globfree(&gl);