+ struct blob_attr *tb[__RPC_F_RW_MAX];
+ int append = O_TRUNC;
+ mode_t prev_mode, mode = 0666;
+ int fd, rv = 0;
+ void *data = NULL;
+ ssize_t data_len = 0;
+
+ blobmsg_parse(rpc_file_rw_policy, __RPC_F_RW_MAX, tb,
+ blob_data(msg), blob_len(msg));
+
+ if (!tb[RPC_F_RW_PATH] || !tb[RPC_F_RW_DATA])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ data = blobmsg_data(tb[RPC_F_RW_DATA]);
+ data_len = blobmsg_data_len(tb[RPC_F_RW_DATA]) - 1;
+
+ if (tb[RPC_F_RW_APPEND] && blobmsg_get_bool(tb[RPC_F_RW_APPEND]))
+ append = O_APPEND;
+
+ if (tb[RPC_F_RW_MODE])
+ mode = blobmsg_get_u32(tb[RPC_F_RW_MODE]);
+
+ prev_mode = umask(0);
+ fd = open(blobmsg_data(tb[RPC_F_RW_PATH]), O_CREAT | O_WRONLY | append, mode);
+ umask(prev_mode);
+ if (fd < 0)
+ return rpc_errno_status();
+
+ if (tb[RPC_F_RW_BASE64] && blobmsg_get_bool(tb[RPC_F_RW_BASE64]))
+ {
+ data_len = b64_decode(data, data, data_len);
+ if (data_len < 0)
+ {
+ rv = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+ }
+
+ if (write(fd, data, data_len) < 0)
+ rv = -1;
+
+out:
+ if (fsync(fd) < 0)
+ rv = -1;
+
+ close(fd);
+ sync();
+
+ if (rv)
+ return rpc_errno_status();
+
+ return 0;
+}
+
+static int
+rpc_file_md5(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ int rv, i;