2 * luci-rpcd - LuCI UBUS RPC server
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 static struct blob_buf buf;
35 static const struct blobmsg_policy file_policy[__RPC_F_MAX] = {
36 [RPC_F_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
37 [RPC_F_DATA] = { .name = "data", .type = BLOBMSG_TYPE_STRING },
40 static const char *d_types[] = {
43 [DT_DIR] = "directory",
48 [DT_UNKNOWN] = "unknown",
53 rpc_errno_status(void)
58 return UBUS_STATUS_PERMISSION_DENIED;
61 return UBUS_STATUS_INVALID_ARGUMENT;
64 return UBUS_STATUS_NOT_FOUND;
67 return UBUS_STATUS_INVALID_ARGUMENT;
70 return UBUS_STATUS_UNKNOWN_ERROR;
74 static struct blob_attr **
75 rpc_check_path(struct blob_attr *msg, char **path, struct stat *s)
77 static struct blob_attr *tb[__RPC_F_MAX];
79 blobmsg_parse(file_policy, __RPC_F_MAX, tb, blob_data(msg), blob_len(msg));
87 *path = blobmsg_data(tb[RPC_F_PATH]);
96 rpc_handle_read(struct ubus_context *ctx, struct ubus_object *obj,
97 struct ubus_request_data *req, const char *method,
98 struct blob_attr *msg)
102 char buffer[RPC_FILE_MAX_SIZE];
105 if (!rpc_check_path(msg, &path, &s))
106 return rpc_errno_status();
108 if (s.st_size >= RPC_FILE_MAX_SIZE)
109 return UBUS_STATUS_NOT_SUPPORTED;
111 if ((fd = open(path, O_RDONLY)) < 0)
112 return rpc_errno_status();
114 if ((rlen = read(fd, buffer, RPC_FILE_MAX_SIZE-1)) > 0)
120 return UBUS_STATUS_NO_DATA;
122 blob_buf_init(&buf, 0);
123 blobmsg_add_string(&buf, "data", buffer);
124 ubus_send_reply(ctx, req, buf.head);
130 rpc_handle_write(struct ubus_context *ctx, struct ubus_object *obj,
131 struct ubus_request_data *req, const char *method,
132 struct blob_attr *msg)
137 struct blob_attr **tb;
139 if (!(tb = rpc_check_path(msg, &path, &s)))
140 return rpc_errno_status();
143 return UBUS_STATUS_INVALID_ARGUMENT;
145 if ((fd = open(path, O_WRONLY)) < 0)
146 return rpc_errno_status();
148 rv = write(fd, blobmsg_data(tb[RPC_F_DATA]), blobmsg_data_len(tb[RPC_F_DATA]));
153 return UBUS_STATUS_NO_DATA;
159 rpc_handle_list(struct ubus_context *ctx, struct ubus_object *obj,
160 struct ubus_request_data *req, const char *method,
161 struct blob_attr *msg)
169 if (!rpc_check_path(msg, &path, &s))
170 return rpc_errno_status();
172 if ((fd = opendir(path)) == NULL)
173 return rpc_errno_status();
175 blob_buf_init(&buf, 0);
176 c = blobmsg_open_array(&buf, "entries");
178 while ((e = readdir(fd)) != NULL)
180 if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, ".."))
183 d = blobmsg_open_table(&buf, NULL);
184 blobmsg_add_string(&buf, "name", e->d_name);
185 blobmsg_add_string(&buf, "type", d_types[e->d_type]);
186 blobmsg_close_table(&buf, d);
189 blobmsg_close_array(&buf, c);
190 ubus_send_reply(ctx, req, buf.head);
196 rpc_handle_stat(struct ubus_context *ctx, struct ubus_object *obj,
197 struct ubus_request_data *req, const char *method,
198 struct blob_attr *msg)
204 if (!rpc_check_path(msg, &path, &s))
205 return rpc_errno_status();
207 blob_buf_init(&buf, 0);
209 type = S_ISREG(s.st_mode) ? DT_REG :
210 S_ISDIR(s.st_mode) ? DT_DIR :
211 S_ISCHR(s.st_mode) ? DT_CHR :
212 S_ISBLK(s.st_mode) ? DT_BLK :
213 S_ISFIFO(s.st_mode) ? DT_FIFO :
214 S_ISLNK(s.st_mode) ? DT_LNK :
215 S_ISSOCK(s.st_mode) ? DT_SOCK :
218 blobmsg_add_string(&buf, "path", path);
219 blobmsg_add_string(&buf, "type", d_types[type]);
220 blobmsg_add_u32(&buf, "size", s.st_size);
221 blobmsg_add_u32(&buf, "mode", s.st_mode);
222 blobmsg_add_u32(&buf, "atime", s.st_atime);
223 blobmsg_add_u32(&buf, "mtime", s.st_mtime);
224 blobmsg_add_u32(&buf, "ctime", s.st_ctime);
225 blobmsg_add_u32(&buf, "inode", s.st_ino);
226 blobmsg_add_u32(&buf, "uid", s.st_uid);
227 blobmsg_add_u32(&buf, "gid", s.st_gid);
229 ubus_send_reply(ctx, req, buf.head);
235 int rpc_file_api_init(struct ubus_context *ctx)
237 static const struct ubus_method file_methods[] = {
238 UBUS_METHOD("read", rpc_handle_read, file_policy),
239 UBUS_METHOD("write", rpc_handle_write, file_policy),
240 UBUS_METHOD("list", rpc_handle_list, file_policy),
241 UBUS_METHOD("stat", rpc_handle_stat, file_policy),
244 static struct ubus_object_type file_type =
245 UBUS_OBJECT_TYPE("luci-rpc-file", file_methods);
247 static struct ubus_object obj = {
250 .methods = file_methods,
251 .n_methods = ARRAY_SIZE(file_methods),
254 return ubus_add_object(ctx, &obj);