gluon/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/upgrade.lua
David Bauer d0551c2dcd web-admin: fix firmware partition name
The rudimentary flash size determination function expects the partition
for the devices firmware to be called "linux" while it is (since quite
some time) "firmware".

Fix this error to display available flash size as well as more useful
error message in case the uploaded firmware image exceeds the flash
space.

Signed-off-by: David Bauer <mail@david-bauer.net>
2021-05-01 03:15:51 +02:00

142 lines
3.7 KiB
Lua

--[[
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
]]--
package 'gluon-web-admin'
local util = require 'gluon.util'
local unistd = require 'posix.unistd'
local file
local tmpfile = "/tmp/firmware.img"
local function filehandler(_, chunk, eof)
if not unistd.access(tmpfile) and not file and chunk and #chunk > 0 then
file = io.open(tmpfile, "w")
end
if file and chunk then
file:write(chunk)
end
if file and eof then
file:close()
end
end
local function action_upgrade(http, renderer)
local fcntl = require 'posix.fcntl'
local stat = require 'posix.sys.stat'
local function fork_exec(argv)
local pid = unistd.fork()
if pid > 0 then
return
elseif pid == 0 then
-- change to root dir
unistd.chdir('/')
-- patch stdin, out, err to /dev/null
local null = fcntl.open('/dev/null', fcntl.O_RDWR)
if null then
unistd.dup2(null, unistd.STDIN_FILENO)
unistd.dup2(null, unistd.STDOUT_FILENO)
unistd.dup2(null, unistd.STDERR_FILENO)
if null > 2 then
unistd.close(null)
end
end
-- Sleep a little so the browser can fetch everything required to
-- display the reboot page, then reboot the device.
unistd.sleep(1)
-- replace with target command
unistd.exec(argv[0], argv)
end
end
local function image_supported(supported_tmpfile)
return (os.execute(string.format("exec /sbin/sysupgrade -T %q >/dev/null", supported_tmpfile)) == 0)
end
local function storage_size()
local size = 0
if unistd.access("/proc/mtd") then
for l in io.lines("/proc/mtd") do
local s, n = l:match('^[^%s]+%s+([^%s]+)%s+[^%s]+%s+"([^%s]+)"')
if n == "firmware" then
size = tonumber(s, 16)
break
end
end
elseif unistd.access("/proc/partitions") then
for l in io.lines("/proc/partitions") do
local b, n = l:match('^%s*%d+%s+%d+%s+([^%s]+)%s+([^%s]+)')
if b and n and not n:match('[0-9]') then
size = tonumber(b) * 1024
break
end
end
end
return size
end
local function image_checksum(checksum_tmpfile)
return (util.exec(string.format("exec sha256sum %q", checksum_tmpfile)):match("^([^%s]+)"))
end
-- Determine state
local step = tonumber(http:getenv("REQUEST_METHOD") == "POST" and http:formvalue("step")) or 1
local has_image = unistd.access(tmpfile)
local has_support = has_image and image_supported(tmpfile)
-- Step 1: file upload, error on unsupported image format
if step == 1 or not has_support then
-- If there is an image but user has requested step 1
-- or type is not supported, then remove it.
if has_image then
unistd.unlink(tmpfile)
end
renderer.render_layout('admin/upgrade', {
bad_image = has_image and not has_support,
}, 'gluon-web-admin')
-- Step 2: present uploaded file, show checksum, confirmation
elseif step == 2 then
renderer.render_layout('admin/upgrade_confirm', {
checksum = image_checksum(tmpfile),
filesize = stat.stat(tmpfile).st_size,
flashsize = storage_size(),
keepconfig = (http:formvalue("keepcfg") == "1"),
}, 'gluon-web-admin')
elseif step == 3 then
local cmd = {[0] = '/sbin/sysupgrade', tmpfile}
if http:formvalue('keepcfg') ~= '1' then
table.insert(cmd, 1, '-n')
end
fork_exec(cmd)
renderer.render_layout('admin/upgrade_reboot', nil, 'gluon-web-admin', {
hidenav = true,
})
end
end
local has_platform = unistd.access("/lib/upgrade/platform.sh")
if has_platform then
local upgrade = entry({"admin", "upgrade"}, call(action_upgrade), _("Upgrade firmware"), 90)
upgrade.filehandler = filehandler
end