uvol: unbreak build and adapt to updated ucode
* 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 <daniel@makrotopia.org>
This commit is contained in:
parent
8324c1fe06
commit
22d202e3a5
6 changed files with 932 additions and 943 deletions
|
@ -67,7 +67,7 @@ define Package/autopart/install
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/uvol/install
|
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_BIN) ./files/uvol.init $(1)/etc/init.d/uvol
|
||||||
$(INSTALL_DATA) ./files/blockdev_common.uc $(1)/usr/lib/uvol/
|
$(INSTALL_DATA) ./files/blockdev_common.uc $(1)/usr/lib/uvol/
|
||||||
$(INSTALL_DATA) ./files/uci.uc $(1)/usr/lib/uvol/
|
$(INSTALL_DATA) ./files/uci.uc $(1)/usr/lib/uvol/
|
||||||
|
|
|
@ -1,64 +1,64 @@
|
||||||
{%
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// Helper functions used to identify the boot device
|
// 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
|
// adapted from /lib/functions.sh
|
||||||
let get_blockdevs = function() {
|
let cmdline_get_var = function(var) {
|
||||||
let devs = [];
|
let cmdline = fs.open("/proc/cmdline", "r");
|
||||||
for (let dev in fs.glob('/dev/*'))
|
let allargs = cmdline.read("all");
|
||||||
if (fs.stat(dev).type == "block")
|
cmdline.close();
|
||||||
push(devs, split(dev, '/')[-1]);
|
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
|
return devs;
|
||||||
let get_uevent_major_minor = function(file) {
|
};
|
||||||
let uevf = fs.open(file, "r");
|
|
||||||
if (!uevf)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
let r = {};
|
// adapted from /lib/upgrade/common.sh
|
||||||
let evl;
|
let get_uevent_major_minor = function(file) {
|
||||||
while ((evl = uevf.read("line"))) {
|
let uevf = fs.open(file, "r");
|
||||||
let ev = split(evl, '=');
|
if (!uevf)
|
||||||
if (ev[0] == "MAJOR")
|
return null;
|
||||||
r.major = +ev[1];
|
|
||||||
if (ev[0] == "MINOR")
|
|
||||||
r.minor = +ev[1];
|
|
||||||
}
|
|
||||||
uevf.close();
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
|
|
||||||
// adapted from /lib/upgrade/common.sh
|
let r = {};
|
||||||
let get_bootdev = function(void) {
|
let evl;
|
||||||
let rootpart = cmdline_get_var("root");
|
while ((evl = uevf.read("line"))) {
|
||||||
let uevent = null;
|
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]")) {
|
// adapted from /lib/upgrade/common.sh
|
||||||
let uuidarg = split(substr(rootpart, 9), '-')[0];
|
let get_bootdev = function(void) {
|
||||||
for (let bd in get_blockdevs()) {
|
let rootpart = cmdline_get_var("root");
|
||||||
let bdf = fs.open(sprintf("/dev/%s", bd), "r");
|
let uevent = null;
|
||||||
bdf.seek(440);
|
|
||||||
let bduuid = bdf.read(4);
|
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]")) {
|
||||||
bdf.close();
|
let uuidarg = split(substr(rootpart, 9), '-')[0];
|
||||||
if (uuidarg == sprintf("%x%x%x%x", ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0))) {
|
for (let bd in get_blockdevs()) {
|
||||||
uevent = sprintf("/sys/class/block/%s/uevent", bd);
|
let bdf = fs.open(sprintf("/dev/%s", bd), "r");
|
||||||
break;
|
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=*") ||
|
} else if (wildcard(rootpart, "PARTUUID=????????-????-????-????-??????????0?/PARTNROFF=*") ||
|
||||||
|
@ -72,52 +72,52 @@
|
||||||
if (!bduuid)
|
if (!bduuid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
let uuid = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
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, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0),
|
||||||
ord(bduuid, 5), ord(bduuid, 4),
|
ord(bduuid, 5), ord(bduuid, 4),
|
||||||
ord(bduuid, 7), ord(bduuid, 6),
|
ord(bduuid, 7), ord(bduuid, 6),
|
||||||
ord(bduuid, 8), ord(bduuid, 9),
|
ord(bduuid, 8), ord(bduuid, 9),
|
||||||
ord(bduuid, 10), ord(bduuid, 11), ord(bduuid, 12), ord(bduuid, 13), ord(bduuid, 14), ord(bduuid, 15));
|
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);
|
|
||||||
|
|
||||||
devid = hex(devid);
|
if (uuidarg == uuid) {
|
||||||
for (let bd in get_blockdevs()) {
|
uevent = sprintf("/sys/class/block/%s/uevent", bd);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
} 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);
|
||||||
|
|
||||||
blockdev_common = {};
|
devid = hex(devid);
|
||||||
blockdev_common.get_partition = get_partition;
|
for (let bd in get_blockdevs()) {
|
||||||
blockdev_common.get_bootdev = get_bootdev;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
{%
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// LVM2 backend for uvol
|
// LVM2 backend for uvol
|
||||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||||
|
@ -10,458 +9,457 @@
|
||||||
// By setting the UCI option 'vg_name' in the 'uvol' section in /etc/config/fstab
|
// 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.
|
// you may set an arbitrary LVM2 volume group to back uvol instad.
|
||||||
|
|
||||||
let lvm_exec = "/sbin/lvm";
|
let lvm_exec = "/sbin/lvm";
|
||||||
|
|
||||||
function lvm(cmd, ...args) {
|
function lvm(cmd, ...args) {
|
||||||
let lvm_json_cmds = [ "lvs", "pvs", "vgs" ];
|
let lvm_json_cmds = [ "lvs", "pvs", "vgs" ];
|
||||||
try {
|
try {
|
||||||
let json_param = "";
|
let json_param = "";
|
||||||
if (cmd in lvm_json_cmds)
|
if (cmd in lvm_json_cmds)
|
||||||
json_param = "--reportformat json --units b ";
|
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 stdout = fs.popen(sprintf("LVM_SUPPRESS_FD_WARNINGS=1 %s %s %s%s", lvm_exec, cmd, json_param, join(" ", args)));
|
||||||
let tmp;
|
let tmp;
|
||||||
if (stdout) {
|
if (stdout) {
|
||||||
tmp = stdout.read("all");
|
tmp = stdout.read("all");
|
||||||
let ret = {};
|
let ret = {};
|
||||||
ret.retval = stdout.close();
|
ret.retval = stdout.close();
|
||||||
if (json_param) {
|
if (json_param) {
|
||||||
let data = json(tmp);
|
let data = json(tmp);
|
||||||
if (data.report)
|
if (data.report)
|
||||||
ret.report = data.report[0];
|
ret.report = data.report[0];
|
||||||
} else {
|
|
||||||
ret.stdout = trim(tmp);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
} else {
|
} else {
|
||||||
printf("lvm cli command failed: %s\n", fs.error());
|
ret.stdout = trim(tmp);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
return ret;
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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_free() {
|
|
||||||
if (!vg || !vg.vg_free_count || !vg.vg_extent_size)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
return sprintf("%d", vg.vg_free_count * vg.vg_extent_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lvm_total() {
|
|
||||||
if (!vg || !vg.vg_extent_count || !vg.vg_extent_size)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
return sprintf("%d", vg.vg_extent_count * vg.vg_extent_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lvm_align() {
|
|
||||||
if (!vg || !vg.vg_extent_size)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
return sprintf("%d", 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vols;
|
|
||||||
}
|
|
||||||
|
|
||||||
function lvm_size(vol_name) {
|
|
||||||
if (!vol_name || !vg_name)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
let res = lvs(vg_name, vol_name);
|
|
||||||
if (!res[0])
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
return sprintf("%d", res[0].lv_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 mode = substr(res[0].lv_name, 0, 2);
|
|
||||||
if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 mode = substr(res[0].lv_name, 0, 2);
|
|
||||||
if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
|
|
||||||
return 22;
|
|
||||||
|
|
||||||
return getdev(res[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lvm_updown(vol_name, up) {
|
|
||||||
if (!vol_name || !vg_name)
|
|
||||||
return 22;
|
|
||||||
|
|
||||||
let res = lvs(vg_name, vol_name);
|
|
||||||
if (!res[0])
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
let lv = res[0];
|
|
||||||
if (!lv.lv_path)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (up && (wildcard(lv.lv_path, "/dev/*/wo_*") ||
|
|
||||||
wildcard(lv.lv_path, "/dev/*/wp_*")))
|
|
||||||
return 22;
|
|
||||||
|
|
||||||
if (up)
|
|
||||||
uvol_uci_commit(vol_name);
|
|
||||||
|
|
||||||
if (lv.lv_active == up)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!up) {
|
|
||||||
let devname = getdev(lv);
|
|
||||||
if (devname)
|
|
||||||
system(sprintf("umount /dev/%s", devname));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
return 22;
|
printf("lvm cli command failed: %s\n", fs.error());
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
printf("Failed to parse lvm cli output: %s\n%s\n", e, e.stacktrace[0].context);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
function pvs() {
|
||||||
if (ret.retval != 0 || lvmode == "r")
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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_free() {
|
||||||
|
if (!vg || !vg.vg_free_count || !vg.vg_extent_size)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return sprintf("%d", vg.vg_free_count * vg.vg_extent_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lvm_total() {
|
||||||
|
if (!vg || !vg.vg_extent_count || !vg.vg_extent_size)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return sprintf("%d", vg.vg_extent_count * vg.vg_extent_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lvm_align() {
|
||||||
|
if (!vg || !vg.vg_extent_size)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return sprintf("%d", 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vols;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lvm_size(vol_name) {
|
||||||
|
if (!vol_name || !vg_name)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
let res = lvs(vg_name, vol_name);
|
||||||
|
if (!res[0])
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return sprintf("%d", res[0].lv_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 mode = substr(res[0].lv_name, 0, 2);
|
||||||
|
if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 mode = substr(res[0].lv_name, 0, 2);
|
||||||
|
if ((mode != "ro" && mode != "rw") || !res[0].lv_active)
|
||||||
|
return 22;
|
||||||
|
|
||||||
|
return getdev(res[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lvm_updown(vol_name, up) {
|
||||||
|
if (!vol_name || !vg_name)
|
||||||
|
return 22;
|
||||||
|
|
||||||
|
let res = lvs(vg_name, vol_name);
|
||||||
|
if (!res[0])
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
let lv = res[0];
|
||||||
|
if (!lv.lv_path)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (up && (wildcard(lv.lv_path, "/dev/*/wo_*") ||
|
||||||
|
wildcard(lv.lv_path, "/dev/*/wp_*")))
|
||||||
|
return 22;
|
||||||
|
|
||||||
|
if (up)
|
||||||
|
uvol_uci_commit(vol_name);
|
||||||
|
|
||||||
|
if (lv.lv_active == up)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!up) {
|
||||||
|
let devname = getdev(lv);
|
||||||
|
if (devname)
|
||||||
|
system(sprintf("umount /dev/%s", devname));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
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);
|
let ret = lvm("lvchange", "-a", "y", lv.lv_full_name);
|
||||||
if (ret.retval != 0)
|
if (ret.retval != 0)
|
||||||
return ret.retval;
|
return ret.retval;
|
||||||
|
|
||||||
let use_f2fs = (lv.lv_size > (100 * 1024 * 1024));
|
let volfile = fs.open(lv.lv_path, "w");
|
||||||
if (use_f2fs) {
|
let ret = lvm_dd(fs.stdin, volfile, vol_size);
|
||||||
let mkfs_ret = system(sprintf("/usr/sbin/mkfs.f2fs -f -l \"%s\" \"%s\"", vol_name, lv.lv_path));
|
volfile.close();
|
||||||
if (mkfs_ret != 0 && mkfs_ret != 134) {
|
if (ret < 0) {
|
||||||
lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name);
|
printf("more %d bytes data than given size!\n", -ret);
|
||||||
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 > 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)
|
if (ret.retval != 0)
|
||||||
return ret.retval;
|
return ret.retval;
|
||||||
|
|
||||||
ret = lvm("lvrename", vg_name, sprintf("wp_%s", vol_name), sprintf("rw_%s", vol_name));
|
let ret = lvm("lvchange", "-p", "r", lv.lv_full_name);
|
||||||
if (ret.retval != 0)
|
if (ret.retval != 0)
|
||||||
return ret.retval;
|
return ret.retval;
|
||||||
|
|
||||||
return 0;
|
let ret = lvm("lvrename", vg_name, sprintf("wo_%s", vol_name), sprintf("ro_%s", vol_name));
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
if (ret.retval != 0)
|
||||||
return ret.retval;
|
return ret.retval;
|
||||||
|
|
||||||
uvol_uci_remove(vol_name);
|
} else {
|
||||||
uvol_uci_commit(vol_name);
|
return 22;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
function lvm_dd(in_fd, out_fd, vol_size) {
|
function lvm_detect() {
|
||||||
let rem = vol_size;
|
let temp_up = [];
|
||||||
let buf;
|
let inactive_lv = lvs(vg_name, null, "lv_skip_activation!=0");
|
||||||
while ((buf = in_fd.read(vg.vg_extent_size)) && (rem > 0)) {
|
for (let lv in inactive_lv) {
|
||||||
rem -= length(buf);
|
lvm("lvchange", "-k", "n", lv.lv_full_name);
|
||||||
if (rem < 0) {
|
lvm("lvchange", "-a", "y", lv.lv_full_name);
|
||||||
buf = substr(buf, 0, rem);
|
push(temp_up, lv.lv_full_name);
|
||||||
}
|
|
||||||
out_fd.write(buf);
|
|
||||||
}
|
|
||||||
return rem;
|
|
||||||
}
|
}
|
||||||
|
sleep(1000);
|
||||||
function lvm_write(vol_name, vol_size) {
|
uvol_uci_init();
|
||||||
if (!vol_name || !vg_name)
|
for (let lv in lvs(vg_name)) {
|
||||||
return 22;
|
let vol_name = substr(lv.lv_name, 3);
|
||||||
|
let vol_mode = substr(lv.lv_name, 0, 2);
|
||||||
let lv = lvs(vg_name, vol_name);
|
uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), vol_mode);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
uvol_uci_commit();
|
||||||
function lvm_detect() {
|
for (let lv_full_name in temp_up) {
|
||||||
let temp_up = [];
|
lvm("lvchange", "-a", "n", lv_full_name);
|
||||||
let inactive_lv = lvs(vg_name, null, "lv_skip_activation!=0");
|
lvm("lvchange", "-k", "y", lv_full_name);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
function lvm_boot() {
|
function lvm_boot() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
backend.backend = "LVM";
|
backend.backend = "LVM";
|
||||||
backend.priority = 50;
|
backend.priority = 50;
|
||||||
backend.init = lvm_init;
|
backend.init = lvm_init;
|
||||||
backend.boot = lvm_boot;
|
backend.boot = lvm_boot;
|
||||||
backend.detect = lvm_detect;
|
backend.detect = lvm_detect;
|
||||||
backend.free = lvm_free;
|
backend.free = lvm_free;
|
||||||
backend.align = lvm_align;
|
backend.align = lvm_align;
|
||||||
backend.total = lvm_total;
|
backend.total = lvm_total;
|
||||||
backend.list = lvm_list;
|
backend.list = lvm_list;
|
||||||
backend.size = lvm_size;
|
backend.size = lvm_size;
|
||||||
backend.status = lvm_status;
|
backend.status = lvm_status;
|
||||||
backend.device = lvm_device;
|
backend.device = lvm_device;
|
||||||
backend.up = lvm_up;
|
backend.up = lvm_up;
|
||||||
backend.down = lvm_down;
|
backend.down = lvm_down;
|
||||||
backend.create = lvm_create;
|
backend.create = lvm_create;
|
||||||
backend.remove = lvm_remove;
|
backend.remove = lvm_remove;
|
||||||
backend.write = lvm_write;
|
backend.write = lvm_write;
|
||||||
%}
|
|
||||||
|
|
|
@ -1,378 +1,376 @@
|
||||||
{%
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// UBI backend for uvol
|
// UBI backend for uvol
|
||||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||||
//
|
//
|
||||||
// This plugin uses UBI on NAND flash as a storage backend for uvol.
|
// This plugin uses UBI on NAND flash as a storage backend for uvol.
|
||||||
|
|
||||||
function read_file(file) {
|
function read_file(file) {
|
||||||
let fp = fs.open(file);
|
let fp = fs.open(file);
|
||||||
if (!fp)
|
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);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
function vol_get_mode(vol_dev, mode) {
|
let var = rtrim(fp.read("all"));
|
||||||
let vol_name = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/name", ubidev, vol_dev));
|
fp.close();
|
||||||
return substr(vol_name, 5, 2);
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkubifs(vol_dev) {
|
function mkdtemp() {
|
||||||
let temp_mp = mkdtemp();
|
math = require("math");
|
||||||
system(sprintf("mount -t ubifs /dev/%s %s", vol_dev, temp_mp));
|
let r1 = math.rand();
|
||||||
system(sprintf("umount %s", temp_mp));
|
let r2 = math.rand();
|
||||||
fs.rmdir(temp_mp);
|
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);
|
||||||
|
}
|
||||||
|
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;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
function block_hotplug(action, devname) {
|
let ret = mkubifs(vol_dev);
|
||||||
return system(sprintf("ACTION=%s DEVNAME=%s /sbin/block hotplug", action, devname));
|
if (ret != 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
function ubi_init(ctx) {
|
uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw");
|
||||||
cursor = ctx.cursor;
|
|
||||||
fs = ctx.fs;
|
|
||||||
|
|
||||||
let ubiver = read_file("/sys/class/ubi/version");
|
let ret = system(sprintf("ubirename /dev/%s \"uvol-wp-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name));
|
||||||
if (ubiver != 1)
|
if (ret != 0)
|
||||||
return false;
|
return ret;
|
||||||
|
|
||||||
let ubidevpath = null;
|
return 0;
|
||||||
for (ubidevpath in fs.glob("/sys/devices/virtual/ubi/*"))
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
if (!ubidevpath)
|
function ubi_remove(vol_name) {
|
||||||
return false;
|
let vol_dev = ubi_get_dev(vol_name);
|
||||||
|
if (!vol_dev)
|
||||||
|
return 2;
|
||||||
|
|
||||||
ubidev = fs.basename(ubidevpath);
|
let vol_mode = vol_get_mode(vol_dev);
|
||||||
ebsize = read_file(sprintf("%s/eraseblock_size", ubidevpath));
|
if (vol_mode == "rw" || vol_mode == "ro")
|
||||||
|
return 16;
|
||||||
|
|
||||||
uvol_uci_add = ctx.uci_add;
|
let volnum = split(vol_dev, "_")[1];
|
||||||
uvol_uci_commit = ctx.uci_commit;
|
|
||||||
uvol_uci_remove = ctx.uci_remove;
|
|
||||||
uvol_uci_init = ctx.uci_init;
|
|
||||||
|
|
||||||
return true;
|
let ret = system(sprintf("ubirmvol /dev/%s -n %d", ubidev, volnum));
|
||||||
}
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
function ubi_free() {
|
uvol_uci_remove(vol_name);
|
||||||
let availeb = read_file(sprintf("/sys/devices/virtual/ubi/%s/avail_eraseblocks", ubidev));
|
uvol_uci_commit(vol_name);
|
||||||
return sprintf("%d", availeb * ebsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ubi_align() {
|
return 0;
|
||||||
return sprintf("%d", ebsize);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function ubi_total() {
|
function ubi_up(vol_name) {
|
||||||
let totaleb = read_file(sprintf("/sys/devices/virtual/ubi/%s/total_eraseblocks", ubidev));
|
let vol_dev = ubi_get_dev(vol_name);
|
||||||
return sprintf("%d", totaleb * ebsize);
|
if (!vol_dev)
|
||||||
}
|
return 2;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
let vol_mode = vol_get_mode(vol_dev);
|
||||||
|
if (vol_mode == "rw" || vol_mode == "ro")
|
||||||
return 0;
|
return 0;
|
||||||
}
|
else if (vol_mode == "wo")
|
||||||
|
return 22;
|
||||||
|
else if (vol_mode == "wp")
|
||||||
|
return 16;
|
||||||
|
|
||||||
function ubi_size(vol_name) {
|
uvol_uci_commit(vol_name);
|
||||||
let vol_dev = ubi_get_dev(vol_name);
|
if (vol_mode == "rd") {
|
||||||
if (!vol_dev)
|
let ret = system(sprintf("ubirename /dev/%s \"uvol-rd-%s\" \"uvol-ro-%s\"", ubidev, vol_name, vol_name));
|
||||||
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)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
let vol_dev = ubi_get_dev(vol_name);
|
return system(sprintf("ubiblock --create /dev/%s", vol_dev));
|
||||||
if (!vol_dev)
|
} else if (vol_mode == "wd") {
|
||||||
return 2;
|
let ret = system(sprintf("ubirename /dev/%s \"uvol-wd-%s\" \"uvol-rw-%s\"", ubidev, vol_name, vol_name));
|
||||||
|
|
||||||
let ret = system(sprintf("ubiupdatevol -t /dev/%s", vol_dev));
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (mode != "wp")
|
return block_hotplug("add", vol_dev);
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
let ret = mkubifs(vol_dev);
|
function ubi_down(vol_name) {
|
||||||
if (ret != 0)
|
let vol_dev = ubi_get_dev(vol_name);
|
||||||
return ret;
|
if (!vol_dev)
|
||||||
|
return 2;
|
||||||
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));
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
|
let vol_mode = vol_get_mode(vol_dev);
|
||||||
|
if (vol_mode == "rd" || vol_mode == "wd")
|
||||||
return 0;
|
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_remove(vol_name) {
|
function ubi_list(search_name) {
|
||||||
let vol_dev = ubi_get_dev(vol_name);
|
let volumes = [];
|
||||||
if (!vol_dev)
|
for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
|
||||||
return 2;
|
let vol = {};
|
||||||
|
let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
|
||||||
|
if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*"))
|
||||||
|
continue;
|
||||||
|
|
||||||
let vol_mode = vol_get_mode(vol_dev);
|
let vol_mode = substr(vol_ubiname, 5, 2);
|
||||||
if (vol_mode == "rw" || vol_mode == "ro")
|
let vol_name = substr(vol_ubiname, 8);
|
||||||
return 16;
|
let vol_size = read_file(sprintf("%s/data_bytes", vol_dir));
|
||||||
|
if (substr(vol_name, 0, 1) == ".")
|
||||||
|
continue;
|
||||||
|
|
||||||
let volnum = split(vol_dev, "_")[1];
|
vol.name = vol_name;
|
||||||
|
vol.mode = vol_mode;
|
||||||
let ret = system(sprintf("ubirmvol /dev/%s -n %d", ubidev, volnum));
|
vol.size = vol_size;
|
||||||
if (ret != 0)
|
push(volumes, vol);
|
||||||
return ret;
|
|
||||||
|
|
||||||
uvol_uci_remove(vol_name);
|
|
||||||
uvol_uci_commit(vol_name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return volumes;
|
||||||
|
}
|
||||||
|
|
||||||
function ubi_up(vol_name) {
|
function ubi_detect() {
|
||||||
let vol_dev = ubi_get_dev(vol_name);
|
let tmpdev = [];
|
||||||
if (!vol_dev)
|
for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) {
|
||||||
return 2;
|
let vol_ubiname = read_file(sprintf("%s/name", vol_dir));
|
||||||
|
|
||||||
let vol_mode = vol_get_mode(vol_dev);
|
if (!wildcard(vol_ubiname, "uvol-r[od]-*"))
|
||||||
if (vol_mode == "rw" || vol_mode == "ro")
|
continue;
|
||||||
return 0;
|
|
||||||
else if (vol_mode == "wo")
|
|
||||||
return 22;
|
|
||||||
else if (vol_mode == "wp")
|
|
||||||
return 16;
|
|
||||||
|
|
||||||
uvol_uci_commit(vol_name);
|
let vol_name = substr(vol_ubiname, 8);
|
||||||
if (vol_mode == "rd") {
|
let vol_mode = substr(vol_ubiname, 5, 2);
|
||||||
let ret = system(sprintf("ubirename /dev/%s \"uvol-rd-%s\" \"uvol-ro-%s\"", ubidev, vol_name, vol_name));
|
let vol_dev = fs.basename(vol_dir);
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return system(sprintf("ubiblock --create /dev/%s", vol_dev));
|
ret = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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 == "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_commit();
|
|
||||||
|
|
||||||
for (vol_dev in tmpdev)
|
|
||||||
system(sprintf("ubiblock --remove /dev/%s", vol_dev));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
if (ret)
|
||||||
return 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;
|
||||||
|
|
||||||
|
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 == "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_commit();
|
||||||
|
|
||||||
|
for (vol_dev in tmpdev)
|
||||||
|
system(sprintf("ubiblock --remove /dev/%s", vol_dev));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
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";
|
function ubi_write(vol_name, write_size) {
|
||||||
backend.priority = 20;
|
let vol_dev = ubi_get_dev(vol_name);
|
||||||
backend.init = ubi_init;
|
if (!vol_dev)
|
||||||
backend.boot = ubi_boot;
|
return 2;
|
||||||
backend.detect = ubi_detect;
|
|
||||||
backend.free = ubi_free;
|
write_size = +write_size;
|
||||||
backend.align = ubi_align;
|
if (write_size <= 0)
|
||||||
backend.total = ubi_total;
|
return 22;
|
||||||
backend.list = ubi_list;
|
|
||||||
backend.size = ubi_size;
|
let vol_mode = vol_get_mode(vol_dev);
|
||||||
backend.status = ubi_status;
|
if (vol_mode != "wo")
|
||||||
backend.device = ubi_device;
|
return 22;
|
||||||
backend.up = ubi_up;
|
|
||||||
backend.down = ubi_down;
|
let ret = system(sprintf("ubiupdatevol -s %s /dev/%s -", write_size, vol_dev));
|
||||||
backend.create = ubi_create;
|
if (ret)
|
||||||
backend.remove = ubi_remove;
|
return ret;
|
||||||
backend.write = ubi_write;
|
|
||||||
%}
|
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;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
{%
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// UCI tools for uvol
|
// UCI tools for uvol
|
||||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||||
|
@ -136,4 +135,3 @@ uvol_uci = {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
%}
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
#!/usr/bin/ucode
|
#!/usr/bin/ucode
|
||||||
{%
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// uvol - storage volume manager for OpenWrt
|
// uvol - storage volume manager for OpenWrt
|
||||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||||
|
|
||||||
function help() {
|
let help_output = "uvol storage volume manager
|
||||||
%}
|
|
||||||
uvol storage volume manager
|
|
||||||
|
|
||||||
syntax: uvol command ...
|
syntax: uvol command ...
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
|
@ -29,102 +25,101 @@ commands:
|
||||||
1 - volume is not ready for use
|
1 - volume is not ready for use
|
||||||
2 - volume doesn'y exist
|
2 - volume doesn'y exist
|
||||||
write volname size write to volume from stdin, size in bytes
|
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");
|
if (!backend) {
|
||||||
let uci = require("uci");
|
printf("No backend available. (tried: %s)\n", join(" ", tried_backends));
|
||||||
let cursor = uci ? uci.cursor() : null;
|
printf("To setup devices with block storage install 'autopart'.\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
let ctx = {};
|
let cmd = shift(ARGV);
|
||||||
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;
|
if (!cmd || cmd == "-h" || cmd == "help") {
|
||||||
let tried_backends = [];
|
help();
|
||||||
for (plugin in fs.glob("/usr/lib/uvol/backends/*.uc")) {
|
return cmd?0:22;
|
||||||
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" &&
|
if (!(cmd in keys(backend))) {
|
||||||
current_backend.init(ctx)) {
|
printf("command %s not found\n", cmd);
|
||||||
backend = current_backend;
|
return 22;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let json_output = false;
|
||||||
|
if (ARGV[0] == "-j") {
|
||||||
|
json_output = true;
|
||||||
shift(ARGV);
|
shift(ARGV);
|
||||||
shift(ARGV);
|
}
|
||||||
let cmd = shift(ARGV);
|
|
||||||
|
|
||||||
if (!cmd || cmd == "-h" || cmd == "help") {
|
let legacy_output = function(var) {
|
||||||
help();
|
let out = "";
|
||||||
return cmd?0:22;
|
if (type(var) == "array") {
|
||||||
}
|
for (let line in var) {
|
||||||
|
|
||||||
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") {
|
|
||||||
out += join(" ", values(line));
|
out += join(" ", values(line));
|
||||||
out += "\n";
|
out += "\n";
|
||||||
}
|
}
|
||||||
return out;
|
} else if (type(var) == "object") {
|
||||||
};
|
out += join(" ", values(line));
|
||||||
|
out += "\n";
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
if (type(backend[cmd]) == "string") {
|
if (type(backend[cmd]) == "string") {
|
||||||
printf("%s\n", backend[cmd]);
|
printf("%s\n", backend[cmd]);
|
||||||
} else if (type(backend[cmd]) == "function") {
|
} else if (type(backend[cmd]) == "function") {
|
||||||
let ret = backend[cmd](...ARGV);
|
let ret = backend[cmd](...ARGV);
|
||||||
if (type(ret) == "int")
|
if (type(ret) == "int")
|
||||||
exit(ret);
|
exit(ret);
|
||||||
|
|
||||||
if (type(ret) == "string") {
|
if (type(ret) == "string") {
|
||||||
printf("%s\n", ret);
|
printf("%s\n", ret);
|
||||||
} else {
|
|
||||||
if (json_output)
|
|
||||||
printf("%.J\n", ret);
|
|
||||||
else
|
|
||||||
printf("%s", legacy_output(ret));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (json_output)
|
if (json_output)
|
||||||
printf("%.J\n", backend[cmd]);
|
printf("%.J\n", ret);
|
||||||
else
|
else
|
||||||
printf("%s\n", legacy_output(backend[cmd]));
|
printf("%s", legacy_output(ret));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (json_output)
|
||||||
|
printf("%.J\n", backend[cmd]);
|
||||||
|
else
|
||||||
|
printf("%s\n", legacy_output(backend[cmd]));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
exit(0);
|
||||||
%}
|
|
||||||
|
|
Loading…
Reference in a new issue