#define UXC_VERSION "0.2"
#define OCI_VERSION_STRING "1.0.2"
-#define UXC_CONFDIR "/etc/uxc"
+#define UXC_ETC_CONFDIR "/etc/uxc"
+#define UXC_VOL_CONFDIR "/var/run/uxc"
static bool verbose = false;
+static char *confdir = UXC_ETC_CONFDIR;
struct runtime_state {
struct avl_node avl;
AVL_TREE(runtime, avl_strcmp, false, NULL);
static struct blob_buf conf;
static struct blob_attr *blockinfo;
+static struct blob_attr *fstabinfo;
static struct ubus_context *ctx;
static int usage(void) {
printf(" [--autostart]\t\t\t\tstart on boot\n");
printf(" [--temp-overlay-size size]\t\tuse tmpfs overlay with {size}\n");
printf(" [--write-overlay-path path]\t\tuse overlay on {path}\n");
- printf(" [--volumes v1,v2,...,vN]\t\trequire volumes to be available\n");
+ printf(" [--mounts v1,v2,...,vN]\t\trequire filesystems to be available\n");
printf("\tstart <conf>\t\t\t\t\tstart container <conf>\n");
printf("\tstate <conf>\t\t\t\t\tget state of container <conf>\n");
printf("\tkill <conf> [<signal>]\t\t\t\tsend signal to container <conf>\n");
glob_t gl;
char *globstr;
void *c, *o;
+ struct stat sb;
+
+ if (!stat(UXC_VOL_CONFDIR, &sb)) {
+ if (sb.st_mode & S_IFDIR)
+ confdir = UXC_VOL_CONFDIR;
+ }
- if (asprintf(&globstr, "%s/*.json", UXC_CONFDIR) == -1)
+ if (asprintf(&globstr, "%s/*.json", confdir) == -1)
return ENOMEM;
blob_buf_init(&conf, 0);
int ret;
*ocistate = NULL;
- asprintf(&objname, "container.%s", name);
+ if (asprintf(&objname, "container.%s", name) == -1)
+ exit(ENOMEM);
+
ret = ubus_lookup_id(ctx, objname, &id);
free(objname);
if (ret)
int rem;
char *bundle = NULL;
char *jail_name = NULL;
+ char *state = NULL;
+ char *tmp;
static struct blob_buf buf;
if (s)
ocistate = s->ocistate;
if (ocistate) {
- printf("%s\n", blobmsg_format_json_indent(ocistate, true, 0));
+ state = blobmsg_format_json_indent(ocistate, true, 0);
+ if (!state)
+ return 1;
+
+ printf("%s\n", state);
+ free(state);
return 0;
}
blobmsg_add_string(&buf, "status", s?"stopped":"uninitialized");
blobmsg_add_string(&buf, "bundle", bundle);
- printf("%s\n", blobmsg_format_json_indent(buf.head, true, 0));
+ tmp = blobmsg_format_json_indent(buf.head, true, 0);
+ if (!tmp) {
+ blob_buf_free(&buf);
+ return ENOMEM;
+ }
+
+ printf("%s\n", tmp);
+ free(tmp);
+
blob_buf_free(&buf);
return 0;
void *in, *ins, *j;
bool found = false;
+ s = avl_find_element(&runtime, name, s, avl);
+
+ if (s && (s->running))
+ return EEXIST;
+
blobmsg_for_each_attr(cur, blob_data(conf.head), rem) {
blobmsg_parse(conf_policy, __CONF_MAX, tb, blobmsg_data(cur), blobmsg_len(cur));
if (!tb[CONF_NAME] || !tb[CONF_PATH])
continue;
found = true;
- path = strdup(blobmsg_get_string(tb[CONF_PATH]));
-
- if (tb[CONF_PIDFILE])
- pidfile = strdup(blobmsg_get_string(tb[CONF_PIDFILE]));
-
- if (tb[CONF_TEMP_OVERLAY_SIZE])
- tmprwsize = strdup(blobmsg_get_string(tb[CONF_TEMP_OVERLAY_SIZE]));
-
- if (tb[CONF_WRITE_OVERLAY_PATH])
- writepath = strdup(blobmsg_get_string(tb[CONF_WRITE_OVERLAY_PATH]));
-
- break;
}
if (!found)
return ENOENT;
- s = avl_find_element(&runtime, name, s, avl);
+ path = blobmsg_get_string(tb[CONF_PATH]);
+
+ if (tb[CONF_PIDFILE])
+ pidfile = blobmsg_get_string(tb[CONF_PIDFILE]);
+
+ if (tb[CONF_TEMP_OVERLAY_SIZE])
+ tmprwsize = blobmsg_get_string(tb[CONF_TEMP_OVERLAY_SIZE]);
+
+ if (tb[CONF_WRITE_OVERLAY_PATH])
+ writepath = blobmsg_get_string(tb[CONF_WRITE_OVERLAY_PATH]);
- if (s && (s->running))
- return EEXIST;
if (tb[CONF_JAIL])
- jailname = strdup(blobmsg_get_string(tb[CONF_JAIL]));
+ jailname = blobmsg_get_string(tb[CONF_JAIL]);
blob_buf_init(&req, 0);
blobmsg_add_string(&req, "name", name);
blobmsg_close_table(&req, in);
blobmsg_close_table(&req, ins);
- if (verbose)
- fprintf(stderr, "adding container to procd:\n\t%s\n",
- blobmsg_format_json_indent(req.head, true, 1));
+ if (verbose) {
+ char *tmp;
+ tmp = blobmsg_format_json_indent(req.head, true, 1);
+ if (!tmp)
+ return ENOMEM;
+
+ fprintf(stderr, "adding container to procd:\n\t%s\n", tmp);
+ free(tmp);
+ }
ret = 0;
if (ubus_lookup_id(ctx, "container", &id) ||
char *objname;
unsigned int id;
- asprintf(&objname, "container.%s", name);
+ if (asprintf(&objname, "container.%s", name) == -1)
+ return ENOMEM;
+
if (ubus_lookup_id(ctx, objname, &id))
return ENOENT;
blobmsg_add_u32(&req, "signal", signal);
blobmsg_add_string(&req, "name", name);
- asprintf(&objname, "container.%s", name);
+ if (asprintf(&objname, "container.%s", name) == -1)
+ return ENOMEM;
+
ret = ubus_lookup_id(ctx, objname, &id);
free(objname);
if (ret)
return ENOTDIR;
}
- ret = mkdir(UXC_CONFDIR, 0755);
+ ret = mkdir(confdir, 0755);
if (ret && errno != EEXIST)
return ret;
- if (asprintf(&fname, "%s/%s.json", UXC_CONFDIR, name) < 1)
+ if (asprintf(&fname, "%s/%s.json", confdir, name) == -1)
return ENOMEM;
f = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
return errno;
if (!add) {
- keeppath = strdup(blobmsg_get_string(tb[CONF_PATH]));
+ keeppath = blobmsg_get_string(tb[CONF_PATH]);
if (tb[CONF_WRITE_OVERLAY_PATH])
- writepath = strdup(blobmsg_get_string(tb[CONF_WRITE_OVERLAY_PATH]));
+ writepath = blobmsg_get_string(tb[CONF_WRITE_OVERLAY_PATH]);
if (tb[CONF_TEMP_OVERLAY_SIZE])
- tmprwsize = strdup(blobmsg_get_string(tb[CONF_TEMP_OVERLAY_SIZE]));
+ tmprwsize = blobmsg_get_string(tb[CONF_TEMP_OVERLAY_SIZE]);
}
blob_buf_init(&req, 0);
}
blobmsg_close_array(&req, mntarr);
}
-
- dprintf(f, "%s\n", blobmsg_format_json_indent(req.head, true, 0));
-
- if (!add)
- free(keeppath);
+ tmp = blobmsg_format_json_indent(req.head, true, 0);
+ if (tmp) {
+ dprintf(f, "%s\n", tmp);
+ free(tmp);
+ }
blob_buf_free(&req);
+ close(f);
return 0;
}
/* check if device 'devname' is mounted according to blockd */
-static int checkblock(char *uuid)
+static int checkblock(const char *uuid)
{
struct blob_attr *tb[__BLOCK_INFO_MAX];
struct blob_attr *cur;
return 1;
}
+enum {
+ UCI_FSTAB_UUID,
+ UCI_FSTAB_ANONYMOUS,
+ __UCI_FSTAB_MAX,
+};
+
+static const struct blobmsg_policy uci_fstab_policy[__UCI_FSTAB_MAX] = {
+ [UCI_FSTAB_UUID] = { .name = "uuid", .type = BLOBMSG_TYPE_STRING },
+ [UCI_FSTAB_ANONYMOUS] = { .name = ".anonymous", .type = BLOBMSG_TYPE_BOOL },
+};
+
+static const char *resolveuuid(const char *volname)
+{
+ struct blob_attr *tb[__UCI_FSTAB_MAX];
+ struct blob_attr *cur;
+ const char *mntname;
+ char *tmpvolname, *replc;
+ int rem, res;
+
+ blobmsg_for_each_attr(cur, fstabinfo, rem) {
+ blobmsg_parse(uci_fstab_policy, __UCI_FSTAB_MAX, tb, blobmsg_data(cur), blobmsg_len(cur));
+
+ if (!tb[UCI_FSTAB_UUID])
+ continue;
+
+ if (tb[UCI_FSTAB_ANONYMOUS] && blobmsg_get_bool(tb[UCI_FSTAB_ANONYMOUS]))
+ continue;
+
+ mntname = blobmsg_name(cur);
+ if (!mntname)
+ continue;
+
+ tmpvolname = strdup(volname);
+ while ((replc = strchr(tmpvolname, '-')))
+ *replc = '_';
+
+ res = strcmp(tmpvolname, mntname);
+ free(tmpvolname);
+
+ if (!res)
+ return blobmsg_get_string(tb[UCI_FSTAB_UUID]);
+ };
+
+ return volname;
+};
+
/* check status of each required volume */
static int checkvolumes(struct blob_attr *volumes)
{
int rem;
blobmsg_for_each_attr(cur, volumes, rem) {
- if (checkblock(blobmsg_get_string(cur)))
+ if (checkblock(resolveuuid(blobmsg_get_string(cur))))
return 1;
}
blockinfo = blob_memdup(blobmsg_data(msg));
}
+static void fstab_cb(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+ fstabinfo = blob_memdup(blobmsg_data(msg));
+}
+
static int uxc_boot(void)
{
struct blob_attr *cur, *tb[__CONF_MAX];
struct runtime_state *s;
+ static struct blob_buf req;
int rem, ret = 0;
char *name;
unsigned int id;
if (ret)
return ENXIO;
+ ret = ubus_lookup_id(ctx, "uci", &id);
+ if (ret)
+ return ENOENT;
+
+ blob_buf_init(&req, 0);
+ blobmsg_add_string(&req, "config", "fstab");
+ blobmsg_add_string(&req, "type", "mount");
+
+ ret = ubus_invoke(ctx, id, "get", req.head, fstab_cb, NULL, 3000);
+ if (ret)
+ return ENXIO;
+
blobmsg_for_each_attr(cur, blob_data(conf.head), rem) {
blobmsg_parse(conf_policy, __CONF_MAX, tb, blobmsg_data(cur), blobmsg_len(cur));
if (!tb[CONF_NAME] || !tb[CONF_PATH] || !tb[CONF_AUTOSTART] || !blobmsg_get_bool(tb[CONF_AUTOSTART]))