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