mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-13 20:08:05 +08:00
🐶 Sync 2026-11-08 23:51:11
This commit is contained in:
1 parent
5a5196e2d6
commit
534c8d6ab2
73 files changed
+12872
-2580
No files matched your search
@@ -136,6 +136,30 @@ function findStorageSize(procmtd, procpart, procmounts) {
|
||||
}
|
||||
|
||||
|
||||
function loadEmmcPartitions() {
|
||||
const devices = Object.create(null);
|
||||
|
||||
return L.resolveDefault(fs.list('/sys/class/block'), []).then(entries =>
|
||||
Promise.all(entries.filter(entry => /^mmcblk\d+(?:p\d+|boot[01])$/.test(entry.name)).map(async entry => {
|
||||
const name = entry.name;
|
||||
const disk = name.match(/^(mmcblk\d+)/)[1];
|
||||
devices[disk] ??= L.resolveDefault(fs.trimmed(`/sys/class/block/${disk}/device/type`), '');
|
||||
if (await devices[disk] != 'MMC')
|
||||
return null;
|
||||
|
||||
const [ uevent, sectors ] = await Promise.all([
|
||||
L.resolveDefault(fs.read(`/sys/class/block/${name}/uevent`), ''),
|
||||
L.resolveDefault(fs.trimmed(`/sys/class/block/${name}/size`), '0')
|
||||
]);
|
||||
const size = +sectors * 512;
|
||||
if (!Number.isSafeInteger(size) || size <= 0)
|
||||
return null;
|
||||
|
||||
return { device: name, name: uevent.match(/^PARTNAME=(.+)$/m)?.[1] || name, size };
|
||||
}))
|
||||
).then(partitions => partitions.filter(Boolean).sort((a, b) => L.naturalCompare(a.device, b.device)));
|
||||
}
|
||||
|
||||
const mapdata = { actions: {}, config: {} };
|
||||
|
||||
return view.extend({
|
||||
@@ -145,7 +169,8 @@ return view.extend({
|
||||
fs.trimmed('/proc/sys/kernel/hostname'),
|
||||
fs.trimmed('/proc/mtd'),
|
||||
fs.trimmed('/proc/partitions'),
|
||||
fs.trimmed('/proc/mounts')
|
||||
fs.trimmed('/proc/mounts'),
|
||||
loadEmmcPartitions()
|
||||
];
|
||||
|
||||
return Promise.all(tasks);
|
||||
@@ -243,18 +268,19 @@ return view.extend({
|
||||
.finally(function() { btn.firstChild.data = _('Upload archive...') });
|
||||
},
|
||||
|
||||
handleBlock(hostname, ev) {
|
||||
const mtdblock = dom.parent(ev.target, '.cbi-section').querySelector('[data-name="mtdselect"] select');
|
||||
const mtdnumber = mtdblock.value;
|
||||
const mtdname = mtdblock.selectedOptions[0].text.replace(/([^a-zA-Z0-9]+)/g, '-');
|
||||
handleBlock(hostname, selector, ev) {
|
||||
const block = dom.parent(ev.target, '.cbi-section').querySelector('[data-name="%s"] select'.format(selector));
|
||||
const device = selector == 'mtdselect' ? 'mtdblock' + block.value : block.value;
|
||||
const name = block.selectedOptions[0].text.replace(/([^a-zA-Z0-9]+)/g, '-');
|
||||
const id = selector == 'mtdselect' ? 'mtd' + block.value : device;
|
||||
const form = E('form', {
|
||||
'method': 'post',
|
||||
'action': L.env.cgi_base + '/cgi-download',
|
||||
'enctype': 'application/x-www-form-urlencoded'
|
||||
}, [
|
||||
E('input', { 'type': 'hidden', 'name': 'sessionid', 'value': rpc.getSessionID() }),
|
||||
E('input', { 'type': 'hidden', 'name': 'path', 'value': '/dev/mtdblock%d'.format(mtdnumber) }),
|
||||
E('input', { 'type': 'hidden', 'name': 'filename', 'value': '%s.mtd%d.%s.bin'.format(hostname, mtdnumber, mtdname) })
|
||||
E('input', { 'type': 'hidden', 'name': 'path', 'value': '/dev/' + device }),
|
||||
E('input', { 'type': 'hidden', 'name': 'filename', 'value': '%s.%s.%s.bin'.format(hostname, id, name) })
|
||||
]);
|
||||
|
||||
ev.currentTarget.parentNode.appendChild(form);
|
||||
@@ -452,7 +478,7 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
render([p_fstat, hostname, procmtd, procpart, procmounts]) {
|
||||
render([p_fstat, hostname, procmtd, procpart, procmounts, emmcPartitions]) {
|
||||
const has_sysupgrade = (p_fstat.type == 'file');
|
||||
const has_rootfs_data = (procmtd.match(/"rootfs_data"/) != null) || (procmounts.match("overlayfs:/overlay / ") != null);
|
||||
const storage_size = findStorageSize(procmtd, procpart, procmounts);
|
||||
@@ -509,10 +535,24 @@ return view.extend({
|
||||
o = ss.option(form.Button, 'mtddownload', _('Download mtdblock'));
|
||||
o.inputstyle = 'action important';
|
||||
o.inputtitle = _('Save mtdblock');
|
||||
o.onclick = L.bind(this.handleBlock, this, hostname);
|
||||
o.onclick = L.bind(this.handleBlock, this, hostname, 'mtdselect');
|
||||
}
|
||||
|
||||
|
||||
if (emmcPartitions.length) {
|
||||
o = s.option(form.SectionValue, 'actions', form.NamedSection, 'actions', 'actions', _('Export eMMC partition'), _('Download the raw contents of the selected eMMC partition.'));
|
||||
ss = o.subsection;
|
||||
|
||||
o = ss.option(form.ListValue, 'emmcselect', _('Choose eMMC partition'));
|
||||
for (const partition of emmcPartitions)
|
||||
o.value(partition.device, '%s (%s, %1024.2mB)'.format(partition.name, partition.device, partition.size));
|
||||
|
||||
o = ss.option(form.Button, 'emmcdl', _('Download eMMC partition'));
|
||||
o.inputstyle = 'action important';
|
||||
o.inputtitle = _('Export partition');
|
||||
o.onclick = L.bind(this.handleBlock, this, hostname, 'emmcselect');
|
||||
}
|
||||
|
||||
o = s.option(form.SectionValue, 'actions', form.NamedSection, 'actions', 'actions', _('Flash new firmware image'),
|
||||
has_sysupgrade
|
||||
? _('Upload a sysupgrade-compatible image here to replace the running firmware.')
|
||||
|
||||
@@ -152,6 +152,12 @@
|
||||
"cgi-io": [ "backup", "download" ],
|
||||
"file": {
|
||||
"/dev/mtdblock[0-9]*": [ "read" ],
|
||||
"/dev/mmcblk[0-9]*p[0-9]*": [ "read" ],
|
||||
"/dev/mmcblk[0-9]*boot[01]": [ "read" ],
|
||||
"/sys/class/block": [ "list" ],
|
||||
"/sys/class/block/mmcblk[0-9]*/device/type": [ "read" ],
|
||||
"/sys/class/block/mmcblk[0-9]*/uevent": [ "read" ],
|
||||
"/sys/class/block/mmcblk[0-9]*/size": [ "read" ],
|
||||
"/etc/sysupgrade.conf": [ "read" ],
|
||||
"/lib/upgrade/platform.sh": [ "list" ],
|
||||
"/proc/[0-9]*/mounts": [ "read" ],
|
||||
@@ -162,7 +168,7 @@
|
||||
"/sbin/sysupgrade --list-backup": [ "exec" ]
|
||||
},
|
||||
"ubus": {
|
||||
"file": [ "exec", "read", "stat" ]
|
||||
"file": [ "exec", "list", "read", "stat" ]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
|
||||
Reference in new issue
Block a user