uci: use per-session save directory and register session destroy callback to purge leftover deltas

This commit is contained in:
Jo-Philipp Wich 2013-09-03 12:42:54 +02:00
parent ad8e937f97
commit b3a5c08e08
2 changed files with 103 additions and 0 deletions

96
uci.c
View file

@ -168,6 +168,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,
"/tmp/.uci-rpc-%s", (char *)blobmsg_data(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
@ -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;
@ -1085,6 +1111,69 @@ out:
}
/*
* Remove given delta save directory (if any).
*/
static void
rpc_uci_purge_savedir(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, "/tmp/.uci-rpc-%s", ses->id);
rpc_uci_purge_savedir(path);
}
/*
* Removes all delta directories which match the /tmp/.uci-rpc-* pattern.
* This is used to clean up garbage when starting rpcd.
*/
static void
rpc_uci_purge_savedirs(void)
{
int i;
glob_t gl;
if (!glob("/tmp/.uci-rpc-*", 0, NULL, &gl))
{
for (i = 0; i < gl.gl_pathc; i++)
rpc_uci_purge_savedir(gl.gl_pathv[i]);
globfree(&gl);
}
}
int rpc_uci_api_init(struct ubus_context *ctx)
{
static const struct ubus_method uci_methods[] = {
@ -1110,10 +1199,17 @@ 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_uci_purge_savedirs();
rpc_session_destroy_cb(&cb);
return ubus_add_object(ctx, &obj);
}

7
uci.h
View file

@ -19,6 +19,13 @@
#ifndef __RPC_UCI_H
#define __RPC_UCI_H
#include <glob.h>
#include <limits.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <inttypes.h>
#include <libubus.h>
#include <uci.h>