luci-mod-system: remplement fstab settings as client side view
authorJo-Philipp Wich <jo@mein.io>
Sat, 21 Sep 2019 16:36:31 +0000 (18:36 +0200)
committerJo-Philipp Wich <jo@mein.io>
Sat, 21 Sep 2019 16:36:31 +0000 (18:36 +0200)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js [new file with mode: 0644]
modules/luci-mod-system/luasrc/controller/admin/system.lua
modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua [deleted file]
modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua [deleted file]
modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua [deleted file]

index 32cb10596bafc3a9b0d0955347ca5a175943509c..af06d840d06f464f5a59e7f50ee050612d52a390 100644 (file)
                                "/*": [ "list" ],
                                "/etc/crontabs/root": [ "read" ],
                                "/etc/dropbear/authorized_keys": [ "read" ],
+                               "/etc/filesystems": [ "read" ],
                                "/etc/rc.local": [ "read" ],
+                               "/proc/filesystems": [ "read" ],
                                "/proc/sys/kernel/hostname": [ "read" ]
                        },
                        "ubus": {
                                "file": [ "list", "read", "stat" ],
                                "iwinfo": [ "assoclist", "freqlist", "txpowerlist", "countrylist" ],
-                               "luci": [ "getBoardJSON", "getDUIDHints", "getHostHints", "getIfaddrs", "getInitList", "getLocaltime", "getTimezones", "getDHCPLeases", "getLEDs", "getNetworkDevices", "getUSBDevices", "getWirelessDevices", "getSwconfigFeatures", "getSwconfigPortState" ],
+                               "luci": [ "getBoardJSON", "getDUIDHints", "getHostHints", "getIfaddrs", "getInitList", "getLocaltime", "getTimezones", "getDHCPLeases", "getLEDs", "getNetworkDevices", "getUSBDevices", "getWirelessDevices", "getSwconfigFeatures", "getSwconfigPortState", "getBlockDevices", "getMountPoints" ],
                                "network.device": [ "status" ],
                                "network.interface": [ "dump" ],
                                "network": [ "get_proto_handlers" ],
                                "/etc/crontabs/root": [ "write" ],
                                "/etc/dropbear/authorized_keys": [ "write" ],
                                "/etc/luci-uploads/*": [ "write" ],
-                               "/etc/rc.local": [ "write" ]
+                               "/etc/rc.local": [ "write" ],
+                               "/sbin/block": [ "exec" ]
                        },
                        "ubus": {
-                               "file": [ "write", "remove" ],
+                               "file": [ "write", "remove", "exec" ],
                                "iwinfo": [ "scan" ],
-                               "luci": [ "setInitAction", "setLocaltime", "setPassword" ],
+                               "luci": [ "setInitAction", "setLocaltime", "setPassword", "setBlockDetect", "setUmount" ],
                                "uci": [ "add", "apply", "confirm", "delete", "order", "set", "rename" ]
                        },
                        "uci": [ "*" ]
diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js
new file mode 100644 (file)
index 0000000..b9028b2
--- /dev/null
@@ -0,0 +1,428 @@
+'use strict';
+'require uci';
+'require rpc';
+'require form';
+
+var callBlockDevices, callMountPoints, callBlockDetect, callUmount,
+    callFileRead, callFileStat, callFileExec;
+
+callBlockDevices = rpc.declare({
+       object: 'luci',
+       method: 'getBlockDevices',
+       expect: { '': {} }
+});
+
+callMountPoints = rpc.declare({
+       object: 'luci',
+       method: 'getMountPoints',
+       expect: { result: [] }
+});
+
+callBlockDetect = rpc.declare({
+       object: 'luci',
+       method: 'setBlockDetect',
+       expect: { result: false }
+});
+
+callUmount = rpc.declare({
+       object: 'luci',
+       method: 'setUmount',
+       params: [ 'path' ],
+       expect: { result: false }
+});
+
+callFileRead = rpc.declare({
+       object: 'file',
+       method: 'read',
+       params: [ 'path' ],
+       expect: { data: '' },
+       filter: function(s) {
+               return (s || '').split(/\n/).filter(function(ln) {
+                       return ln.match(/\S/) && !ln.match(/^nodev\t/);
+               }).map(function(ln) {
+                       return ln.trim();
+               });
+       }
+});
+
+callFileStat = rpc.declare({
+       object: 'file',
+       method: 'stat',
+       params: [ 'path' ],
+       expect: { '': {} },
+       filter: function(st) {
+               return (L.isObject(st) && st.path != null);
+       }
+});
+
+callFileExec = rpc.declare({
+       object: 'file',
+       method: 'exec',
+       params: [ 'command', 'params' ],
+       expect: { code: 255 }
+});
+
+function device_textvalue(devices, section_id) {
+       var v = (uci.get('fstab', section_id, 'uuid') || '').toLowerCase(),
+           e = Object.keys(devices).filter(function(dev) { return (devices[dev].uuid || '-').toLowerCase() == v })[0];
+
+       if (v) {
+               this.section.devices[section_id] = devices[e];
+
+               if (e && devices[e].size)
+                       return E('span', 'UUID: %h (%s, %1024.2mB)'.format(v, devices[e].dev, devices[e].size));
+               else if (e)
+                       return E('span', 'UUID: %h (%s)'.format(v, devices[e].dev));
+               else
+                       return E('span', 'UUID: %h (<em>%s</em>)'.format(v, _('not present')));
+       }
+
+       v = uci.get('fstab', section_id, 'label');
+       e = Object.keys(devices).filter(function(dev) { return devices[dev].label == v })[0];
+
+       if (v) {
+               this.section.devices[section_id] = this.section.devices[section_id] || devices[e];
+
+               if (e && devices[e].size)
+                       return E('span', 'Label: %h (%s, %1024.2mB)'.format(v, devices[e].dev, devices[e].size));
+               else if (e)
+                       return E('span', 'Label: %h (%s)'.format(v, devices[e].dev));
+               else
+                       return E('span', 'Label: %h (<em>%s</em>)'.format(v, _('not present')));
+       }
+
+       v = uci.get('fstab', section_id, 'device');
+       e = Object.keys(devices).filter(function(dev) { return devices[dev].dev == v })[0];
+
+       if (v) {
+               this.section.devices[section_id] = this.section.devices[section_id] || devices[e];
+
+               if (e && devices[e].size)
+                       return E('span', '%h (%1024.2mB)'.format(v, devices[e].size));
+               else if (e)
+                       return E('span', '%h'.format(v));
+               else
+                       return E('span', '%h (<em>%s</em>)'.format(v, _('not present')));
+       }
+}
+
+return L.view.extend({
+       handleDetect: function(m, ev) {
+               return callBlockDetect()
+                       .then(L.bind(uci.unload, uci, 'fstab'))
+                       .then(L.bind(m.render, m));
+       },
+
+       handleMountAll: function(m, ev) {
+               return callFileExec('/sbin/block', ['mount'])
+                       .then(function(rc) {
+                               if (rc != 0)
+                                       L.ui.addNotification(null, E('p', _('The <em>block mount</em> command failed with code %d').format(rc)));
+                       })
+                       .then(L.bind(uci.unload, uci, 'fstab'))
+                       .then(L.bind(m.render, m));
+       },
+
+       handleUmount: function(m, path, ev) {
+               return callUmount(path)
+                       .then(L.bind(uci.unload, uci, 'fstab'))
+                       .then(L.bind(m.render, m));
+       },
+
+       load: function() {
+               return Promise.all([
+                       callBlockDevices(),
+                       callFileRead('/proc/filesystems'),
+                       callFileRead('/etc/filesystems'),
+                       callFileStat('/usr/sbin/e2fsck'),
+                       callFileStat('/usr/sbin/fsck.f2fs'),
+                       callFileStat('/usr/sbin/dosfsck'),
+                       callFileStat('/usr/bin/btrfsck')
+               ]);
+       },
+
+       render: function(results) {
+               var devices = results[0],
+                   procfs = results[1],
+                   etcfs = results[2],
+                   triggers = {},
+                   trigger, m, s, o;
+
+               var filesystems = procfs.concat(etcfs.filter(function(fs) {
+                       return procfs.indexOf(fs) < 0;
+               })).sort();
+
+               var fsck = {
+                       ext2: results[3],
+                       ext3: results[3],
+                       ext4: results[3],
+                       f2fs: results[4],
+                       vfat: results[5],
+                       btrfs: results[6]
+               };
+
+               m = new form.Map('fstab', _('Mount Points'));
+
+               s = m.section(form.TypedSection, 'global', _('Global Settings'));
+               s.addremove = false;
+               s.anonymous = true;
+
+               o = s.option(form.Button, '_detect', _('Generate Config'), _('Find all currently attached filesystems and swap and replace configuration with defaults based on what was detected'));
+               o.onclick = this.handleDetect.bind(this, m);
+               o.inputstyle = 'reload';
+
+               o = s.option(form.Button, '_mountall', _('Mount attached devices'), _('Attempt to enable configured mount points for attached devices'));
+               o.onclick = this.handleMountAll.bind(this, m);
+               o.inputstyle = 'reload';
+
+               o = s.option(form.Flag, 'anon_swap', _('Anonymous Swap'), _('Mount swap not specifically configured'));
+               o.default = o.disabled;
+               o.rmempty = false;
+
+               o = s.option(form.Flag, 'anon_mount', _('Anonymous Mount'), _('Mount filesystems not specifically configured'));
+               o.default = o.disabled;
+               o.rmempty = false;
+
+               o = s.option(form.Flag, 'auto_swap', _('Automount Swap'), _('Automatically mount swap on hotplug'));
+               o.default = o.enabled;
+               o.rmempty = false;
+
+               o = s.option(form.Flag, 'auto_mount', _('Automount Filesystem'), _('Automatically mount filesystems on hotplug'));
+               o.default = o.enabled;
+               o.rmempty = false;
+
+               o = s.option(form.Flag, 'check_fs', _('Check filesystems before mount'), _('Automatically check filesystem for errors before mounting'));
+               o.default = o.disabled;
+               o.rmempty = false;
+
+
+               // Mount status table
+               o = s.option(form.DummyValue, '_mtab');
+
+               o.load = function(section_id) {
+                       return callMountPoints().then(L.bind(function(mounts) {
+                               this.mounts = mounts;
+                       }, this));
+               };
+
+               o.render = L.bind(function(view, section_id) {
+                       var table = E('div', { 'class': 'table' }, [
+                               E('div', { 'class': 'tr table-titles' }, [
+                                       E('div', { 'class': 'th' }, _('Filesystem')),
+                                       E('div', { 'class': 'th' }, _('Mount Point')),
+                                       E('div', { 'class': 'th center' }, _('Available')),
+                                       E('div', { 'class': 'th center' }, _('Used')),
+                                       E('div', { 'class': 'th' }, _('Unmount'))
+                               ])
+                       ]);
+
+                       var rows = [];
+
+                       for (var i = 0; i < this.mounts.length; i++) {
+                               var used = this.mounts[i].size - this.mounts[i].free,
+                                   umount = true;
+
+                               if (/^\/(overlay|rom|tmp(?:\/.+)?|dev(?:\/.+)?|)$/.test(this.mounts[i].mount))
+                                       umount = false;
+
+                               rows.push([
+                                       this.mounts[i].device,
+                                       this.mounts[i].mount,
+                                       '%1024.2mB / %1024.2mB'.format(this.mounts[i].avail, this.mounts[i].size),
+                                       '%.2f%% (%1024.2mB)'.format(100 / this.mounts[i].size * used, used),
+                                       umount ? E('button', {
+                                               'class': 'btn cbi-button-remove',
+                                               'click': L.ui.createHandlerFn(view, 'handleUmount', m, this.mounts[i].mount)
+                                       }, [ _('Unmount') ]) : '-'
+                               ]);
+                       }
+
+                       cbi_update_table(table, rows, E('em', _('Unable to obtain mount information')));
+
+                       return E([], [ E('h3', _('Mounted file systems')), table ]);
+               }, o, this);
+
+
+               // Mounts
+               s = m.section(form.GridSection, 'mount', _('Mount Points'), _('Mount Points define at which point a memory device will be attached to the filesystem'));
+               s.modaltitle = _('Mount Points - Mount Entry');
+               s.anonymous = true;
+               s.addremove = true;
+               s.sortable  = true;
+               s.devices   = {};
+
+               s.renderHeaderRows = function(/* ... */) {
+                       var trEls = form.GridSection.prototype.renderHeaderRows.apply(this, arguments);
+                       return trEls.childNodes[0];
+               }
+
+               s.tab('general', _('General Settings'));
+               s.tab('advanced', _('Advanced Settings'));
+
+               o = s.taboption('general', form.Flag, 'enabled', _('Enabled'));
+               o.rmempty  = false;
+               o.editable = true;
+
+               o = s.taboption('general', form.DummyValue, '_device', _('Device'));
+               o.rawhtml   = true;
+               o.modalonly = false;
+               o.write = function() {};
+               o.remove = function() {};
+               o.textvalue = device_textvalue.bind(o, devices);
+
+               o = s.taboption('general', form.Value, 'uuid', _('UUID'), _('If specified, mount the device by its UUID instead of a fixed device node'));
+               o.modalonly = true;
+               o.value('', _('-- match by uuid --'));
+
+               var devs = Object.keys(devices).sort();
+               for (var i = 0; i < devs.length; i++) {
+                       var dev = devices[devs[i]];
+                       if (dev.uuid && dev.size)
+                               o.value(dev.uuid, '%s (%s, %1024.2mB)'.format(dev.uuid, dev.dev, dev.size));
+                       else if (dev.uuid)
+                               o.value(dev.uuid, '%s (%s)'.format(dev.uuid, dev.dev));
+               }
+
+               o = s.taboption('general', form.Value, 'label', _('Label'), _('If specified, mount the device by the partition label instead of a fixed device node'));
+               o.modalonly = true;
+               o.depends('uuid', '');
+               o.value('', _('-- match by label --'));
+
+               for (var i = 0; i < devs.length; i++) {
+                       var dev = devices[devs[i]];
+                       if (dev.label && dev.size)
+                               o.value(dev.label, '%s (%s, %1024.2mB)'.format(dev.label, dev.dev, dev.size));
+                       else if (dev.label)
+                               o.value(dev.label, '%s (%s)'.format(dev.label, dev.dev));
+               }
+
+               o = s.taboption('general', form.Value, 'device', _('Device'), _('The device file of the memory or partition (<abbr title="for example">e.g.</abbr> <code>/dev/sda1</code>)'));
+               o.modalonly = true;
+               o.depends({ uuid: '', label: '' });
+
+               for (var i = 0; i < devs.length; i++) {
+                       var dev = devices[devs[i]];
+                       if (dev.size)
+                               o.value(dev.dev, '%s (%1024.2mB)'.format(dev.dev, dev.size));
+                       else
+                               o.value(dev.dev);
+               }
+
+               o = s.taboption('general', form.Value, 'target', _('Mount point'), _('Specifies the directory the device is attached to'));
+               o.value('/', _('Use as root filesystem (/)'));
+               o.value('/overlay', _('Use as external overlay (/overlay)'));
+               o.rmempty = false;
+
+               o = s.taboption('general', form.DummyValue, '__notice', _('Root preparation'));
+               o.depends('target', '/');
+               o.modalonly = true;
+               o.rawhtml = true;
+               o.default = '' +
+                       '<p>%s</p>'.format(_('Make sure to clone the root filesystem using something like the commands below:')) +
+                       '<pre>' +
+                               'mkdir -p /tmp/introot\n' +
+                               'mkdir -p /tmp/extroot\n' +
+                               'mount --bind / /tmp/introot\n' +
+                               'mount /dev/sda1 /tmp/extroot\n' +
+                               'tar -C /tmp/introot -cvf - . | tar -C /tmp/extroot -xf -\n' +
+                               'umount /tmp/introot\n' +
+                               'umount /tmp/extroot\n' +
+                       '</pre>'
+               ;
+
+               o = s.taboption('advanced', form.ListValue, 'fstype', _('Filesystem'));
+
+               o.textvalue = function(section_id) {
+                       var dev = this.section.devices[section_id],
+                           text = this.cfgvalue(section_id) || 'auto';
+
+                       if (dev && dev.type && dev.type != text)
+                               text += ' (%s)'.format(dev.type);
+
+                       return text;
+               };
+
+               o.value('', 'auto');
+
+               for (var i = 0; i < filesystems.length; i++)
+                       o.value(filesystems[i]);
+
+               o = s.taboption('advanced', form.Value, 'options', _('Mount options'), _('See "mount" manpage for details'));
+               o.textvalue = function(section_id) { return this.cfgvalue(section_id) || 'defaults' };
+               o.placeholder = 'defaults';
+
+               s.taboption('advanced', form.Flag, 'enabled_fsck', _('Run filesystem check'), _('Run a filesystem check before mounting the device'));
+
+
+               // Swaps
+               s = m.section(form.GridSection, 'swap', _('SWAP'), _('If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable <abbr title="Random Access Memory">RAM</abbr>. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the <abbr title="Random Access Memory">RAM</abbr>.'));
+               s.modaltitle = _('Mount Points - Swap Entry');
+               s.anonymous = true;
+               s.addremove = true;
+               s.sortable  = true;
+               s.devices   = {};
+
+               s.renderHeaderRows = function(/* ... */) {
+                       var trEls = form.GridSection.prototype.renderHeaderRows.apply(this, arguments);
+                       trEls.childNodes[0].childNodes[1].style.width = '90%';
+                       return trEls.childNodes[0];
+               }
+
+               o = s.option(form.Flag, 'enabled', _('Enabled'));
+               o.rmempty  = false;
+               o.editable = true;
+
+               o = s.option(form.DummyValue, '_device', _('Device'));
+               o.modalonly = false;
+               o.textvalue = device_textvalue.bind(o, devices);
+
+               o = s.option(form.Value, 'uuid', _('UUID'), _('If specified, mount the device by its UUID instead of a fixed device node'));
+               o.modalonly = true;
+               o.value('', _('-- match by uuid --'));
+
+               var devs = Object.keys(devices).sort();
+               for (var i = 0; i < devs.length; i++) {
+                       var dev = devices[devs[i]];
+                       if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
+                               continue;
+
+                       if (dev.uuid && dev.size)
+                               o.value(dev.uuid, '%s (%s, %1024.2mB)'.format(dev.uuid, dev.dev, dev.size));
+                       else if (dev.uuid)
+                               o.value(dev.uuid, '%s (%s)'.format(dev.uuid, dev.dev));
+               }
+
+               o = s.option(form.Value, 'label', _('Label'), _('If specified, mount the device by the partition label instead of a fixed device node'));
+               o.modalonly = true;
+               o.depends('uuid', '');
+               o.value('', _('-- match by label --'));
+
+               for (var i = 0; i < devs.length; i++) {
+                       var dev = devices[devs[i]];
+                       if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
+                               continue;
+
+                       if (dev.label && dev.size)
+                               o.value(dev.label, '%s (%s, %1024.2mB)'.format(dev.label, dev.dev, dev.size));
+                       else if (dev.label)
+                               o.value(dev.label, '%s (%s)'.format(dev.label, dev.dev));
+               }
+
+               o = s.option(form.Value, 'device', _('Device'), _('The device file of the memory or partition (<abbr title="for example">e.g.</abbr> <code>/dev/sda1</code>)'));
+               o.modalonly = true;
+               o.depends({ uuid: '', label: '' });
+
+               for (var i = 0; i < devs.length; i++) {
+                       var dev = devices[devs[i]];
+                       if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
+                               continue;
+
+                       if (dev.size)
+                               o.value(dev.dev, '%s (%1024.2mB)'.format(dev.dev, dev.size));
+                       else
+                               o.value(dev.dev);
+               }
+
+               return m.render();
+       }
+});
index 0ce08d10bdf9d3bfc5a9c80477ecd41de5b93c1e..eaf1105dd61ee67b1deebc952ba510fa4433bdc8 100644 (file)
@@ -23,9 +23,7 @@ function index()
        entry({"admin", "system", "crontab"}, view("system/crontab"), _("Scheduled Tasks"), 46)
 
        if fs.access("/sbin/block") and fs.access("/etc/config/fstab") then
-               entry({"admin", "system", "fstab"}, cbi("admin_system/fstab"), _("Mount Points"), 50)
-               entry({"admin", "system", "fstab", "mount"}, cbi("admin_system/fstab/mount"), nil).leaf = true
-               entry({"admin", "system", "fstab", "swap"},  cbi("admin_system/fstab/swap"),  nil).leaf = true
+               entry({"admin", "system", "mounts"}, view("system/mounts"), _("Mount Points"), 50)
        end
 
        local nodes, number = fs.glob("/sys/class/leds/*")
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua
deleted file mode 100644 (file)
index 4a31146..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
--- Copyright 2008 Steven Barth <steven@midlink.org>
--- Licensed to the public under the Apache License 2.0.
-
-require("luci.tools.webadmin")
-
-local fs   = require "nixio.fs"
-local util = require "nixio.util"
-local tp   = require "luci.template.parser"
-
-local block = io.popen("block info", "r")
-local ln, dev, devices = nil, nil, {}
-
-repeat
-       ln = block:read("*l")
-       dev = ln and ln:match("^/dev/(.-):")
-
-       if dev then
-               local e, s, key, val = { }
-
-               for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
-                       e[key:lower()] = val
-                       devices[val] = e
-               end
-
-               s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev)))
-
-               e.dev  = "/dev/%s" % dev
-               e.size = s and math.floor(s / 2048)
-
-               devices[e.dev] = e
-       end
-until not ln
-
-block:close()
-
-m = Map("fstab", translate("Mount Points"))
-s = m:section(TypedSection, "global", translate("Global Settings"))
-s.addremove = false
-s.anonymous = true
-
-detect = s:option(Button, "block_detect", translate("Generate Config"), translate("Find all currently attached filesystems and swap and replace configuration with defaults based on what was detected"))
-detect.inputstyle = "reload"
-
-detect.write = function(self, section)
-       luci.sys.call("block detect >/etc/config/fstab")
-       luci.http.redirect(luci.dispatcher.build_url("admin/system", "fstab"))
-end
-
-o = s:option(Flag, "anon_swap", translate("Anonymous Swap"), translate("Mount swap not specifically configured"))
-o.default = o.disabled
-o.rmempty = false
-
-o = s:option(Flag, "anon_mount", translate("Anonymous Mount"), translate("Mount filesystems not specifically configured"))
-o.default = o.disabled
-o.rmempty = false
-
-o = s:option(Flag, "auto_swap", translate("Automount Swap"), translate("Automatically mount swap on hotplug"))
-o.default = o.enabled
-o.rmempty = false
-
-o = s:option(Flag, "auto_mount", translate("Automount Filesystem"), translate("Automatically mount filesystems on hotplug"))
-o.default = o.enabled
-o.rmempty = false
-
-o = s:option(Flag, "check_fs", translate("Check filesystems before mount"), translate("Automatically check filesystem for errors before mounting"))
-o.default = o.disabled
-o.rmempty = false
-
-local mounts = luci.sys.mounts()
-local non_system_mounts = {}
-for rawmount, val in pairs(mounts) do
-    if (string.find(val.mountpoint, "/tmp/.jail") == nil) then
-      repeat 
-          val.umount = false
-          if (val.mountpoint == "/") then
-              break
-          elseif (val.mountpoint == "/overlay") then
-              break
-          elseif (val.mountpoint == "/rom") then
-              break
-          elseif (val.mountpoint == "/tmp") then
-              break
-          elseif (val.mountpoint == "/tmp/shm") then
-              break
-          elseif (val.mountpoint == "/tmp/upgrade") then
-              break
-          elseif (val.mountpoint == "/dev") then
-              break
-          end
-          val.umount = true
-      until true
-      non_system_mounts[rawmount] = val       
-   end   
-end
-
-v = m:section(Table, non_system_mounts, translate("Mounted file systems"))
-
-fs = v:option(DummyValue, "fs", translate("Filesystem"))
-
-mp = v:option(DummyValue, "mountpoint", translate("Mount Point"))
-
-avail = v:option(DummyValue, "avail", translate("Available"))
-function avail.cfgvalue(self, section)
-       return luci.tools.webadmin.byte_format(
-               ( tonumber(mounts[section].available) or 0 ) * 1024
-       ) .. " / " .. luci.tools.webadmin.byte_format(
-               ( tonumber(mounts[section].blocks) or 0 ) * 1024
-       )
-end
-
-used = v:option(DummyValue, "used", translate("Used"))
-function used.cfgvalue(self, section)
-       return ( mounts[section].percent or "0%" ) .. " (" ..
-       luci.tools.webadmin.byte_format(
-               ( tonumber(mounts[section].used) or 0 ) * 1024
-       ) .. ")"
-end
-
-unmount = v:option(Button, "unmount", translate("Unmount"))
-function unmount.cfgvalue(self, section)
-       return non_system_mounts[section].umount
-end
-
-unmount.render = function(self, section, scope)
-       self.title = translate("Unmount")
-       self.inputstyle = "remove"
-       Button.render(self, section, scope)
-end
-
-unmount.write = function(self, section)
-       if non_system_mounts[section].umount then
-               luci.sys.call("/bin/umount '%s'" % luci.util.shellstartsqescape(non_system_mounts[section].mountpoint))
-               return luci.http.redirect(luci.dispatcher.build_url("admin/system", "fstab"))
-        end
-end
-
-mount = m:section(TypedSection, "mount", translate("Mount Points"), translate("Mount Points define at which point a memory device will be attached to the filesystem"))
-mount.anonymous = true
-mount.addremove = true
-mount.template = "cbi/tblsection"
-mount.extedit  = luci.dispatcher.build_url("admin/system/fstab/mount/%s")
-
-mount.create = function(...)
-       local sid = TypedSection.create(...)
-       if sid then
-               luci.http.redirect(mount.extedit % sid)
-               return
-       end
-end
-
-
-mount:option(Flag, "enabled", translate("Enabled")).rmempty = false
-
-dev = mount:option(DummyValue, "device", translate("Device"))
-dev.rawhtml = true
-dev.cfgvalue = function(self, section)
-       local v, e
-
-       v = m.uci:get("fstab", section, "uuid")
-       e = v and devices[v:lower()]
-       if v and e and e.size then
-               return "UUID: %s (%s, %d MB)" %{ tp.pcdata(v), e.dev, e.size }
-       elseif v and e then
-               return "UUID: %s (%s)" %{ tp.pcdata(v), e.dev }
-       elseif v then
-               return "UUID: %s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
-       end
-
-       v = m.uci:get("fstab", section, "label")
-       e = v and devices[v]
-       if v and e and e.size then
-               return "Label: %s (%s, %d MB)" %{ tp.pcdata(v), e.dev, e.size }
-       elseif v and e then
-               return "Label: %s (%s)" %{ tp.pcdata(v), e.dev }
-       elseif v then
-               return "Label: %s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
-       end
-
-       v = Value.cfgvalue(self, section) or "?"
-       e = v and devices[v]
-       if v and e and e.size then
-               return "%s (%d MB)" %{ tp.pcdata(v), e.size }
-       elseif v and e then
-               return tp.pcdata(v)
-       elseif v then
-               return "%s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
-       end
-end
-
-mp = mount:option(DummyValue, "target", translate("Mount Point"))
-mp.cfgvalue = function(self, section)
-       if m.uci:get("fstab", section, "is_rootfs") == "1" then
-               return "/overlay"
-       else
-               return Value.cfgvalue(self, section) or "?"
-       end
-end
-
-fs = mount:option(DummyValue, "fstype", translate("Filesystem"))
-fs.cfgvalue = function(self, section)
-       local v, e
-
-       v = m.uci:get("fstab", section, "uuid")
-       v = v and v:lower() or m.uci:get("fstab", section, "label")
-       v = v or m.uci:get("fstab", section, "device")
-
-       e = v and devices[v]
-
-       return e and e.type or m.uci:get("fstab", section, "fstype") or "?"
-end
-
-op = mount:option(DummyValue, "options", translate("Options"))
-op.cfgvalue = function(self, section)
-       return Value.cfgvalue(self, section) or "defaults"
-end
-
-rf = mount:option(DummyValue, "is_rootfs", translate("Root"))
-rf.cfgvalue = function(self, section)
-       local target = m.uci:get("fstab", section, "target")
-       if target == "/" then
-               return translate("yes")
-       elseif target == "/overlay" then
-               return translate("overlay")
-       else
-               return translate("no")
-       end
-end
-
-ck = mount:option(DummyValue, "enabled_fsck", translate("Check"))
-ck.cfgvalue = function(self, section)
-       return Value.cfgvalue(self, section) == "1"
-               and translate("yes") or translate("no")
-end
-
-
-swap = m:section(TypedSection, "swap", translate("SWAP"), translate("If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable <abbr title=\"Random Access Memory\">RAM</abbr>. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the <abbr title=\"Random Access Memory\">RAM</abbr>."))
-swap.anonymous = true
-swap.addremove = true
-swap.template = "cbi/tblsection"
-swap.extedit  = luci.dispatcher.build_url("admin/system/fstab/swap/%s")
-
-swap.create = function(...)
-       local sid = TypedSection.create(...)
-       if sid then
-               luci.http.redirect(swap.extedit % sid)
-               return
-       end
-end
-
-
-swap:option(Flag, "enabled", translate("Enabled")).rmempty = false
-
-dev = swap:option(DummyValue, "device", translate("Device"))
-dev.cfgvalue = function(self, section)
-       local v
-
-       v = m.uci:get("fstab", section, "uuid")
-       if v then return "UUID: %s" % v end
-
-       v = m.uci:get("fstab", section, "label")
-       if v then return "Label: %s" % v end
-
-       v = Value.cfgvalue(self, section) or "?"
-       e = v and devices[v]
-       if v and e and e.size then
-               return "%s (%s MB)" % {v, e.size}
-       else
-               return v
-       end
-end
-
-return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua
deleted file mode 100644 (file)
index f21a277..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
--- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local fs   = require "nixio.fs"
-local util = require "nixio.util"
-
-local has_fscheck = fs.access("/usr/sbin/e2fsck")
-
-local block = io.popen("block info", "r")
-local ln, dev, devices = nil, nil, {}
-
-repeat
-       ln = block:read("*l")
-       dev = ln and ln:match("^/dev/(.-):")
-
-       if dev then
-               local e, s, key, val = { }
-
-               for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
-                       e[key:lower()] = val
-               end
-
-               s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev)))
-
-               e.dev  = "/dev/%s" % dev
-               e.size = s and math.floor(s / 2048)
-
-               devices[#devices+1] = e
-       end
-until not ln
-
-block:close()
-
-
-m = Map("fstab", translate("Mount Points - Mount Entry"))
-m.redirect = luci.dispatcher.build_url("admin/system/fstab")
-
-if not arg[1] or m.uci:get("fstab", arg[1]) ~= "mount" then
-       luci.http.redirect(m.redirect)
-       return
-end
-
-
-
-mount = m:section(NamedSection, arg[1], "mount", translate("Mount Entry"))
-mount.anonymous = true
-mount.addremove = false
-
-mount:tab("general",  translate("General Settings"))
-mount:tab("advanced", translate("Advanced Settings"))
-
-
-mount:taboption("general", Flag, "enabled", translate("Enable this mount")).rmempty = false
-
-
-o = mount:taboption("general", Value, "uuid", translate("UUID"),
-       translate("If specified, mount the device by its UUID instead of a fixed device node"))
-
-o:value("", translate("-- match by uuid --"))
-
-for i, d in ipairs(devices) do
-       if d.uuid and d.size then
-               o:value(d.uuid, "%s (%s, %d MB)" %{ d.uuid, d.dev, d.size })
-       elseif d.uuid then
-               o:value(d.uuid, "%s (%s)" %{ d.uuid, d.dev })
-       end
-end
-
-
-o = mount:taboption("general", Value, "label", translate("Label"),
-       translate("If specified, mount the device by the partition label instead of a fixed device node"))
-
-o:value("", translate("-- match by label --"))
-
-o:depends("uuid", "")
-
-for i, d in ipairs(devices) do
-       if d.label and d.size then
-               o:value(d.label, "%s (%s, %d MB)" %{ d.label, d.dev, d.size })
-       elseif d.label then
-               o:value(d.label, "%s (%s)" %{ d.label, d.dev })
-       end
-end
-
-
-o = mount:taboption("general", Value, "device", translate("Device"),
-       translate("The device file of the memory or partition (<abbr title=\"for example\">e.g.</abbr> <code>/dev/sda1</code>)"))
-
-o:value("", translate("-- match by device --"))
-
-o:depends({ uuid = "", label = "" })
-
-for i, d in ipairs(devices) do
-       if d.size then
-               o:value(d.dev, "%s (%d MB)" %{ d.dev, d.size })
-       else
-               o:value(d.dev)
-       end
-end
-
-
-o = mount:taboption("general", Value, "target", translate("Mount point"),
-       translate("Specifies the directory the device is attached to"))
-
-o:value("/", translate("Use as root filesystem (/)"))
-o:value("/overlay", translate("Use as external overlay (/overlay)"))
-
-
-o = mount:taboption("general", DummyValue, "__notice", translate("Root preparation"))
-o:depends("target", "/")
-o.rawhtml = true
-o.default = [[
-<p>%s</p><pre>mkdir -p /tmp/introot
-mkdir -p /tmp/extroot
-mount --bind / /tmp/introot
-mount /dev/sda1 /tmp/extroot
-tar -C /tmp/introot -cvf - . | tar -C /tmp/extroot -xf -
-umount /tmp/introot
-umount /tmp/extroot</pre>
-]] %{
-       translate("Make sure to clone the root filesystem using something like the commands below:"),
-
-}
-
-
-o = mount:taboption("advanced", Value, "fstype", translate("Filesystem"),
-       translate("The filesystem that was used to format the memory (<abbr title=\"for example\">e.g.</abbr> <samp><abbr title=\"Third Extended Filesystem\">ext3</abbr></samp>)"))
-
-o:value("", "auto")
-
-local fs
-for fs in io.lines("/proc/filesystems") do
-       fs = fs:match("%S+")
-       if fs ~= "nodev" then
-               o:value(fs)
-       end
-end
-
-local ok, lines = pcall(io.lines, "/etc/filesystem")
-if ok then
-       local fs
-       for fs in lines do
-               o:value(fs)
-       end
-end
-
-o = mount:taboption("advanced", Value, "options", translate("Mount options"),
-       translate("See \"mount\" manpage for details"))
-
-o.placeholder = "defaults"
-
-
-if has_fscheck then
-       o = mount:taboption("advanced", Flag, "enabled_fsck", translate("Run filesystem check"),
-               translate("Run a filesystem check before mounting the device"))
-end
-
-return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua
deleted file mode 100644 (file)
index 82468d5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
--- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local fs   = require "nixio.fs"
-local util = require "nixio.util"
-
-local devices = {}
-util.consume((fs.glob("/dev/sd*")), devices)
-util.consume((fs.glob("/dev/hd*")), devices)
-util.consume((fs.glob("/dev/scd*")), devices)
-util.consume((fs.glob("/dev/mmc*")), devices)
-
-local size = {}
-for i, dev in ipairs(devices) do
-       local s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev:sub(6))))
-       size[dev] = s and math.floor(s / 2048)
-end
-
-
-m = Map("fstab", translate("Mount Points - Swap Entry"))
-m.redirect = luci.dispatcher.build_url("admin/system/fstab")
-
-if not arg[1] or m.uci:get("fstab", arg[1]) ~= "swap" then
-       luci.http.redirect(m.redirect)
-       return
-end
-
-
-mount = m:section(NamedSection, arg[1], "swap", translate("Swap Entry"))
-mount.anonymous = true
-mount.addremove = false
-
-mount:tab("general",  translate("General Settings"))
-mount:tab("advanced", translate("Advanced Settings"))
-
-
-mount:taboption("general", Flag, "enabled", translate("Enable this swap")).rmempty = false
-
-
-o = mount:taboption("general", Value, "device", translate("Device"),
-       translate("The device file of the memory or partition (<abbr title=\"for example\">e.g.</abbr> <code>/dev/sda1</code>)"))
-
-for i, d in ipairs(devices) do
-       o:value(d, size[d] and "%s (%s MB)" % {d, size[d]})
-end
-
-o = mount:taboption("advanced", Value, "uuid", translate("UUID"),
-       translate("If specified, mount the device by its UUID instead of a fixed device node"))
-
-o = mount:taboption("advanced", Value, "label", translate("Label"),
-       translate("If specified, mount the device by the partition label instead of a fixed device node"))
-
-
-return m