You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

130 lines
3.3 KiB

#!/usr/bin/ucode -R
// SPDX-License-Identifier: GPL-2.0-or-later
// uvol - storage volume manager for OpenWrt
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
let help_output = "uvol storage volume manager
syntax: uvol command ...
commands:
boot get active volumes ready (called on boot)
free show number of bytes available
total show total number of bytes
align show sector size in bytes
list [volname] list volumes
create volname size type create new volume
size: in bytes
type: 'ro' or 'rw'
remove volname delete volume
device volname show block device for mounting
size volname show size of volume
up volname get volume ready for mounting
down volname take volume down after unmounting
status volname return status of volume
return code: 0 - volume is ready for use
1 - volume is not ready for use
2 - volume doesn't exist
write volname size write to volume from stdin, size in bytes
";
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;
}
}
if (!backend) {
printf("No backend available. (tried: %s)\n", join(" ", tried_backends));
printf("To setup devices with block storage install 'autopart'.\n");
exit(2);
}
// The below code is needed as older versions of ucode pass the complete cmdline via ARGV
// Once we can rely in more recent ucode the while loop can be replaced by simply
// let cmd = shift(ARGV);
let skip = null;
let cmd = null;
let skip_argv = ["/usr/bin/ucode", "-R", "/usr/sbin/uvol"];
while (skip = shift(ARGV)) {
if (skip != shift(skip_argv)) {
cmd = skip;
break;
}
}
if (!cmd || cmd == "-h" || cmd == "help") {
printf("%s", help_output);
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") {
out += join(" ", values(var));
out += "\n";
} else if (type(var) == "string") {
out += var;
out += "\n";
}
return out;
};
if (type(backend[cmd]) == "function") {
let ret = backend[cmd](...ARGV);
if (type(ret) == "int") {
exit(ret);
} else {
if (json_output)
printf("%.J\n", ret);
else
printf("%s", legacy_output(ret));
}
} else {
if (json_output)
printf("%.J\n", backend[cmd]);
else
printf("%s\n", legacy_output(backend[cmd]));
}
exit(0);