From 538dc7edf0da387169d83599fe0774ea080b4a37 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Wed, 24 Jul 2024 11:07:41 +0200 Subject: [PATCH] ostree: move admindir to /etc/alternatives.admindir `ostree container commit` wipes /var and thereby erases the data in /var/lib/alternatives; the directory used to store configs/symlinks of alternatives. /var is not a good place for storing such configs since it won't receive updates on bootc images either. We need to move to another location. Hence, use /etc/alternatives.admindir when running on an ostree-based system unless /var/lib/alternatives is already present; a user may have worked around the problem. This way we enable alternatives to work on ostree-based systems without breaking backwards compat. Fixes: #9 Signed-off-by: Valentin Rothberg --- Makefile | 1 - alternatives.8 | 2 ++ alternatives.c | 34 ++++++++++++++++++++++++++++++---- chkconfig.spec | 5 +++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 95ae1b49..eada102a 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,6 @@ install: [ -d $(DESTDIR)/$(SBINDIR) ] || mkdir -p $(DESTDIR)/$(SBINDIR) [ -d $(DESTDIR)/$(MANDIR) ] || mkdir -p $(DESTDIR)/$(MANDIR) [ -d $(DESTDIR)/$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)/$(MANDIR)/man8 - [ -d $(DESTDIR)/$(ALTDIR) ] || mkdir -p -m 755 $(DESTDIR)/$(ALTDIR) [ -d $(DESTDIR)/$(ALTDATADIR) ] || mkdir -p -m 755 $(DESTDIR)/$(ALTDATADIR) [ -d $(DESTDIR)/$(SYSTEMDUTILDIR) ] || mkdir -p -m 755 $(DESTDIR)/$(SYSTEMDUTILDIR) diff --git a/alternatives.8 b/alternatives.8 index d3bbf6bd..a04785ee 100644 --- a/alternatives.8 +++ b/alternatives.8 @@ -214,6 +214,7 @@ A directory, by default containing .BR alternatives ' state information. +/etc/alternatives.admindir on OSTree-based systems. .TP link group A set of related symlinks, intended to be updated as a group. @@ -416,6 +417,7 @@ option. .TP .I /var/lib/alternatives/ The default administration directory. +/etc/alternatives.admindir on OSTree-based systems. Can be overridden by the .B --admindir option. diff --git a/alternatives.c b/alternatives.c index 2ce628a7..c573e0f0 100644 --- a/alternatives.c +++ b/alternatives.c @@ -566,6 +566,15 @@ static int fileExists(char *path) { return !stat(path, &sbuf); } +static int dirExists(char *path) { + struct stat sbuf; + + if (stat(path, &sbuf)) + return 0; + + return !!S_ISDIR(sbuf.st_mode); +} + static int facilityBelongsToUs(char *facility, const char *altDir) { char buf[PATH_MAX]; if (readlink(facility, buf, sizeof(buf)) <= 0) @@ -1321,6 +1330,10 @@ static int listServices(const char *altDir, const char *stateDir, int flags) { return 0; } +static int isOSTree() { + return fileExists("/run/ostree-booted") || isLink("/ostree"); +} + int main(int argc, const char **argv) { const char **nextArg; char *end; @@ -1331,8 +1344,7 @@ int main(int argc, const char **argv) { struct alternative newAlt = {-1, {NULL, NULL, NULL}, NULL, NULL, 0, NULL}; int flags = 0; char *altDir = "/etc/alternatives"; - char *stateDir = "/var/lib/alternatives"; - struct stat sb; + char *stateDir= NULL; struct linkSet newSet = {NULL, NULL, NULL}; setlocale(LC_ALL, ""); @@ -1454,12 +1466,26 @@ int main(int argc, const char **argv) { } } - if (stat(altDir, &sb) || !S_ISDIR(sb.st_mode) || access(altDir, F_OK)) { + if (!dirExists(altDir)) { fprintf(stderr, _("altdir %s invalid\n"), altDir); exit(2); } - if (stat(stateDir, &sb) || !S_ISDIR(sb.st_mode) || access(stateDir, F_OK)) { + // if the stateDir is not explicitly set, we will use /var/lib/alternatives on normal systems + // and /etc/alternatives-admindir on OSTree systems, if the dir does not exist, we will create it + // if the stateDir is explicitly set, we will *not* try to create the dir and fail immediately if it does not exist + if (!stateDir) { + stateDir = "/var/lib/alternatives"; + if (!dirExists(stateDir)) { + if (isOSTree()) + stateDir = "/etc/alternatives-admindir"; + + if (mkdir(stateDir, 0755) < 0 && errno != EEXIST) { + fprintf(stderr, _("failed to create admindir: %s\n"), strerror(errno)); + exit(2); + } + } + } else if (!dirExists(stateDir)) { fprintf(stderr, _("admindir %s invalid\n"), stateDir); exit(2); } diff --git a/chkconfig.spec b/chkconfig.spec index 00e9b99f..3e4f1a10 100644 --- a/chkconfig.spec +++ b/chkconfig.spec @@ -19,7 +19,7 @@ Provides: /sbin/chkconfig %description Chkconfig is a basic system utility. It updates and queries runlevel information for system services. Chkconfig manipulates the numerous -symbolic links in /etc/rc.d, to relieve system administrators of some +symbolic links in /etc/rc.d, to relieve system administrators of some of the drudgery of manually editing the symbolic links. %package -n ntsysv @@ -95,11 +95,12 @@ mkdir -p $RPM_BUILD_ROOT/etc/chkconfig.d %files -n alternatives %license COPYING %dir /etc/alternatives +%ghost %dir %attr(755, root, root) /etc/alternatives.admindir +%ghost %dir %attr(755, root, root) /var/lib/alternatives %{_sbindir}/update-alternatives %{_sbindir}/alternatives %{_mandir}/*/update-alternatives* %{_mandir}/*/alternatives* -%dir /var/lib/alternatives %changelog * Tue Jul 30 2024 Jan Macku - 1.29-1