diff --git a/user/libeconf-devel b/user/libeconf-devel new file mode 120000 index 0000000000..fb1a5b94e8 --- /dev/null +++ b/user/libeconf-devel @@ -0,0 +1 @@ +libeconf \ No newline at end of file diff --git a/user/libeconf-progs b/user/libeconf-progs new file mode 120000 index 0000000000..fb1a5b94e8 --- /dev/null +++ b/user/libeconf-progs @@ -0,0 +1 @@ +libeconf \ No newline at end of file diff --git a/user/libeconf/patches/meson.patch b/user/libeconf/patches/meson.patch new file mode 100644 index 0000000000..c02d3a5564 --- /dev/null +++ b/user/libeconf/patches/meson.patch @@ -0,0 +1,12 @@ +--- a/meson.build 2024-09-20 17:11:49.271033354 -0300 ++++ a/meson.build 2024-09-20 17:11:58.804736776 -0300 +@@ -15,8 +15,7 @@ + inc = include_directories('include') + + add_project_arguments(['-D_GNU_SOURCE=1', +- '-DXTSTRINGDEFINES', +- '-D_FORTIFY_SOURCE=2'], language : 'c') ++ '-DXTSTRINGDEFINES'], language : 'c') + + possible_cc_flags = [ + '-Dwerror=true', diff --git a/user/libeconf/patches/tests.patch b/user/libeconf/patches/tests.patch new file mode 100644 index 0000000000..9d2e50fd0b --- /dev/null +++ b/user/libeconf/patches/tests.patch @@ -0,0 +1,10 @@ +Fails on Musl +--- a/tests/meson.build 2024-09-18 07:53:14.000000000 -0300 ++++ b/tests/meson.build 2024-09-20 07:10:42.449539955 -0300 +@@ -203,6 +203,3 @@ + test('tst-shells2', tst_shells2_exe) + + +-test('tst_econftool1', find_program('tst-econftool1.sh')) +-test('tst_econftool_show1', find_program('tst-econftool_show1.sh')) +-test('tst_econftool_cat', find_program('tst-econftool_cat.sh')) diff --git a/user/libeconf/template.py b/user/libeconf/template.py new file mode 100644 index 0000000000..8bd57d5008 --- /dev/null +++ b/user/libeconf/template.py @@ -0,0 +1,27 @@ +pkgname = "libeconf" +pkgver = "0.7.4" +pkgrel = 0 +build_style = "meson" +configure_args = ["-Ddefault_library=shared"] +hostmakedepends = ["meson", "pkgconf", "doxygen"] +pkgdesc = "Config file parser" +maintainer = "tulilirockz " +license = "MIT" +url = "https://github.com/openSUSE/libeconf" +source = f"{url}/archive/refs/tags/v{pkgver}.tar.gz" +sha256 = "4174ca94e958cbb6c8bb4ea9e6909877d6178e00b6a65349eade64a462534da0" +options = ["linkundefver"] + + +def post_install(self): + self.install_license("LICENSE") + + +@subpackage("libeconf-devel") +def _(self): + return self.default_devel() + + +@subpackage("libeconf-progs") +def _(self): + return self.default_progs() diff --git a/user/transactional-update-devel b/user/transactional-update-devel new file mode 120000 index 0000000000..e64d81930a --- /dev/null +++ b/user/transactional-update-devel @@ -0,0 +1 @@ +transactional-update \ No newline at end of file diff --git a/user/transactional-update-initramfs-tools b/user/transactional-update-initramfs-tools new file mode 120000 index 0000000000..e64d81930a --- /dev/null +++ b/user/transactional-update-initramfs-tools @@ -0,0 +1 @@ +transactional-update \ No newline at end of file diff --git a/user/transactional-update-libs b/user/transactional-update-libs new file mode 120000 index 0000000000..e64d81930a --- /dev/null +++ b/user/transactional-update-libs @@ -0,0 +1 @@ +transactional-update \ No newline at end of file diff --git a/user/transactional-update/files/tukit.hook b/user/transactional-update/files/tukit.hook new file mode 100644 index 0000000000..c56df31bac --- /dev/null +++ b/user/transactional-update/files/tukit.hook @@ -0,0 +1,5 @@ +#!/bin/sh + +. /usr/share/initramfs-tools/hook-functions + +manual_add_modules overlay diff --git a/user/transactional-update/files/tukit.init-bottom b/user/transactional-update/files/tukit.init-bottom new file mode 100644 index 0000000000..e91af72e1f --- /dev/null +++ b/user/transactional-update/files/tukit.init-bottom @@ -0,0 +1,18 @@ +#!/bin/sh + +. /scripts/local +. /scripts/functions + + +if read_fstab_entry /var; then + log_begin_msg "Mounting var filesystem" + mountfs /etc + log_end_msg +fi + +if read_fstab_entry /etc; then + log_begin_msg "Mounting etc overlay" + mountfs /etc + log_end_msg +fi + diff --git a/user/transactional-update/files/tukitd b/user/transactional-update/files/tukitd new file mode 100644 index 0000000000..ea1dbdd52d --- /dev/null +++ b/user/transactional-update/files/tukitd @@ -0,0 +1,5 @@ +type = process +command = /usr/bin/tukitd +before = pre-local.target +depends-on = early-fs-pre.target +smooth-recovery = true diff --git a/user/transactional-update/patches/cxx.patch b/user/transactional-update/patches/cxx.patch new file mode 100644 index 0000000000..0186fce04b --- /dev/null +++ b/user/transactional-update/patches/cxx.patch @@ -0,0 +1,33 @@ +--- a/lib/Supplement.cpp ++++ b/lib/Supplement.cpp +@@ -21,7 +21,7 @@ Supplements::Supplements(fs::path snapshot): + // those directories are deleted in the end by adding them to the list of temporary files + void Supplements::createDirs(fs::path dir) { + fs::path stump{snapshot}; +- for (auto& component: dir.relative_path()) { ++ for (const auto& component: dir.relative_path()) { + stump /= component; + if (! fs::exists(stump)) { + fs::create_directories(stump); + +--- a/lib/Snapshot/Snapper.cpp ++++ b/lib/Snapshot/Snapper.cpp +@@ -5,6 +5,7 @@ + Snapper backend for snapshot handling + */ + ++#include + #include "Snapper.hpp" + #include "Exceptions.hpp" + #include "Util.hpp" + +--- a/tukit/tukit.cpp ++++ b/tukit/tukit.cpp +@@ -5,6 +5,7 @@ + transactional-update - apply updates to the system in an atomic way + */ + ++#include + #include "tukit.hpp" + #include "Configuration.hpp" + #include "SnapshotManager.hpp" diff --git a/user/transactional-update/patches/etc.patch b/user/transactional-update/patches/etc.patch new file mode 100644 index 0000000000..1fadd5f832 --- /dev/null +++ b/user/transactional-update/patches/etc.patch @@ -0,0 +1,10 @@ +--- a/etc/Makefile.am ++++ b/etc/Makefile.am +@@ -2,5 +2,5 @@ + # SPDX-FileCopyrightText: 2018-2021 SUSE LLC + + EXTRA_DIST = transactional-update.conf tukit.conf +-configdir = $(prefix)$(sysconfdir) ++configdir = $(sysconfdir) + config_DATA = $(EXTRA_DIST) + diff --git a/user/transactional-update/patches/no-rpm.patch b/user/transactional-update/patches/no-rpm.patch new file mode 100644 index 0000000000..3d14d15c97 --- /dev/null +++ b/user/transactional-update/patches/no-rpm.patch @@ -0,0 +1,22 @@ +--- a/configure.ac 2024-09-20 06:10:04.979023142 -0300 ++++ b/configure.ac 2024-09-20 09:08:17.039005737 -0300 +@@ -56,8 +56,6 @@ + PKG_CHECK_MODULES([ECONF], [libeconf]) + PKG_CHECK_MODULES([SELINUX], [libselinux]) + PKG_CHECK_MODULES([LIBMOUNT], [mount]) +-PKG_CHECK_MODULES([LIBRPM], [rpm >= 4.15], AC_DEFINE([HAVE_RPMDBCOOKIE]), +- [PKG_CHECK_MODULES([LIBRPM], [rpm])]) + PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd]) + + AC_ARG_WITH([doc], + +--- a/tukit.pc.in 2024-09-20 06:10:04.986023030 -0300 ++++ b/tukit.pc.in 2024-09-20 17:57:45.272302671 -0300 +@@ -7,6 +7,6 @@ + Description: Toolkit library for operating system transactional updates + Version: @VERSION@ + URL: https://github.com/openSUSE/transactional-update +-Requires.private: rpm, libeconf, mount ++Requires.private: libeconf, mount + Cflags: -I${includedir} + Libs: -L${libdir} -ltukit diff --git a/user/transactional-update/patches/selinux.patch b/user/transactional-update/patches/selinux.patch new file mode 100644 index 0000000000..f27406f90b --- /dev/null +++ b/user/transactional-update/patches/selinux.patch @@ -0,0 +1,120 @@ +diff --git a/configure.ac b/configure.ac +index d78d48c..9dd6dbe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -54,7 +54,6 @@ AC_PROG_LN_S + LT_INIT([disable-static]) + + PKG_CHECK_MODULES([ECONF], [libeconf]) +-PKG_CHECK_MODULES([SELINUX], [libselinux]) + PKG_CHECK_MODULES([LIBMOUNT], [mount]) + PKG_CHECK_MODULES([LIBRPM], [rpm >= 4.15], AC_DEFINE([HAVE_RPMDBCOOKIE]), + [PKG_CHECK_MODULES([LIBRPM], [rpm])]) +diff --git a/lib/Overlay.cpp b/lib/Overlay.cpp +index 2ea711a..81c1bf5 100644 +--- a/lib/Overlay.cpp ++++ b/lib/Overlay.cpp +@@ -15,8 +15,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include +@@ -120,18 +118,7 @@ bool Overlay::sync(string base, fs::path snapRoot) { + previousEtc->mount(previousOvl.upperdir.parent_path() / "sync"); + tulog.info("Syncing /etc of previous snapshot ", previousSnapId, " as base into new snapshot ", snapRoot); + +- if (is_selinux_enabled()) { +- tulog.info("SELinux is enabled."); +- } +- +- try { +- Util::exec("rsync --quiet --archive --inplace --xattrs --exclude='/fstab' --acls --delete " + syncSource + " " + string(snapRoot) + "/etc 2>&1"); +- } catch (exception &e) { +- // rsync will fail when synchronizing pre-SELinux snapshots as soon as SELinux enabled, +- // so try again without the SELinux xattrs. +- tulog.info("Retrying rsync without SELinux xattrs..."); +- Util::exec("rsync --quiet --archive --inplace --xattrs --filter='-x security.selinux' --exclude='/fstab' --acls --delete " + syncSource + " " + string(snapRoot) + "/etc"); +- } ++ Util::exec("rsync --quiet --archive --inplace --xattrs --filter='-x security.selinux' --exclude='/fstab' --acls --delete " + syncSource + " " + string(snapRoot) + "/etc"); + + return true; + } +@@ -200,16 +187,6 @@ void Overlay::create(string base, string snapshot, fs::path snapRoot) { + throw std::runtime_error{"could not set permissions of " + upperdir.string() + ": " + std::string(strerror(errno))}; + } + +- char* context = NULL; +- if (getfilecon("/etc", &context) > 0) { +- tulog.debug("selinux context on /etc: " + std::string(context)); +- if (setfilecon(upperdir.c_str(), context) != 0) { +- freecon(context); +- throw std::runtime_error{"applying selinux context failed: " + std::string(strerror(errno))}; +- } +- freecon(context); +- } +- + // Assemble the new lowerdirs + lowerdirs.clear(); + lowerdirs.push_back(parent.upperdir); +diff --git a/lib/Transaction.cpp b/lib/Transaction.cpp +index dd4c472..3cc4e16 100644 +--- a/lib/Transaction.cpp ++++ b/lib/Transaction.cpp +@@ -25,8 +25,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include +@@ -128,44 +126,6 @@ void Transaction::impl::snapMount() { + dirsToMount.push_back(std::make_unique("/var/lib/ca-certificates")); + if (fs::is_directory("/var/lib/alternatives")) + dirsToMount.push_back(std::make_unique("/var/lib/alternatives")); +- if (fs::is_directory("/var/lib/selinux")) +- dirsToMount.push_back(std::make_unique("/var/lib/selinux")); +- if (is_selinux_enabled()) { +- // If packages installed files into /var (which is not allowed, but still happens), they will end +- // up in the root file system, but will always be shadowed by the real /var mount. Due to that they +- // also won't be relabelled at any time. During updates this may cause problems if packages try to +- // access those leftover directories with wrong permissions, so they have to be relabelled manually... +- BindMount selinuxVar("/var/lib/selinux", 0, true); +- selinuxVar.mount(bindDir); +- BindMount selinuxEtc("/etc/selinux", 0, true); +- selinuxEtc.mount(bindDir); +- +- // restorecon keeps open file handles, so execute it in a child process - umount will fail otherwise +- pid_t childPid = fork(); +- if (childPid < 0) { +- throw std::runtime_error{"Forking for SELinux relabelling failed: " + std::string(strerror(errno))}; +- } else if (childPid == 0) { +- if (chroot(bindDir.c_str()) < 0) { +- tulog.error("Chrooting to " + bindDir.native() + " for SELinux relabelling failed: " + std::string(strerror(errno))); +- _exit(errno); +- } +- unsigned int restoreconOptions = SELINUX_RESTORECON_RECURSE | SELINUX_RESTORECON_IGNORE_DIGEST; +- if (tulog.level >= TULogLevel::Info) +- restoreconOptions |= SELINUX_RESTORECON_VERBOSE; +- if (selinux_restorecon("/var", restoreconOptions) < 0) { +- tulog.error("Relabelling of snapshot /var failed: " + std::string(strerror(errno))); +- _exit(errno); +- } +- _exit(0); +- } +- else { +- int status; +- waitpid(childPid, &status, 0); +- if ((WIFEXITED(status) && WEXITSTATUS(status) != 0) || WIFSIGNALED(status)) { +- throw std::runtime_error{"SELinux relabelling failed."}; +- } +- } +- } + } + + std::unique_ptr mntEtc{new Mount{"/etc"}}; diff --git a/user/transactional-update/patches/sysroot.patch b/user/transactional-update/patches/sysroot.patch new file mode 100644 index 0000000000..11fd95d663 --- /dev/null +++ b/user/transactional-update/patches/sysroot.patch @@ -0,0 +1,38 @@ +This allows it so we can actually use this program without an initramFS that will mount the DRACUT_SYSROOT directory + +- tulip + +--- a/lib/Configuration.cpp 2024-09-20 19:51:59.844936442 -0300 ++++ a/lib/Configuration.cpp 2024-09-20 19:52:07.022826879 -0300 +@@ -21,7 +21,7 @@ + if (error) + throw std::runtime_error{"Could not create default configuration."}; + std::map defaults = { +- {"DRACUT_SYSROOT", "/sysroot"}, ++ {"DRACUT_SYSROOT", "/"}, + {"LOCKFILE", "/var/run/tukit.lock"}, + {"OVERLAY_DIR", "/var/lib/overlay"}, + {"REBOOT_ALLOW_SOFT_REBOOT", "true"}, +--- a/lib/Overlay.cpp ++++ b/lib/Overlay.cpp +@@ -51,12 +51,18 @@ Overlay::Overlay(string snapshot): + mntEtc.setTabSource(snap->getRoot() / "etc" / "fstab"); + // Read data from fstab if this is an existing snapshot, just use the defaults otherwise + try { +- upperdir = regex_replace(mntEtc.getOption("upperdir"), std::regex("^" + config.get("DRACUT_SYSROOT")), ""); ++ if (config.get("DRACUT_SYSROOT") == "/") { ++ upperdir = mntEtc.getOption("upperdir"); ++ } else { ++ upperdir = regex_replace(mntEtc.getOption("upperdir"), std::regex("^" + config.get("DRACUT_SYSROOT")), ""); ++ } + const string fstabLowerdirs = mntEtc.getOption("lowerdir"); + string lowerdir; + stringstream ss(fstabLowerdirs); + while (getline(ss, lowerdir, ':')) { +- lowerdir = regex_replace(lowerdir, std::regex("^" + config.get("DRACUT_SYSROOT")), ""); ++ if (config.get("DRACUT_SYSROOT") != "/") { ++ lowerdir = regex_replace(lowerdir, std::regex("^" + config.get("DRACUT_SYSROOT")), ""); ++ } + lowerdirs.push_back(lowerdir); + } + } catch (exception &e) {} diff --git a/user/transactional-update/patches/systemd.patch b/user/transactional-update/patches/systemd.patch new file mode 100644 index 0000000000..5e604a3ba4 --- /dev/null +++ b/user/transactional-update/patches/systemd.patch @@ -0,0 +1,21 @@ +--- a/Makefile.am 2024-09-20 06:24:22.612601858 -0300 ++++ b/Makefile.am 2024-09-20 06:24:31.382453168 -0300 +@@ -5,7 +5,7 @@ + # + AUTOMAKE_OPTIONS = 1.6 foreign check-news dist-xz + # +-SUBDIRS = lib tukit dbus sbin man systemd logrotate dracut doc etc ++SUBDIRS = lib tukit dbus man logrotate doc etc + + CLEANFILES = *~ tukit.pc + +--- a/dbus/Makefile.am 2024-09-16 13:09:12.000000000 -0300 ++++ a/dbus/Makefile.am.new 2024-09-21 10:18:22.692117647 -0300 +@@ -12,7 +12,5 @@ + dbussystembusservice_DATA = org.opensuse.tukit.service + dbusinterfacesdir = @DBUSINTERFACESDIR@ + dbusinterfaces_DATA = org.opensuse.tukit.Transaction.xml org.opensuse.tukit.Snapshot.xml +-systemdsystemunitdir = @SYSTEMDDIR@ +-systemdsystemunit_DATA = tukitd.service + + EXTRA_DIST = $(DATA) diff --git a/user/transactional-update/template.py b/user/transactional-update/template.py new file mode 100644 index 0000000000..d642a61361 --- /dev/null +++ b/user/transactional-update/template.py @@ -0,0 +1,48 @@ +pkgname = "transactional-update" +pkgver = "4.8.3" +pkgrel = 0 +build_style = "gnu_configure" +configure_env = { + "SYSTEMDDIR": "/usr/lib/systemd/system", + "TMPFILESDIR": "/usr/lib/tmpfiles.d", + "DRACUTDIR": "/usr/lib/dracut/modules.d", +} +hostmakedepends = ["autoconf-archive", "automake", "pkgconf", "slibtool"] +makedepends = [ + "dbus-devel", + "elogind-devel", + "libeconf-devel", + "libmount-devel", + "udev-devel", +] +depends = ["snapper"] +pkgdesc = "Toolkit for atomic updates" +maintainer = "tulilirockz " +license = "LGPL-2.1-or-later AND GPL-2.0-or-later" +url = "https://github.com/openSUSE/transactional-update" +source = f"{url}/archive/refs/tags/v{pkgver}.tar.gz" +sha256 = "2dc4e39b361d4d776ec3e9eef8ab6ca55e710a859b95477a77e5818d046838a7" + + +def post_install(self): + self.install_service(self.files_path / "tukitd") + self.install_initramfs(self.files_path / "tukit.hook") + self.install_initramfs(self.files_path / "tukit.init-bottom", "init-bottom") + + +@subpackage("transactional-update-initramfs-tools") +def _(self): + self.subdesc = "initramfs scripts" + self.install_if = [] + self.depends = ["initramfs-tools", self.parent] + return ["usr/share/initramfs-tools"] + + +@subpackage("transactional-update-devel") +def _(self): + return self.default_devel() + + +@subpackage("transactional-update-libs") +def _(self): + return self.default_libs()