summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am28
-rw-r--r--man/systemctl.xml3
-rw-r--r--man/systemd.preset.xml4
-rw-r--r--man/systemd.unit.xml36
-rw-r--r--src/shared/install.c100
-rw-r--r--system-preset/90-systemd.preset7
l---------units/user/bluetooth.target1
l---------units/user/busnames.target1
l---------units/user/paths.target1
l---------units/user/printer.target1
l---------units/user/shutdown.target1
l---------units/user/smartcard.target1
l---------units/user/sockets.target1
l---------units/user/sound.target1
l---------units/user/timers.target1
15 files changed, 125 insertions, 62 deletions
diff --git a/Makefile.am b/Makefile.am
index d4e3e9a013..a1bb21e4fc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -575,7 +575,16 @@ dist_userunit_DATA = \
units/user/default.target \
units/user/exit.target \
units/user/graphical-session.target \
- units/user/graphical-session-pre.target
+ units/user/graphical-session-pre.target \
+ units/user/bluetooth.target \
+ units/user/busnames.target \
+ units/user/paths.target \
+ units/user/printer.target \
+ units/user/shutdown.target \
+ units/user/smartcard.target \
+ units/user/sockets.target \
+ units/user/sound.target \
+ units/user/timers.target
nodist_userunit_DATA = \
units/user/systemd-exit.service
@@ -634,6 +643,10 @@ EXTRA_DIST += \
units/rc-local.service.in \
units/halt-local.service.in
+GENERAL_ALIASES += \
+ $(systemunitdir)/reboot.target $(pkgsysconfdir)/system/ctrl-alt-del.target \
+ $(systemunitdir)/machines.target $(pkgsysconfdir)/system/multi-user.target.wants/machines.target
+
# automake is broken and can't handle files with a dash in front
# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=14728#8
units-install-hook:
@@ -6292,19 +6305,6 @@ SYSTEM_UNIT_ALIASES += \
reboot.target ctrl-alt-del.target \
getty@.service autovt@.service
-USER_UNIT_ALIASES += \
- $(systemunitdir)/shutdown.target shutdown.target \
- $(systemunitdir)/sockets.target sockets.target \
- $(systemunitdir)/timers.target timers.target \
- $(systemunitdir)/paths.target paths.target \
- $(systemunitdir)/bluetooth.target bluetooth.target \
- $(systemunitdir)/printer.target printer.target \
- $(systemunitdir)/sound.target sound.target \
- $(systemunitdir)/smartcard.target smartcard.target
-
-USER_UNIT_ALIASES += \
- $(systemunitdir)/busnames.target busnames.target
-
GENERAL_ALIASES += \
$(systemunitdir)/remote-fs.target $(pkgsysconfdir)/system/multi-user.target.wants/remote-fs.target \
$(systemunitdir)/getty@.service $(pkgsysconfdir)/system/getty.target.wants/getty@tty1.service \
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 9762fd0450..fde4f4f3bb 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1092,7 +1092,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
enabled and disabled, or only enabled, or only disabled.</para>
<para>If the unit carries no install information, it will be silently ignored
- by this command.</para>
+ by this command. <replaceable>NAME</replaceable> must be the real unit name,
+ any alias names are ignored silently.</para>
<para>For more information on the preset policy format, see
<citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml
index b7164014f0..d09167baaf 100644
--- a/man/systemd.preset.xml
+++ b/man/systemd.preset.xml
@@ -98,6 +98,10 @@
Empty lines and lines whose first non-whitespace character is # or
; are ignored.</para>
+ <para>Presets must refer to the "real" unit file, and not to any aliases. See
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a description of unit aliasing.</para>
+
<para>Two different directives are understood:
<literal>enable</literal> may be used to enable units by default,
<literal>disable</literal> to disable units by default.</para>
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 85a7b12d76..f818e772a9 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -144,21 +144,31 @@
<option>false</option> and <option>off</option> are
equivalent.</para>
- <para>Time span values encoded in unit files can be written in
- various formats. A stand-alone number specifies a time in seconds.
- If suffixed with a time unit, the unit is honored. A concatenation
- of multiple values with units is supported, in which case the
- values are added up. Example: "50" refers to 50 seconds; "2min
- 200ms" refers to 2 minutes plus 200 milliseconds, i.e. 120200ms.
- The following time units are understood: s, min, h, d, w, ms, us.
- For details see
+ <para>Time span values encoded in unit files can be written in various formats. A stand-alone number specifies a
+ time in seconds. If suffixed with a time unit, the unit is honored. A concatenation of multiple values with units
+ is supported, in which case the values are added up. Example: <literal>50</literal> refers to 50 seconds;
+ <literal>2min 200ms</literal> refers to 2 minutes and 200 milliseconds, i.e. 120200 ms. The following time units
+ are understood: <literal>s</literal>, <literal>min</literal>, <literal>h</literal>, <literal>d</literal>,
+ <literal>w</literal>, <literal>ms</literal>, <literal>us</literal>. For details see
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
- <para>Empty lines and lines starting with # or ; are
- ignored. This may be used for commenting. Lines ending
- in a backslash are concatenated with the following
- line while reading and the backslash is replaced by a
- space character. This may be used to wrap long lines.</para>
+ <para>Empty lines and lines starting with <literal>#</literal> or <literal>;</literal> are ignored. This may be
+ used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the
+ backslash is replaced by a space character. This may be used to wrap long lines.</para>
+
+ <para>Units can be aliased (have an alternative name), by creating a symlink from the new name to the existing name
+ in one of the unit search paths. For example, <filename>systemd-networkd.service</filename> has the alias
+ <filename>dbus-org.freedesktop.network1.service</filename>, created during installation as the symlink
+ <filename>/usr/lib/systemd/system/dbus-org.freedesktop.network1.service</filename>. In addition, unit files may
+ specify aliases through the <varname>Alias=</varname> directive in the [Install] section; those aliases are only
+ effective when the unit is enabled. When the unit is enabled, symlinks will be created for those names, and removed
+ when the unit is disabled. For example, <filename>reboot.target</filename> specifies
+ <varname>Alias=ctrl-alt-del.target</varname>, so when enabled it will be invoked whenever CTRL+ALT+DEL is
+ pressed. Alias names may be used in commands like <command>enable</command>, <command>disable</command>,
+ <command>start</command>, <command>stop</command>, <command>status</command>, …, and in unit dependency directives
+ <varname>Wants=</varname>, <varname>Requires=</varname>, <varname>Before=</varname>, <varname>After=</varname>, …,
+ with the limitation that aliases specified through <varname>Alias=</varname> are only effective when the unit is
+ enabled. Aliases cannot be used with the <command>preset</command> command.</para>
<para>Along with a unit file <filename>foo.service</filename>, the
directory <filename>foo.service.wants/</filename> may exist. All
diff --git a/src/shared/install.c b/src/shared/install.c
index e740ef3910..6a16f8985b 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -393,19 +393,40 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
log_error_errno(r, "Failed to %s: %m.", verb);
}
+/**
+ * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
+ * wc should be the full path in the host file system.
+ */
+static bool chroot_symlinks_same(const char *root, const char *wd, const char *a, const char *b) {
+ assert(path_is_absolute(wd));
+
+ /* This will give incorrect results if the paths are relative and go outside
+ * of the chroot. False negatives are possible. */
+
+ a = strjoina(path_is_absolute(a) ? root : wd, "/", a);
+ b = strjoina(path_is_absolute(b) ? root : wd, "/", b);
+ return path_equal_or_files_same(a, b);
+}
+
static int create_symlink(
+ const LookupPaths *paths,
const char *old_path,
const char *new_path,
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
- _cleanup_free_ char *dest = NULL;
+ _cleanup_free_ char *dest = NULL, *dirname = NULL;
+ const char *rp;
int r;
assert(old_path);
assert(new_path);
+ rp = skip_root(paths, old_path);
+ if (rp)
+ old_path = rp;
+
/* Actually create a symlink, and remember that we did. Is
* smart enough to check if there's already a valid symlink in
* place.
@@ -436,7 +457,11 @@ static int create_symlink(
return r;
}
- if (path_equal(dest, old_path))
+ dirname = dirname_malloc(new_path);
+ if (!dirname)
+ return -ENOMEM;
+
+ if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path))
return 1;
if (!force) {
@@ -620,7 +645,7 @@ static int remove_marked_symlinks(
fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (fd < 0)
- return -errno;
+ return errno == ENOENT ? 0 : -errno;
do {
int q, cfd;
@@ -903,6 +928,10 @@ static int install_info_may_process(
return 0;
}
+/**
+ * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
+ * hashmap, or retrieves the existing one if already present.
+ */
static int install_info_add(
InstallContext *c,
const char *name,
@@ -1334,9 +1363,8 @@ static int install_info_follow(
}
/**
- * Search for the unit file. If the unit name is a symlink,
- * follow the symlink to the target, maybe more than once.
- * Propagate the instance name if present.
+ * Search for the unit file. If the unit name is a symlink, follow the symlink to the
+ * target, maybe more than once. Propagate the instance name if present.
*/
static int install_info_traverse(
UnitFileScope scope,
@@ -1421,6 +1449,10 @@ static int install_info_traverse(
return 0;
}
+/**
+ * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
+ * or the name (otherwise). root_dir is prepended to the path.
+ */
static int install_info_add_auto(
InstallContext *c,
const LookupPaths *paths,
@@ -1479,7 +1511,6 @@ static int install_info_symlink_alias(
STRV_FOREACH(s, i->aliases) {
_cleanup_free_ char *alias_path = NULL, *dst = NULL;
- const char *rp;
q = install_full_printf(i, *s, &dst);
if (q < 0)
@@ -1489,9 +1520,7 @@ static int install_info_symlink_alias(
if (!alias_path)
return -ENOMEM;
- rp = skip_root(paths, i->path);
-
- q = create_symlink(rp ?: i->path, alias_path, force, changes, n_changes);
+ q = create_symlink(paths, i->path, alias_path, force, changes, n_changes);
if (r == 0)
r = q;
}
@@ -1535,7 +1564,6 @@ static int install_info_symlink_wants(
STRV_FOREACH(s, list) {
_cleanup_free_ char *path = NULL, *dst = NULL;
- const char *rp;
q = install_full_printf(i, *s, &dst);
if (q < 0)
@@ -1550,9 +1578,7 @@ static int install_info_symlink_wants(
if (!path)
return -ENOMEM;
- rp = skip_root(paths, i->path);
-
- q = create_symlink(rp ?: i->path, path, true, changes, n_changes);
+ q = create_symlink(paths, i->path, path, true, changes, n_changes);
if (r == 0)
r = q;
}
@@ -1569,7 +1595,6 @@ static int install_info_symlink_link(
unsigned *n_changes) {
_cleanup_free_ char *path = NULL;
- const char *rp;
int r;
assert(i);
@@ -1587,9 +1612,7 @@ static int install_info_symlink_link(
if (!path)
return -ENOMEM;
- rp = skip_root(paths, i->path);
-
- return create_symlink(rp ?: i->path, path, force, changes, n_changes);
+ return create_symlink(paths, i->path, path, force, changes, n_changes);
}
static int install_info_apply(
@@ -1663,6 +1686,17 @@ static int install_context_apply(
if (r < 0)
return r;
+ /* We can attempt to process a masked unit when a different unit
+ * that we were processing specifies it in DefaultInstance= or Also=. */
+ if (i->type == UNIT_FILE_TYPE_MASKED) {
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL);
+ if (r >= 0)
+ /* Assume that some *could* have been enabled here, avoid
+ * "empty [Install] section" warning. */
+ r += 1;
+ continue;
+ }
+
if (i->type != UNIT_FILE_TYPE_REGULAR)
continue;
@@ -1765,7 +1799,7 @@ int unit_file_mask(
if (!path)
return -ENOMEM;
- q = create_symlink("/dev/null", path, force, changes, n_changes);
+ q = create_symlink(&paths, "/dev/null", path, force, changes, n_changes);
if (q < 0 && r >= 0)
r = q;
}
@@ -1925,14 +1959,12 @@ int unit_file_link(
r = 0;
STRV_FOREACH(i, todo) {
_cleanup_free_ char *new_path = NULL;
- const char *old_path;
- old_path = skip_root(&paths, *i);
new_path = path_make_absolute(basename(*i), config_path);
if (!new_path)
return -ENOMEM;
- q = create_symlink(old_path ?: *i, new_path, force, changes, n_changes);
+ q = create_symlink(&paths, *i, new_path, force, changes, n_changes);
if (q < 0 && r >= 0)
r = q;
}
@@ -1967,7 +1999,6 @@ int unit_file_revert(
unsigned *n_changes) {
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- /* _cleanup_(install_context_done) InstallContext c = {}; */
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_strv_free_ char **todo = NULL;
size_t n_todo = 0, n_allocated = 0;
@@ -2312,7 +2343,7 @@ int unit_file_set_default(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
UnitFileInstallInfo *i;
- const char *new_path, *old_path;
+ const char *new_path;
int r;
assert(scope >= 0);
@@ -2335,10 +2366,8 @@ int unit_file_set_default(
if (r < 0)
return r;
- old_path = skip_root(&paths, i->path);
new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET);
-
- return create_symlink(old_path ?: i->path, new_path, force, changes, n_changes);
+ return create_symlink(&paths, i->path, new_path, force, changes, n_changes);
}
int unit_file_get_default(
@@ -2685,18 +2714,25 @@ static int preset_prepare_one(
InstallContext *plus,
InstallContext *minus,
LookupPaths *paths,
- UnitFilePresetMode mode,
const char *name,
Presets presets,
UnitFileChange **changes,
unsigned *n_changes) {
+ _cleanup_(install_context_done) InstallContext tmp = {};
UnitFileInstallInfo *i;
int r;
- if (install_info_find(plus, name) ||
- install_info_find(minus, name))
+ if (install_info_find(plus, name) || install_info_find(minus, name))
+ return 0;
+
+ r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
+ if (r < 0)
+ return r;
+ if (!streq(name, i->name)) {
+ log_debug("Skipping %s because is an alias for %s", name, i->name);
return 0;
+ }
r = query_presets(name, presets);
if (r < 0)
@@ -2748,7 +2784,7 @@ int unit_file_preset(
return r;
STRV_FOREACH(i, files) {
- r = preset_prepare_one(scope, &plus, &minus, &paths, mode, *i, presets, changes, n_changes);
+ r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
if (r < 0)
return r;
}
@@ -2809,7 +2845,7 @@ int unit_file_preset_all(
continue;
/* we don't pass changes[] in, because we want to handle errors on our own */
- r = preset_prepare_one(scope, &plus, &minus, &paths, mode, de->d_name, presets, NULL, 0);
+ r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
if (r == -ERFKILL)
r = unit_file_changes_add(changes, n_changes,
UNIT_FILE_IS_MASKED, de->d_name, NULL);
diff --git a/system-preset/90-systemd.preset b/system-preset/90-systemd.preset
index ee1b864bcf..0f494b7552 100644
--- a/system-preset/90-systemd.preset
+++ b/system-preset/90-systemd.preset
@@ -15,6 +15,7 @@ enable getty@.service
enable systemd-timesyncd.service
enable systemd-networkd.service
enable systemd-resolved.service
+enable systemd-networkd-wait-online.service
disable console-getty.service
disable console-shell.service
@@ -23,10 +24,12 @@ disable debug-shell.service
disable halt.target
disable kexec.target
disable poweroff.target
-disable reboot.target
+enable reboot.target
disable rescue.target
+disable exit.target
disable syslog.socket
disable systemd-journal-gatewayd.*
-disable systemd-networkd-wait-online.service
+disable systemd-journal-remote.*
+disable systemd-journal-upload.*
diff --git a/units/user/bluetooth.target b/units/user/bluetooth.target
new file mode 120000
index 0000000000..72e74be0a1
--- /dev/null
+++ b/units/user/bluetooth.target
@@ -0,0 +1 @@
+../bluetooth.target \ No newline at end of file
diff --git a/units/user/busnames.target b/units/user/busnames.target
new file mode 120000
index 0000000000..04f4ba1345
--- /dev/null
+++ b/units/user/busnames.target
@@ -0,0 +1 @@
+../busnames.target \ No newline at end of file
diff --git a/units/user/paths.target b/units/user/paths.target
new file mode 120000
index 0000000000..33545d24f3
--- /dev/null
+++ b/units/user/paths.target
@@ -0,0 +1 @@
+../paths.target \ No newline at end of file
diff --git a/units/user/printer.target b/units/user/printer.target
new file mode 120000
index 0000000000..8b8d5511cd
--- /dev/null
+++ b/units/user/printer.target
@@ -0,0 +1 @@
+../printer.target \ No newline at end of file
diff --git a/units/user/shutdown.target b/units/user/shutdown.target
new file mode 120000
index 0000000000..a9de83782f
--- /dev/null
+++ b/units/user/shutdown.target
@@ -0,0 +1 @@
+../shutdown.target \ No newline at end of file
diff --git a/units/user/smartcard.target b/units/user/smartcard.target
new file mode 120000
index 0000000000..f7a23b6b6d
--- /dev/null
+++ b/units/user/smartcard.target
@@ -0,0 +1 @@
+../smartcard.target \ No newline at end of file
diff --git a/units/user/sockets.target b/units/user/sockets.target
new file mode 120000
index 0000000000..a9e4b97184
--- /dev/null
+++ b/units/user/sockets.target
@@ -0,0 +1 @@
+../sockets.target \ No newline at end of file
diff --git a/units/user/sound.target b/units/user/sound.target
new file mode 120000
index 0000000000..17c8e9d6e1
--- /dev/null
+++ b/units/user/sound.target
@@ -0,0 +1 @@
+../sound.target \ No newline at end of file
diff --git a/units/user/timers.target b/units/user/timers.target
new file mode 120000
index 0000000000..f98b68a84d
--- /dev/null
+++ b/units/user/timers.target
@@ -0,0 +1 @@
+../timers.target \ No newline at end of file