Skip to content

Commit

Permalink
ostree: move admindir to /etc/alternatives.admindir
Browse files Browse the repository at this point in the history
`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 <[email protected]>
  • Loading branch information
vrothberg committed Jul 30, 2024
1 parent ed8a2a4 commit d52444f
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 12 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ PROG = chkconfig
BINDIR = /sbin
SBINDIR = /usr/sbin
MANDIR = /usr/man
ALTDIR = /var/lib/alternatives
LIBEXECDIR = /usr/libexec
ALTDATADIR = /etc/alternatives
SYSTEMDUTILDIR = $(shell pkg-config --variable=systemdutildir systemd)
SUBDIRS = po
Expand Down Expand Up @@ -55,7 +55,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)

Expand All @@ -66,6 +65,9 @@ install:
install -m 755 alternatives $(DESTDIR)/$(SBINDIR)/alternatives
ln -s alternatives $(DESTDIR)/$(SBINDIR)/update-alternatives

install -m 755 alternatives-migration $(DESTDIR)/$(LIBEXECDIR)/alternatives-migration
install -m systemd/alternatives-migration.service $(DESTDIR)/$(SYSTEMDUTILDIR)/system/alternatives-migration.service

for i in $(MAN); do \
install -m 644 $$i $(DESTDIR)/$(MANDIR)/man`echo $$i | sed "s/.*\.//"`/$$i ; \
done
Expand Down
18 changes: 18 additions & 0 deletions alternatives-migration
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/sh

# Already symlinked, nothing to do
if [[ -L /var/lib/alternatives ]]; then

Check warning

Code scanning / shellcheck

SC3010 Warning

In POSIX sh, [[ ]] is undefined.
exit 0;
fi

# Make sure that the admindir exists
mkdir -p /etc/alternatives.admindir

# Migrate the contents
if [[ -d /var/lib/alternatives ]]; then

Check warning

Code scanning / shellcheck

SC3010 Warning

In POSIX sh, [[ ]] is undefined.
mv /var/lib/alternatives/* /etc/alternatives.admindir
rm -r /var/lib/alternatives
fi

# Create the symlink
ln -s /etc/alternatives.admindir /var/lib/alternatives
6 changes: 4 additions & 2 deletions alternatives.8
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,11 @@ containing the symlinks.
.TP
administrative directory
A directory, by default
.IR /var/lib/alternatives ,
.IR /etc/alternatives.admindir ,
containing
.BR alternatives '
state information.
/var/lib/alternatives symlinks to it.
.TP
link group
A set of related symlinks, intended to be updated as a group.
Expand Down Expand Up @@ -414,8 +415,9 @@ Can be overridden by the
.B --altdir
option.
.TP
.I /var/lib/alternatives/
.I /etc/alternatives.admindir/
The default administration directory.
/var/lib/alternatives symlinks to it.
Can be overridden by the
.B --admindir
option.
Expand Down
37 changes: 37 additions & 0 deletions alternatives.c
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,30 @@ static int listServices(const char *altDir, const char *stateDir, int flags) {
return 0;
}

int dirExists(const char *path) {
struct stat sb;

if (stat(path, &sb) || !S_ISDIR(sb.st_mode) || access(path, F_OK)) {
if (errno == ENOENT) {
return 0;
}
fprintf(stderr, _("admindir %s invalid\n"), path);
exit(2);
}

return 1;
}

int canUseAlternativeAdminDirUnderOSTree() {
if (dirExists("/var/lib/alternatives")) { return 0; }

if (fileExists("/run/ostree-booted") || isLink("/ostree")) {
return 1;
}

return 0;
}

int main(int argc, const char **argv) {
const char **nextArg;
char *end;
Expand All @@ -1304,13 +1328,18 @@ int main(int argc, const char **argv) {
struct stat sb;
struct linkSet newSet = {NULL, NULL, NULL};

if (canUseAlternativeAdminDirUnderOSTree()) {
stateDir = "/etc/alternatives.admindir";
}

setlocale(LC_ALL, "");
bindtextdomain("chkconfig", "/usr/share/locale");
textdomain("chkconfig");

if (!argv[1])
return usage(2);

int statedir_changed = 0;
nextArg = argv + 1;
while (*nextArg) {
if (!strcmp(*nextArg, "--install")) {
Expand Down Expand Up @@ -1408,6 +1437,7 @@ int main(int argc, const char **argv) {
altDir = normalize_path_alloc(*nextArg);
nextArg++;
} else if (!strcmp(*nextArg, "--admindir")) {
statedir_changed = 1;
nextArg++;
if (!*nextArg)
usage(2);
Expand All @@ -1428,6 +1458,13 @@ int main(int argc, const char **argv) {
exit(2);
}

if ((statedir_changed == 0) && (dirExists(stateDir) == 0)) {
if (mkdir(stateDir, 0755) == -1) {
fprintf(stderr, _("creating admindir: %s\n"), strerror(errno));
exit(2);
}
}

if (stat(stateDir, &sb) || !S_ISDIR(sb.st_mode) || access(stateDir, F_OK)) {
fprintf(stderr, _("admindir %s invalid\n"), stateDir);
exit(2);
Expand Down
10 changes: 8 additions & 2 deletions chkconfig.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ License: GPL-2.0-only
URL: https://github.com/fedora-sysv/chkconfig
Source: https://github.com/fedora-sysv/chkconfig/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz

BuildRequires: gcc gettext libselinux-devel make newt-devel popt-devel pkgconfig(systemd)
BuildRequires: gcc gettext libselinux-devel make newt-devel popt-devel pkgconfig(systemd) systemd-rpm-macros
# beakerlib might not be available on CentOS Stream any more
%if 0%{?fedora}
BuildRequires: beakerlib
Expand Down Expand Up @@ -93,11 +93,17 @@ mkdir -p $RPM_BUILD_ROOT/etc/chkconfig.d
%files -n alternatives
%license COPYING
%dir /etc/alternatives
%ghost /etc/alternatives.admindir
%ghost /var/lib/alternatives
%dir %{_libexecdir}/alternatives-migration
%{_prefix}/lib/systemd/system/alternatives-migration.service
%{_sbindir}/update-alternatives
%{_sbindir}/alternatives
%{_mandir}/*/update-alternatives*
%{_mandir}/*/alternatives*
%dir /var/lib/alternatives

%postun
%systemd_postun alternatives-migration.service

%changelog
* Fri Jun 21 2024 Jan Macku <[email protected]> - 1.28-1
Expand Down
17 changes: 11 additions & 6 deletions po/chkconfig.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-26 11:46+0200\n"
"POT-Creation-Date: 2024-07-30 14:56+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down Expand Up @@ -562,22 +562,27 @@ msgstr ""
msgid "failed to remove %s: %s\n"
msgstr ""

#: ../alternatives.c:1365
#: ../alternatives.c:1300 ../alternatives.c:1469
#, c-format
msgid "admindir %s invalid\n"
msgstr ""

#: ../alternatives.c:1394
#, c-format
msgid "--family can't contain the symbol '@'\n"
msgstr ""

#: ../alternatives.c:1427
#: ../alternatives.c:1457
#, c-format
msgid "altdir %s invalid\n"
msgstr ""

#: ../alternatives.c:1432
#: ../alternatives.c:1463
#, c-format
msgid "admindir %s invalid\n"
msgid "creating admindir: %s\n"
msgstr ""

#: ../alternatives.c:1442
#: ../alternatives.c:1479
#, c-format
msgid "alternatives version %s\n"
msgstr ""
18 changes: 18 additions & 0 deletions systemd/alternatives-migration.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Migrate /var/lib/alternatives to /etc/alternatives.admindir
Documentation=man:alternatives(8)

# This should run before any other daemons/tools that may use alternatives
DefaultDependencies=no
After=sysinit.target
Before=basic.target shutdown.target
Conflicts=shutdown.target
# In case /var is remote-mounted
RequiresMountsFor=/var

[Service]
Type=oneshot
ExecStart=/usr/libexec/alternatives-migration

[Install]
WantedBy=default.target

0 comments on commit d52444f

Please sign in to comment.