diff --git a/admin/autoupdater/files/usr/lib/autoupdater/abort.d/README b/admin/autoupdater/files/usr/lib/autoupdater/abort.d/README new file mode 100644 index 0000000..014518a --- /dev/null +++ b/admin/autoupdater/files/usr/lib/autoupdater/abort.d/README @@ -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. diff --git a/admin/autoupdater/files/usr/lib/autoupdater/download.d/95drop_caches b/admin/autoupdater/files/usr/lib/autoupdater/download.d/95drop_caches new file mode 100755 index 0000000..814159f --- /dev/null +++ b/admin/autoupdater/files/usr/lib/autoupdater/download.d/95drop_caches @@ -0,0 +1,4 @@ +#!/bin/sh + +sync +sysctl -w vm.drop_caches=3 diff --git a/admin/autoupdater/files/usr/lib/autoupdater/download.d/README b/admin/autoupdater/files/usr/lib/autoupdater/download.d/README new file mode 100644 index 0000000..c1c53e5 --- /dev/null +++ b/admin/autoupdater/files/usr/lib/autoupdater/download.d/README @@ -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. diff --git a/admin/autoupdater/files/usr/lib/lua/autoupdater/util.lua b/admin/autoupdater/files/usr/lib/lua/autoupdater/util.lua index 08c03db..d5dd67e 100644 --- a/admin/autoupdater/files/usr/lib/lua/autoupdater/util.lua +++ b/admin/autoupdater/files/usr/lib/lua/autoupdater/util.lua @@ -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') diff --git a/admin/autoupdater/files/usr/sbin/autoupdater b/admin/autoupdater/files/usr/sbin/autoupdater index 73510b1..681d35c 100755 --- a/admin/autoupdater/files/usr/sbin/autoupdater +++ b/admin/autoupdater/files/usr/sbin/autoupdater @@ -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