// SPDX-License-Identifier: GPL-2.0-or-later // UCI tools for uvol // (c) 2022 Daniel Golle let uci_spooldir = "/var/spool/uvol"; let init_spooldir = function(void) { parentdir = fs.stat(fs.dirname(uci_spooldir)); if (!parentdir || parentdir.type != "directory") fs.mkdir(fs.dirname(uci_spooldir), 0755); fs.mkdir(uci_spooldir, 0700); }; uvol_uci = { uvol_uci_add: function(vol_name, dev_name, mode) { try { let autofs = false; let uuid; let target; if (mode == "ro") autofs = true; let uciname = replace(vol_name, /[-.]/g, "_"); uciname = replace(uciname, /!([:alnum:]_)/g, ""); let bdinfo_p = fs.popen("/sbin/block info"); let bdinfo_l; while (bdinfo_l = bdinfo_p.read("line")) { if (substr(bdinfo_l, 0, length(dev_name) + 1) != dev_name + ":") continue; let bdinfo_e = split(bdinfo_l, " "); shift(bdinfo_e); for (let bdinfo_a in bdinfo_e) { let bdinfo_v = split(bdinfo_a, "="); if (bdinfo_v[0] && bdinfo_v[0] == "UUID") { uuid = trim(bdinfo_v[1], "\""); break; } } break; } if (!uuid) return 22; if (uciname == "_meta") target = "/tmp/run/uvol/.meta"; else if (substr(uciname, 0, 1) == "_") return 1; else target = sprintf("/tmp/run/uvol/%s", vol_name); init_spooldir(); let remspool = sprintf("%s/remove-%s", uci_spooldir, uciname); if (fs.stat(remspool)) fs.unlink(remspool); let addobj = {}; addobj.name=uciname; addobj.uuid=uuid; addobj.target=target; addobj.options=mode; addobj.autofs=autofs; addobj.enabled=true; let spoolfile = fs.open(sprintf("%s/add-%s", uci_spooldir, uciname), "w"); spoolfile.write(addobj); spoolfile.close(); } catch(e) { printf("adding UCI section to spool failed"); return -1; } return 0; }, uvol_uci_remove: function(vol_name) { let uciname = replace(vol_name, /[-.]/g, "_"); uciname = replace(uciname, /!([:alnum:]_)/g, ""); let addspool = sprintf("%s/add-%s", uci_spooldir, uciname); if (fs.stat(addspool)) { fs.unlink(addspool); return 0; } init_spooldir(); let spoolfile = fs.open(sprintf("%s/remove-%s", uci_spooldir, uciname), "w"); spoolfile.write(uciname); spoolfile.close(); return 0; }, uvol_uci_commit: function(vol_name) { try { let uciname = null; if (vol_name) { uciname = replace(vol_name, /[-.]/g, "_"); uciname = replace(uciname, /!([:alnum:]_)/g, ""); } for (let file in fs.glob(sprintf("%s/*-%s", uci_spooldir, uciname?uciname:"*"))) { let action = split(fs.basename(file), "-")[0]; let spoolfd = fs.open(file, "r"); let spoolstr = spoolfd.read("all"); spoolfd.close(); fs.unlink(file); if (action == "remove") { cursor.delete("fstab", spoolstr); } else if (action == "add") { let spoolobj = json(spoolstr); cursor.set("fstab", spoolobj.name, "mount"); for (key in keys(spoolobj)) { if (key == "name") continue; cursor.set("fstab", spoolobj.name, key, spoolobj[key]); } } } cursor.commit(); } catch(e) { printf("committing UCI spool failed"); return -1; } return 0; }, uvol_uci_init: function () { cursor.load("fstab"); let f = cursor.get("fstab", "@uvol[0]", "initialized"); if (f == 1) return 0; cursor.add("fstab", "uvol"); cursor.set("fstab", "@uvol[-1]", "initialized", true); cursor.commit(); cursor.unload("fstab"); return 0; } };