autoupdater: add download.d and abort.d directories

All executables in download.d are executed before after the update manifest
has been verified, but before the image is downloaded. This can be used to
stop non-essential services to free RAM.

abort.d is run when the download has failed and should revert the actions
of download.d.
This commit is contained in:
Matthias Schiffer 2016-01-10 13:32:35 +01:00
parent 3d98695abc
commit b7ce1a2002
5 changed files with 56 additions and 6 deletions

View File

@ -0,0 +1,6 @@
Executable files in abort.d will be executed if downloading the upgrade
image has failed and should revert the actions from download.d.
We can't really do anything when the download has succeeded, but the
flashing has failed, as the autoupdater process will have been replaced by
sysupgrade by then.

View File

@ -0,0 +1,4 @@
#!/bin/sh
sync
sysctl -w vm.drop_caches=3

View File

@ -0,0 +1,2 @@
Executable files in download.d will be executed after the update manifest
has been verified, but before the actual image is downloaded.

View File

@ -1,9 +1,9 @@
local io = io
local math = math
local nixio = require 'nixio'
local fs = require 'nixio.fs'
local util = require 'nixio.util'
module 'autoupdater.util'
module('autoupdater.util', package.seeall)
-- Executes a command in the background, without parsing the command through a shell (in contrast to os.execute)
@ -42,6 +42,39 @@ function popen(...)
end
-- Executes all executable files in a directory
function run_dir(dir)
local function is_ok(entry)
if entry:sub(1, 1) == '.' then
return false
end
local file = dir .. '/' .. entry
if fs.stat(file, 'type') ~= 'reg' then
return false
end
if not fs.access(file, 'x') then
return false
end
return true
end
local files = util.consume(fs.dir(dir))
if not files then
return
end
table.sort(files)
for _, entry in ipairs(files) do
if is_ok(entry) then
exec(dir .. '/' .. entry)
end
end
end
-- Seeds Lua's random generator from /dev/urandom
function randomseed()
local f = io.open('/dev/urandom', 'r')

View File

@ -241,6 +241,10 @@ end
-- Tries to perform an update from a given mirror
local function autoupdate(mirror)
local download_d_dir = '/usr/lib/autoupdater/download.d'
local abort_d_dir = '/usr/lib/autoupdater/abort.d'
local manifest = read_manifest(mirror)
if not manifest then
return false
@ -259,13 +263,12 @@ local function autoupdate(mirror)
return true
end
autoupdater_util.exec('sync')
autoupdater_util.exec('sysctl', '-w', 'vm.drop_caches=3')
autoupdater_util.run_dir(download_d_dir)
collectgarbage()
local image = os.tmpname()
if not fetch_firmware(mirror, manifest.filename, image) then
autoupdater_util.run_dir(abort_d_dir)
return false
end
@ -275,6 +278,7 @@ local function autoupdate(mirror)
if checksum ~= manifest.checksum then
io.stderr:write('Invalid image checksum!\n')
os.remove(image)
autoupdater_util.run_dir(abort_d_dir)
return false
end
@ -294,6 +298,7 @@ local function autoupdate(mirror)
-- We output the error message through stdout as stderr isn't available anymore
io.write('Failed to call sysupgrade?\n')
os.remove(image)
autoupdater_util.run_dir(abort_d_dir)
os.exit(1)
end