+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;
+ char *path = NULL;
+
+ if (!rpc_check_path(msg, R, "write", &path, NULL))
+ return rpc_errno_status();
+
+ 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;
+}
+