-- This is intended to be run as an RPM scriptlet.
-- Keep this file in sync with the convert-to-edition
-- shell script
local VARIANT_FILE = "/usr/lib/variant"
-- Read in /usr/lib/variant and determine the edition
local function read_variant()
local variant
local f = io.open(VARIANT_FILE, "r")
if f ~= nil then
while true do
local line = f:read()
if line == nil then
break
end
local m = line:match("^VARIANT_ID=([^\n]+)")
if m ~= nil then
variant = m
end
end
f:close()
end
return variant
end
-- Atomically replace a file with new contents
local function writefile(path, data)
local tmp = path .. ".convert-to-edition"
local f = io.open(tmp, "w+")
if f == nil then
return
end
f:write(data)
f:close()
if not os.rename(tmp, path) then
os.remove(tmp)
end
end
-- Forcibly replace a symlink
local function symlink(from, to)
os.remove(to)
assert(posix.symlink(from, to))
end
-- Run a subroutine in a child process
local function execute(...)
local pid = posix.fork()
if pid == 0 then
posix.exec(...)
posix.exit(1)
elseif pid ~= -1 then
local status = posix.wait(pid)
if status ~= 0 then
local program = ...
error(program .. " exited with status " .. status)
end
end
end
-- Remove preset files for other editions
-- This should never be necessary, but it's best to be safe
local function clear_presets()
local path = "/usr/lib/systemd/system-preset"
for file in posix.files(path) do
if file:match("^80%-.*%.preset$") then
os.remove(path .. "/" .. file)
end
end
end
-- Get a list of presets that need to be enabled or disabled
-- as part of the installation of this edition
local function read_presets(path)
local result = {}
local f = assert(io.open(path))
if f ~= nil then
while true do
local line = f:read()
if line == nil then
break
end
local cmd, arg = line:match("^([^ \t]+)[ \t]+([^\n \t]+)")
if cmd == "enable" or cmd == "disable" then
result[#result + 1] = arg
end
end
f:close()
end
return result
end
local function set_variant(variant)
writefile(VARIANT_FILE, "VARIANT_ID=" .. variant .. "\n")
end
local function set_release(release)
symlink("./os.release.d/os-release-" .. release, "/usr/lib/os-release")
end
local function set_edition_swidtag(release)
symlink("/usr/lib/os.release.d/Fedora-" .. release .. ".swidtag", "%{_swidtagdir}/org.fedoraproject.Fedora-edition.swidtag")
end
local function unset_edition_swidtag()
os.remove("%{_swidtagdir}/org.fedoraproject.Fedora-edition.swidtag")
end
-- release: the VARIANT_ID for os-release
-- presets: whether this edition has extra presets beyond the
-- defaults to enable or disable
local variants = {
atomichost = {release = "atomichost", presets = false},
cloud = {release = "cloud", presets = false},
cinnamon = {release = "cinnamon", presets = false},
container = {release = "container", presets = false},
coreos = {release = "coreos", presets = false},
iot = {release = "iot", presets = true},
kde = {release = "kde", presets = false},
matecompiz = {release = "matecompiz", presets = false},
nonproduct = {release = "fedora", presets = false},
server = {release = "server", presets = true},
silverblue = {release = "silverblue", presets = false},
soas = {release = "soas", presets = false},
workstation = {release = "workstation", presets = true},
xfce = {release = "xfce", presets = false},
}
-- Call out to systemctl to enable or disable presets
local function set_presets(edition, apply_presets)
if variants[edition].presets then
local target = "/usr/lib/systemd/system-preset/80-" .. edition .. ".preset"
symlink("../../os.release.d/presets/80-" .. edition .. ".preset", target)
if apply_presets then
local presets = read_presets(target)
local systemctl = "/usr/bin/systemctl"
if posix.access(systemctl, "x") then
--fork off a systemctl call
local pid = assert(posix.fork())
if pid == 0 then
-- Child
posix.exec(systemctl, "preset", "-q", table.unpack(presets))
-- In case exec() fails
os.exit(17)
else
-- RPM
assert(posix.wait(pid))
end
end
end
end
end
local function convert_to_edition(edition, apply_presets)
local variant = variants[edition]
if variant == nil then
error("undefined edition: " .. edition)
end
set_release(variant.release)
-- Symlink the correct edition .swidtag for anything but nonproduct
if edition == "nonproduct" then
unset_edition_swidtag()
else
set_edition_swidtag(variant.release)
end
clear_presets()
set_presets(edition, apply_presets)
end
local function install_edition(edition)
-- Create the variant file if it does not already exist. This needs
-- to be done on both installation and upgrade, to ensure that we
-- upgrade from F23 and earlier properly.
if not posix.access(VARIANT_FILE, "f") then
set_variant(edition)
end
if read_variant() == edition then
-- (On initial installation only), fix up after %%systemd_post
-- in packages possibly installed before our preset file was
-- added
-- On upgrades, do not enable or disable presets to avoid
-- surprising the user
local initial_install = arg[2] == 1
convert_to_edition(edition, initial_install)
end
end
local function uninstall_edition(edition)
-- If we are uninstalling, we need to reset the variant file and
-- force the os-release file back to os-release-fedora. We do this
-- in %%preun so that we don't have any time where the os-release
-- symlink is dangling (since in %%postun, the os-release-$EDITION
-- file will have already been removed)
if arg[2] == 0 then
if read_variant() == edition then
set_variant("nonproduct")
convert_to_edition("nonproduct", false)
end
end
end