uvol: unbreak build and adapt to updated ucode
authorDaniel Golle <redacted>
Thu, 31 Mar 2022 20:41:17 +0000 (21:41 +0100)
committerDaniel Golle <redacted>
Thu, 31 Mar 2022 21:28:27 +0000 (22:28 +0100)
 * Fix build which was broken by a wrong path in the Makefile.

Adapt to ucode commit 4618807 ("main: rework CLI frontend"):
 * ucode now no longer needs the {% %} around each code file, remove
   that and safe one level of indentation.
 * ARGV now no longer includes ucode executable and script itself

Fixes: 6350c7bc6 ("uvol: replace with re-write in ucode")
Signed-off-by: Daniel Golle <redacted>
utils/uvol/Makefile
utils/uvol/files/blockdev_common.uc
utils/uvol/files/lvm.uc
utils/uvol/files/ubi.uc
utils/uvol/files/uci.uc
utils/uvol/files/uvol

index 21d46fcff1832617de3125057599322fb7dda440..410788df334ba856489ffe8ae08367dae75465af 100644 (file)
@@ -67,7 +67,7 @@ define Package/autopart/install
 endef
 
 define Package/uvol/install
-       $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/uvol/backends $(1)/usr/sbin $(1)/etc/uci-defaults
+       $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/lib/uvol/backends $(1)/usr/sbin $(1)/etc/uci-defaults
        $(INSTALL_BIN) ./files/uvol.init $(1)/etc/init.d/uvol
        $(INSTALL_DATA) ./files/blockdev_common.uc $(1)/usr/lib/uvol/
        $(INSTALL_DATA) ./files/uci.uc $(1)/usr/lib/uvol/
index f45e573d264f703957c80bacd7a7d1426665ed5a..8edf65bfe3721010a3a78d7559bb2833cc17f594 100644 (file)
@@ -1,64 +1,64 @@
-{%
 // SPDX-License-Identifier: GPL-2.0-or-later
 // Helper functions used to identify the boot device
-       // adapted from /lib/functions.sh
-       let cmdline_get_var = function(var) {
-               let cmdline = fs.open("/proc/cmdline", "r");
-               let allargs = cmdline.read("all");
-               cmdline.close();
-               let ret = null;
-               for (let arg in split(allargs, /[ \t\n]/)) {
-                       let el = split(arg, "=");
-                       if (shift(el) == var)
-                               return join("=", el);
-               }
-               return ret;
-       };
 
-       // adapted from /lib/upgrade/common.sh
-       let get_blockdevs = function() {
-               let devs = [];
-               for (let dev in fs.glob('/dev/*'))
-                       if (fs.stat(dev).type == "block")
-                               push(devs, split(dev, '/')[-1]);
+// adapted from /lib/functions.sh
+let cmdline_get_var = function(var) {
+       let cmdline = fs.open("/proc/cmdline", "r");
+       let allargs = cmdline.read("all");
+       cmdline.close();
+       let ret = null;
+       for (let arg in split(allargs, /[ \t\n]/)) {
+               let el = split(arg, "=");
+               if (shift(el) == var)
+                       return join("=", el);
+       }
+       return ret;
+};
 
-               return devs;
-       };
+// adapted from /lib/upgrade/common.sh
+let get_blockdevs = function() {
+       let devs = [];
+       for (let dev in fs.glob('/dev/*'))
+               if (fs.stat(dev).type == "block")
+                       push(devs, split(dev, '/')[-1]);
 
-       // adapted from /lib/upgrade/common.sh
-       let get_uevent_major_minor = function(file) {
-               let uevf = fs.open(file, "r");
-               if (!uevf)
-                       return null;
+       return devs;
+};
 
-               let r = {};
-               let evl;
-               while ((evl = uevf.read("line"))) {
-               let ev = split(evl, '=');
-                       if (ev[0] == "MAJOR")
-                               r.major = +ev[1];
-                       if (ev[0] == "MINOR")
-                               r.minor = +ev[1];
-               }
-               uevf.close();
-               return r;
-       };
+// adapted from /lib/upgrade/common.sh
+let get_uevent_major_minor = function(file) {
+       let uevf = fs.open(file, "r");
+       if (!uevf)
+               return null;
 
-       // adapted from /lib/upgrade/common.sh
-       let get_bootdev = function(void) {
-               let rootpart = cmdline_get_var("root");
-               let uevent = null;
+       let r = {};
+       let evl;
+       while ((evl = uevf.read("line"))) {
+       let ev = split(evl, '=');
+               if (ev[0] == "MAJOR")
+                       r.major = +ev[1];
+               if (ev[0] == "MINOR")
+                       r.minor = +ev[1];
+       }
+       uevf.close();
+       return r;
+};
 
-               if (wildcard(rootpart, "PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9]")) {
-                       let uuidarg = split(substr(rootpart, 9), '-')[0];
-                       for (let bd in get_blockdevs()) {
-                               let bdf = fs.open(sprintf("/dev/%s", bd), "r");
-                               bdf.seek(440);
-                               let bduuid = bdf.read(4);
-                               bdf.close();
-                               if (uuidarg == sprintf("%x%x%x%x", ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0))) {
-                                       uevent = sprintf("/sys/class/block/%s/uevent", bd);
-                                       break;
+// adapted from /lib/upgrade/common.sh
+let get_bootdev = function(void) {
+       let rootpart = cmdline_get_var("root");
+       let uevent = null;
+
+       if (wildcard(rootpart, "PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9]")) {
+               let uuidarg = split(substr(rootpart, 9), '-')[0];
+               for (let bd in get_blockdevs()) {
+                       let bdf = fs.open(sprintf("/dev/%s", bd), "r");
+                       bdf.seek(440);
+                       let bduuid = bdf.read(4);
+                       bdf.close();
+                       if (uuidarg == sprintf("%x%x%x%x", ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0))) {
+                               uevent = sprintf("/sys/class/block/%s/uevent", bd);
+                               break;
                                }
                        }
                } else if (wildcard(rootpart, "PARTUUID=????????-????-????-????-??????????0?/PARTNROFF=*") ||
                                if (!bduuid)
                                        continue;
 
-                               let uuid = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                       ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0),
-                                       ord(bduuid, 5), ord(bduuid, 4),
-                                       ord(bduuid, 7), ord(bduuid, 6),
-                                       ord(bduuid, 8), ord(bduuid, 9),
-                                       ord(bduuid, 10), ord(bduuid, 11), ord(bduuid, 12), ord(bduuid, 13), ord(bduuid, 14), ord(bduuid, 15));
-                               if (uuidarg == uuid) {
-                                       uevent = sprintf("/sys/class/block/%s/uevent", bd);
-                                       break;
-                               }
-                       }
-               } else if (wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9]") ||
-                          wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9]") ||
-                          wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9]") ||
-                          wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9][a-f0-9]")) {
-                       let devid = rootpart;
-                       if (substr(devid, 0, 2) == "0x")
-                               devid = substr(devid, 2);
+                       let uuid = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                               ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0),
+                               ord(bduuid, 5), ord(bduuid, 4),
+                               ord(bduuid, 7), ord(bduuid, 6),
+                               ord(bduuid, 8), ord(bduuid, 9),
+                               ord(bduuid, 10), ord(bduuid, 11), ord(bduuid, 12), ord(bduuid, 13), ord(bduuid, 14), ord(bduuid, 15));
 
-                       devid = hex(devid);
-                       for (let bd in get_blockdevs()) {
-                               let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
-                               if (r && (r.major == devid / 256) && (r.minor == devid % 256)) {
-                                       uevent = sprintf("/sys/class/block/%s/../uevent", bd);
-                                       break;
-                               }
+                       if (uuidarg == uuid) {
+                               uevent = sprintf("/sys/class/block/%s/uevent", bd);
+                               break;
                        }
-               } else if (wildcard(rootpart, "/dev/*")) {
-                       uevent = sprintf("/sys/class/block/%s/../uevent", split(rootpart, '/')[-1]);
                }
-                       return get_uevent_major_minor(uevent);
-       };
+       } else if (wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9]") ||
+                  wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9]") ||
+                  wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9]") ||
+                  wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9][a-f0-9]")) {
+               let devid = rootpart;
+               if (substr(devid, 0, 2) == "0x")
+                       devid = substr(devid, 2);
 
-       // adapted from /lib/upgrade/common.sh
-       let get_partition = function(dev, num) {
+               devid = hex(devid);
                for (let bd in get_blockdevs()) {
                        let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
-                       if (r.major == dev.major && r.minor == dev.minor + num) {
-                               return bd;
+                       if (r && (r.major == devid / 256) && (r.minor == devid % 256)) {
+                               uevent = sprintf("/sys/class/block/%s/../uevent", bd);
                                break;
                        }
                }
-               return null;
-       };
+       } else if (wildcard(rootpart, "/dev/*")) {
+               uevent = sprintf("/sys/class/block/%s/../uevent", split(rootpart, '/')[-1]);
+       }
+       return get_uevent_major_minor(uevent);
+};
+
+// adapted from /lib/upgrade/common.sh
+let get_partition = function(dev, num) {
+       for (let bd in get_blockdevs()) {
+               let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
+               if (r.major == dev.major && r.minor == dev.minor + num) {
+                       return bd;
+                       break;
+               }
+       }
+       return null;
+};
 
-       blockdev_common = {};
-       blockdev_common.get_partition = get_partition;
-       blockdev_common.get_bootdev = get_bootdev;
-%}
+blockdev_common = {};
+blockdev_common.get_partition = get_partition;
+blockdev_common.get_bootdev = get_bootdev;
index 5be27e5c2c665c92f82ecb68134116e2b582d80a..d05701dc4a145fc1d6075bcaa0c13e26d2db4728 100644 (file)
@@ -1,4 +1,3 @@
-{%
 // SPDX-License-Identifier: GPL-2.0-or-later
 // LVM2 backend for uvol
 //  (c) 2022 Daniel Golle <daniel@makrotopia.org>
 // By setting the UCI option 'vg_name' in the 'uvol' section in /etc/config/fstab
 // you may set an arbitrary LVM2 volume group to back uvol instad.
 
-       let lvm_exec = "/sbin/lvm";
-
-       function lvm(cmd, ...args) {
-               let lvm_json_cmds = [ "lvs", "pvs", "vgs" ];
-               try {
-                       let json_param = "";
-                       if (cmd in lvm_json_cmds)
-                               json_param = "--reportformat json --units b ";
-                       let stdout = fs.popen(sprintf("LVM_SUPPRESS_FD_WARNINGS=1 %s %s %s%s", lvm_exec, cmd, json_param, join(" ", args)));
-                       let tmp;
-                       if (stdout) {
-                               tmp = stdout.read("all");
-                               let ret = {};
-                               ret.retval = stdout.close();
-                               if (json_param) {
-                                       let data = json(tmp);
-                                       if (data.report)
-                                               ret.report = data.report[0];
-                               } else {
-                                       ret.stdout = trim(tmp);
-                               }
-                               return ret;
+let lvm_exec = "/sbin/lvm";
+
+function lvm(cmd, ...args) {
+       let lvm_json_cmds = [ "lvs", "pvs", "vgs" ];
+       try {
+               let json_param = "";
+               if (cmd in lvm_json_cmds)
+                       json_param = "--reportformat json --units b ";
+               let stdout = fs.popen(sprintf("LVM_SUPPRESS_FD_WARNINGS=1 %s %s %s%s", lvm_exec, cmd, json_param, join(" ", args)));
+               let tmp;
+               if (stdout) {
+                       tmp = stdout.read("all");
+                       let ret = {};
+                       ret.retval = stdout.close();
+                       if (json_param) {
+                               let data = json(tmp);
+                               if (data.report)
+                                       ret.report = data.report[0];
                        } else {
-                               printf("lvm cli command failed: %s\n", fs.error());
+                               ret.stdout = trim(tmp);
                        }
-               } catch(e) {
-                       printf("Failed to parse lvm cli output: %s\n%s\n", e, e.stacktrace[0].context);
+                       return ret;
+               } else {
+                       printf("lvm cli command failed: %s\n", fs.error());
                }
-               return null;
+       } catch(e) {
+               printf("Failed to parse lvm cli output: %s\n%s\n", e, e.stacktrace[0].context);
        }
+       return null;
+}
 
-       function pvs() {
-               let fstab = cursor.get_all('fstab');
-               for (let k, section in fstab) {
-                       if (section['.type'] != 'uvol' || !section.vg_name)
-                               continue;
+function pvs() {
+       let fstab = cursor.get_all('fstab');
+       for (let k, section in fstab) {
+               if (section['.type'] != 'uvol' || !section.vg_name)
+                       continue;
 
-                       return section.vg_name;
-               }
-               include("/usr/lib/uvol/blockdev_common.uc");
-               let rootdev = blockdev_common.get_partition(blockdev_common.get_bootdev(), 0);
-               let tmp = lvm("pvs", "-o", "vg_name", "-S", sprintf("\"pv_name=~^/dev/%s.*\$\"", rootdev));
-               if (tmp.report.pv)
-                       return tmp.report.pv[0].vg_name;
-               else
-                       return null;
+               return section.vg_name;
        }
-
-       function vgs(vg_name) {
-               let tmp = lvm("vgs", "-o", "vg_extent_size,vg_extent_count,vg_free_count", "-S", sprintf("\"vg_name=%s\"", vg_name));
-               let ret = null;
-               if (tmp && tmp.report.vg) {
-                       ret = tmp.report.vg;
-                       for (let r in ret) {
-                               r.vg_extent_size = +(rtrim(r.vg_extent_size, "B"));
-                               r.vg_extent_count = +r.vg_extent_count;
-                               r.vg_free_count = +r.vg_free_count;
-                       }
+       include("/usr/lib/uvol/blockdev_common.uc");
+       let rootdev = blockdev_common.get_partition(blockdev_common.get_bootdev(), 0);
+       let tmp = lvm("pvs", "-o", "vg_name", "-S", sprintf("\"pv_name=~^/dev/%s.*\$\"", rootdev));
+       if (tmp.report.pv)
+               return tmp.report.pv[0].vg_name;
+       else
+               return null;
+}
+
+function vgs(vg_name) {
+       let tmp = lvm("vgs", "-o", "vg_extent_size,vg_extent_count,vg_free_count", "-S", sprintf("\"vg_name=%s\"", vg_name));
+       let ret = null;
+       if (tmp && tmp.report.vg) {
+               ret = tmp.report.vg;
+               for (let r in ret) {
+                       r.vg_extent_size = +(rtrim(r.vg_extent_size, "B"));
+                       r.vg_extent_count = +r.vg_extent_count;
+                       r.vg_free_count = +r.vg_free_count;
                }
-               if (ret)
-                       return ret[0];
-               else
-                       return null;
        }
-
-       function lvs(vg_name, vol_name, extra_exp) {
-               let ret = [];
-               if (!vol_name)
-                       vol_name = ".*";
-
-               let lvexpr = sprintf("\"lvname=~^[rw][owp]_%s\$ && vg_name=%s%s%s\"",
-                                    vol_name, vg_name, extra_exp?" && ":"", extra_exp?extra_exp:"");
-               let tmp = lvm("lvs", "-o", "lv_active,lv_name,lv_full_name,lv_size,lv_path,lv_dm_path", "-S", lvexpr);
-               if (tmp && tmp.report.lv) {
-                       ret = tmp.report.lv;
-                       for (let r in ret) {
-                               r.lv_size = +(rtrim(r.lv_size, "B"));
-                               r.lv_active = (r.lv_active == "active");
-                       }
+       if (ret)
+               return ret[0];
+       else
+               return null;
+}
+
+function lvs(vg_name, vol_name, extra_exp) {
+       let ret = [];
+       if (!vol_name)
+               vol_name = ".*";
+
+       let lvexpr = sprintf("\"lvname=~^[rw][owp]_%s\$ && vg_name=%s%s%s\"",
+                            vol_name, vg_name, extra_exp?" && ":"", extra_exp?extra_exp:"");
+       let tmp = lvm("lvs", "-o", "lv_active,lv_name,lv_full_name,lv_size,lv_path,lv_dm_path", "-S", lvexpr);
+       if (tmp && tmp.report.lv) {
+               ret = tmp.report.lv;
+               for (let r in ret) {
+                       r.lv_size = +(rtrim(r.lv_size, "B"));
+                       r.lv_active = (r.lv_active == "active");
                }
-               return ret;
        }
+       return ret;
+}
 
-       function getdev(lv) {
-               if (!lv)
-                       return null;
+function getdev(lv) {
+       if (!lv)
+               return null;
 
-               for (let dms in fs.glob("/sys/devices/virtual/block/dm-*")) {
-                       let f = fs.open(sprintf("%s/dm/name", dms), "r");
-                       if (!f)
-                               continue;
+       for (let dms in fs.glob("/sys/devices/virtual/block/dm-*")) {
+               let f = fs.open(sprintf("%s/dm/name", dms), "r");
+               if (!f)
+                       continue;
 
-                       let dm_name = trim(f.read("all"));
-                       f.close();
-                       if ( split(lv.lv_dm_path, '/')[-1] == dm_name )
-                               return split(dms, '/')[-1]
-               }
-               return null;
+               let dm_name = trim(f.read("all"));
+               f.close();
+               if ( split(lv.lv_dm_path, '/')[-1] == dm_name )
+                       return split(dms, '/')[-1]
        }
+       return null;
+}
 
-       function lvm_init(ctx) {
-               cursor = ctx.cursor;
-               fs = ctx.fs;
-               if (!fs.access(lvm_exec, "x"))
-                       return false;
-
-               vg_name = pvs();
-               if (!vg_name)
-                       return false;
-
-               vg = vgs(vg_name);
-               uvol_uci_add = ctx.uci_add;
-               uvol_uci_commit = ctx.uci_commit;
-               uvol_uci_remove = ctx.uci_remove;
-               uvol_uci_init = ctx.uci_init;
-               return true;
-       }
+function lvm_init(ctx) {
+       cursor = ctx.cursor;
+       fs = ctx.fs;
+       if (!fs.access(lvm_exec, "x"))
+               return false;
 
-       function lvm_free() {
-               if (!vg || !vg.vg_free_count || !vg.vg_extent_size)
-                       return 2;
+       vg_name = pvs();
+       if (!vg_name)
+               return false;
 
-               return sprintf("%d", vg.vg_free_count * vg.vg_extent_size);
-       }
+       vg = vgs(vg_name);
+       uvol_uci_add = ctx.uci_add;
+       uvol_uci_commit = ctx.uci_commit;
+       uvol_uci_remove = ctx.uci_remove;
+       uvol_uci_init = ctx.uci_init;
+       return true;
+}
 
-       function lvm_total() {
-               if (!vg || !vg.vg_extent_count || !vg.vg_extent_size)
-                       return 2;
+function lvm_free() {
+       if (!vg || !vg.vg_free_count || !vg.vg_extent_size)
+               return 2;
 
-               return sprintf("%d", vg.vg_extent_count * vg.vg_extent_size);
-       }
+       return sprintf("%d", vg.vg_free_count * vg.vg_extent_size);
+}
 
-       function lvm_align() {
-               if (!vg || !vg.vg_extent_size)
-                       return 2;
+function lvm_total() {
+       if (!vg || !vg.vg_extent_count || !vg.vg_extent_size)
+               return 2;
 
-               return sprintf("%d", vg.vg_extent_size);
-       }
+       return sprintf("%d", vg.vg_extent_count * vg.vg_extent_size);
+}
 
-       function lvm_list(vol_name) {
-               let vols = [];
-
-               if (!vg_name)
-                       return vols;
-
-               let res = lvs(vg_name, vol_name);
-               for (let lv in res) {
-                       let vol = {};
-                       if (substr(lv.lv_name, 3, 1) == ".")
-                               continue;
-
-                       vol.name = substr(lv.lv_name, 3);
-                       vol.mode = substr(lv.lv_name, 0, 2);
-                       if (!lv.lv_active) {
-                               if (vol.mode == "ro")
-                                       vol.mode = "rd";
-                               if (vol.mode == "rw")
-                                       vol.mode = "wd";
-                       }
-                       vol.size = lv.lv_size;
-                       push(vols, vol);
-               }
+function lvm_align() {
+       if (!vg || !vg.vg_extent_size)
+               return 2;
 
-               return vols;
-       }
+       return sprintf("%d", vg.vg_extent_size);
+}
 
-       function lvm_size(vol_name) {
-               if (!vol_name || !vg_name)
-                       return 2;
+function lvm_list(vol_name) {
+       let vols = [];
 
-               let res = lvs(vg_name, vol_name);
-               if (!res[0])
-                       return 2;
+       if (!vg_name)
+               return vols;
 
-               return sprintf("%d", res[0].lv_size);
+       let res = lvs(vg_name, vol_name);
+       for (let lv in res) {
+               let vol = {};
+               if (substr(lv.lv_name, 3, 1) == ".")
+                       continue;
+
+               vol.name = substr(lv.lv_name, 3);
+               vol.mode = substr(lv.lv_name, 0, 2);
+               if (!lv.lv_active) {
+                       if (vol.mode == "ro")
+                               vol.mode = "rd";
+                       if (vol.mode == "rw")
+                               vol.mode = "wd";
+               }
+               vol.size = lv.lv_size;
+               push(vols, vol);
        }
 
-       function lvm_status(vol_name) {
-               if (!vol_name || !vg_name)
-                       return 22;
+       return vols;
+}
 
-               let res = lvs(vg_name, vol_name);
-               if (!res[0])
-                       return 2;
+function lvm_size(vol_name) {
+       if (!vol_name || !vg_name)
+               return 2;
 
-               let mode = substr(res[0].lv_name, 0, 2);
-               if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
-                       return 1;
+       let res = lvs(vg_name, vol_name);
+       if (!res[0])
+               return 2;
 
-               return 0;
-       }
+       return sprintf("%d", res[0].lv_size);
+}
 
-       function lvm_device(vol_name) {
-               if (!vol_name || !vg_name)
-                       return 22;
+function lvm_status(vol_name) {
+       if (!vol_name || !vg_name)
+               return 22;
 
-               let res = lvs(vg_name, vol_name);
-               if (!res[0])
-                       return 2;
+       let res = lvs(vg_name, vol_name);
+       if (!res[0])
+               return 2;
 
-               let mode = substr(res[0].lv_name, 0, 2);
-               if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
-                       return 22;
+       let mode = substr(res[0].lv_name, 0, 2);
+       if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
+               return 1;
 
-               return getdev(res[0]);
-       }
+       return 0;
+}
 
-       function lvm_updown(vol_name, up) {
-               if (!vol_name || !vg_name)
-                       return 22;
+function lvm_device(vol_name) {
+       if (!vol_name || !vg_name)
+               return 22;
 
-               let res = lvs(vg_name, vol_name);
-               if (!res[0])
-                       return 2;
+       let res = lvs(vg_name, vol_name);
+       if (!res[0])
+               return 2;
 
-               let lv = res[0];
-               if (!lv.lv_path)
-                       return 2;
+       let mode = substr(res[0].lv_name, 0, 2);
+       if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
+               return 22;
 
-               if (up && (wildcard(lv.lv_path, "/dev/*/wo_*") ||
-                          wildcard(lv.lv_path, "/dev/*/wp_*")))
-                       return 22;
+       return getdev(res[0]);
+}
 
-               if (up)
-                       uvol_uci_commit(vol_name);
+function lvm_updown(vol_name, up) {
+       if (!vol_name || !vg_name)
+               return 22;
 
-               if (lv.lv_active == up)
-                       return 0;
+       let res = lvs(vg_name, vol_name);
+       if (!res[0])
+               return 2;
 
-               if (!up) {
-                       let devname = getdev(lv);
-                       if (devname)
-                               system(sprintf("umount /dev/%s", devname));
-               }
+       let lv = res[0];
+       if (!lv.lv_path)
+               return 2;
 
-               let lvchange_r = lvm("lvchange", up?"-k":"-a", "n", lv.lv_full_name);
-               if (up && lvchange_r.retval != 0)
-                       return lvchange_r.retval;
+       if (up && (wildcard(lv.lv_path, "/dev/*/wo_*") ||
+                  wildcard(lv.lv_path, "/dev/*/wp_*")))
+               return 22;
 
-               lvchange_r = lvm("lvchange", up?"-a":"-k", "y", lv.lv_full_name);
-               if (lvchange_r.retval != 0)
-                       return lvchange_r.retval;
+       if (up)
+               uvol_uci_commit(vol_name);
 
-               return 0
-       }
+       if (lv.lv_active == up)
+               return 0;
 
-       function lvm_up(vol_name) {
-               return lvm_updown(vol_name, true);
+       if (!up) {
+               let devname = getdev(lv);
+               if (devname)
+                       system(sprintf("umount /dev/%s", devname));
        }
 
-       function lvm_down(vol_name) {
-               return lvm_updown(vol_name, false);
+       let lvchange_r = lvm("lvchange", up?"-k":"-a", "n", lv.lv_full_name);
+       if (up && lvchange_r.retval != 0)
+               return lvchange_r.retval;
+
+       lvchange_r = lvm("lvchange", up?"-a":"-k", "y", lv.lv_full_name);
+       if (lvchange_r.retval != 0)
+               return lvchange_r.retval;
+
+       return 0
+}
+
+function lvm_up(vol_name) {
+       return lvm_updown(vol_name, true);
+}
+
+function lvm_down(vol_name) {
+       return lvm_updown(vol_name, false);
+}
+
+function lvm_create(vol_name, vol_size, vol_mode) {
+       if (!vol_name || !vg_name)
+               return 22;
+
+       vol_size = +vol_size;
+       if (vol_size <= 0)
+               return 22;
+
+       let res = lvs(vg_name, vol_name);
+       if (res[0])
+               return 17;
+
+       let size_ext = vol_size / vg.vg_extent_size;
+       if (vol_size % vg.vg_extent_size)
+               ++size_ext;
+       let lvmode, mode;
+       if (vol_mode == "ro" || vol_mode == "wo") {
+               lvmode = "r";
+               mode = "wo";
+       } else if (vol_mode == "rw") {
+               lvmode = "rw";
+               mode = "wp";
+       } else {
+               return 22;
        }
 
-       function lvm_create(vol_name, vol_size, vol_mode) {
-               if (!vol_name || !vg_name)
-                       return 22;
-
-               vol_size = +vol_size;
-               if (vol_size <= 0)
-                       return 22;
-
-               let res = lvs(vg_name, vol_name);
-               if (res[0])
-                       return 17;
-
-               let size_ext = vol_size / vg.vg_extent_size;
-               if (vol_size % vg.vg_extent_size)
-                       ++size_ext;
-               let lvmode, mode;
-               if (vol_mode == "ro" || vol_mode == "wo") {
-                       lvmode = "r";
-                       mode = "wo";
-               } else if (vol_mode == "rw") {
-                       lvmode = "rw";
-                       mode = "wp";
-               } else {
-                       return 22;
+       let ret = lvm("lvcreate", "-p", lvmode, "-a", "n", "-y", "-W", "n", "-Z", "n", "-n", sprintf("%s_%s", mode, vol_name), "-l", size_ext, vg_name);
+       if (ret.retval != 0 || lvmode == "r")
+               return ret.retval;
+
+       let lv = lvs(vg_name, vol_name);
+       if (!lv[0] || !lv[0].lv_full_name)
+               return 22;
+
+       lv = lv[0];
+       let ret = lvm("lvchange", "-a", "y", lv.lv_full_name);
+       if (ret.retval != 0)
+               return ret.retval;
+
+       let use_f2fs = (lv.lv_size > (100 * 1024 * 1024));
+       if (use_f2fs) {
+               let mkfs_ret = system(sprintf("/usr/sbin/mkfs.f2fs -f -l \"%s\" \"%s\"", vol_name, lv.lv_path));
+               if (mkfs_ret != 0 && mkfs_ret != 134) {
+                       lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name);
+                       if (lvchange_r.retval != 0)
+                               return lvchange_r.retval;
+                       return mkfs_ret;
                }
+       } else {
+               let mkfs_ret = system(sprintf("/usr/sbin/mke2fs -F -L \"%s\" \"%s\"", vol_name, lv.lv_path));
+               if (mkfs_ret != 0) {
+                       lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name);
+                       if (lvchange_r.retval != 0)
+                               return lvchange_r.retval;
+                       return mkfs_ret;
+               }
+       }
+       uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "rw");
+
+       ret = lvm("lvchange", "-a", "n", lv.lv_full_name);
+       if (ret.retval != 0)
+               return ret.retval;
+
+       ret = lvm("lvrename", vg_name, sprintf("wp_%s", vol_name), sprintf("rw_%s", vol_name));
+       if (ret.retval != 0)
+               return ret.retval;
+
+       return 0;
+}
+
+function lvm_remove(vol_name) {
+       if (!vol_name || !vg_name)
+               return 22;
+
+       let res = lvs(vg_name, vol_name);
+       if (!res[0])
+               return 2;
+
+       if (res[0].lv_active)
+               return 16;
+
+       let ret = lvm("lvremove", "-y", res[0].lv_full_name);
+       if (ret.retval != 0)
+               return ret.retval;
+
+       uvol_uci_remove(vol_name);
+       uvol_uci_commit(vol_name);
+       return 0;
+}
+
+function lvm_dd(in_fd, out_fd, vol_size) {
+       let rem = vol_size;
+       let buf;
+       while ((buf = in_fd.read(vg.vg_extent_size)) && (rem > 0)) {
+               rem -= length(buf);
+               if (rem < 0) {
+                       buf = substr(buf, 0, rem);
+               }
+               out_fd.write(buf);
+       }
+       return rem;
+}
 
-               let ret = lvm("lvcreate", "-p", lvmode, "-a", "n", "-y", "-W", "n", "-Z", "n", "-n", sprintf("%s_%s", mode, vol_name), "-l", size_ext, vg_name);
-               if (ret.retval != 0 || lvmode == "r")
-                       return ret.retval;
+function lvm_write(vol_name, vol_size) {
+       if (!vol_name || !vg_name)
+               return 22;
 
-               let lv = lvs(vg_name, vol_name);
-               if (!lv[0] || !lv[0].lv_full_name)
-                       return 22;
+       let lv = lvs(vg_name, vol_name);
+       if (!lv[0] || !lv[0].lv_full_name)
+               return 2;
 
-               lv = lv[0];
-               let ret = lvm("lvchange", "-a", "y", lv.lv_full_name);
-               if (ret.retval != 0)
-                       return ret.retval;
+       lv = lv[0];
+       vol_size = +vol_size;
+       if (vol_size > lv.lv_size)
+               return 27;
 
-               let use_f2fs = (lv.lv_size > (100 * 1024 * 1024));
-               if (use_f2fs) {
-                       let mkfs_ret = system(sprintf("/usr/sbin/mkfs.f2fs -f -l \"%s\" \"%s\"", vol_name, lv.lv_path));
-                       if (mkfs_ret != 0 && mkfs_ret != 134) {
-                               lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name);
-                               if (lvchange_r.retval != 0)
-                                       return lvchange_r.retval;
-                               return mkfs_ret;
-                       }
-               } else {
-                       let mkfs_ret = system(sprintf("/usr/sbin/mke2fs -F -L \"%s\" \"%s\"", vol_name, lv.lv_path));
-                       if (mkfs_ret != 0) {
-                               lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name);
-                               if (lvchange_r.retval != 0)
-                                       return lvchange_r.retval;
-                               return mkfs_ret;
-                       }
-               }
-               uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "rw");
-
-               ret = lvm("lvchange", "-a", "n", lv.lv_full_name);
+       if (wildcard(lv.lv_path, "/dev/*/wo_*")) {
+               let ret = lvm("lvchange", "-p", "rw", lv.lv_full_name);
                if (ret.retval != 0)
                        return ret.retval;
 
-               ret = lvm("lvrename", vg_name, sprintf("wp_%s", vol_name), sprintf("rw_%s", vol_name));
+               let ret = lvm("lvchange", "-a", "y", lv.lv_full_name);
                if (ret.retval != 0)
                        return ret.retval;
 
-               return 0;
-       }
+               let volfile = fs.open(lv.lv_path, "w");
+               let ret = lvm_dd(fs.stdin, volfile, vol_size);
+               volfile.close();
+               if (ret < 0) {
+                       printf("more %d bytes data than given size!\n", -ret);
+               }
 
-       function lvm_remove(vol_name) {
-               if (!vol_name || !vg_name)
-                       return 22;
+               if (ret > 0) {
+                       printf("reading finished %d bytes before given size!\n", ret);
+               }
 
-               let res = lvs(vg_name, vol_name);
-               if (!res[0])
-                       return 2;
+               uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "ro");
 
-               if (res[0].lv_active)
-                       return 16;
+               let ret = lvm("lvchange", "-a", "n", lv.lv_full_name);
+               if (ret.retval != 0)
+                       return ret.retval;
 
-               let ret = lvm("lvremove", "-y", res[0].lv_full_name);
+               let ret = lvm("lvchange", "-p", "r", lv.lv_full_name);
                if (ret.retval != 0)
                        return ret.retval;
 
-               uvol_uci_remove(vol_name);
-               uvol_uci_commit(vol_name);
-               return 0;
-       }
+               let ret = lvm("lvrename", vg_name, sprintf("wo_%s", vol_name), sprintf("ro_%s", vol_name));
+               if (ret.retval != 0)
+                       return ret.retval;
 
-       function lvm_dd(in_fd, out_fd, vol_size) {
-               let rem = vol_size;
-               let buf;
-               while ((buf = in_fd.read(vg.vg_extent_size)) && (rem > 0)) {
-                       rem -= length(buf);
-                       if (rem < 0) {
-                               buf = substr(buf, 0, rem);
-                       }
-                       out_fd.write(buf);
-               }
-               return rem;
+       } else {
+               return 22;
        }
-
-       function lvm_write(vol_name, vol_size) {
-               if (!vol_name || !vg_name)
-                       return 22;
-
-               let lv = lvs(vg_name, vol_name);
-               if (!lv[0] || !lv[0].lv_full_name)
-                       return 2;
-
-               lv = lv[0];
-               vol_size = +vol_size;
-               if (vol_size > lv.lv_size)
-                       return 27;
-
-               if (wildcard(lv.lv_path, "/dev/*/wo_*")) {
-                       let ret = lvm("lvchange", "-p", "rw", lv.lv_full_name);
-                       if (ret.retval != 0)
-                               return ret.retval;
-
-                       let ret = lvm("lvchange", "-a", "y", lv.lv_full_name);
-                       if (ret.retval != 0)
-                               return ret.retval;
-
-                       let volfile = fs.open(lv.lv_path, "w");
-                       let ret = lvm_dd(fs.stdin, volfile, vol_size);
-                       volfile.close();
-                       if (ret < 0) {
-                               printf("more %d bytes data than given size!\n", -ret);
-                       }
-
-                       if (ret > 0) {
-                               printf("reading finished %d bytes before given size!\n", ret);
-                       }
-
-                       uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "ro");
-
-                       let ret = lvm("lvchange", "-a", "n", lv.lv_full_name);
-                       if (ret.retval != 0)
-                               return ret.retval;
-
-                       let ret = lvm("lvchange", "-p", "r", lv.lv_full_name);
-                       if (ret.retval != 0)
-                               return ret.retval;
-
-                       let ret = lvm("lvrename", vg_name, sprintf("wo_%s", vol_name), sprintf("ro_%s", vol_name));
-                       if (ret.retval != 0)
-                               return ret.retval;
-
-               } else {
-                       return 22;
-               }
-               return 0;
+       return 0;
+}
+
+function lvm_detect() {
+       let temp_up = [];
+       let inactive_lv = lvs(vg_name, null, "lv_skip_activation!=0");
+       for (let lv in inactive_lv) {
+               lvm("lvchange", "-k", "n", lv.lv_full_name);
+               lvm("lvchange", "-a", "y", lv.lv_full_name);
+               push(temp_up, lv.lv_full_name);
        }
-
-       function lvm_detect() {
-               let temp_up = [];
-               let inactive_lv = lvs(vg_name, null, "lv_skip_activation!=0");
-               for (let lv in inactive_lv) {
-                       lvm("lvchange", "-k", "n", lv.lv_full_name);
-                       lvm("lvchange", "-a", "y", lv.lv_full_name);
-                       push(temp_up, lv.lv_full_name);
-               }
-               sleep(1000);
-               uvol_uci_init();
-               for (let lv in lvs(vg_name)) {
-                       let vol_name = substr(lv.lv_name, 3);
-                       let vol_mode = substr(lv.lv_name, 0, 2);
-                       uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), vol_mode);
-               }
-               uvol_uci_commit();
-               for (let lv_full_name in temp_up) {
-                       lvm("lvchange", "-a", "n", lv_full_name);
-                       lvm("lvchange", "-k", "y", lv_full_name);
-               }
-               return 0;
+       sleep(1000);
+       uvol_uci_init();
+       for (let lv in lvs(vg_name)) {
+               let vol_name = substr(lv.lv_name, 3);
+               let vol_mode = substr(lv.lv_name, 0, 2);
+               uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), vol_mode);
        }
-
-       function lvm_boot() {
-               return 0;
+       uvol_uci_commit();
+       for (let lv_full_name in temp_up) {
+               lvm("lvchange", "-a", "n", lv_full_name);
+               lvm("lvchange", "-k", "y", lv_full_name);
        }
-
-       backend.backend = "LVM";
-       backend.priority = 50;
-       backend.init = lvm_init;
-       backend.boot = lvm_boot;
-       backend.detect = lvm_detect;
-       backend.free = lvm_free;
-       backend.align = lvm_align;
-       backend.total = lvm_total;
-       backend.list = lvm_list;
-       backend.size = lvm_size;
-       backend.status = lvm_status;
-       backend.device = lvm_device;
-       backend.up = lvm_up;
-       backend.down = lvm_down;
-       backend.create = lvm_create;
-       backend.remove = lvm_remove;
-       backend.write = lvm_write;
-%}
+       return 0;
+}
+
+function lvm_boot() {
+       return 0;
+}
+
+backend.backend = "LVM";
+backend.priority = 50;
+backend.init = lvm_init;
+backend.boot = lvm_boot;
+backend.detect = lvm_detect;
+backend.free = lvm_free;
+backend.align = lvm_align;
+backend.total = lvm_total;
+backend.list = lvm_list;
+backend.size = lvm_size;
+backend.status = lvm_status;
+backend.device = lvm_device;
+backend.up = lvm_up;
+backend.down = lvm_down;
+backend.create = lvm_create;
+backend.remove = lvm_remove;
+backend.write = lvm_write;
index 6f1cfbcd75da4781cffafa7e71bbc2238c17c8b7..7d0872b1698aba3697e150ecf5c2c67e349ffcf4 100644 (file)
-{%
 // SPDX-License-Identifier: GPL-2.0-or-later
 // UBI backend for uvol
 //  (c) 2022 Daniel Golle <daniel@makrotopia.org>
 //
 // This plugin uses UBI on NAND flash as a storage backend for uvol.
 
-       function read_file(file) {
-               let fp = fs.open(file);
-               if (!fp)
-                       return null;
-
-               let var = rtrim(fp.read("all"));
-               fp.close();
-               return var;
-       }
-
-       function mkdtemp() {
-               math = require("math");
-               let r1 = math.rand();
-               let r2 = math.rand();
-               let randbytes = chr((r1 >> 24) & 0xff, (r1 >> 16) & 0xff, (r1 >> 8) & 0xff, r1 & 0xff,
-                                   (r2 >> 24) & 0xff, (r2 >> 16) & 0xff, (r2 >> 8) & 0xff, r2 & 0xff);
-
-               let randstr = replace(b64enc(randbytes), /[\/-_.=]/g, "");
-               let dirname = sprintf("/tmp/uvol-%s", randstr);
-               fs.mkdir(dirname, 0700);
-               return dirname;
-       }
-
-       function ubi_get_dev(vol_name) {
-               let wcstring = sprintf("uvol-[rw][owpd]-%s", vol_name);
-               for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
-                       let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
-                       if (wildcard(vol_ubiname, wcstring))
-                               return fs.basename(vol_dir);
-               }
+function read_file(file) {
+       let fp = fs.open(file);
+       if (!fp)
                return null;
-       }
 
-       function vol_get_mode(vol_dev, mode) {
-               let vol_name = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/name", ubidev, vol_dev));
-               return substr(vol_name, 5, 2);
+       let var = rtrim(fp.read("all"));
+       fp.close();
+       return var;
+}
+
+function mkdtemp() {
+       math = require("math");
+       let r1 = math.rand();
+       let r2 = math.rand();
+       let randbytes = chr((r1 >> 24) & 0xff, (r1 >> 16) & 0xff, (r1 >> 8) & 0xff, r1 & 0xff,
+                           (r2 >> 24) & 0xff, (r2 >> 16) & 0xff, (r2 >> 8) & 0xff, r2 & 0xff);
+
+       let randstr = replace(b64enc(randbytes), /[\/-_.=]/g, "");
+       let dirname = sprintf("/tmp/uvol-%s", randstr);
+       fs.mkdir(dirname, 0700);
+       return dirname;
+}
+
+function ubi_get_dev(vol_name) {
+       let wcstring = sprintf("uvol-[rw][owpd]-%s", vol_name);
+       for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
+               let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
+               if (wildcard(vol_ubiname, wcstring))
+                       return fs.basename(vol_dir);
        }
-
-       function mkubifs(vol_dev) {
-               let temp_mp = mkdtemp();
-               system(sprintf("mount -t ubifs /dev/%s %s", vol_dev, temp_mp));
-               system(sprintf("umount %s", temp_mp));
-               fs.rmdir(temp_mp);
+       return null;
+}
+
+function vol_get_mode(vol_dev, mode) {
+       let vol_name = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/name", ubidev, vol_dev));
+       return substr(vol_name, 5, 2);
+}
+
+function mkubifs(vol_dev) {
+       let temp_mp = mkdtemp();
+       system(sprintf("mount -t ubifs /dev/%s %s", vol_dev, temp_mp));
+       system(sprintf("umount %s", temp_mp));
+       fs.rmdir(temp_mp);
+       return 0;
+}
+
+function block_hotplug(action, devname) {
+       return system(sprintf("ACTION=%s DEVNAME=%s /sbin/block hotplug", action, devname));
+}
+
+function ubi_init(ctx) {
+       cursor = ctx.cursor;
+       fs = ctx.fs;
+
+       let ubiver = read_file("/sys/class/ubi/version");
+       if (ubiver != 1)
+               return false;
+
+       let ubidevpath = null;
+       for (ubidevpath in fs.glob("/sys/devices/virtual/ubi/*"))
+               break;
+
+       if (!ubidevpath)
+               return false;
+
+       ubidev = fs.basename(ubidevpath);
+       ebsize = read_file(sprintf("%s/eraseblock_size", ubidevpath));
+
+       uvol_uci_add = ctx.uci_add;
+       uvol_uci_commit = ctx.uci_commit;
+       uvol_uci_remove = ctx.uci_remove;
+       uvol_uci_init = ctx.uci_init;
+
+       return true;
+}
+
+function ubi_free() {
+       let availeb = read_file(sprintf("/sys/devices/virtual/ubi/%s/avail_eraseblocks", ubidev));
+       return sprintf("%d", availeb * ebsize);
+}
+
+function ubi_align() {
+       return sprintf("%d", ebsize);
+}
+
+function ubi_total() {
+       let totaleb = read_file(sprintf("/sys/devices/virtual/ubi/%s/total_eraseblocks", ubidev));
+       return sprintf("%d", totaleb * ebsize);
+}
+
+function ubi_status(vol_name) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
+
+       let vol_mode = vol_get_mode(vol_dev);
+       if (vol_mode == "wo") return 22;
+       if (vol_mode == "wp") return 16;
+       if (vol_mode == "wd") return 1;
+       if (vol_mode == "ro" &&
+           !fs.access(sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "r")) return 1;
+
+       return 0;
+}
+
+function ubi_size(vol_name) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
+
+       let vol_size = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/data_bytes", ubidev, vol_dev));
+       return sprintf("%d", vol_size);
+}
+
+function ubi_device(vol_name) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
+
+       let vol_mode = vol_get_mode(vol_dev);
+       if (vol_mode == "ro")
+               return sprintf("/dev/ubiblock%s", substr(vol_dev, 3));
+       else if (vol_mode == "rw")
+               return sprintf("/dev/%s", vol_dev);
+
+       return null;
+}
+
+function ubi_create(vol_name, vol_size, vol_mode) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (vol_dev)
+               return 17;
+
+       let mode;
+       if (vol_mode == "ro" || vol_mode == "wo")
+               mode = "wo";
+       else if (vol_mode == "rw")
+               mode = "wp";
+       else
+               return 22;
+
+       let vol_size = +vol_size;
+       if (vol_size <= 0)
+               return 22;
+       let ret = system(sprintf("ubimkvol /dev/%s -N \"uvol-%s-%s\" -s %d", ubidev, mode, vol_name, vol_size));
+       if (ret != 0)
+               return ret;
+
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
+
+       let ret = system(sprintf("ubiupdatevol -t /dev/%s", vol_dev));
+       if (ret != 0)
+               return ret;
+
+       if (mode != "wp")
                return 0;
-       }
 
-       function block_hotplug(action, devname) {
-               return system(sprintf("ACTION=%s DEVNAME=%s /sbin/block hotplug", action, devname));
-       }
+       let ret = mkubifs(vol_dev);
+       if (ret != 0)
+               return ret;
 
-       function ubi_init(ctx) {
-               cursor = ctx.cursor;
-               fs = ctx.fs;
+       uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw");
 
-               let ubiver = read_file("/sys/class/ubi/version");
-               if (ubiver != 1)
-                       return false;
+       let ret = system(sprintf("ubirename /dev/%s \"uvol-wp-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name));
+       if (ret != 0)
+               return ret;
 
-               let ubidevpath = null;
-               for (ubidevpath in fs.glob("/sys/devices/virtual/ubi/*"))
-                       break;
+       return 0;
+}
 
-               if (!ubidevpath)
-                       return false;
+function ubi_remove(vol_name) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
 
-               ubidev = fs.basename(ubidevpath);
-               ebsize = read_file(sprintf("%s/eraseblock_size", ubidevpath));
+       let vol_mode = vol_get_mode(vol_dev);
+       if (vol_mode == "rw" || vol_mode == "ro")
+               return 16;
 
-               uvol_uci_add = ctx.uci_add;
-               uvol_uci_commit = ctx.uci_commit;
-               uvol_uci_remove = ctx.uci_remove;
-               uvol_uci_init = ctx.uci_init;
+       let volnum = split(vol_dev, "_")[1];
 
-               return true;
-       }
-
-       function ubi_free() {
-               let availeb = read_file(sprintf("/sys/devices/virtual/ubi/%s/avail_eraseblocks", ubidev));
-               return sprintf("%d", availeb * ebsize);
-       }
-
-       function ubi_align() {
-               return sprintf("%d", ebsize);
-       }
+       let ret = system(sprintf("ubirmvol /dev/%s -n %d", ubidev, volnum));
+       if (ret != 0)
+               return ret;
 
-       function ubi_total() {
-               let totaleb = read_file(sprintf("/sys/devices/virtual/ubi/%s/total_eraseblocks", ubidev));
-               return sprintf("%d", totaleb * ebsize);
-       }
+       uvol_uci_remove(vol_name);
+       uvol_uci_commit(vol_name);
 
-       function ubi_status(vol_name) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
+       return 0;
+}
 
-               let vol_mode = vol_get_mode(vol_dev);
-               if (vol_mode == "wo") return 22;
-               if (vol_mode == "wp") return 16;
-               if (vol_mode == "wd") return 1;
-               if (vol_mode == "ro" &&
-                   !fs.access(sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "r")) return 1;
+function ubi_up(vol_name) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
 
+       let vol_mode = vol_get_mode(vol_dev);
+       if (vol_mode == "rw" || vol_mode == "ro")
                return 0;
-       }
-
-       function ubi_size(vol_name) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
-
-               let vol_size = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/data_bytes", ubidev, vol_dev));
-               return sprintf("%d", vol_size);
-       }
-
-       function ubi_device(vol_name) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
-
-               let vol_mode = vol_get_mode(vol_dev);
-               if (vol_mode == "ro")
-                       return sprintf("/dev/ubiblock%s", substr(vol_dev, 3));
-               else if (vol_mode == "rw")
-                       return sprintf("/dev/%s", vol_dev);
-
-               return null;
-       }
-
-       function ubi_create(vol_name, vol_size, vol_mode) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (vol_dev)
-                       return 17;
-
-               let mode;
-               if (vol_mode == "ro" || vol_mode == "wo")
-                       mode = "wo";
-               else if (vol_mode == "rw")
-                       mode = "wp";
-               else
-                       return 22;
-
-               let vol_size = +vol_size;
-               if (vol_size <= 0)
-                       return 22;
-               let ret = system(sprintf("ubimkvol /dev/%s -N \"uvol-%s-%s\" -s %d", ubidev, mode, vol_name, vol_size));
+       else if (vol_mode == "wo")
+               return 22;
+       else if (vol_mode == "wp")
+               return 16;
+
+       uvol_uci_commit(vol_name);
+       if (vol_mode == "rd") {
+               let ret = system(sprintf("ubirename /dev/%s \"uvol-rd-%s\" \"uvol-ro-%s\"", ubidev, vol_name, vol_name));
                if (ret != 0)
                        return ret;
 
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
-
-               let ret = system(sprintf("ubiupdatevol -t /dev/%s", vol_dev));
-               if (ret != 0)
-                       return ret;
-
-               if (mode != "wp")
-                       return 0;
-
-               let ret = mkubifs(vol_dev);
-               if (ret != 0)
-                       return ret;
-
-               uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw");
-
-               let ret = system(sprintf("ubirename /dev/%s \"uvol-wp-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name));
+               return system(sprintf("ubiblock --create /dev/%s", vol_dev));
+       } else if (vol_mode == "wd") {
+               let ret = system(sprintf("ubirename /dev/%s \"uvol-wd-%s\" \"uvol-rw-%s\"", ubidev, vol_name, vol_name));
                if (ret != 0)
                        return ret;
 
-               return 0;
+               return block_hotplug("add", vol_dev);
        }
+       return 0;
+}
 
-       function ubi_remove(vol_name) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
-
-               let vol_mode = vol_get_mode(vol_dev);
-               if (vol_mode == "rw" || vol_mode == "ro")
-                       return 16;
-
-               let volnum = split(vol_dev, "_")[1];
-
-               let ret = system(sprintf("ubirmvol /dev/%s -n %d", ubidev, volnum));
-               if (ret != 0)
-                       return ret;
-
-               uvol_uci_remove(vol_name);
-               uvol_uci_commit(vol_name);
+function ubi_down(vol_name) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
 
+       let vol_mode = vol_get_mode(vol_dev);
+       if (vol_mode == "rd" || vol_mode == "wd")
                return 0;
+       else if (vol_mode == "wo")
+               return 22;
+       else if (vol_mode == "wp")
+               return 16;
+       else if (vol_mode == "ro") {
+               system(sprintf("umount /dev/ubiblock%s 2>&1 >/dev/null", substr(vol_dev, 3)));
+               system(sprintf("ubiblock --remove /dev/%s", vol_dev));
+               let ret = system(sprintf("ubirename /dev/%s \"uvol-ro-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name));
+               return ret;
+       } else if (vol_mode == "rw") {
+               system(sprintf("umount /dev/%s 2>&1 >/dev/null", vol_dev));
+               let ret = system(sprintf("ubirename /dev/%s \"uvol-rw-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name));
+               block_hotplug("remove", vol_dev);
+               return ret;
        }
-
-       function ubi_up(vol_name) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
-
-               let vol_mode = vol_get_mode(vol_dev);
-               if (vol_mode == "rw" || vol_mode == "ro")
-                       return 0;
-               else if (vol_mode == "wo")
-                       return 22;
-               else if (vol_mode == "wp")
-                       return 16;
-
-               uvol_uci_commit(vol_name);
-               if (vol_mode == "rd") {
-                       let ret = system(sprintf("ubirename /dev/%s \"uvol-rd-%s\" \"uvol-ro-%s\"", ubidev, vol_name, vol_name));
-                       if (ret != 0)
-                               return ret;
-
-                       return system(sprintf("ubiblock --create /dev/%s", vol_dev));
-               } else if (vol_mode == "wd") {
-                       let ret = system(sprintf("ubirename /dev/%s \"uvol-wd-%s\" \"uvol-rw-%s\"", ubidev, vol_name, vol_name));
-                       if (ret != 0)
-                               return ret;
-
-                       return block_hotplug("add", vol_dev);
-               }
-               return 0;
-       }
-
-       function ubi_down(vol_name) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
-
-               let vol_mode = vol_get_mode(vol_dev);
-               if (vol_mode == "rd" || vol_mode == "wd")
-                       return 0;
-               else if (vol_mode == "wo")
-                       return 22;
-               else if (vol_mode == "wp")
-                       return 16;
-               else if (vol_mode == "ro") {
-                       system(sprintf("umount /dev/ubiblock%s 2>&1 >/dev/null", substr(vol_dev, 3)));
-                       system(sprintf("ubiblock --remove /dev/%s", vol_dev));
-                       let ret = system(sprintf("ubirename /dev/%s \"uvol-ro-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name));
-                       return ret;
-               } else if (vol_mode == "rw") {
-                       system(sprintf("umount /dev/%s 2>&1 >/dev/null", vol_dev));
-                       let ret = system(sprintf("ubirename /dev/%s \"uvol-rw-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name));
-                       block_hotplug("remove", vol_dev);
-                       return ret;
-               }
-               return 0;
-       }
-
-       function ubi_list(search_name) {
-               let volumes = [];
-               for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
-                       let vol = {};
-                       let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
-                       if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*"))
-                               continue;
-
-                       let vol_mode = substr(vol_ubiname, 5, 2);
-                       let vol_name = substr(vol_ubiname, 8);
-                       let vol_size = read_file(sprintf("%s/data_bytes", vol_dir));
-                       if (substr(vol_name, 0, 1) == ".")
-                               continue;
-
-                       vol.name = vol_name;
-                       vol.mode = vol_mode;
-                       vol.size = vol_size;
-                       push(volumes, vol);
-               }
-               return volumes;
+       return 0;
+}
+
+function ubi_list(search_name) {
+       let volumes = [];
+       for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
+               let vol = {};
+               let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
+               if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*"))
+                       continue;
+
+               let vol_mode = substr(vol_ubiname, 5, 2);
+               let vol_name = substr(vol_ubiname, 8);
+               let vol_size = read_file(sprintf("%s/data_bytes", vol_dir));
+               if (substr(vol_name, 0, 1) == ".")
+                       continue;
+
+               vol.name = vol_name;
+               vol.mode = vol_mode;
+               vol.size = vol_size;
+               push(volumes, vol);
        }
+       return volumes;
+}
 
-       function ubi_detect() {
-               let tmpdev = [];
-               for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
-                       let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
+function ubi_detect() {
+       let tmpdev = [];
+       for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
+               let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
 
-                       if (!wildcard(vol_ubiname, "uvol-r[od]-*"))
-                               continue;
+               if (!wildcard(vol_ubiname, "uvol-r[od]-*"))
+                       continue;
 
-                       let vol_name = substr(vol_ubiname, 8);
-                       let vol_mode = substr(vol_ubiname, 5, 2);
-                       let vol_dev = fs.basename(vol_dir);
+               let vol_name = substr(vol_ubiname, 8);
+               let vol_mode = substr(vol_ubiname, 5, 2);
+               let vol_dev = fs.basename(vol_dir);
 
-                       ret = system(sprintf("ubiblock --create /dev/%s", vol_dev));
-                       if (ret)
-                               continue;
-
-                       if (vol_mode == "rd")
-                               push(tmpdev, vol_dev);
-               }
-
-               uvol_uci_init();
-
-               for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
-                       let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
-                       if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*"))
-                               continue;
+               ret = system(sprintf("ubiblock --create /dev/%s", vol_dev));
+               if (ret)
+                       continue;
 
-                       let vol_dev = fs.basename(vol_dir);
-                       let vol_name = substr(vol_ubiname, 8);
-                       let vol_mode = substr(vol_ubiname, 5, 2);
+               if (vol_mode == "rd")
+                       push(tmpdev, vol_dev);
+       }
 
-                       if (vol_mode == "ro" || vol_mode == "rd")
-                               uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro");
-                       else if (vol_mode == "rw" || vol_mode == "wd")
-                               uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw");
-               }
+       uvol_uci_init();
 
-               uvol_uci_commit();
+       for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
+               let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
+               if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*"))
+                       continue;
 
-               for (vol_dev in tmpdev)
-                       system(sprintf("ubiblock --remove /dev/%s", vol_dev));
+               let vol_dev = fs.basename(vol_dir);
+               let vol_name = substr(vol_ubiname, 8);
+               let vol_mode = substr(vol_ubiname, 5, 2);
 
-               return 0;
+               if (vol_mode == "ro" || vol_mode == "rd")
+                       uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro");
+               else if (vol_mode == "rw" || vol_mode == "wd")
+                       uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw");
        }
 
-       function ubi_boot() {
-               for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
-                       let vol_dev = fs.basename(vol_dir);
-                       let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
-
-                       if (!wildcard(vol_ubiname, "uvol-ro-*"))
-                               continue;
-
-                       system(sprintf("ubiblock --create /dev/%s", vol_dev));
-               }
-       }
+       uvol_uci_commit();
 
-       function ubi_write(vol_name, write_size) {
-               let vol_dev = ubi_get_dev(vol_name);
-               if (!vol_dev)
-                       return 2;
+       for (vol_dev in tmpdev)
+               system(sprintf("ubiblock --remove /dev/%s", vol_dev));
 
-               write_size = +write_size;
-               if (write_size <= 0)
-                       return 22;
+       return 0;
+}
 
-               let vol_mode = vol_get_mode(vol_dev);
-               if (vol_mode != "wo")
-                       return 22;
+function ubi_boot() {
+       for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
+               let vol_dev = fs.basename(vol_dir);
+               let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
 
-               let ret = system(sprintf("ubiupdatevol -s %s /dev/%s -", write_size, vol_dev));
-               if (ret)
-                       return ret;
+               if (!wildcard(vol_ubiname, "uvol-ro-*"))
+                       continue;
 
                system(sprintf("ubiblock --create /dev/%s", vol_dev));
-               uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro");
-               system(sprintf("ubiblock --remove /dev/%s", vol_dev));
-               system(sprintf("ubirename /dev/%s \"uvol-wo-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name));
-
-               return 0;
        }
-
-       backend.backend = "UBI";
-       backend.priority = 20;
-       backend.init = ubi_init;
-       backend.boot = ubi_boot;
-       backend.detect = ubi_detect;
-       backend.free = ubi_free;
-       backend.align = ubi_align;
-       backend.total = ubi_total;
-       backend.list = ubi_list;
-       backend.size = ubi_size;
-       backend.status = ubi_status;
-       backend.device = ubi_device;
-       backend.up = ubi_up;
-       backend.down = ubi_down;
-       backend.create = ubi_create;
-       backend.remove = ubi_remove;
-       backend.write = ubi_write;
-%}
+}
+
+function ubi_write(vol_name, write_size) {
+       let vol_dev = ubi_get_dev(vol_name);
+       if (!vol_dev)
+               return 2;
+
+       write_size = +write_size;
+       if (write_size <= 0)
+               return 22;
+
+       let vol_mode = vol_get_mode(vol_dev);
+       if (vol_mode != "wo")
+               return 22;
+
+       let ret = system(sprintf("ubiupdatevol -s %s /dev/%s -", write_size, vol_dev));
+       if (ret)
+               return ret;
+
+       system(sprintf("ubiblock --create /dev/%s", vol_dev));
+       uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro");
+       system(sprintf("ubiblock --remove /dev/%s", vol_dev));
+       system(sprintf("ubirename /dev/%s \"uvol-wo-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name));
+
+       return 0;
+}
+
+backend.backend = "UBI";
+backend.priority = 20;
+backend.init = ubi_init;
+backend.boot = ubi_boot;
+backend.detect = ubi_detect;
+backend.free = ubi_free;
+backend.align = ubi_align;
+backend.total = ubi_total;
+backend.list = ubi_list;
+backend.size = ubi_size;
+backend.status = ubi_status;
+backend.device = ubi_device;
+backend.up = ubi_up;
+backend.down = ubi_down;
+backend.create = ubi_create;
+backend.remove = ubi_remove;
+backend.write = ubi_write;
index 24589ca4cbdba9683c3bf2b138a81b7646f74259..be3bae13639b5632d62d9d4dc3e2ca0353c37fb7 100644 (file)
@@ -1,4 +1,3 @@
-{%
 // SPDX-License-Identifier: GPL-2.0-or-later
 // UCI tools for uvol
 //  (c) 2022 Daniel Golle <daniel@makrotopia.org>
@@ -136,4 +135,3 @@ uvol_uci = {
                return 0;
        }
 };
-%}
index f89b96687e6b5aff71bfb75417a03bb43e45a31f..692606895f22f68a7b68903b436d817f7fd165c6 100644 (file)
@@ -1,13 +1,9 @@
 #!/usr/bin/ucode
-{%
 // SPDX-License-Identifier: GPL-2.0-or-later
 // uvol - storage volume manager for OpenWrt
 //  (c) 2022 Daniel Golle <daniel@makrotopia.org>
 
-       function help() {
-       %}
-uvol storage volume manager
-
+let help_output = "uvol storage volume manager
 syntax: uvol command ...
 
 commands:
@@ -29,102 +25,101 @@ commands:
                  1 - volume is not ready for use
                  2 - volume doesn'y exist
   write volname size           write to volume from stdin, size in bytes
-{%
+"
+
+function help() {
+       printf("%s", help_output);
+);
+
+let fs = require("fs");
+let uci = require("uci");
+let cursor = uci ? uci.cursor() : null;
+
+let ctx = {};
+ctx.cursor = cursor;
+ctx.fs = fs;
+include("/usr/lib/uvol/uci.uc");
+ctx.uci_add = uvol_uci.uvol_uci_add;
+ctx.uci_remove = uvol_uci.uvol_uci_remove;
+ctx.uci_commit = uvol_uci.uvol_uci_commit;
+ctx.uci_init = uvol_uci.uvol_uci_init;
+
+let backend = null;
+let tried_backends = [];
+for (plugin in fs.glob("/usr/lib/uvol/backends/*.uc")) {
+       let current_backend = {};
+       include(plugin, { backend: current_backend });
+       push(tried_backends, current_backend.backend);
+       if (type(backend) == "object" &&
+           type(backend.priority) == "int" &&
+           type(current_backend.priority) == "int" &&
+           backend.priority > current_backend.priority)
+               continue;
+       if (type(current_backend.init) == "function" &&
+           current_backend.init(ctx)) {
+               backend = current_backend;
+               break;
        }
+}
 
-       let fs = require("fs");
-       let uci = require("uci");
-       let cursor = uci ? uci.cursor() : null;
+if (!backend) {
+       printf("No backend available. (tried: %s)\n", join(" ", tried_backends));
+       printf("To setup devices with block storage install 'autopart'.\n");
+       exit(2);
+}
 
-       let ctx = {};
-       ctx.cursor = cursor;
-       ctx.fs = fs;
-       include("/usr/lib/uvol/uci.uc");
-       ctx.uci_add = uvol_uci.uvol_uci_add;
-       ctx.uci_remove = uvol_uci.uvol_uci_remove;
-       ctx.uci_commit = uvol_uci.uvol_uci_commit;
-       ctx.uci_init = uvol_uci.uvol_uci_init;
+let cmd = shift(ARGV);
 
-       let backend = null;
-       let tried_backends = [];
-       for (plugin in fs.glob("/usr/lib/uvol/backends/*.uc")) {
-               let current_backend = {};
-               include(plugin, { backend: current_backend });
-               push(tried_backends, current_backend.backend);
-               if (type(backend) == "object" &&
-                   type(backend.priority) == "int" &&
-                   type(current_backend.priority) == "int" &&
-                   backend.priority > current_backend.priority)
-                       continue;
+if (!cmd || cmd == "-h" || cmd == "help") {
+       help();
+       return cmd?0:22;
+}
 
-               if (type(current_backend.init) == "function" &&
-                   current_backend.init(ctx)) {
-                       backend = current_backend;
-                       break;
-               }
-       }
-
-       if (!backend) {
-               printf("No backend available. (tried: %s)\n", join(" ", tried_backends));
-               printf("To setup devices with block storage install 'autopart'.\n");
-               exit(2);
-       }
+if (!(cmd in keys(backend))) {
+       printf("command %s not found\n", cmd);
+       return 22;
+}
 
+let json_output = false;
+if (ARGV[0] == "-j") {
+       json_output = true;
        shift(ARGV);
-       shift(ARGV);
-       let cmd = shift(ARGV);
-
-       if (!cmd || cmd == "-h" || cmd == "help") {
-               help();
-               return cmd?0:22;
-       }
+}
 
-       if (!(cmd in keys(backend))) {
-               printf("command %s not found\n", cmd);
-               return 22;
-       }
-
-       let json_output = false;
-       if (ARGV[0] == "-j") {
-               json_output = true;
-               shift(ARGV);
-       }
-
-       let legacy_output = function(var) {
-               let out = "";
-               if (type(var) == "array") {
-                       for (let line in var) {
-                               out += join(" ", values(line));
-                               out += "\n";
-                       }
-               } else if (type(var) == "object") {
+let legacy_output = function(var) {
+       let out = "";
+       if (type(var) == "array") {
+               for (let line in var) {
                        out += join(" ", values(line));
                        out += "\n";
                }
-               return out;
-       };
-
-       if (type(backend[cmd]) == "string") {
-               printf("%s\n", backend[cmd]);
-       } else if (type(backend[cmd]) == "function") {
-               let ret = backend[cmd](...ARGV);
-               if (type(ret) == "int")
-                       exit(ret);
-
-               if (type(ret) == "string") {
-                       printf("%s\n", ret);
-               } else {
-                       if (json_output)
-                               printf("%.J\n", ret);
-                       else
-                               printf("%s", legacy_output(ret));
-               }
+       } else if (type(var) == "object") {
+               out += join(" ", values(line));
+               out += "\n";
+       }
+       return out;
+};
+
+if (type(backend[cmd]) == "string") {
+       printf("%s\n", backend[cmd]);
+} else if (type(backend[cmd]) == "function") {
+       let ret = backend[cmd](...ARGV);
+       if (type(ret) == "int")
+               exit(ret);
+
+       if (type(ret) == "string") {
+               printf("%s\n", ret);
        } else {
                if (json_output)
-                       printf("%.J\n", backend[cmd]);
+                       printf("%.J\n", ret);
                else
-                       printf("%s\n", legacy_output(backend[cmd]));
+                       printf("%s", legacy_output(ret));
        }
-
-       return 0;
-%}
+} else {
+       if (json_output)
+               printf("%.J\n", backend[cmd]);
+       else
+               printf("%s\n", legacy_output(backend[cmd]));
+}
+
+exit(0);
git clone https://git.99rst.org/PROJECT