summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/automount.c2
-rw-r--r--src/core/cgroup.c11
-rw-r--r--src/core/device.c4
-rw-r--r--src/core/killall.c3
-rw-r--r--src/core/load-fragment-gperf.gperf.m422
-rw-r--r--src/core/load-fragment.c123
-rw-r--r--src/core/machine-id-setup.c2
-rw-r--r--src/core/manager.c16
-rw-r--r--src/core/mount-setup.c2
-rw-r--r--src/core/mount.c2
-rw-r--r--src/core/namespace.c6
-rw-r--r--src/core/scope.c7
-rw-r--r--src/core/service.c35
-rw-r--r--src/core/service.h2
-rw-r--r--src/core/socket.c8
-rw-r--r--src/core/swap.c2
-rw-r--r--src/core/umount.c19
-rw-r--r--src/core/unit-printf.c61
-rw-r--r--src/core/unit.c14
19 files changed, 191 insertions, 150 deletions
diff --git a/src/core/automount.c b/src/core/automount.c
index 5fa6eb7b18..8ff1ca90f7 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -783,7 +783,7 @@ static int automount_start(Unit *u) {
assert(a);
assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
- if (path_is_mount_point(a->where, 0) > 0) {
+ if (path_is_mount_point(a->where, NULL, 0) > 0) {
log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where);
return -EEXIST;
}
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 6dab6e9043..5789e2aa82 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -287,14 +287,21 @@ static int lookup_block_device(const char *p, dev_t *dev) {
static int whitelist_device(const char *path, const char *node, const char *acc) {
char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
struct stat st;
+ bool ignore_notfound;
int r;
assert(path);
assert(acc);
+ if (node[0] == '-') {
+ /* Non-existent paths starting with "-" must be silently ignored */
+ node++;
+ ignore_notfound = true;
+ } else
+ ignore_notfound = false;
+
if (stat(node, &st) < 0) {
- /* path starting with "-" must be silently ignored */
- if (errno == ENOENT && startswith(node, "-"))
+ if (errno == ENOENT && ignore_notfound)
return 0;
return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
diff --git a/src/core/device.c b/src/core/device.c
index 8e2e3c7bed..e345552f24 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -359,7 +359,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
fail:
log_unit_warning_errno(u, r, "Failed to set up device unit: %m");
- if (delete && u)
+ if (delete)
unit_free(u);
return r;
@@ -418,7 +418,7 @@ static int device_process_new(Manager *m, struct udev_device *dev) {
* aliases */
alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
for (;;) {
- _cleanup_free_ char *word = NULL, *k = NULL;
+ _cleanup_free_ char *word = NULL;
r = extract_first_word(&alias, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
diff --git a/src/core/killall.c b/src/core/killall.c
index 3bc19e9c84..b3aa22adc5 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -24,6 +24,7 @@
#include "alloc-util.h"
#include "def.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "killall.h"
@@ -172,7 +173,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
if (!dir)
return -errno;
- while ((d = readdir(dir))) {
+ FOREACH_DIRENT_ALL(d, dir, break) {
pid_t pid;
int r;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index f4ef5a0140..2610442b91 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -191,13 +191,13 @@ Unit.IgnoreOnIsolate, config_parse_bool, 0,
Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout)
Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
-Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg)
+Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg)
Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
m4_dnl The following is a legacy alias name for compatibility
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
-Unit.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg)
+Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
@@ -254,7 +254,7 @@ m4_dnl The following three only exist for compatibility, they moved into Unit, s
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
-Service.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg)
+Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg)
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action)
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
@@ -272,8 +272,8 @@ Service.FileDescriptorStoreMax, config_parse_unsigned, 0,
Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
Service.Sockets, config_parse_service_sockets, 0, 0
Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
-Service.USBFunctionDescriptors, config_parse_path, 0, offsetof(Service, usb_function_descriptors)
-Service.USBFunctionStrings, config_parse_path, 0, offsetof(Service, usb_function_strings)
+Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors)
+Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings)
EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
@@ -332,9 +332,9 @@ Socket.Service, config_parse_socket_service, 0,
Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
m4_ifdef(`HAVE_SMACK',
-`Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
-Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in)
-Socket.SmackLabelIPOut, config_parse_string, 0, offsetof(Socket, smack_ip_out)',
+`Socket.SmackLabel, config_parse_unit_string_printf, 0, offsetof(Socket, smack)
+Socket.SmackLabelIPIn, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_in)
+Socket.SmackLabelIPOut, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_out)',
`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
@@ -354,9 +354,9 @@ BusName.AllowWorld, config_parse_bus_policy_world, 0,
BusName.SELinuxContext, config_parse_exec_selinux_context, 0, 0
BusName.AcceptFileDescriptors, config_parse_bool, 0, offsetof(BusName, accept_fd)
m4_dnl
-Mount.What, config_parse_string, 0, offsetof(Mount, parameters_fragment.what)
+Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
Mount.Where, config_parse_path, 0, offsetof(Mount, where)
-Mount.Options, config_parse_string, 0, offsetof(Mount, parameters_fragment.options)
+Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype)
Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec)
Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
@@ -373,7 +373,7 @@ Automount.TimeoutIdleSec, config_parse_sec, 0,
m4_dnl
Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
-Swap.Options, config_parse_string, 0, offsetof(Swap, parameters_fragment.options)
+Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec)
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 970eed27c1..687cd1dd31 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -579,6 +579,7 @@ int config_parse_exec(
void *userdata) {
ExecCommand **e = data;
+ Unit *u = userdata;
const char *p;
bool semicolon;
int r;
@@ -604,8 +605,7 @@ int config_parse_exec(
_cleanup_free_ ExecCommand *nce = NULL;
_cleanup_strv_free_ char **n = NULL;
size_t nlen = 0, nbufsize = 0;
- char *f;
- int i;
+ const char *f;
semicolon = false;
@@ -614,7 +614,7 @@ int config_parse_exec(
return 0;
f = firstword;
- for (i = 0; i < 3; i++) {
+ for (;;) {
/* We accept an absolute path as first argument.
* If it's prefixed with - and the path doesn't exist,
* we ignore it instead of erroring out;
@@ -631,47 +631,47 @@ int config_parse_exec(
f++;
}
- if (isempty(f)) {
+ r = unit_full_printf(u, f, &path);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", f);
+ return 0;
+ }
+
+ if (isempty(path)) {
/* First word is either "-" or "@" with no command. */
log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
return 0;
}
- if (!string_is_safe(f)) {
+ if (!string_is_safe(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
return 0;
}
- if (!path_is_absolute(f)) {
+ if (!path_is_absolute(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
return 0;
}
- if (endswith(f, "/")) {
+ if (endswith(path, "/")) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
return 0;
}
- if (f == firstword) {
- path = firstword;
- firstword = NULL;
- } else {
- path = strdup(f);
- if (!path)
- return log_oom();
- }
-
if (!separate_argv0) {
+ char *w = NULL;
+
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- f = strdup(path);
- if (!f)
+
+ w = strdup(path);
+ if (!w)
return log_oom();
- n[nlen++] = f;
+ n[nlen++] = w;
n[nlen] = NULL;
}
path_kill_slashes(path);
while (!isempty(p)) {
- _cleanup_free_ char *word = NULL;
+ _cleanup_free_ char *word = NULL, *resolved = NULL;
/* Check explicitly for an unquoted semicolon as
* command separator token. */
@@ -682,18 +682,21 @@ int config_parse_exec(
break;
}
- /* Check for \; explicitly, to not confuse it with \\;
- * or "\;" or "\\;" etc. extract_first_word would
- * return the same for all of those. */
+ /* Check for \; explicitly, to not confuse it with \\; or "\;" or "\\;" etc.
+ * extract_first_word() would return the same for all of those. */
if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) {
+ char *w;
+
p += 2;
p += strspn(p, WHITESPACE);
+
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- f = strdup(";");
- if (!f)
+
+ w = strdup(";");
+ if (!w)
return log_oom();
- n[nlen++] = f;
+ n[nlen++] = w;
n[nlen] = NULL;
continue;
}
@@ -701,14 +704,20 @@ int config_parse_exec(
r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
if (r == 0)
break;
- else if (r < 0)
+ if (r < 0)
return 0;
+ r = unit_full_printf(u, word, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to resolve unit specifiers on %s, ignoring: %m", word);
+ return 0;
+ }
+
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- n[nlen++] = word;
+ n[nlen++] = resolved;
n[nlen] = NULL;
- word = NULL;
+ resolved = NULL;
}
if (!n || !n[0]) {
@@ -1326,7 +1335,7 @@ int config_parse_exec_selinux_context(
} else
ignore = false;
- r = unit_name_printf(u, rvalue, &k);
+ r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
@@ -1374,7 +1383,7 @@ int config_parse_exec_apparmor_profile(
} else
ignore = false;
- r = unit_name_printf(u, rvalue, &k);
+ r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
@@ -1422,7 +1431,7 @@ int config_parse_exec_smack_process_label(
} else
ignore = false;
- r = unit_name_printf(u, rvalue, &k);
+ r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
@@ -1689,7 +1698,7 @@ int config_parse_fdname(
return 0;
}
- r = unit_name_printf(UNIT(s), rvalue, &p);
+ r = unit_full_printf(UNIT(s), rvalue, &p);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
return 0;
@@ -2555,7 +2564,7 @@ int config_parse_unit_requires_mounts_for(
assert(data);
for (p = rvalue;; ) {
- _cleanup_free_ char *word = NULL;
+ _cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
@@ -2573,9 +2582,15 @@ int config_parse_unit_requires_mounts_for(
continue;
}
- r = unit_require_mounts_for(u, word);
+ r = unit_full_printf(u, word, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit name \"%s\", ignoring: %m", word);
+ continue;
+ }
+
+ r = unit_require_mounts_for(u, resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", resolved);
continue;
}
}
@@ -3710,7 +3725,7 @@ int config_parse_runtime_directory(
return 0;
}
- r = unit_name_printf(u, word, &k);
+ r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to resolve specifiers in \"%s\", ignoring: %m", word);
@@ -3812,8 +3827,8 @@ int config_parse_namespace_path_strv(
void *data,
void *userdata) {
+ Unit *u = userdata;
char*** sv = data;
- const char *prev;
const char *cur;
int r;
@@ -3828,10 +3843,10 @@ int config_parse_namespace_path_strv(
return 0;
}
- prev = cur = rvalue;
+ cur = rvalue;
for (;;) {
- _cleanup_free_ char *word = NULL;
- int offset;
+ _cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL;
+ bool ignore_enoent;
r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
@@ -3839,31 +3854,37 @@ int config_parse_namespace_path_strv(
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage, ignoring: %s", prev);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
return 0;
}
if (!utf8_is_valid(word)) {
log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
- prev = cur;
continue;
}
- offset = word[0] == '-';
- if (!path_is_absolute(word + offset)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", word);
- prev = cur;
+ ignore_enoent = word[0] == '-';
+
+ r = unit_full_printf(u, word + ignore_enoent, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s: %m", word);
+ continue;
+ }
+
+ if (!path_is_absolute(resolved)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", resolved);
continue;
}
- path_kill_slashes(word + offset);
+ path_kill_slashes(resolved);
- r = strv_push(sv, word);
+ joined = strjoin(ignore_enoent ? "-" : "", resolved);
+
+ r = strv_push(sv, joined);
if (r < 0)
return log_oom();
- prev = cur;
- word = NULL;
+ joined = NULL;
}
return 0;
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 76dfcfa6d7..c83bb561c7 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -199,7 +199,7 @@ int machine_id_commit(const char *root) {
etc_machine_id = prefix_roota(root, "/etc/machine-id");
- r = path_is_mount_point(etc_machine_id, 0);
+ r = path_is_mount_point(etc_machine_id, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id);
if (r == 0) {
diff --git a/src/core/manager.c b/src/core/manager.c
index 1f663d3c1d..1192b20b74 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/kd.h>
@@ -233,6 +232,7 @@ static void manager_print_jobs_in_progress(Manager *m) {
static int have_ask_password(void) {
_cleanup_closedir_ DIR *dir;
+ struct dirent *de;
dir = opendir("/run/systemd/ask-password");
if (!dir) {
@@ -242,19 +242,11 @@ static int have_ask_password(void) {
return -errno;
}
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(dir);
- if (!de && errno > 0)
- return -errno;
- if (!de)
- return false;
-
+ FOREACH_DIRENT_ALL(de, dir, return -errno) {
if (startswith(de->d_name, "ask."))
return true;
}
+ return false;
}
static int manager_dispatch_ask_password_fd(sd_event_source *source,
@@ -2958,7 +2950,7 @@ static void manager_notify_finished(Manager *m) {
total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
log_struct(LOG_INFO,
- LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
+ LOG_MESSAGE_ID(SD_MESSAGE_USER_STARTUP_FINISHED),
"USERSPACE_USEC="USEC_FMT, userspace_usec,
LOG_MESSAGE("Startup finished in %s.",
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)),
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index ca63a93e8b..6338067d7e 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -159,7 +159,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
if (relabel)
(void) label_fix(p->where, true, true);
- r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
+ r = path_is_mount_point(p->where, NULL, AT_SYMLINK_FOLLOW);
if (r < 0 && r != -ENOENT) {
log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, r, "Failed to determine whether %s is a mount point: %m", p->where);
return (p->mode & MNT_FATAL) ? r : 0;
diff --git a/src/core/mount.c b/src/core/mount.c
index 1c2be28d55..0c4d061c27 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1509,7 +1509,7 @@ static int mount_setup_unit(
fail:
log_warning_errno(r, "Failed to set up mount unit: %m");
- if (delete && u)
+ if (delete)
unit_free(u);
return r;
diff --git a/src/core/namespace.c b/src/core/namespace.c
index e9ad26bfc3..aca47a4d2f 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -596,7 +596,7 @@ static int apply_mount(
case READONLY:
case READWRITE:
- r = path_is_mount_point(bind_mount_path(m), 0);
+ r = path_is_mount_point(bind_mount_path(m), NULL, 0);
if (r < 0)
return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", bind_mount_path(m));
if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */
@@ -665,7 +665,7 @@ static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned
_cleanup_free_ char *chased = NULL;
int k;
- k = chase_symlinks(bind_mount_path(f), root_directory, &chased);
+ k = chase_symlinks(bind_mount_path(f), root_directory, 0, &chased);
if (k < 0) {
/* Get only real errors */
if (r >= 0 && (k != -ENOENT || !f->ignore))
@@ -860,7 +860,7 @@ int setup_namespace(
if (root_directory) {
/* Turn directory into bind mount, if it isn't one yet */
- r = path_is_mount_point(root_directory, AT_SYMLINK_FOLLOW);
+ r = path_is_mount_point(root_directory, NULL, AT_SYMLINK_FOLLOW);
if (r < 0)
goto finish;
if (r == 0) {
diff --git a/src/core/scope.c b/src/core/scope.c
index d6e1f8e392..9540fb67d9 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -273,7 +273,9 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
if (state == SCOPE_STOP_SIGTERM)
skip_signal = bus_scope_send_request_stop(s) > 0;
- if (!skip_signal) {
+ if (skip_signal)
+ r = 1; /* wait */
+ else {
r = unit_kill_context(
UNIT(s),
&s->kill_context,
@@ -283,8 +285,7 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
-1, -1, false);
if (r < 0)
goto fail;
- } else
- r = 1;
+ }
if (r > 0) {
r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
diff --git a/src/core/service.c b/src/core/service.c
index c68a7122b6..576416ad29 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -49,7 +49,6 @@
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
-#include "unit-printf.h"
#include "unit.h"
#include "utf8.h"
#include "util.h"
@@ -1205,7 +1204,7 @@ static int service_spawn(
ExecFlags flags,
pid_t *_pid) {
- _cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL, **fd_names = NULL;
+ _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL, **fd_names = NULL;
_cleanup_free_ int *fds = NULL;
unsigned n_fds = 0, n_env = 0;
const char *path;
@@ -1263,10 +1262,6 @@ static int service_spawn(
if (r < 0)
return r;
- r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
- if (r < 0)
- return r;
-
our_env = new0(char*, 9);
if (!our_env)
return -ENOMEM;
@@ -1349,7 +1344,7 @@ static int service_spawn(
} else
path = UNIT(s)->cgroup_path;
- exec_params.argv = argv;
+ exec_params.argv = c->argv;
exec_params.environment = final_env;
exec_params.fds = fds;
exec_params.fd_names = fd_names;
@@ -1714,7 +1709,7 @@ static void service_enter_running(Service *s, ServiceResult f) {
}
} else if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
else if (s->remain_after_exit)
service_set_state(s, SERVICE_EXITED);
else
@@ -1851,7 +1846,7 @@ static void service_enter_start(Service *s) {
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start' task: %m");
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
static void service_enter_start_pre(Service *s) {
@@ -1997,9 +1992,7 @@ static void service_run_next_control(Service *s) {
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m");
- if (s->state == SERVICE_START_PRE)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
- else if (s->state == SERVICE_STOP)
+ if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_STOP))
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
@@ -2600,7 +2593,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
case SERVICE_START:
if (s->type == SERVICE_NOTIFY) {
/* No chance of getting a ready notification anymore */
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL);
break;
}
@@ -2613,7 +2606,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
service_unwatch_pid_file(s);
if (s->state == SERVICE_START)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL);
else
service_enter_stop(s, SERVICE_FAILURE_PROTOCOL);
}
@@ -2747,17 +2740,17 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (f == SERVICE_SUCCESS)
service_enter_start_post(s);
else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
} else if (s->type == SERVICE_NOTIFY) {
/* Only enter running through a notification, so that the
* SERVICE_START state signifies that no ready notification
* has been received */
if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
else if (!s->remain_after_exit)
/* The service has never been active */
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
@@ -2837,7 +2830,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (f == SERVICE_SUCCESS)
service_enter_start(s);
else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
case SERVICE_START:
@@ -2846,7 +2839,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
break;
if (f != SERVICE_SUCCESS) {
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
}
@@ -2863,7 +2856,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (!has_start_post && r < 0) {
r = service_demand_pid_file(s);
if (r < 0 || !cgroup_good(s))
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
} else
@@ -2959,7 +2952,7 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
case SERVICE_START_PRE:
case SERVICE_START:
log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", s->state == SERVICE_START ? "Start" : "Start-pre");
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_START_POST:
diff --git a/src/core/service.h b/src/core/service.h
index e09722a952..ff9cfaeb88 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -79,6 +79,8 @@ typedef enum NotifyState {
_NOTIFY_STATE_INVALID = -1
} NotifyState;
+/* The values of this enum are referenced in man/systemd.exec.xml and src/shared/bus-unit-util.c.
+ * Update those sources for each change to this enum. */
typedef enum ServiceResult {
SERVICE_SUCCESS,
SERVICE_FAILURE_RESOURCES, /* a bit of a misnomer, just our catch-all error for errnos we didn't expect */
diff --git a/src/core/socket.c b/src/core/socket.c
index 1a53d47f21..fee9b702e6 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -54,7 +54,6 @@
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
-#include "unit-printf.h"
#include "unit.h"
#include "user-util.h"
#include "in-addr-util.h"
@@ -1740,7 +1739,6 @@ static int socket_coldplug(Unit *u) {
}
static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
- _cleanup_free_ char **argv = NULL;
pid_t pid;
int r;
ExecParameters exec_params = {
@@ -1772,11 +1770,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
if (r < 0)
return r;
- r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
- if (r < 0)
- return r;
-
- exec_params.argv = argv;
+ exec_params.argv = c->argv;
exec_params.environment = UNIT(s)->manager->environment;
exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
diff --git a/src/core/swap.c b/src/core/swap.c
index bf404db8c3..e9468e105c 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -420,7 +420,7 @@ static int swap_setup_unit(
fail:
log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
- if (delete && u)
+ if (delete)
unit_free(u);
return r;
diff --git a/src/core/umount.c b/src/core/umount.c
index 1e5459ed80..2f4b12bdb9 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -344,24 +344,29 @@ static int delete_loopback(const char *device) {
}
static int delete_dm(dev_t devnum) {
- _cleanup_close_ int fd = -1;
- int r;
+
struct dm_ioctl dm = {
- .version = {DM_VERSION_MAJOR,
- DM_VERSION_MINOR,
- DM_VERSION_PATCHLEVEL},
+ .version = {
+ DM_VERSION_MAJOR,
+ DM_VERSION_MINOR,
+ DM_VERSION_PATCHLEVEL
+ },
.data_size = sizeof(dm),
.dev = devnum,
};
+ _cleanup_close_ int fd = -1;
+
assert(major(devnum) != 0);
fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
if (fd < 0)
return -errno;
- r = ioctl(fd, DM_DEV_REMOVE, &dm);
- return r >= 0 ? 0 : -errno;
+ if (ioctl(fd, DM_DEV_REMOVE, &dm) < 0)
+ return -errno;
+
+ return 0;
}
static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 1f5dc6fd88..746e1a46ef 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -78,12 +78,18 @@ static int specifier_filename(char specifier, void *data, void *userdata, char *
return unit_name_to_path(u->id, ret);
}
+static void bad_specifier(Unit *u, char specifier) {
+ log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
+}
+
static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
char *n;
assert(u);
+ bad_specifier(u, specifier);
+
if (u->cgroup_path)
n = strdup(u->cgroup_path);
else
@@ -101,6 +107,8 @@ static int specifier_cgroup_root(char specifier, void *data, void *userdata, cha
assert(u);
+ bad_specifier(u, specifier);
+
n = strdup(u->manager->cgroup_root);
if (!n)
return -ENOMEM;
@@ -115,6 +123,8 @@ static int specifier_cgroup_slice(char specifier, void *data, void *userdata, ch
assert(u);
+ bad_specifier(u, specifier);
+
if (UNIT_ISSET(u->slice)) {
Unit *slice;
@@ -194,13 +204,20 @@ static int specifier_user_shell(char specifier, void *data, void *userdata, char
int unit_name_printf(Unit *u, const char* format, char **ret) {
/*
- * This will use the passed string as format string and
- * replace the following specifiers:
+ * This will use the passed string as format string and replace the following specifiers (which should all be
+ * safe for inclusion in unit names):
*
* %n: the full id of the unit (foo@bar.waldo)
* %N: the id of the unit without the suffix (foo@bar)
* %p: the prefix (foo)
* %i: the instance (bar)
+ *
+ * %U: the UID of the running user
+ * %u: the username of the running user
+ *
+ * %m: the machine ID of the running system
+ * %H: the host name of the running system
+ * %b: the boot ID of the running system
*/
const Specifier table[] = {
@@ -208,7 +225,14 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
{ 'N', specifier_prefix_and_instance, NULL },
{ 'p', specifier_prefix, NULL },
{ 'i', specifier_string, u->instance },
- { 0, NULL, NULL }
+
+ { 'U', specifier_user_id, NULL },
+ { 'u', specifier_user_name, NULL },
+
+ { 'm', specifier_machine_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'b', specifier_boot_id, NULL },
+ {}
};
assert(u);
@@ -220,22 +244,23 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
int unit_full_printf(Unit *u, const char *format, char **ret) {
- /* This is similar to unit_name_printf() but also supports
- * unescaping. Also, adds a couple of additional codes:
+ /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes
+ * (which are likely not suitable for unescaped inclusion in unit names):
+ *
+ * %f: the unescaped instance if set, otherwise the id unescaped as path
+ * %c: cgroup path of unit (deprecated)
+ * %r: where units in this slice are placed in the cgroup tree (deprecated)
+ * %R: the root of this systemd's instance tree (deprecated)
+ * %t: the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
+ *
+ * %h: the homedir of the running user
+ * %s: the shell of the running user
+ *
+ * %v: `uname -r` of the running system
*
- * %f the instance if set, otherwise the id
- * %c cgroup path of unit
- * %r where units in this slice are placed in the cgroup tree
- * %R the root of this systemd's instance tree
- * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
- * %U the UID of the running user
- * %u the username of the running user
- * %h the homedir of the running user
- * %s the shell of the running user
- * %m the machine ID of the running system
- * %H the host name of the running system
- * %b the boot ID of the running system
- * %v `uname -r` of the running system
+ * NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of the unit
+ * file itself are broken by design, as they would resolve differently depending on whether they are used
+ * before or after the relevant configuration setting. Hence: don't add them.
*/
const Specifier table[] = {
diff --git a/src/core/unit.c b/src/core/unit.c
index cba6342eca..ab40135736 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -516,7 +516,8 @@ void unit_free(Unit *u) {
Iterator i;
char *t;
- assert(u);
+ if (!u)
+ return;
if (u->transient_file)
fclose(u->transient_file);
@@ -3754,14 +3755,14 @@ int unit_kill_context(
bool main_pid_alien) {
bool wait_for_exit = false, send_sighup;
- cg_kill_log_func_t log_func;
+ cg_kill_log_func_t log_func = NULL;
int sig, r;
assert(u);
assert(c);
- /* Kill the processes belonging to this unit, in preparation for shutting the unit down. Returns > 0 if we
- * killed something worth waiting for, 0 otherwise. */
+ /* Kill the processes belonging to this unit, in preparation for shutting the unit down.
+ * Returns > 0 if we killed something worth waiting for, 0 otherwise. */
if (c->kill_mode == KILL_NONE)
return 0;
@@ -3773,9 +3774,8 @@ int unit_kill_context(
IN_SET(k, KILL_TERMINATE, KILL_TERMINATE_AND_LOG) &&
sig != SIGHUP;
- log_func =
- k != KILL_TERMINATE ||
- IN_SET(sig, SIGKILL, SIGABRT) ? log_kill : NULL;
+ if (k != KILL_TERMINATE || IN_SET(sig, SIGKILL, SIGABRT))
+ log_func = log_kill;
if (main_pid > 0) {
if (log_func)