int prev_fd = open(".", O_RDONLY | O_DIRECTORY);
system_fd_set_cloexec(prev_fd);
if (fd >= 0)
- fchdir(fd);
+ if (fchdir(fd)) {}
return prev_fd;
}
static void
netifd_dir_pop(int prev_fd)
{
- fchdir(prev_fd);
+ if (prev_fd < 0)
+ return;
+
+ if (fchdir(prev_fd)) {}
close(prev_fd);
}
cb(script, name, obj);
}
+static void
+netifd_init_extdev_handler(const char *config_file, json_object *obj,
+ create_extdev_handler_cb cb)
+{
+ json_object *tmp, *cfg, *info, *stats;
+ const char *name, *ubus_name, *br_prefix = NULL;
+ bool bridge_support = true;
+ char *err_missing;
+
+ if (!json_check_type(obj, json_type_object))
+ return;
+
+ tmp = json_get_field(obj, "name", json_type_string);
+ if (!tmp) {
+ err_missing = "name";
+ goto field_missing;
+ }
+
+ name = json_object_get_string(tmp);
+
+ tmp = json_get_field(obj, "ubus_name", json_type_string);
+ if (!tmp) {
+ err_missing = "ubus_name";
+ goto field_missing;
+ }
+
+ ubus_name = json_object_get_string(tmp);
+
+ tmp = json_get_field(obj, "bridge", json_type_string);
+ if (!tmp || !strcmp(json_object_get_string(tmp), "0"))
+ bridge_support = false;
+
+ if (bridge_support) {
+ tmp = json_get_field(obj, "br-prefix", json_type_string);
+ if (!tmp)
+ br_prefix = name;
+ else
+ br_prefix = json_object_get_string(tmp);
+ }
+
+ tmp = json_get_field(obj, "config", json_type_array);
+ if (!tmp) {
+ err_missing = "config";
+ goto field_missing;
+ }
+
+ cfg = tmp;
+
+ info = json_get_field(obj, "info", json_type_array);
+ stats = json_get_field(obj, "stats", json_type_array);
+
+ cb(config_file, name, ubus_name, bridge_support, br_prefix, cfg, info, stats);
+ return;
+
+field_missing:
+ netifd_log_message(L_WARNING, "external device handler description '%s' is"
+ "missing field '%s'\n", config_file, err_missing);
+}
+
static void
netifd_parse_script_handler(const char *name, script_dump_cb cb)
{
tok = json_tokener_new();
obj = json_tokener_parse_ex(tok, start, len);
- if (!is_error(obj)) {
+ if (obj) {
netifd_init_script_handler(name, obj, cb);
json_object_put(obj);
json_tokener_free(tok);
pclose(f);
}
+static void
+netifd_parse_extdev_handler(const char *path_to_file, create_extdev_handler_cb cb)
+{
+ struct json_tokener *tok = NULL;
+ json_object *obj;
+ FILE *file;
+ int len;
+ char buf[512], *start;
+
+ file = fopen(path_to_file, "r");
+ if (!file)
+ return;
+
+ do {
+ start = fgets(buf, sizeof(buf), file);
+ if (!start)
+ continue;
+
+ len = strlen(start);
+
+ if (!tok)
+ tok = json_tokener_new();
+
+ obj = json_tokener_parse_ex(tok, start, len);
+
+ if (obj) {
+ netifd_init_extdev_handler(path_to_file, obj, cb);
+ json_object_put(obj);
+ json_tokener_free(tok);
+ tok = NULL;
+ } else if (start[len - 1] == '\n') {
+ json_tokener_free(tok);
+ tok = NULL;
+ }
+ } while (!feof(file) && !ferror(file));
+
+ if (tok)
+ json_tokener_free(tok);
+
+ fclose(file);
+}
+
void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
{
glob_t g;
int i, prev_fd;
prev_fd = netifd_dir_push(dir_fd);
- glob("./*.sh", 0, NULL, &g);
+ if (glob("./*.sh", 0, NULL, &g)) {
+ netifd_dir_pop(prev_fd);
+ return;
+ }
+
for (i = 0; i < g.gl_pathc; i++)
netifd_parse_script_handler(g.gl_pathv[i], cb);
netifd_dir_pop(prev_fd);
+
+ globfree(&g);
+}
+
+void
+netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb)
+{
+ glob_t g;
+ int prev_fd;
+
+ prev_fd = netifd_dir_push(dir_fd);
+ glob("*.json", 0, NULL, &g);
+ for (int i = 0; i < g.gl_pathc; i++)
+ netifd_parse_extdev_handler(g.gl_pathv[i], cb);
+ netifd_dir_pop(prev_fd);
}
char *
{
struct blobmsg_policy *attrs;
char *str_buf, *str_cur;
+ char const **validate;
int str_len = 0;
int i;
if (!attrs)
return NULL;
+ validate = calloc(1, sizeof(char*) * config->n_params);
+ if (!validate)
+ goto error;
+
config->params = attrs;
+ config->validate = validate;
for (i = 0; i < config->n_params; i++) {
json_object *cur, *name, *type;
str_cur = str_buf;
for (i = 0; i < config->n_params; i++) {
const char *name = attrs[i].name;
+ char *delim;
attrs[i].name = str_cur;
str_cur += sprintf(str_cur, "%s", name) + 1;
+ delim = strchr(attrs[i].name, ':');
+ if (delim) {
+ *delim = '\0';
+ validate[i] = ++delim;
+ } else {
+ validate[i] = NULL;
+ }
}
return str_buf;
error:
free(attrs);
+ if (validate)
+ free(validate);
config->n_params = 0;
return NULL;
}