Commit 0a8c29c1 authored by Michael Biebl's avatar Michael Biebl
Browse files

Add support for LSB facilities defined by insserv

Parse /etc/insserv.conf.d content and /etc/insserv.conf and generate systemd
unit drop-in files to add corresponding dependencies. Also ship targets for
the Debian specific $x-display-manager and $mail-transport-agent system
facilities.

Closes: #690892
parent 10c0c175
......@@ -53,6 +53,13 @@ systemd (204-9) UNRELEASED; urgency=medium
* Make libpam-systemd depend on systemd-sysv | systemd-shim. Packages that
need logind functionality should depend on libpam-systemd.
[ Michael Biebl ]
* Add support for LSB facilities defined by insserv.
Parse /etc/insserv.conf.d content and /etc/insserv.conf and generate
systemd unit drop-in files to add corresponding dependencies. Also ship
targets for the Debian specific $x-display-manager and
$mail-transport-agent system facilities. (Closes: #690892)
-- Michael Biebl <biebl@debian.org> Sat, 26 Apr 2014 10:41:18 +0200
systemd (204-8) unstable; urgency=low
......
From: Michael Biebl <biebl@debian.org>
Date: Sat, 9 Feb 2013 15:55:43 +0100
Subject: Fix mounting of remote filesystems, like NFS
Mounting remote filesystems, like NFS, via /etc/fstab using _netdev is
currently broken for two reasons:
- The nfs-common and rpcbind init scripts aren't correctly ordered
because rpcbind uses an insserv specific configuration file which
systemd doesn't parse, to define the $portmap system facility.
As a result nfs-common is started too early, before rpcbind is
running, and so the rpc.statd daemon simply exits.
- systemd automatically mounts filesystems with the _netdev option via
remote-fs.target. This target should block until network.target is
active. The network.target is currently not properly hooked up so
systemd tries to mount those filesystems too early, when the network
is not yet up. The result is a timeout during boot and a failed mount
attempt.
This workaround does the following:
- Since the only provider for the portmap facility is the rpcbind
init script, we map this directly to rpcbind.service instead of
rpcbind.target. This ensures correct odering for init scripts using
Required-Start: $portmap.
- Remote mounts are no longer hooked up in the remote-fs.target, ie.
they are not started by systemd anymore. Instead we rely on the
if-up.d mountnfs hook to mount those types of filesystems.
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=673309
---
src/core/service.c | 2 +-
src/core/special.h | 2 +-
src/fstab-generator/fstab-generator.c | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/core/service.c b/src/core/service.c
index 9377a81..83203e2 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -360,7 +360,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char
* To break the loop, just ignore it */
"network", SPECIAL_NETWORK_TARGET,
"named", SPECIAL_NSS_LOOKUP_TARGET,
- "portmap", SPECIAL_RPCBIND_TARGET,
+ "portmap", SPECIAL_RPCBIND_SERVICE,
"remote_fs", SPECIAL_REMOTE_FS_TARGET,
"syslog", SPECIAL_SYSLOG_TARGET,
"time", SPECIAL_TIME_SYNC_TARGET,
diff --git a/src/core/special.h b/src/core/special.h
index 6865c04..7132a35 100644
--- a/src/core/special.h
+++ b/src/core/special.h
@@ -61,7 +61,7 @@
/* LSB compatibility */
#define SPECIAL_NETWORK_TARGET "network.target" /* LSB's $network */
#define SPECIAL_NSS_LOOKUP_TARGET "nss-lookup.target" /* LSB's $named */
-#define SPECIAL_RPCBIND_TARGET "rpcbind.target" /* LSB's $portmap */
+#define SPECIAL_RPCBIND_SERVICE "rpcbind.service" /* LSB's $portmap */
#define SPECIAL_SYSLOG_TARGET "syslog.target" /* LSB's $syslog */
#define SPECIAL_TIME_SYNC_TARGET "time-sync.target" /* LSB's $time */
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index cda98cd..ceab9e7 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -313,7 +313,8 @@ static int add_mount(
}
if (!noauto) {
- if (post) {
+ /* don't start network mounts automatically, we do that via ifupdown hooks for now */
+ if (post && !streq(post, SPECIAL_REMOTE_FS_TARGET)) {
lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
if (!lnk)
return log_oom();
From: Michael Biebl <biebl@debian.org>
Date: Fri, 28 Jun 2013 17:54:41 +0200
Subject: insserv.conf generator
Parse /etc/insserv.conf.d content and /etc/insserv.conf and generate
systemd unit drop-in files to add corresponding dependencies.
This patch is based on work by Frederic Crozat <fcrozat@suse.com>.
See [0] for the original patch.
It has the following modifications:
- it removes support for boot. and bool.localfs which is a SuSE specific
extension
- it ensures that targets do not start other targets or services
[0] https://build.opensuse.org/package/view_file/openSUSE:Factory/systemd/insserv-generator.patch
---
Makefile.am | 9 +
src/insserv-generator/Makefile | 28 +++
src/insserv-generator/insserv-generator.c | 310 ++++++++++++++++++++++++++++++
3 files changed, 347 insertions(+)
create mode 100644 src/insserv-generator/Makefile
create mode 100644 src/insserv-generator/insserv-generator.c
diff --git a/Makefile.am b/Makefile.am
index 6944fbc..0e6bd17 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -315,6 +315,7 @@ rootlibexec_PROGRAMS = \
systemd-sleep
systemgenerator_PROGRAMS = \
+ systemd-insserv-generator \
systemd-getty-generator \
systemd-fstab-generator \
systemd-system-update-generator
@@ -1519,6 +1520,14 @@ systemd_delta_LDADD = \
libsystemd-shared.la
# ------------------------------------------------------------------------------
+systemd_insserv_generator_SOURCES = \
+ src/insserv-generator/insserv-generator.c
+
+systemd_insserv_generator_LDADD = \
+ libsystemd-label.la \
+ libsystemd-shared.la
+
+# ------------------------------------------------------------------------------
systemd_getty_generator_SOURCES = \
src/getty-generator/getty-generator.c
diff --git a/src/insserv-generator/Makefile b/src/insserv-generator/Makefile
new file mode 100644
index 0000000..9d07505
--- /dev/null
+++ b/src/insserv-generator/Makefile
@@ -0,0 +1,28 @@
+# This file is part of systemd.
+#
+# Copyright 2010 Lennart Poettering
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+# This file is a dirty trick to simplify compilation from within
+# emacs. This file is not intended to be distributed. So, don't touch
+# it, even better ignore it!
+
+all:
+ $(MAKE) -C ..
+
+clean:
+ $(MAKE) -C .. clean
+
+.PHONY: all clean
diff --git a/src/insserv-generator/insserv-generator.c b/src/insserv-generator/insserv-generator.c
new file mode 100644
index 0000000..5b4407e
--- /dev/null
+++ b/src/insserv-generator/insserv-generator.c
@@ -0,0 +1,310 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "mkdir.h"
+#include "log.h"
+#include "fileio.h"
+#include "unit-name.h"
+#include "special.h"
+#include "path-util.h"
+#include "util.h"
+#include "strv.h"
+
+static const char *arg_dest = "/tmp";
+
+static char *sysv_translate_name(const char *name) {
+ char *r;
+
+ r = new(char, strlen(name) + sizeof(".service"));
+ if (!r)
+ return NULL;
+
+ if (endswith(name, ".sh"))
+ /* Drop .sh suffix */
+ strcpy(stpcpy(r, name) - 3, ".service");
+ else
+ /* Normal init script name */
+ strcpy(stpcpy(r, name), ".service");
+
+ return r;
+}
+
+static int sysv_translate_facility(const char *name, const char *filename, char **_r) {
+
+ /* We silently ignore the $ prefix here. According to the LSB
+ * spec it simply indicates whether something is a
+ * standardized name or a distribution-specific one. Since we
+ * just follow what already exists and do not introduce new
+ * uses or names we don't care who introduced a new name. */
+
+ static const char * const table[] = {
+ /* LSB defined facilities */
+ "local_fs", NULL,
+ "network", SPECIAL_NETWORK_TARGET,
+ "named", SPECIAL_NSS_LOOKUP_TARGET,
+ "portmap", SPECIAL_RPCBIND_TARGET,
+ "remote_fs", SPECIAL_REMOTE_FS_TARGET,
+ "syslog", NULL,
+ "time", SPECIAL_TIME_SYNC_TARGET,
+ };
+
+ unsigned i;
+ char *r;
+ const char *n;
+
+ assert(name);
+ assert(_r);
+
+ n = *name == '$' ? name + 1 : name;
+
+ for (i = 0; i < ELEMENTSOF(table); i += 2) {
+
+ if (!streq(table[i], n))
+ continue;
+
+ if (!table[i+1])
+ return 0;
+
+ r = strdup(table[i+1]);
+ if (!r)
+ return log_oom();
+
+ goto finish;
+ }
+
+ /* If we don't know this name, fallback heuristics to figure
+ * out whether something is a target or a service alias. */
+
+ if (*name == '$') {
+ if (!unit_prefix_is_valid(n))
+ return -EINVAL;
+
+ /* Facilities starting with $ are most likely targets */
+ r = unit_name_build(n, NULL, ".target");
+ } else if (filename && streq(name, filename))
+ /* Names equaling the file name of the services are redundant */
+ return 0;
+ else
+ /* Everything else we assume to be normal service names */
+ r = sysv_translate_name(n);
+
+ if (!r)
+ return -ENOMEM;
+
+finish:
+ *_r = r;
+
+ return 1;
+}
+
+
+
+static int parse_insserv_conf(const char* filename) {
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ if (!(f = fopen(filename, "re"))) {
+ log_debug("Failed to open file %s", filename);
+ r = errno == ENOENT ? 0 : -errno;
+ return r;
+ }
+
+ while (!feof(f)) {
+ char l[LINE_MAX], *t;
+ _cleanup_strv_free_ char **parsed = NULL;
+
+ if (!fgets(l, sizeof(l), f)) {
+ if (feof(f))
+ break;
+
+ r = -errno;
+ log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
+ return -r;
+ }
+
+ t = strstrip(l);
+ if (*t != '$' && *t != '<')
+ continue;
+
+ parsed = strv_split(t,WHITESPACE);
+ /* we ignore <interactive>, not used, equivalent to X-Interactive */
+ if (parsed && !startswith_no_case (parsed[0], "<interactive>")) {
+ _cleanup_free_ char *facility = NULL;
+ if (sysv_translate_facility(parsed[0], NULL, &facility) < 0 || !facility)
+ continue;
+ if (streq(facility, SPECIAL_REMOTE_FS_TARGET)) {
+ _cleanup_free_ char *unit = NULL;
+ /* insert also a Wants dependency from remote-fs-pre on remote-fs */
+ unit = strjoin(arg_dest, "/remote-fs.target.d/50-",basename(filename),".conf", NULL);
+ if (!unit)
+ return log_oom();
+
+ mkdir_parents_label(unit, 0755);
+
+ r = write_string_file(unit,
+ "# Automatically generated by systemd-insserv-generator\n\n"
+ "[Unit]\n"
+ "Wants=remote-fs-pre.target\n");
+ if (r)
+ return r;
+ free (facility);
+ facility=strdup(SPECIAL_REMOTE_FS_PRE_TARGET);
+ }
+ if (facility && endswith(facility, ".target")) {
+ char *name, **j;
+ FILE *file = NULL;
+
+ STRV_FOREACH (j, parsed+1) {
+ _cleanup_free_ char *unit = NULL;
+ _cleanup_free_ char *dep = NULL;
+
+ /* targets should not pull in and activate other targets so skip them */
+ if (*j[0] == '!')
+ continue;
+
+ if (*j[0] == '+')
+ name = *j+1;
+ else
+ name = *j;
+ if ((sysv_translate_facility(name, NULL, &dep) < 0) || !dep)
+ continue;
+
+ unit = strjoin(arg_dest, "/", dep, ".d/50-",basename(filename),"-",parsed[0],".conf", NULL);
+ if (!unit)
+ return log_oom();
+
+ mkdir_parents_label(unit, 0755);
+
+ file = fopen(unit, "wxe");
+ if (!file) {
+ if (errno == EEXIST)
+ log_error("Failed to create drop-in file %s", unit);
+ else
+ log_error("Failed to create drop-in file %s: %m", unit);
+ return -errno;
+ }
+
+ fprintf(file,
+ "# Automatically generated by systemd-insserv-generator\n\n"
+ "[Unit]\n"
+ "Wants=%s\n"
+ "Before=%s\n",
+ facility, facility);
+
+ fflush(file);
+ if (ferror(file)) {
+ log_error("Failed to write unit file %s: %m", unit);
+ return -errno;
+ }
+ fclose(file);
+
+ if (*j[0] != '+') {
+ free (unit);
+ unit = strjoin(arg_dest, "/", facility, ".d/50-hard-dependency-",basename(filename),"-",parsed[0],".conf", NULL);
+ if (!unit)
+ return log_oom();
+
+ mkdir_parents_label(unit, 0755);
+
+ file = fopen(unit, "wxe");
+ if (!file) {
+ if (errno == EEXIST)
+ log_error("Failed to create drop-in file %s, as it already exists", unit);
+ else
+ log_error("Failed to create drop-in file %s: %m", unit);
+ return -errno;
+ }
+
+
+ fprintf(file,
+ "# Automatically generated by systemd-insserv-generator\n\n"
+ "[Unit]\n"
+ "SourcePath=%s\n"
+ "Requires=%s\n",
+ filename, dep);
+ fflush(file);
+ if (ferror(file)) {
+ log_error("Failed to write unit file %s: %m", unit);
+ return -errno;
+ }
+ fclose(file);
+ }
+ }
+ }
+ }
+ }
+ return r;
+}
+
+static int parse_insserv(void) {
+ DIR *d = NULL;
+ struct dirent *de;
+ int r = 0;
+
+ if (!(d = opendir("/etc/insserv.conf.d/"))) {
+ if (errno != ENOENT) {
+ log_debug("opendir() failed on /etc/insserv.conf.d/ %s", strerror(errno));
+ }
+ } else {
+
+ while ((de = readdir(d))) {
+ char *path = NULL;
+ if (ignore_file(de->d_name))
+ continue;
+
+ path = strjoin("/etc/insserv.conf.d/", de->d_name, NULL);
+ parse_insserv_conf(path);
+ free(path);
+ }
+ closedir (d);
+ }
+
+ r = parse_insserv_conf("/etc/insserv.conf");
+
+ return r;
+}
+
+int main(int argc, char *argv[]) {
+ int r = 0;
+
+ if (argc > 1 && argc != 4) {
+ log_error("This program takes three or no arguments.");
+ return EXIT_FAILURE;
+ }
+
+ if (argc > 1)
+ arg_dest = argv[1];
+
+ log_set_target(LOG_TARGET_SAFE);
+ log_parse_environment();
+ log_open();
+
+ umask(0022);
+
+ r = parse_insserv();
+
+ return (r < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
From: Michael Biebl <biebl@debian.org>
Date: Sat, 26 Apr 2014 14:25:41 +0200
Subject: Add targets for compatibility with Debian insserv system facilities
---
Makefile.am | 6 ++++++
units/mail-transport-agent.target | 12 ++++++++++++
units/x-display-manager.target | 12 ++++++++++++
3 files changed, 30 insertions(+)
create mode 100644 units/mail-transport-agent.target
create mode 100644 units/x-display-manager.target
diff --git a/Makefile.am b/Makefile.am
index 0e6bd17..7026b15 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -449,6 +449,12 @@ nodist_systemunit_DATA = \
units/initrd-switch-root.service \
units/systemd-nspawn@.service
+if HAVE_SYSV_COMPAT
+nodist_systemunit_DATA += \
+ units/x-display-manager.target \
+ units/mail-transport-agent.target
+endif
+
dist_userunit_DATA = \
units/user/default.target \
units/user/exit.target
diff --git a/units/mail-transport-agent.target b/units/mail-transport-agent.target
new file mode 100644
index 0000000..4d74ec7
--- /dev/null
+++ b/units/mail-transport-agent.target
@@ -0,0 +1,12 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+# This exists mostly for compatibility with SysV/LSB units
+# depending on the $mail-transport-agent system facility.
+[Unit]
+Description=Mail Transport Agent
+RefuseManualStart=yes
diff --git a/units/x-display-manager.target b/units/x-display-manager.target
new file mode 100644
index 0000000..a528dff
--- /dev/null
+++ b/units/x-display-manager.target
@@ -0,0 +1,12 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+# This exists mostly for compatibility with SysV/LSB units
+# depending on the $x-display-manager system facility.
+[Unit]
+Description=X11 Display Manager
+RefuseManualStart=yes
......@@ -45,10 +45,11 @@
0045-Revert-service-ignore-dependencies-on-syslog-and-loc.patch
0046-Revert-service-drop-support-for-SysV-scripts-for-the.patch
0047-ignore-chkconfig-headers-entirely-they-are-often-bro.patch
0048-Fix-mounting-of-remote-filesystems-like-NFS.patch
0049-Order-remote-fs.target-after-local-fs.target.patch
0050-Load-sg-module-from-80-drivers.rules.patch
0051-Updates-to-default-device-permissions.patch
0052-Set-default-polling-interval-on-removable-devices-as.patch
0053-Make-sd_login_monitor_new-work-for-logind-without-sy.patch
0054-logind-if-a-user-is-sitting-in-front-of-the-computer.patch
0048-Order-remote-fs.target-after-local-fs.target.patch
0049-Load-sg-module-from-80-drivers.rules.patch
0050-Updates-to-default-device-permissions.patch
0051-Set-default-polling-interval-on-removable-devices-as.patch
0052-Make-sd_login_monitor_new-work-for-logind-without-sy.patch
0053-logind-if-a-user-is-sitting-in-front-of-the-computer.patch
0054-insserv.conf-generator.patch
0055-Add-targets-for-compatibility-with-Debian-insserv-sy.patch
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment