summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-09-03 08:18:39 +0200
committerJo-Philipp Wich <jo@mein.io>2019-09-03 11:27:44 +0200
commit345363bf473fc6d2e35667758c3588d7f379b86f (patch)
tree7541344bfb407a637c86a1ef6a741b844c1a0a86
parent604db20aa6b1e573ddc0d5d3662988244701b13f (diff)
downloadrpcd-345363bf473fc6d2e35667758c3588d7f379b86f.tar.gz
file: add remove operation
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--file.c94
1 files changed, 88 insertions, 6 deletions
diff --git a/file.c b/file.c
index 40ed9b9..be272f9 100644
--- a/file.c
+++ b/file.c
@@ -577,6 +577,87 @@ rpc_file_stat(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
+static int
+rpc_file_remove_recursive(const char *path);
+
+static int
+rpc_file_remove_recursive(const char *path)
+{
+ DIR *fd;
+ int err = 0;
+ struct stat s;
+ struct dirent *e;
+ char *entrypath;
+
+ if ((fd = opendir(path)) == NULL)
+ return rpc_errno_status();
+
+ for (e = readdir(fd); e != NULL && err == 0; e = readdir(fd))
+ {
+ if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, ".."))
+ continue;
+
+ if (asprintf(&entrypath, "%s/%s", path, e->d_name) >= 0)
+ {
+ if (!lstat(entrypath, &s))
+ {
+ if (S_ISDIR(s.st_mode))
+ err = rpc_file_remove_recursive(entrypath);
+ else if (unlink(entrypath))
+ err = rpc_errno_status();
+ }
+
+ free(entrypath);
+ }
+ else
+ {
+ err = UBUS_STATUS_UNKNOWN_ERROR;
+ }
+ }
+
+ closedir(fd);
+
+ if (!err && rmdir(path))
+ return rpc_errno_status();
+
+ return err;
+}
+
+static int
+rpc_file_remove(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct stat s;
+ struct blob_attr *tb[__RPC_F_R_MAX];
+ char *path = NULL;
+
+ blobmsg_parse(rpc_file_r_policy, __RPC_F_R_MAX, tb,
+ blob_data(msg), blob_len(msg));
+
+ if (!tb[RPC_F_RW_PATH])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ path = rpc_canonicalize_path(blobmsg_get_string(tb[RPC_F_RW_PATH]));
+
+ if (path == NULL)
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ if (!rpc_file_write_access(tb[RPC_F_R_SESSION], path))
+ return UBUS_STATUS_PERMISSION_DENIED;
+
+ if (lstat(path, &s))
+ return rpc_errno_status();
+
+ if (S_ISDIR(s.st_mode))
+ return rpc_file_remove_recursive(path);
+
+ if (unlink(path))
+ return rpc_errno_status();
+
+ return 0;
+}
+
static const char *
rpc_file_exec_lookup(const char *cmd)
{
@@ -901,12 +982,13 @@ static int
rpc_file_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
{
static const struct ubus_method file_methods[] = {
- UBUS_METHOD("read", rpc_file_read, rpc_file_rb_policy),
- UBUS_METHOD("write", rpc_file_write, rpc_file_rw_policy),
- UBUS_METHOD("list", rpc_file_list, rpc_file_r_policy),
- UBUS_METHOD("stat", rpc_file_stat, rpc_file_r_policy),
- UBUS_METHOD("md5", rpc_file_md5, rpc_file_r_policy),
- UBUS_METHOD("exec", rpc_file_exec, rpc_exec_policy),
+ UBUS_METHOD("read", rpc_file_read, rpc_file_rb_policy),
+ UBUS_METHOD("write", rpc_file_write, rpc_file_rw_policy),
+ UBUS_METHOD("list", rpc_file_list, rpc_file_r_policy),
+ UBUS_METHOD("stat", rpc_file_stat, rpc_file_r_policy),
+ UBUS_METHOD("md5", rpc_file_md5, rpc_file_r_policy),
+ UBUS_METHOD("remove", rpc_file_remove, rpc_file_r_policy),
+ UBUS_METHOD("exec", rpc_file_exec, rpc_exec_policy),
};
static struct ubus_object_type file_type =