X-Git-Url: http://git.archive.openwrt.org/?p=project%2Frpcd.git;a=blobdiff_plain;f=uci.c;h=a445d0828c826d4c67383fc31320bb096b85d4c3;hp=0409a07d72927d41f9a066cb6b8441a2943acb07;hb=f1882ac5bde4ef6c75e22a3c89c367d51ac891c8;hpb=c2a7fcf947f250dd2edf881af518fbd7b8a9d677 diff --git a/uci.c b/uci.c index 0409a07..a445d08 100644 --- a/uci.c +++ b/uci.c @@ -1,5 +1,5 @@ /* - * luci-rpcd - LuCI UBUS RPC server + * rpcd - UBUS RPC server * * Copyright (C) 2013 Jo-Philipp Wich * @@ -16,8 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "uci.h" -#include "session.h" +#include +#include static struct blob_buf buf; static struct uci_context *cursor; @@ -169,6 +169,28 @@ rpc_uci_status(void) } /* + * Setup per-session delta save directory. If the passed "sid" blob attribute + * pointer is NULL then the precedure was not invoked through the ubus-rpc so + * we do not perform session isolation and use the default save directory. + */ +static void +rpc_uci_set_savedir(struct blob_attr *sid) +{ + char path[PATH_MAX]; + + if (!sid) + { + uci_set_savedir(cursor, "/tmp/.uci"); + return; + } + + snprintf(path, sizeof(path) - 1, + RPC_UCI_SAVEDIR_PREFIX "%s", blobmsg_get_string(sid)); + + uci_set_savedir(cursor, path); +} + +/* * Test read access to given config. If the passed "sid" blob attribute pointer * is NULL then the precedure was not invoked through the ubus-rpc so we do not * perform access control and always assume true. @@ -176,6 +198,8 @@ rpc_uci_status(void) static bool rpc_uci_read_access(struct blob_attr *sid, struct blob_attr *config) { + rpc_uci_set_savedir(sid); + if (!sid) return true; @@ -191,6 +215,8 @@ rpc_uci_read_access(struct blob_attr *sid, struct blob_attr *config) static bool rpc_uci_write_access(struct blob_attr *sid, struct blob_attr *config) { + rpc_uci_set_savedir(sid); + if (!sid) return true; @@ -1021,19 +1047,22 @@ rpc_uci_revert_commit(struct blob_attr *msg, bool commit) return UBUS_STATUS_PERMISSION_DENIED; ptr.package = blobmsg_data(tb[RPC_C_CONFIG]); - uci_load(cursor, ptr.package, &p); - - if (!p || uci_lookup_ptr(cursor, &ptr, NULL, true) || !ptr.p) - goto out; if (commit) - uci_commit(cursor, &p, false); - else - uci_revert(cursor, &ptr); + { + uci_load(cursor, ptr.package, &p); -out: - if (p) - uci_unload(cursor, p); + if (p) + { + uci_commit(cursor, &p, false); + uci_unload(cursor, p); + } + } + else + { + if (!uci_lookup_ptr(cursor, &ptr, NULL, true) && ptr.p) + uci_revert(cursor, &ptr); + } return rpc_uci_status(); } @@ -1082,6 +1111,68 @@ out: } +/* + * Remove given delta save directory (if any). + */ +static void +rpc_uci_purge_dir(const char *path) +{ + DIR *d; + struct stat s; + struct dirent *e; + char file[PATH_MAX]; + + if (stat(path, &s) || !S_ISDIR(s.st_mode)) + return; + + if ((d = opendir(path)) != NULL) + { + while ((e = readdir(d)) != NULL) + { + snprintf(file, sizeof(file) - 1, "%s/%s", path, e->d_name); + + if (stat(file, &s) || !S_ISREG(s.st_mode)) + continue; + + unlink(file); + } + + closedir(d); + + rmdir(path); + } +} + +/* + * Session destroy callback to purge associated delta directory. + */ +static void +rpc_uci_purge_savedir_cb(struct rpc_session *ses, void *priv) +{ + char path[PATH_MAX]; + + snprintf(path, sizeof(path) - 1, RPC_UCI_SAVEDIR_PREFIX "%s", ses->id); + rpc_uci_purge_dir(path); +} + +/* + * Removes all delta directories which match the RPC_UCI_SAVEDIR_PREFIX. + * This is used to clean up garbage when starting rpcd. + */ +void rpc_uci_purge_savedirs(void) +{ + int i; + glob_t gl; + + if (!glob(RPC_UCI_SAVEDIR_PREFIX "*", 0, NULL, &gl)) + { + for (i = 0; i < gl.gl_pathc; i++) + rpc_uci_purge_dir(gl.gl_pathv[i]); + + globfree(&gl); + } +} + int rpc_uci_api_init(struct ubus_context *ctx) { static const struct ubus_method uci_methods[] = { @@ -1107,10 +1198,16 @@ int rpc_uci_api_init(struct ubus_context *ctx) .n_methods = ARRAY_SIZE(uci_methods), }; + static struct rpc_session_cb cb = { + .cb = rpc_uci_purge_savedir_cb + }; + cursor = uci_alloc_context(); if (!cursor) return UBUS_STATUS_UNKNOWN_ERROR; + rpc_session_destroy_cb(&cb); + return ubus_add_object(ctx, &obj); }