uxc: resolve volume UUIDs by name of UCI fstab section
authorDaniel Golle <daniel@makrotopia.org>
Sat, 24 Jul 2021 22:51:37 +0000 (23:51 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Sat, 24 Jul 2021 23:52:06 +0000 (00:52 +0100)
Allow identifying volumes which are required for a container to start
by their UCI section name in /etc/config/fstab, which is also where
'uvol' puts the volume name.
Using filesystem UUID instead is still possible as well.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
uxc.c

diff --git a/uxc.c b/uxc.c
index b801d7f906574be3a43863d943a7c7773fecd100..5b39e9089cfc1038b6677f677c48b92ab4d3af62 100644 (file)
--- a/uxc.c
+++ b/uxc.c
@@ -82,6 +82,7 @@ static struct option long_options[] = {
 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) {
@@ -701,7 +702,7 @@ static const struct blobmsg_policy block_info_policy[__BLOCK_INFO_MAX] = {
 
 
 /* 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;
@@ -720,6 +721,52 @@ static int checkblock(char *uuid)
        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)
 {
@@ -727,7 +774,7 @@ 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;
        }
 
@@ -739,10 +786,16 @@ static void block_cb(struct ubus_request *req, int type, struct blob_attr *msg)
        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;
@@ -755,6 +808,18 @@ static int uxc_boot(void)
        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]))