summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-01-03 18:41:32 +0100
committerGitHub <noreply@github.com>2018-01-03 18:41:32 +0100
commitfb92330cccb5c0e9ca30249ff4da800d5d068825 (patch)
treeec8afe44461bba060e202ebe46aedc7877aabb54
parent7f9ac71c76f8157707fb36e1b316961aa4db0ac8 (diff)
parent681ae88e06f2acbfb3b7adf681a681c32c1d5843 (diff)
downloadsystemd-fb92330cccb5c0e9ca30249ff4da800d5d068825.tar.gz
Merge pull request #7759 from yuwata/dbus-api
DBus-API: add more options in transient units
-rw-r--r--TRANSIENT-SETTINGS.md184
-rw-r--r--man/systemd.scope.xml2
-rw-r--r--src/basic/errno-list.h4
-rw-r--r--src/basic/parse-util.c3
-rw-r--r--src/basic/process-util.h7
-rw-r--r--src/basic/securebits-util.h8
-rw-r--r--src/basic/signal-util.h7
-rw-r--r--src/basic/socket-util.c12
-rw-r--r--src/basic/socket-util.h1
-rw-r--r--src/core/dbus-automount.c25
-rw-r--r--src/core/dbus-cgroup.c370
-rw-r--r--src/core/dbus-execute.c798
-rw-r--r--src/core/dbus-execute.h2
-rw-r--r--src/core/dbus-kill.c80
-rw-r--r--src/core/dbus-manager.c6
-rw-r--r--src/core/dbus-mount.c46
-rw-r--r--src/core/dbus-path.c74
-rw-r--r--src/core/dbus-scope.c19
-rw-r--r--src/core/dbus-service.c346
-rw-r--r--src/core/dbus-socket.c402
-rw-r--r--src/core/dbus-timer.c196
-rw-r--r--src/core/dbus-unit.c264
-rw-r--r--src/core/dbus-util.c119
-rw-r--r--src/core/dbus-util.h351
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/load-fragment.c64
-rw-r--r--src/core/meson.build2
-rw-r--r--src/core/namespace.c24
-rw-r--r--src/core/namespace.h2
-rw-r--r--src/shared/bus-unit-util.c394
-rw-r--r--src/shared/condition.h14
-rw-r--r--src/shared/nsflags.h7
32 files changed, 2068 insertions, 1766 deletions
diff --git a/TRANSIENT-SETTINGS.md b/TRANSIENT-SETTINGS.md
index cbdf83f24c..3614456acf 100644
--- a/TRANSIENT-SETTINGS.md
+++ b/TRANSIENT-SETTINGS.md
@@ -10,12 +10,12 @@ ones currently available in transient units are prefixed with `✓`.
## Generic Unit Settings
-Only the most important generic unit settings are available for transient units.
+Most generic unit settings are available for transient units.
```
✓ Description=
- Documentation=
- SourcePath=
+✓ Documentation=
+✓ SourcePath=
✓ Requires=
✓ Requisite=
✓ Wants=
@@ -27,69 +27,70 @@ Only the most important generic unit settings are available for transient units.
✓ PropagatesReloadTo=
✓ ReloadPropagatedFrom=
✓ PartOf=
- JoinsNamespaceOf=
- RequiresMountsFor=
- StopWhenUnneeded=
- RefuseManualStart=
- RefuseManualStop=
- AllowIsolate=
+✓ JoinsNamespaceOf=
+✓ RequiresMountsFor=
+✓ StopWhenUnneeded=
+✓ RefuseManualStart=
+✓ RefuseManualStop=
+✓ AllowIsolate=
✓ DefaultDependencies=
- OnFailureJobMode=
- OnFailureIsolate=
- IgnoreOnIsolate=
- JobTimeoutSec=
- JobRunningTimeoutSec=
- JobTimeoutAction=
- JobTimeoutRebootArgument=
- StartLimitIntervalSec=SECONDS
- StartLimitBurst=UNSIGNED
- StartLimitAction=ACTION
+✓ OnFailureJobMode=
+✓ IgnoreOnIsolate=
+✓ JobTimeoutSec=
+✓ JobRunningTimeoutSec=
+✓ JobTimeoutAction=
+✓ JobTimeoutRebootArgument=
+✓ StartLimitIntervalSec=SECONDS
+✓ StartLimitBurst=UNSIGNED
+✓ StartLimitAction=ACTION
✓ FailureAction=
✓ SuccessAction=
✓ AddRef=
- RebootArgument=STRING
- ConditionPathExists=
- ConditionPathExistsGlob=
- ConditionPathIsDirectory=
- ConditionPathIsSymbolicLink=
- ConditionPathIsMountPoint=
- ConditionPathIsReadWrite=
- ConditionDirectoryNotEmpty=
- ConditionFileNotEmpty=
- ConditionFileIsExecutable=
- ConditionNeedsUpdate=
- ConditionFirstBoot=
- ConditionKernelCommandLine=
- ConditionArchitecture=
- ConditionVirtualization=
- ConditionSecurity=
- ConditionCapability=
- ConditionHost=
- ConditionACPower=
- ConditionUser=
- ConditionGroup=
- ConditionControlGroupController=
- AssertPathExists=
- AssertPathExistsGlob=
- AssertPathIsDirectory=
- AssertPathIsSymbolicLink=
- AssertPathIsMountPoint=
- AssertPathIsReadWrite=
- AssertDirectoryNotEmpty=
- AssertFileNotEmpty=
- AssertFileIsExecutable=
- AssertNeedsUpdate=
- AssertFirstBoot=
- AssertKernelCommandLine=
- AssertArchitecture=
- AssertVirtualization=
- AssertSecurity=
- AssertCapability=
- AssertHost=
- AssertACPower=
- AssertUser=
- AssertGroup=
- AssertControlGroupController=
+✓ RebootArgument=STRING
+✓ ConditionPathExists=
+✓ ConditionPathExistsGlob=
+✓ ConditionPathIsDirectory=
+✓ ConditionPathIsSymbolicLink=
+✓ ConditionPathIsMountPoint=
+✓ ConditionPathIsReadWrite=
+✓ ConditionDirectoryNotEmpty=
+✓ ConditionFileNotEmpty=
+✓ ConditionFileIsExecutable=
+✓ ConditionNeedsUpdate=
+✓ ConditionFirstBoot=
+✓ ConditionKernelCommandLine=
+✓ ConditionKernelVersion=
+✓ ConditionArchitecture=
+✓ ConditionVirtualization=
+✓ ConditionSecurity=
+✓ ConditionCapability=
+✓ ConditionHost=
+✓ ConditionACPower=
+✓ ConditionUser=
+✓ ConditionGroup=
+✓ ConditionControlGroupController=
+✓ AssertPathExists=
+✓ AssertPathExistsGlob=
+✓ AssertPathIsDirectory=
+✓ AssertPathIsSymbolicLink=
+✓ AssertPathIsMountPoint=
+✓ AssertPathIsReadWrite=
+✓ AssertDirectoryNotEmpty=
+✓ AssertFileNotEmpty=
+✓ AssertFileIsExecutable=
+✓ AssertNeedsUpdate=
+✓ AssertFirstBoot=
+✓ AssertKernelCommandLine=
+✓ AssertKernelVersion=
+✓ AssertArchitecture=
+✓ AssertVirtualization=
+✓ AssertSecurity=
+✓ AssertCapability=
+✓ AssertHost=
+✓ AssertACPower=
+✓ AssertUser=
+✓ AssertGroup=
+✓ AssertControlGroupController=
✓ CollectMode=
```
@@ -256,63 +257,63 @@ All process killing settings are available for transient units:
## Service Unit Settings
-Only the most important service settings are available for transient units.
+Most service unit settings are available for transient units.
```
- PIDFile=
+✓ PIDFile=
✓ ExecStartPre=
✓ ExecStart=
✓ ExecStartPost=
✓ ExecReload=
✓ ExecStop=
✓ ExecStopPost=
- RestartSec=
- TimeoutStartSec=
- TimeoutStopSec=
- TimeoutSec=
+✓ RestartSec=
+✓ TimeoutStartSec=
+✓ TimeoutStopSec=
+✓ TimeoutSec=
✓ RuntimeMaxSec=
- WatchdogSec=
+✓ WatchdogSec=
✓ Type=
✓ Restart=
- PermissionsStartOnly=
- RootDirectoryStartOnly=
+✓ PermissionsStartOnly=
+✓ RootDirectoryStartOnly=
✓ RemainAfterExit=
- GuessMainPID=
- RestartPreventExitStatus=
- RestartForceExitStatus=
- SuccessExitStatus=
+✓ GuessMainPID=
+✓ RestartPreventExitStatus=
+✓ RestartForceExitStatus=
+✓ SuccessExitStatus=
✓ NonBlocking=
- BusName=
+✓ BusName=
✓ FileDescriptorStoreMax=
✓ NotifyAccess=
Sockets=
- USBFunctionDescriptors=
- USBFunctionStrings=
+✓ USBFunctionDescriptors=
+✓ USBFunctionStrings=
```
## Mount Unit Settings
-Only the most important mount unit settings are currently available to transient units:
+All mount unit settings are available to transient units:
```
✓ What=
- Where=
+✓ Where=
✓ Options=
✓ Type=
- TimeoutSec=
- DirectoryMode=
- SloppyOptions=
- LazyUnmount=
- ForceUnmount=
+✓ TimeoutSec=
+✓ DirectoryMode=
+✓ SloppyOptions=
+✓ LazyUnmount=
+✓ ForceUnmount=
```
## Automount Unit Settings
-Only one automount unit setting is currently available to transient units:
+All automount unit setting is available to transient units:
```
- Where=
- DirectoryMode=
+✓ Where=
+✓ DirectoryMode=
✓ TimeoutIdleSec=
```
@@ -343,8 +344,11 @@ of their own beyond the generic unit and resource control settings.
## Scope Unit Settings
Scope units are fully supported as transient units (in fact they only exist as
-such), but they have no settings of their own beyond the generic unit,
-resource control, and process killing settings.
+such).
+
+```
+✓ TimeoutStopSec=
+```
## Socket Unit Settings
diff --git a/man/systemd.scope.xml b/man/systemd.scope.xml
index 092361c6b0..1128d236ce 100644
--- a/man/systemd.scope.xml
+++ b/man/systemd.scope.xml
@@ -100,8 +100,6 @@
late system shutdown should disable
<varname>DefaultDependencies=</varname> option.</para></listitem>
</itemizedlist>
-
- <para></para>
</refsect1>
<refsect1>
diff --git a/src/basic/errno-list.h b/src/basic/errno-list.h
index 4e9b75a7ea..38beaf96dd 100644
--- a/src/basic/errno-list.h
+++ b/src/basic/errno-list.h
@@ -20,6 +20,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
/*
* MAX_ERRNO is defined as 4095 in linux/err.h
* We use the same value here.
@@ -28,3 +29,6 @@
const char *errno_to_name(int id);
int errno_from_name(const char *name);
+static inline bool errno_is_valid(int n) {
+ return n > 0 && n <= ERRNO_MAX;
+}
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index d03f60e01a..33f94f3fc2 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -283,7 +283,8 @@ int parse_errno(const char *t) {
if (r < 0)
return r;
- if (e < 0 || e > ERRNO_MAX)
+ /* 0 is also allowed here */
+ if (!errno_is_valid(e) && e != 0)
return -ERANGE;
return e;
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 1dd62c6d0a..b20e527af7 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -137,6 +137,13 @@ static inline bool pid_is_valid(pid_t p) {
return p > 0;
}
+static inline int sched_policy_to_string_alloc_with_check(int n, char **s) {
+ if (!sched_policy_is_valid(n))
+ return -EINVAL;
+
+ return sched_policy_to_string_alloc(n, s);
+}
+
int ioprio_parse_priority(const char *s, int *ret);
pid_t getpid_cached(void);
diff --git a/src/basic/securebits-util.h b/src/basic/securebits-util.h
index aaa192f0a5..069d215488 100644
--- a/src/basic/securebits-util.h
+++ b/src/basic/securebits-util.h
@@ -24,6 +24,14 @@
int secure_bits_to_string_alloc(int i, char **s);
int secure_bits_from_string(const char *s);
+
static inline bool secure_bits_is_valid(int i) {
return ((SECURE_ALL_BITS | SECURE_ALL_LOCKS) & i) == i;
}
+
+static inline int secure_bits_to_string_alloc_with_check(int n, char **s) {
+ if (!secure_bits_is_valid(n))
+ return -EINVAL;
+
+ return secure_bits_to_string_alloc(n, s);
+}
diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h
index 76b239b1fc..f6c3396ebe 100644
--- a/src/basic/signal-util.h
+++ b/src/basic/signal-util.h
@@ -55,3 +55,10 @@ static inline void block_signals_reset(sigset_t *ss) {
static inline bool SIGNAL_VALID(int signo) {
return signo > 0 && signo < _NSIG;
}
+
+static inline const char* signal_to_string_with_check(int n) {
+ if (!SIGNAL_VALID(n))
+ return NULL;
+
+ return signal_to_string(n);
+}
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index b765fb6125..54d526a521 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -821,6 +821,18 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
+SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) {
+ int r;
+
+ r = parse_boolean(n);
+ if (r > 0)
+ return SOCKET_ADDRESS_IPV6_ONLY;
+ if (r == 0)
+ return SOCKET_ADDRESS_BOTH;
+
+ return socket_address_bind_ipv6_only_from_string(n);
+}
+
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
assert(a);
assert(b);
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 0f84a5e93e..ba5be9b67d 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -120,6 +120,7 @@ int getnameinfo_pretty(int fd, char **ret);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
+SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *s);
int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s) _pure_;
diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c
index 4b1b86f7b9..113d352a43 100644
--- a/src/core/dbus-automount.c
+++ b/src/core/dbus-automount.c
@@ -21,6 +21,7 @@
#include "automount.h"
#include "bus-util.h"
#include "dbus-automount.h"
+#include "dbus-util.h"
#include "string-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult);
@@ -41,7 +42,7 @@ static int bus_automount_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
- int r;
+ Unit *u = UNIT(a);
assert(a);
assert(name);
@@ -49,24 +50,16 @@ static int bus_automount_set_transient_property(
flags |= UNIT_PRIVATE;
- if (streq(name, "TimeoutIdleUSec")) {
- usec_t timeout_idle_usec;
+ if (streq(name, "Where"))
+ return bus_set_transient_path(u, name, &a->where, message, flags, error);
- r = sd_bus_message_read(message, "t", &timeout_idle_usec);
- if (r < 0)
- return r;
+ if (streq(name, "TimeoutIdleUSec"))
+ return bus_set_transient_usec_fix_0(u, name, &a->timeout_idle_usec, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- char time[FORMAT_TIMESPAN_MAX];
+ if (streq(name, "DirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &a->directory_mode, message, flags, error);
- a->timeout_idle_usec = timeout_idle_usec;
- unit_write_settingf(UNIT(a), flags, name, "TimeoutIdleSec=%s\n",
- format_timespan(time, sizeof(time), timeout_idle_usec, USEC_PER_MSEC));
- }
- } else
- return 0;
-
- return 1;
+ return 0;
}
int bus_automount_set_property(
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index 755b66ef8f..cd57cefabc 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -28,6 +28,7 @@
#include "cgroup-util.h"
#include "cgroup.h"
#include "dbus-cgroup.h"
+#include "dbus-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
@@ -413,6 +414,41 @@ static int bus_cgroup_set_transient_property(
return 0;
}
+static int bus_cgroup_set_boolean(
+ Unit *u,
+ const char *name,
+ bool *p,
+ CGroupMask mask,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+
+ int b, r;
+
+ assert(p);
+
+ r = sd_bus_message_read(message, "b", &b);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ *p = b;
+ unit_invalidate_cgroup(u, mask);
+ unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
+ }
+
+ return 1;
+}
+
+static BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID,);
+static BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID,);
+static BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID,);
+static BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID,);
+static BUS_DEFINE_SET_CGROUP_WEIGHT(memory, CGROUP_MASK_MEMORY, , CGROUP_LIMIT_MAX, "infinity");
+static BUS_DEFINE_SET_CGROUP_WEIGHT(tasks_max, CGROUP_MASK_PIDS, , (uint64_t) -1, "infinity");
+static BUS_DEFINE_SET_CGROUP_SCALE(memory, CGROUP_MASK_MEMORY, physical_memory_scale);
+static BUS_DEFINE_SET_CGROUP_SCALE(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale);
+
int bus_cgroup_set_property(
Unit *u,
CGroupContext *c,
@@ -431,74 +467,82 @@ int bus_cgroup_set_property(
flags |= UNIT_PRIVATE;
- if (streq(name, "CPUAccounting")) {
- int b;
+ if (streq(name, "CPUAccounting"))
+ return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU, message, flags, error);
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
+ if (streq(name, "CPUWeight"))
+ return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->cpu_accounting = b;
- unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU);
- unit_write_settingf(u, flags, name, "CPUAccounting=%s", yes_no(b));
- }
+ if (streq(name, "StartupCPUWeight"))
+ return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
- return 1;
+ if (streq(name, "CPUShares"))
+ return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
- } else if (STR_IN_SET(name, "CPUWeight", "StartupCPUWeight")) {
- uint64_t weight;
+ if (streq(name, "StartupCPUShares"))
+ return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
- r = sd_bus_message_read(message, "t", &weight);
- if (r < 0)
- return r;
+ if (streq(name, "IOAccounting"))
+ return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
- if (!CGROUP_WEIGHT_IS_OK(weight))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
+ if (streq(name, "IOWeight"))
+ return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "CPUWeight"))
- c->cpu_weight = weight;
- else /* "StartupCPUWeight" */
- c->startup_cpu_weight = weight;
+ if (streq(name, "StartupIOWeight"))
+ return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
- unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
+ if (streq(name, "BlockIOAccounting"))
+ return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
- if (weight == CGROUP_WEIGHT_INVALID)
- unit_write_settingf(u, flags, name, "%s=", name);
- else
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, weight);
- }
+ if (streq(name, "BlockIOWeight"))
+ return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
- return 1;
+ if (streq(name, "StartupBlockIOWeight"))
+ return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
- } else if (STR_IN_SET(name, "CPUShares", "StartupCPUShares")) {
- uint64_t shares;
+ if (streq(name, "MemoryAccounting"))
+ return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
- r = sd_bus_message_read(message, "t", &shares);
- if (r < 0)
- return r;
+ if (streq(name, "MemoryLow"))
+ return bus_cgroup_set_memory(u, name, &c->memory_low, message, flags, error);
- if (!CGROUP_CPU_SHARES_IS_OK(shares))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
+ if (streq(name, "MemoryHigh"))
+ return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "CPUShares"))
- c->cpu_shares = shares;
- else /* "StartupCPUShares" */
- c->startup_cpu_shares = shares;
+ if (streq(name, "MemorySwapMax"))
+ return bus_cgroup_set_memory(u, name, &c->memory_swap_max, message, flags, error);
- unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
+ if (streq(name, "MemoryMax"))
+ return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
- if (shares == CGROUP_CPU_SHARES_INVALID)
- unit_write_settingf(u, flags, name, "%s=", name);
- else
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, shares);
- }
+ if (streq(name, "MemoryLimit"))
+ return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
- return 1;
+ if (streq(name, "MemoryLowScale"))
+ return bus_cgroup_set_memory_scale(u, name, &c->memory_low, message, flags, error);
+
+ if (streq(name, "MemoryHighScale"))
+ return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
+
+ if (streq(name, "MemorySwapMaxScale"))
+ return bus_cgroup_set_memory_scale(u, name, &c->memory_swap_max, message, flags, error);
+
+ if (streq(name, "MemoryMaxScale"))
+ return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
- } else if (streq(name, "CPUQuotaPerSecUSec")) {
+ if (streq(name, "MemoryLimitScale"))
+ return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
+
+ if (streq(name, "TasksAccountingScale"))
+ return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error);
+
+ if (streq(name, "TasksMax"))
+ return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error);
+
+ if (streq(name, "TasksMaxScale"))
+ return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error);
+
+ if (streq(name, "CPUQuotaPerSecUSec")) {
uint64_t u64;
r = sd_bus_message_read(message, "t", &u64);
@@ -524,47 +568,6 @@ int bus_cgroup_set_property(
return 1;
- } else if (streq(name, "IOAccounting")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->io_accounting = b;
- unit_invalidate_cgroup(u, CGROUP_MASK_IO);
- unit_write_settingf(u, flags, name, "IOAccounting=%s", yes_no(b));
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "IOWeight", "StartupIOWeight")) {
- uint64_t weight;
-
- r = sd_bus_message_read(message, "t", &weight);
- if (r < 0)
- return r;
-
- if (!CGROUP_WEIGHT_IS_OK(weight))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "IOWeight"))
- c->io_weight = weight;
- else /* "StartupIOWeight" */
- c->startup_io_weight = weight;
-
- unit_invalidate_cgroup(u, CGROUP_MASK_IO);
-
- if (weight == CGROUP_WEIGHT_INVALID)
- unit_write_settingf(u, flags, name, "%s=", name);
- else
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, weight);
- }
-
- return 1;
-
} else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
const char *path;
unsigned n = 0;
@@ -691,7 +694,7 @@ int bus_cgroup_set_property(
free(a);
return -ENOMEM;
}
- LIST_PREPEND(device_weights,c->io_device_weights, a);
+ LIST_PREPEND(device_weights, c->io_device_weights, a);
}
a->weight = weight;
@@ -735,47 +738,6 @@ int bus_cgroup_set_property(
return 1;
- } else if (streq(name, "BlockIOAccounting")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->blockio_accounting = b;
- unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
- unit_write_settingf(u, flags, name, "BlockIOAccounting=%s", yes_no(b));
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight")) {
- uint64_t weight;
-
- r = sd_bus_message_read(message, "t", &weight);
- if (r < 0)
- return r;
-
- if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "BlockIOWeight"))
- c->blockio_weight = weight;
- else /* "StartupBlockIOWeight" */
- c->startup_blockio_weight = weight;
-
- unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
-
- if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
- unit_write_settingf(u, flags, name, "%s=", name);
- else
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, weight);
- }
-
- return 1;
-
} else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
const char *path;
bool read = true;
@@ -918,7 +880,7 @@ int bus_cgroup_set_property(
free(a);
return -ENOMEM;
}
- LIST_PREPEND(device_weights,c->blockio_device_weights, a);
+ LIST_PREPEND(device_weights, c->blockio_device_weights, a);
}
a->weight = weight;
@@ -963,89 +925,6 @@ int bus_cgroup_set_property(
return 1;
- } else if (streq(name, "MemoryAccounting")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->memory_accounting = b;
- unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
- unit_write_settingf(u, flags, name, "MemoryAccounting=%s", yes_no(b));
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit")) {
- uint64_t v;
-
- r = sd_bus_message_read(message, "t", &v);
- if (r < 0)
- return r;
- if (v <= 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is too small", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "MemoryLow"))
- c->memory_low = v;
- else if (streq(name, "MemoryHigh"))
- c->memory_high = v;
- else if (streq(name, "MemorySwapMax"))
- c->memory_swap_max = v;
- else if (streq(name, "MemoryMax"))
- c->memory_max = v;
- else /* "MemoryLimit" */
- c->memory_limit = v;
-
- unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
-
- if (v == CGROUP_LIMIT_MAX)
- unit_write_settingf(u, flags, name, "%s=infinity", name);
- else
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, v);
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale", "MemorySwapMaxScale", "MemoryLimitScale")) {
- uint32_t raw;
- uint64_t v;
-
- r = sd_bus_message_read(message, "u", &raw);
- if (r < 0)
- return r;
-
- v = physical_memory_scale(raw, UINT32_MAX);
- if (v <= 0 || v == UINT64_MAX)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is out of range", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- const char *e;
-
- /* Chop off suffix */
- assert_se(e = endswith(name, "Scale"));
- name = strndupa(name, e - name);
-
- if (streq(name, "MemoryLow"))
- c->memory_low = v;
- else if (streq(name, "MemoryHigh"))
- c->memory_high = v;
- else if (streq(name, "MemorySwapMax"))
- c->memory_swap_max = v;
- else if (streq(name, "MemoryMax"))
- c->memory_max = v;
- else /* "MemoryLimit" */
- c->memory_limit = v;
-
- unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
- unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name,
- (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
- }
-
- return 1;
-
} else if (streq(name, "DevicePolicy")) {
const char *policy;
CGroupDevicePolicy p;
@@ -1156,63 +1035,6 @@ int bus_cgroup_set_property(
return 1;
- } else if (streq(name, "TasksAccounting")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->tasks_accounting = b;
- unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
- unit_write_settingf(u, flags, name, "TasksAccounting=%s", yes_no(b));
- }
-
- return 1;
-
- } else if (streq(name, "TasksMax")) {
- uint64_t limit;
-
- r = sd_bus_message_read(message, "t", &limit);
- if (r < 0)
- return r;
- if (limit <= 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is too small", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->tasks_max = limit;
- unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
-
- if (limit == (uint64_t) -1)
- unit_write_setting(u, flags, name, "TasksMax=infinity");
- else
- unit_write_settingf(u, flags, name, "TasksMax=%" PRIu64, limit);
- }
-
- return 1;
-
- } else if (streq(name, "TasksMaxScale")) {
- uint64_t limit;
- uint32_t raw;
-
- r = sd_bus_message_read(message, "u", &raw);
- if (r < 0)
- return r;
-
- limit = system_tasks_max_scale(raw, UINT32_MAX);
- if (limit <= 0 || limit >= UINT64_MAX)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is out of range", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->tasks_max = limit;
- unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
- unit_write_settingf(u, flags, name, "TasksMax=%" PRIu32 "%%",
- (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
- }
-
- return 1;
-
} else if (streq(name, "IPAccounting")) {
int b;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 55e8349fc5..352852a75e 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -32,6 +32,7 @@
#include "capability-util.h"
#include "cpu-set-util.h"
#include "dbus-execute.h"
+#include "dbus-util.h"
#include "env-util.h"
#include "errno-list.h"
#include "escape.h"
@@ -1036,7 +1037,7 @@ int bus_property_get_exec_command_list(
return sd_bus_message_close_container(reply);
}
-int bus_exec_command_set_transient_property(
+int bus_set_transient_exec_command(
Unit *u,
const char *name,
ExecCommand **exec_command,
@@ -1151,6 +1152,45 @@ int bus_exec_command_set_transient_property(
return 1;
}
+static int parse_personality(const char *s, unsigned long *p) {
+ unsigned long v;
+
+ assert(p);
+
+ v = personality_from_string(s);
+ if (v == PERSONALITY_INVALID)
+ return -EINVAL;
+
+ *p = v;
+ return 0;
+}
+
+static const char* mount_propagation_flags_to_string_with_check(unsigned long n) {
+ if (!IN_SET(n, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
+ return NULL;
+
+ return mount_propagation_flags_to_string(n);
+}
+
+static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(sched_priority, "i", int32_t, int, "%" PRIi32, sched_priority_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice, "i", int32_t, int, "%" PRIi32, nice_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, parse_protect_system_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, parse_protect_home_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(sched_policy, "i", int32_t, int, "%" PRIi32, sched_policy_to_string_alloc_with_check);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flag_to_string_many_with_check);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
+
int bus_exec_context_set_transient_property(
Unit *u,
ExecContext *c,
@@ -1169,31 +1209,172 @@ int bus_exec_context_set_transient_property(
flags |= UNIT_PRIVATE;
- if (STR_IN_SET(name, "User", "Group")) {
- const char *uu;
+ if (streq(name, "User"))
+ return bus_set_transient_user(u, name, &c->user, message, flags, error);
- r = sd_bus_message_read(message, "s", &uu);
- if (r < 0)
- return r;
+ if (streq(name, "Group"))
+ return bus_set_transient_user(u, name, &c->group, message, flags, error);
- if (!isempty(uu) && !valid_user_group_name_or_id(uu))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, uu);
+ if (streq(name, "TTYPath"))
+ return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ if (streq(name, "RootImage"))
+ return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
- if (streq(name, "User"))
- r = free_and_strdup(&c->user, empty_to_null(uu));
- else /* "Group" */
- r = free_and_strdup(&c->group, empty_to_null(uu));
- if (r < 0)
- return r;
+ if (streq(name, "RootDirectory"))
+ return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, uu);
- }
+ if (streq(name, "SyslogIdentifier"))
+ return bus_set_transient_string(u, name, &c->syslog_identifier, message, flags, error);
- return 1;
+ if (streq(name, "LogLevelMax"))
+ return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error);
+
+ if (streq(name, "CPUSchedulingPriority"))
+ return bus_set_transient_sched_priority(u, name, &c->cpu_sched_priority, message, flags, error);
+
+ if (streq(name, "Personality"))
+ return bus_set_transient_personality(u, name, &c->personality, message, flags, error);
+
+ if (streq(name, "Nice"))
+ return bus_set_transient_nice(u, name, &c->nice, message, flags, error);
+
+ if (streq(name, "StandardInput"))
+ return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error);
+
+ if (streq(name, "StandardOutput"))
+ return bus_set_transient_std_output(u, name, &c->std_output, message, flags, error);
+
+ if (streq(name, "StandardError"))
+ return bus_set_transient_std_output(u, name, &c->std_error, message, flags, error);
+
+ if (streq(name, "IgnoreSIGPIPE"))
+ return bus_set_transient_bool(u, name, &c->ignore_sigpipe, message, flags, error);
+
+ if (streq(name, "TTYVHangup"))
+ return bus_set_transient_bool(u, name, &c->tty_vhangup, message, flags, error);
+
+ if (streq(name, "TTYReset"))
+ return bus_set_transient_bool(u, name, &c->tty_reset, message, flags, error);
+
+ if (streq(name, "TTYVTDisallocate"))
+ return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error);
+
+ if (streq(name, "PrivateTmp"))
+ return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error);
+
+ if (streq(name, "PrivateDevices"))
+ return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
+
+ if (streq(name, "PrivateNetwork"))
+ return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
+
+ if (streq(name, "PrivateUsers"))
+ return bus_set_transient_bool(u, name, &c->private_users, message, flags, error);
+
+ if (streq(name, "NoNewPrivileges"))
+ return bus_set_transient_bool(u, name, &c->no_new_privileges, message, flags, error);
+
+ if (streq(name, "SyslogLevelPrefix"))
+ return bus_set_transient_bool(u, name, &c->syslog_level_prefix, message, flags, error);
+
+ if (streq(name, "MemoryDenyWriteExecute"))
+ return bus_set_transient_bool(u, name, &c->memory_deny_write_execute, message, flags, error);
+
+ if (streq(name, "RestrictRealtime"))
+ return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
+
+ if (streq(name, "DynamicUser"))
+ return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
+
+ if (streq(name, "RemoveIPC"))
+ return bus_set_transient_bool(u, name, &c->remove_ipc, message, flags, error);
+
+ if (streq(name, "ProtectKernelTunables"))
+ return bus_set_transient_bool(u, name, &c->protect_kernel_tunables, message, flags, error);
+
+ if (streq(name, "ProtectKernelModules"))
+ return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error);
+
+ if (streq(name, "ProtectControlGroups"))
+ return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
+
+ if (streq(name, "MountAPIVFS"))
+ return bus_set_transient_bool(u, name, &c->mount_apivfs, message, flags, error);
+
+ if (streq(name, "CPUSchedulingResetOnFork"))
+ return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error);
+
+ if (streq(name, "NonBlocking"))
+ return bus_set_transient_bool(u, name, &c->non_blocking, message, flags, error);
+
+ if (streq(name, "LockPersonality"))
+ return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
+
+ if (streq(name, "UtmpIdentifier"))
+ return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error);
+
+ if (streq(name, "UtmpMode"))
+ return bus_set_transient_utmp_mode(u, name, &c->utmp_mode, message, flags, error);
+
+ if (streq(name, "PAMName"))
+ return bus_set_transient_string(u, name, &c->pam_name, message, flags, error);
+
+ if (streq(name, "TimerSlackNSec"))
+ return bus_set_transient_nsec(u, name, &c->timer_slack_nsec, message, flags, error);
+
+ if (streq(name, "ProtectSystem"))
+ return bus_set_transient_protect_system(u, name, &c->protect_system, message, flags, error);
+
+ if (streq(name, "ProtectHome"))
+ return bus_set_transient_protect_home(u, name, &c->protect_home, message, flags, error);
+
+ if (streq(name, "KeyringMode"))
+ return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error);
- } else if (streq(name, "SupplementaryGroups")) {
+ if (streq(name, "RuntimeDirectoryPreserve"))
+ return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
+
+ if (streq(name, "UMask"))
+ return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error);
+
+ if (streq(name, "RuntimeDirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error);
+
+ if (streq(name, "StateDirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error);
+
+ if (streq(name, "CacheDirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CACHE].mode, message, flags, error);
+
+ if (streq(name, "LogsDirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_LOGS].mode, message, flags, error);
+
+ if (streq(name, "ConfigurationDirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CONFIGURATION].mode, message, flags, error);
+
+ if (streq(name, "SELinuxContext"))
+ return bus_set_transient_string(u, name, &c->selinux_context, message, flags, error);
+
+ if (streq(name, "SecureBits"))
+ return bus_set_transient_secure_bits(u, name, &c->secure_bits, message, flags, error);
+
+ if (streq(name, "CapabilityBoundingSet"))
+ return bus_set_transient_capability(u, name, &c->capability_bounding_set, message, flags, error);
+
+ if (streq(name, "AmbientCapabilities"))
+ return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error);
+
+ if (streq(name, "CPUSchedulingPolicy"))
+ return bus_set_transient_sched_policy(u, name, &c->cpu_sched_policy, message, flags, error);
+
+ if (streq(name, "RestrictNamespaces"))
+ return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error);
+
+ if (streq(name, "MountFlags"))
+ return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error);
+
+ if (streq(name, "SupplementaryGroups")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
@@ -1227,23 +1408,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "SyslogIdentifier")) {
- const char *id;
-
- r = sd_bus_message_read(message, "s", &id);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- r = free_and_strdup(&c->syslog_identifier, empty_to_null(id));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "SyslogIdentifier=%s", id);
- }
-
- return 1;
} else if (streq(name, "SyslogLevel")) {
int32_t level;
@@ -1260,6 +1424,7 @@ int bus_exec_context_set_transient_property(
}
return 1;
+
} else if (streq(name, "SyslogFacility")) {
int32_t facility;
@@ -1277,23 +1442,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "LogLevelMax")) {
- int32_t level;
-
- r = sd_bus_message_read(message, "i", &level);
- if (r < 0)
- return r;
-
- if (!log_level_is_valid(level))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Maximum log level value out of range");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->log_level_max = level;
- unit_write_settingf(u, flags, name, "LogLevelMax=%i", level);
- }
-
- return 1;
-
} else if (streq(name, "LogExtraFields")) {
size_t n = 0;
@@ -1367,75 +1515,14 @@ int bus_exec_context_set_transient_property(
}
return 1;
-
- } else if (streq(name, "SecureBits")) {
- int n;
-
- r = sd_bus_message_read(message, "i", &n);
- if (r < 0)
- return r;
-
- if (!secure_bits_is_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid secure bits");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- _cleanup_free_ char *str = NULL;
-
- c->secure_bits = n;
- r = secure_bits_to_string_alloc(n, &str);
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags, name, "SecureBits=%s", str);
- }
-
- return 1;
- } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
- uint64_t n;
-
- r = sd_bus_message_read(message, "t", &n);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- _cleanup_free_ char *str = NULL;
-
- if (streq(name, "CapabilityBoundingSet"))
- c->capability_bounding_set = n;
- else /* "AmbientCapabilities" */
- c->capability_ambient_set = n;
-
- r = capability_set_to_string_alloc(n, &str);
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags, name, "%s=%s", name, str);
- }
-
- return 1;
-
- } else if (streq(name, "Personality")) {
- const char *s;
- unsigned long p;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- p = personality_from_string(s);
- if (p == PERSONALITY_INVALID)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid personality");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->personality = p;
- unit_write_settingf(u, flags, name, "%s=%s", name, s);
- }
-
- return 1;
+ }
#if HAVE_SECCOMP
- } else if (streq(name, "SystemCallFilter")) {
+ if (streq(name, "SystemCallErrorNumber"))
+ return bus_set_transient_errno(u, name, &c->syscall_errno, message, flags, error);
+
+ if (streq(name, "SystemCallFilter")) {
int whitelist;
_cleanup_strv_free_ char **l = NULL;
@@ -1546,24 +1633,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "SystemCallErrorNumber")) {
- int32_t n;
-
- r = sd_bus_message_read(message, "i", &n);
- if (r < 0)
- return r;
-
- if (n <= 0 || n > ERRNO_MAX)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SystemCallErrorNumber");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->syscall_errno = n;
-
- unit_write_settingf(u, flags, name, "SystemCallErrorNumber=%d", n);
- }
-
- return 1;
-
} else if (streq(name, "RestrictAddressFamilies")) {
int whitelist;
_cleanup_strv_free_ char **l = NULL;
@@ -1628,49 +1697,9 @@ int bus_exec_context_set_transient_property(
}
return 1;
+ }
#endif
-
- } else if (streq(name, "CPUSchedulingPolicy")) {
- int32_t n;
-
- r = sd_bus_message_read(message, "i", &n);
- if (r < 0)
- return r;
-
- if (!sched_policy_is_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- _cleanup_free_ char *str = NULL;
-
- c->cpu_sched_policy = n;
- r = sched_policy_to_string_alloc(n, &str);
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", str);
- }
-
- return 1;
-
- } else if (streq(name, "CPUSchedulingPriority")) {
- int32_t n;
-
- r = sd_bus_message_read(message, "i", &n);
- if (r < 0)
- return r;
-
- if (!sched_priority_is_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->cpu_sched_priority = n;
- unit_write_settingf(u, flags, name, "CPUSchedulingPriority=%i", n);
- }
-
- return 1;
-
- } else if (streq(name, "CPUAffinity")) {
+ if (streq(name, "CPUAffinity")) {
const void *a;
size_t n = 0;
@@ -1736,22 +1765,6 @@ int bus_exec_context_set_transient_property(
}
return 1;
- } else if (streq(name, "Nice")) {
- int32_t n;
-
- r = sd_bus_message_read(message, "i", &n);
- if (r < 0)
- return r;
-
- if (!nice_is_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->nice = n;
- unit_write_settingf(u, flags, name, "Nice=%i", n);
- }
-
- return 1;
} else if (streq(name, "IOSchedulingClass")) {
int32_t q;
@@ -1797,33 +1810,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (STR_IN_SET(name, "TTYPath", "RootDirectory", "RootImage")) {
- const char *s;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- if (!isempty(s) && !path_is_absolute(s))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "TTYPath"))
- r = free_and_strdup(&c->tty_path, empty_to_null(s));
- else if (streq(name, "RootImage"))
- r = free_and_strdup(&c->root_image, empty_to_null(s));
- else {
- assert(streq(name, "RootDirectory"));
- r = free_and_strdup(&c->root_directory, empty_to_null(s));
- }
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, s);
- }
-
- return 1;
-
} else if (streq(name, "WorkingDirectory")) {
const char *s;
bool missing_ok;
@@ -1859,66 +1845,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "StandardInput")) {
- const char *s;
- ExecInput p;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- p = exec_input_from_string(s);
- if (p < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->std_input = p;
-
- unit_write_settingf(u, flags, name, "StandardInput=%s", exec_input_to_string(p));
- }
-
- return 1;
-
- } else if (streq(name, "StandardOutput")) {
- const char *s;
- ExecOutput p;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- p = exec_output_from_string(s);
- if (p < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->std_output = p;
-
- unit_write_settingf(u, flags, name, "StandardOutput=%s", exec_output_to_string(p));
- }
-
- return 1;
-
- } else if (streq(name, "StandardError")) {
- const char *s;
- ExecOutput p;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- p = exec_output_from_string(s);
- if (p < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->std_error = p;
-
- unit_write_settingf(u, flags, name, "StandardError=%s", exec_output_to_string(p));
- }
-
- return 1;
-
} else if (STR_IN_SET(name,
"StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
const char *s;
@@ -2051,124 +1977,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (STR_IN_SET(name,
- "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
- "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
- "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
- "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
- "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
- "CPUSchedulingResetOnFork", "NonBlocking", "LockPersonality")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "IgnoreSIGPIPE"))
- c->ignore_sigpipe = b;
- else if (streq(name, "TTYVHangup"))
- c->tty_vhangup = b;
- else if (streq(name, "TTYReset"))
- c->tty_reset = b;
- else if (streq(name, "TTYVTDisallocate"))
- c->tty_vt_disallocate = b;
- else if (streq(name, "PrivateTmp"))
- c->private_tmp = b;
- else if (streq(name, "PrivateDevices"))
- c->private_devices = b;
- else if (streq(name, "PrivateNetwork"))
- c->private_network = b;
- else if (streq(name, "PrivateUsers"))
- c->private_users = b;
- else if (streq(name, "NoNewPrivileges"))
- c->no_new_privileges = b;
- else if (streq(name, "SyslogLevelPrefix"))
- c->syslog_level_prefix = b;
- else if (streq(name, "MemoryDenyWriteExecute"))
- c->memory_deny_write_execute = b;
- else if (streq(name, "RestrictRealtime"))
- c->restrict_realtime = b;
- else if (streq(name, "DynamicUser"))
- c->dynamic_user = b;
- else if (streq(name, "RemoveIPC"))
- c->remove_ipc = b;
- else if (streq(name, "ProtectKernelTunables"))
- c->protect_kernel_tunables = b;
- else if (streq(name, "ProtectKernelModules"))
- c->protect_kernel_modules = b;
- else if (streq(name, "ProtectControlGroups"))
- c->protect_control_groups = b;
- else if (streq(name, "MountAPIVFS"))
- c->mount_apivfs = b;
- else if (streq(name, "CPUSchedulingResetOnFork"))
- c->cpu_sched_reset_on_fork = b;
- else if (streq(name, "NonBlocking"))
- c->non_blocking = b;
- else if (streq(name, "LockPersonality"))
- c->lock_personality = b;
-
- unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
- }
-
- return 1;
-
- } else if (streq(name, "UtmpIdentifier")) {
- const char *id;
-
- r = sd_bus_message_read(message, "s", &id);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- r = free_and_strdup(&c->utmp_id, empty_to_null(id));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "UtmpIdentifier=%s", strempty(id));
- }
-
- return 1;
-
- } else if (streq(name, "UtmpMode")) {
- const char *s;
- ExecUtmpMode m;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- m = exec_utmp_mode_from_string(s);
- if (m < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->utmp_mode = m;
-
- unit_write_settingf(u, flags, name, "UtmpMode=%s", exec_utmp_mode_to_string(m));
- }
-
- return 1;
-
- } else if (streq(name, "PAMName")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- r = free_and_strdup(&c->pam_name, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "PAMName=%s", strempty(n));
- }
-
- return 1;
-
} else if (streq(name, "Environment")) {
_cleanup_strv_free_ char **l = NULL;
@@ -2241,21 +2049,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "TimerSlackNSec")) {
-
- nsec_t n;
-
- r = sd_bus_message_read(message, "t", &n);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->timer_slack_nsec = n;
- unit_write_settingf(u, flags, name, "TimerSlackNSec=" NSEC_FMT, n);
- }
-
- return 1;
-
} else if (streq(name, "OOMScoreAdjust")) {
int oa;
@@ -2413,9 +2206,6 @@ int bus_exec_context_set_transient_property(
char *i = *p;
size_t offset;
- if (!utf8_is_valid(i))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
-
offset = i[0] == '-';
offset += i[offset] == '+';
if (!path_is_absolute(i + offset))
@@ -2452,123 +2242,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "ProtectSystem")) {
- const char *s;
- ProtectSystem ps;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- r = parse_boolean(s);
- if (r > 0)
- ps = PROTECT_SYSTEM_YES;
- else if (r == 0)
- ps = PROTECT_SYSTEM_NO;
- else {
- ps = protect_system_from_string(s);
- if (ps < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
- }
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->protect_system = ps;
- unit_write_settingf(u, flags, name, "%s=%s", name, s);
- }
-
- return 1;
-
- } else if (streq(name, "ProtectHome")) {
- const char *s;
- ProtectHome ph;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- r = parse_boolean(s);
- if (r > 0)
- ph = PROTECT_HOME_YES;
- else if (r == 0)
- ph = PROTECT_HOME_NO;
- else {
- ph = protect_home_from_string(s);
- if (ph < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
- }
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->protect_home = ph;
- unit_write_settingf(u, flags, name, "%s=%s", name, s);
- }
-
- return 1;
-
- } else if (streq(name, "KeyringMode")) {
-
- const char *s;
- ExecKeyringMode m;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- m = exec_keyring_mode_from_string(s);
- if (m < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid keyring mode");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->keyring_mode = m;
-
- unit_write_settingf(u, flags, name, "KeyringMode=%s", exec_keyring_mode_to_string(m));
- }
-
- return 1;
-
- } else if (streq(name, "RuntimeDirectoryPreserve")) {
- const char *s;
- ExecPreserveMode m;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- m = exec_preserve_mode_from_string(s);
- if (m < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid preserve mode");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->runtime_directory_preserve_mode = m;
-
- unit_write_settingf(u, flags, name, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m));
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
- mode_t m;
-
- r = sd_bus_message_read(message, "u", &m);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- ExecDirectoryType i;
-
- if (streq(name, "UMask"))
- c->umask = m;
- else
- for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
- if (startswith(name, exec_directory_type_to_string(i))) {
- c->directories[i].mode = m;
- break;
- }
-
- unit_write_settingf(u, flags, name, "%s=%040o", name, m);
- }
-
- return 1;
-
} else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
@@ -2614,24 +2287,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "SELinuxContext")) {
- const char *s;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- r = free_and_strdup(&c->selinux_context, empty_to_null(s));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(s));
- }
-
- return 1;
-
} else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
int ignore;
const char *s;
@@ -2670,43 +2325,6 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (streq(name, "RestrictNamespaces")) {
- uint64_t rf;
-
- r = sd_bus_message_read(message, "t", &rf);
- if (r < 0)
- return r;
- if ((rf & NAMESPACE_FLAGS_ALL) != rf)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown namespace types");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- _cleanup_free_ char *s = NULL;
-
- r = namespace_flag_to_string_many(rf, &s);
- if (r < 0)
- return r;
-
- c->restrict_namespaces = rf;
- unit_write_settingf(u, flags, name, "%s=%s", name, s);
- }
-
- return 1;
- } else if (streq(name, "MountFlags")) {
- uint64_t fl;
-
- r = sd_bus_message_read(message, "t", &fl);
- if (r < 0)
- return r;
- if (!IN_SET(fl, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount propagation flags");
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->mount_flags = fl;
-
- unit_write_settingf(u, flags, name, "%s=%s", name, mount_propagation_flags_to_string(fl));
- }
-
- return 1;
} else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
unsigned empty = true;
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index 3654598f4b..4d9b368f81 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -44,4 +44,4 @@ int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *int
int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
-int bus_exec_command_set_transient_property(Unit *u, const char *name, ExecCommand **exec_command, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_exec_command(Unit *u, const char *name, ExecCommand **exec_command, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index bf3bbb2047..53d0aad63b 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -20,6 +20,7 @@
#include "bus-util.h"
#include "dbus-kill.h"
+#include "dbus-util.h"
#include "kill.h"
#include "signal-util.h"
@@ -34,6 +35,9 @@ const sd_bus_vtable bus_kill_vtable[] = {
SD_BUS_VTABLE_END
};
+static BUS_DEFINE_SET_TRANSIENT_PARSE(kill_mode, KillMode, kill_mode_from_string);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING(kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
+
int bus_kill_context_set_transient_property(
Unit *u,
KillContext *c,
@@ -42,8 +46,6 @@ int bus_kill_context_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
- int r;
-
assert(u);
assert(c);
assert(name);
@@ -51,75 +53,17 @@ int bus_kill_context_set_transient_property(
flags |= UNIT_PRIVATE;
- if (streq(name, "KillMode")) {
- const char *m;
- KillMode k;
-
- r = sd_bus_message_read(message, "s", &m);
- if (r < 0)
- return r;
-
- k = kill_mode_from_string(m);
- if (k < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Kill mode '%s' not known.", m);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->kill_mode = k;
-
- unit_write_settingf(u, flags, name, "KillMode=%s", kill_mode_to_string(k));
- }
-
- return 1;
-
- } else if (streq(name, "KillSignal")) {
- int sig;
-
- r = sd_bus_message_read(message, "i", &sig);
- if (r < 0)
- return r;
-
- if (!SIGNAL_VALID(sig))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal %i out of range", sig);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->kill_signal = sig;
-
- unit_write_settingf(u, flags, name, "KillSignal=%s", signal_to_string(sig));
- }
-
- return 1;
-
- } else if (streq(name, "SendSIGHUP")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->send_sighup = b;
-
- unit_write_settingf(u, flags, name, "SendSIGHUP=%s", yes_no(b));
- }
-
- return 1;
-
- } else if (streq(name, "SendSIGKILL")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- c->send_sigkill = b;
+ if (streq(name, "KillMode"))
+ return bus_set_transient_kill_mode(u, name, &c->kill_mode, message, flags, error);
- unit_write_settingf(u, flags, name, "SendSIGKILL=%s", yes_no(b));
- }
+ if (streq(name, "SendSIGHUP"))
+ return bus_set_transient_bool(u, name, &c->send_sighup, message, flags, error);
- return 1;
+ if (streq(name, "SendSIGKILL"))
+ return bus_set_transient_bool(u, name, &c->send_sigkill, message, flags, error);
- }
+ if (streq(name, "KillSignal"))
+ return bus_set_transient_kill_signal(u, name, &c->kill_signal, message, flags, error);
return 0;
}
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index ec9e65879f..721cad454d 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -2423,8 +2423,10 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("DefaultStartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* obsolete alias name */
+ SD_BUS_PROPERTY("DefaultStartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ /* The following two items are obsolete alias */
+ SD_BUS_PROPERTY("DefaultStartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 628bce0b6a..9e52f55fa5 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -23,6 +23,7 @@
#include "dbus-execute.h"
#include "dbus-kill.h"
#include "dbus-mount.h"
+#include "dbus-util.h"
#include "mount.h"
#include "string-util.h"
#include "unit.h"
@@ -129,9 +130,7 @@ static int bus_mount_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
- const char *new_property;
- char **property;
- int r;
+ Unit *u = UNIT(m);
assert(m);
assert(name);
@@ -139,29 +138,34 @@ static int bus_mount_set_transient_property(
flags |= UNIT_PRIVATE;
+ if (streq(name, "Where"))
+ return bus_set_transient_path(u, name, &m->where, message, flags, error);
+
if (streq(name, "What"))
- property = &m->parameters_fragment.what;
- else if (streq(name, "Options"))
- property = &m->parameters_fragment.options;
- else if (streq(name, "Type"))
- property = &m->parameters_fragment.fstype;
- else
- return 0;
-
- r = sd_bus_message_read(message, "s", &new_property);
- if (r < 0)
- return r;
+ return bus_set_transient_string(u, name, &m->parameters_fragment.what, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ if (streq(name, "Options"))
+ return bus_set_transient_string(u, name, &m->parameters_fragment.options, message, flags, error);
- r = free_and_strdup(property, new_property);
- if (r < 0)
- return r;
+ if (streq(name, "Type"))
+ return bus_set_transient_string(u, name, &m->parameters_fragment.fstype, message, flags, error);
- unit_write_settingf(UNIT(m), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, new_property);
- }
+ if (streq(name, "TimeoutUSec"))
+ return bus_set_transient_usec_fix_0(u, name, &m->timeout_usec, message, flags, error);
- return 1;
+ if (streq(name, "DirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &m->directory_mode, message, flags, error);
+
+ if (streq(name, "SloppyOptions"))
+ return bus_set_transient_bool(u, name, &m->sloppy_options, message, flags, error);
+
+ if (streq(name, "LazyUnmount"))
+ return bus_set_transient_bool(u, name, &m->lazy_unmount, message, flags, error);
+
+ if (streq(name, "ForceUnmount"))
+ return bus_set_transient_bool(u, name, &m->force_unmount, message, flags, error);
+
+ return 0;
}
int bus_mount_set_property(
diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c
index d9cf212eb7..b3f502f4c9 100644
--- a/src/core/dbus-path.c
+++ b/src/core/dbus-path.c
@@ -21,6 +21,7 @@
#include "alloc-util.h"
#include "bus-util.h"
#include "dbus-path.h"
+#include "dbus-util.h"
#include "list.h"
#include "path.h"
#include "path-util.h"
@@ -105,30 +106,38 @@ static int bus_path_set_transient_property(
flags |= UNIT_PRIVATE;
- if (STR_IN_SET(name, "PathExists", "PathExistsGlob", "PathChanged", "PathModified", "DirectoryNotEmpty")) {
- const char *str;
- PathType b;
+ if (streq(name, "MakeDirectory"))
+ return bus_set_transient_bool(u, name, &p->make_directory, message, flags, error);
- b = path_type_from_string(name);
- if (b < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown path type");
+ if (streq(name, "DirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &p->directory_mode, message, flags, error);
- r = sd_bus_message_read(message, "s", &str);
+ if (streq(name, "Paths")) {
+ const char *type_name, *path;
+ bool empty = true;
+
+ r = sd_bus_message_enter_container(message, 'a', "(ss)");
if (r < 0)
return r;
- if (!isempty(str) && !path_is_absolute(str))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path is not absolute");
+ while ((r = sd_bus_message_read(message, "(ss)", &type_name, &path)) > 0) {
+ PathType t;
+
+ t = path_type_from_string(type_name);
+ if (t < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown path type: %s", type_name);
+
+ if (isempty(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in %s is empty", type_name);
+
+ if (!path_is_absolute(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in %s is not absolute: %s", type_name, path);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (isempty(str)) {
- path_free_specs(p);
- unit_write_settingf(u, flags, name, "%s=", name);
- } else {
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *k;
PathSpec *s;
- k = strdup(str);
+ k = strdup(path);
if (!k)
return -ENOMEM;
@@ -139,48 +148,29 @@ static int bus_path_set_transient_property(
s->unit = u;
s->path = path_kill_slashes(k);
k = NULL;
- s->type = b;
+ s->type = t;
s->inotify_fd = -1;
LIST_PREPEND(spec, p->specs, s);
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, str);
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", type_name, path);
}
- }
-
- return 1;
-
- } else if (streq(name, "MakeDirectory")) {
- int b;
- r = sd_bus_message_read(message, "b", &b);
+ empty = false;
+ }
if (r < 0)
return r;
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- p->make_directory = b;
- unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
- }
-
- return 1;
-
- } else if (streq(name, "DirectoryMode")) {
- mode_t m;
-
- r = sd_bus_message_read(message, "u", &m);
+ r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- p->directory_mode = m;
- unit_write_settingf(u, flags, name, "%s=%040o", name, m);
+ if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
+ path_free_specs(p);
+ unit_write_settingf(u, flags, name, "PathExists=");
}
return 1;
-
- } else if (streq(name, "Unit")) {
- /* not implemented yet */
- return 0;
}
return 0;
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index 9195ad36d0..a0c4a65b33 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -26,6 +26,7 @@
#include "dbus-kill.h"
#include "dbus-scope.h"
#include "dbus-unit.h"
+#include "dbus-util.h"
#include "dbus.h"
#include "scope.h"
#include "selinux-access.h"
@@ -84,6 +85,9 @@ static int bus_scope_set_transient_property(
flags |= UNIT_PRIVATE;
+ if (streq(name, "TimeoutStopUSec"))
+ return bus_set_transient_usec(UNIT(s), name, &s->timeout_stop_usec, message, flags, error);
+
if (streq(name, "PIDs")) {
unsigned n = 0;
uint32_t pid;
@@ -139,21 +143,6 @@ static int bus_scope_set_transient_property(
}
return 1;
-
- } else if (streq(name, "TimeoutStopUSec")) {
- uint64_t t;
-
- r = sd_bus_message_read(message, "t", &t);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->timeout_stop_usec = t;
-
- unit_write_settingf(UNIT(s), flags, name, "TimeoutStopSec=" USEC_FMT "us", t);
- }
-
- return 1;
}
return 0;
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index c5eba5f4e5..6de905b69c 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -22,15 +22,20 @@
#include "alloc-util.h"
#include "async.h"
+#include "bus-internal.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
#include "dbus-kill.h"
#include "dbus-service.h"
+#include "dbus-util.h"
+#include "exit-status.h"
#include "fd-util.h"
#include "fileio.h"
+#include "parse-util.h"
#include "path-util.h"
#include "service.h"
+#include "signal-util.h"
#include "string-util.h"
#include "strv.h"
#include "unit.h"
@@ -41,6 +46,71 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, Servi
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
+static int property_get_exit_status_set(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExitStatusSet *status_set = userdata;
+ Iterator i;
+ void *id;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(status_set);
+
+ r = sd_bus_message_open_container(reply, 'r', "aiai");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "i");
+ if (r < 0)
+ return r;
+
+ SET_FOREACH(id, status_set->status, i) {
+ int val = PTR_TO_INT(id);
+
+ if (val < 0 || val > 255)
+ continue;
+
+ r = sd_bus_message_append_basic(reply, 'i', &val);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "i");
+ if (r < 0)
+ return r;
+
+ SET_FOREACH(id, status_set->signal, i) {
+ int val = PTR_TO_INT(id);
+ const char *str;
+
+ str = signal_to_string(val);
+ if (!str)
+ continue;
+
+ r = sd_bus_message_append_basic(reply, 'i', &val);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_close_container(reply);
+}
+
const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -57,6 +127,9 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RestartPreventExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, restart_prevent_status), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RestartForceExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, restart_force_status), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SuccessExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, success_status), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -88,159 +161,210 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_VTABLE_END
};
-static int bus_service_set_transient_property(
- Service *s,
+static int bus_set_transient_exit_status(
+ Unit *u,
const char *name,
+ ExitStatusSet *status_set,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
- ServiceExecCommand ci;
+ const int *status, *signal;
+ size_t sz_status, sz_signal, i;
int r;
- assert(s);
- assert(name);
- assert(message);
-
- flags |= UNIT_PRIVATE;
+ r = sd_bus_message_enter_container(message, 'r', "aiai");
+ if (r < 0)
+ return r;
- if (streq(name, "RemainAfterExit")) {
- int b;
+ r = sd_bus_message_read_array(message, 'i', (const void **) &status, &sz_status);
+ if (r < 0)
+ return r;
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
+ r = sd_bus_message_read_array(message, 'i', (const void **) &signal, &sz_signal);
+ if (r < 0)
+ return r;
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->remain_after_exit = b;
- unit_write_settingf(UNIT(s), flags, name, "RemainAfterExit=%s", yes_no(b));
- }
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+ if (sz_status == 0 && sz_signal == 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) {
+ exit_status_set_free(status_set);
+ unit_write_settingf(u, flags, name, "%s=", name);
return 1;
+ }
- } else if (streq(name, "Type")) {
- const char *t;
- ServiceType k;
+ for (i = 0; i < sz_status; i++) {
+ if (status[i] < 0 || status[i] > 255)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid status code in %s: %i", name, status[i]);
- r = sd_bus_message_read(message, "s", &t);
- if (r < 0)
- return r;
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ r = set_ensure_allocated(&status_set->status, NULL);
+ if (r < 0)
+ return r;
- k = service_type_from_string(t);
- if (k < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
+ r = set_put(status_set->status, INT_TO_PTR(status[i]));
+ if (r < 0)
+ return r;
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->type = k;
- unit_write_settingf(UNIT(s), flags, name, "Type=%s", service_type_to_string(s->type));
+ unit_write_settingf(u, flags, name, "%s=%i", name, status[i]);
}
+ }
- return 1;
- } else if (streq(name, "RuntimeMaxUSec")) {
- usec_t u;
+ for (i = 0; i < sz_signal; i++) {
+ const char *str;
- r = sd_bus_message_read(message, "t", &u);
- if (r < 0)
- return r;
+ str = signal_to_string(signal[i]);
+ if (!str)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal in %s: %i", name, signal[i]);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->runtime_max_usec = u;
- unit_write_settingf(UNIT(s), flags, name, "RuntimeMaxSec=" USEC_FMT "us", u);
+ r = set_ensure_allocated(&status_set->signal, NULL);
+ if (r < 0)
+ return r;
+
+ r = set_put(status_set->signal, INT_TO_PTR(signal[i]));
+ if (r < 0)
+ return r;
+
+ unit_write_settingf(u, flags, name, "%s=%s", name, str);
}
+ }
- return 1;
+ return 1;
+}
- } else if (streq(name, "Restart")) {
- ServiceRestart sr;
- const char *v;
+static int bus_set_transient_std_fd(
+ Unit *u,
+ const char *name,
+ int *p,
+ bool *b,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
- r = sd_bus_message_read(message, "s", &v);
- if (r < 0)
- return r;
+ int fd, r;
- if (isempty(v))
- sr = SERVICE_RESTART_NO;
- else {
- sr = service_restart_from_string(v);
- if (sr < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid restart setting: %s", v);
- }
+ assert(p);
+ assert(b);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->restart = sr;
- unit_write_settingf(UNIT(s), flags, name, "Restart=%s", service_restart_to_string(sr));
- }
+ r = sd_bus_message_read(message, "h", &fd);
+ if (r < 0)
+ return r;
- return 1;
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ int copy;
- } else if (STR_IN_SET(name,
- "StandardInputFileDescriptor",
- "StandardOutputFileDescriptor",
- "StandardErrorFileDescriptor")) {
- int fd;
+ copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ if (copy < 0)
+ return -errno;
- r = sd_bus_message_read(message, "h", &fd);
- if (r < 0)
- return r;
+ asynchronous_close(*p);
+ *p = copy;
+ *b = true;
+ }
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- int copy;
-
- copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
- if (copy < 0)
- return -errno;
-
- if (streq(name, "StandardInputFileDescriptor")) {
- asynchronous_close(s->stdin_fd);
- s->stdin_fd = copy;
- } else if (streq(name, "StandardOutputFileDescriptor")) {
- asynchronous_close(s->stdout_fd);
- s->stdout_fd = copy;
- } else {
- asynchronous_close(s->stderr_fd);
- s->stderr_fd = copy;
- }
-
- s->exec_context.stdio_as_fds = true;
- }
+ return 1;
+}
+static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string);
+static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, service_name_is_valid);
- return 1;
+static int bus_service_set_transient_property(
+ Service *s,
+ const char *name,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
- } else if (streq(name, "FileDescriptorStoreMax")) {
- uint32_t u;
+ Unit *u = UNIT(s);
+ ServiceExecCommand ci;
+ int r;
- r = sd_bus_message_read(message, "u", &u);
- if (r < 0)
- return r;
+ assert(s);
+ assert(name);
+ assert(message);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->n_fd_store_max = (unsigned) u;
- unit_write_settingf(UNIT(s), flags, name, "FileDescriptorStoreMax=%" PRIu32, u);
- }
+ flags |= UNIT_PRIVATE;
- return 1;
+ if (streq(name, "PermissionsStartOnly"))
+ return bus_set_transient_bool(u, name, &s->permissions_start_only, message, flags, error);
- } else if (streq(name, "NotifyAccess")) {
- const char *t;
- NotifyAccess k;
+ if (streq(name, "RootDirectoryStartOnly"))
+ return bus_set_transient_bool(u, name, &s->root_directory_start_only, message, flags, error);
- r = sd_bus_message_read(message, "s", &t);
- if (r < 0)
- return r;
+ if (streq(name, "RemainAfterExit"))
+ return bus_set_transient_bool(u, name, &s->remain_after_exit, message, flags, error);
- k = notify_access_from_string(t);
- if (k < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid notify access setting %s", t);
+ if (streq(name, "GuessMainPID"))
+ return bus_set_transient_bool(u, name, &s->guess_main_pid, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->notify_access = k;
- unit_write_settingf(UNIT(s), flags, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
- }
+ if (streq(name, "Type"))
+ return bus_set_transient_service_type(u, name, &s->type, message, flags, error);
- return 1;
+ if (streq(name, "RestartUSec"))
+ return bus_set_transient_usec(u, name, &s->restart_usec, message, flags, error);
+
+ if (streq(name, "TimeoutStartUSec")) {
+ r = bus_set_transient_usec(u, name, &s->timeout_start_usec, message, flags, error);
+ if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags))
+ s->start_timeout_defined = true;
+
+ return r;
+ }
+
+ if (streq(name, "TimeoutStopUSec"))
+ return bus_set_transient_usec(u, name, &s->timeout_stop_usec, message, flags, error);
+
+ if (streq(name, "RuntimeMaxUSec"))
+ return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error);
+
+ if (streq(name, "WatchdogUSec"))
+ return bus_set_transient_usec(u, name, &s->watchdog_usec, message, flags, error);
+
+ if (streq(name, "FileDescriptorStoreMax"))
+ return bus_set_transient_unsigned(u, name, &s->n_fd_store_max, message, flags, error);
+
+ if (streq(name, "NotifyAccess"))
+ return bus_set_transient_notify_access(u, name, &s->notify_access, message, flags, error);
+
+ if (streq(name, "PIDFile"))
+ return bus_set_transient_path(u, name, &s->pid_file, message, flags, error);
+
+ if (streq(name, "USBFunctionDescriptors"))
+ return bus_set_transient_path(u, name, &s->usb_function_descriptors, message, flags, error);
+
+ if (streq(name, "USBFunctionStrings"))
+ return bus_set_transient_path(u, name, &s->usb_function_strings, message, flags, error);
+
+ if (streq(name, "BusName"))
+ return bus_set_transient_bus_name(u, name, &s->bus_name, message, flags, error);
+
+ if (streq(name, "Restart"))
+ return bus_set_transient_service_restart(u, name, &s->restart, message, flags, error);
+
+ if (streq(name, "RestartPreventExitStatus"))
+ return bus_set_transient_exit_status(u, name, &s->restart_prevent_status, message, flags, error);
+
+ if (streq(name, "RestartForceExitStatus"))
+ return bus_set_transient_exit_status(u, name, &s->restart_force_status, message, flags, error);
+
+ if (streq(name, "SuccessExitStatus"))
+ return bus_set_transient_exit_status(u, name, &s->success_status, message, flags, error);
+
+ if ((ci = service_exec_command_from_string(name)) >= 0)
+ return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
+
+ if (streq(name, "StandardInputFileDescriptor"))
+ return bus_set_transient_std_fd(u, name, &s->stdin_fd, &s->exec_context.stdio_as_fds, message, flags, error);
+
+ if (streq(name, "StandardOutputFileDescriptor"))
+ return bus_set_transient_std_fd(u, name, &s->stdout_fd, &s->exec_context.stdio_as_fds, message, flags, error);
- } else if ((ci = service_exec_command_from_string(name)) >= 0)
- return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
+ if (streq(name, "StandardErrorFileDescriptor"))
+ return bus_set_transient_std_fd(u, name, &s->stderr_fd, &s->exec_context.stdio_as_fds, message, flags, error);
return 0;
}
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index e73ae9ddfa..035651f213 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -24,6 +24,7 @@
#include "dbus-execute.h"
#include "dbus-kill.h"
#include "dbus-socket.h"
+#include "dbus-util.h"
#include "fd-util.h"
#include "parse-util.h"
#include "path-util.h"
@@ -32,8 +33,6 @@
#include "socket-util.h"
#include "string-util.h"
#include "unit.h"
-#include "user-util.h"
-#include "utf8.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
@@ -171,6 +170,26 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_VTABLE_END
};
+static inline bool check_size_t_truncation(uint64_t t) {
+ return (size_t) t == t;
+}
+
+static inline const char* socket_protocol_to_name_supported(int32_t i) {
+ if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
+ return NULL;
+
+ return socket_protocol_to_name(i);
+}
+
+static BUS_DEFINE_SET_TRANSIENT(int, "i", int32_t, int, "%" PRIi32);
+static BUS_DEFINE_SET_TRANSIENT(message_queue, "x", int64_t, long, "%" PRIi64);
+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(size_t_check_truncation, "t", uint64_t, size_t, "%" PRIu64, check_size_t_truncation);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, parse_socket_address_bind_ipv6_only_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_name_supported);
+
static int bus_socket_set_transient_property(
Socket *s,
const char *name,
@@ -188,333 +207,139 @@ static int bus_socket_set_transient_property(
flags |= UNIT_PRIVATE;
- if (STR_IN_SET(name,
- "Accept", "Writable", "KeepAlive", "NoDelay", "FreeBind", "Transparent", "Broadcast",
- "PassCredentials", "PassSecurity", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
+ if (streq(name, "Accept"))
+ return bus_set_transient_bool(u, name, &s->accept, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "Accept"))
- s->accept = b;
- else if (streq(name, "Writable"))
- s->writable = b;
- else if (streq(name, "KeepAlive"))
- s->keep_alive = b;
- else if (streq(name, "NoDelay"))
- s->no_delay = b;
- else if (streq(name, "FreeBind"))
- s->free_bind = b;
- else if (streq(name, "Transparent"))
- s->transparent = b;
- else if (streq(name, "Broadcast"))
- s->broadcast = b;
- else if (streq(name, "PassCredentials"))
- s->pass_cred = b;
- else if (streq(name, "PassSecurity"))
- s->pass_sec = b;
- else if (streq(name, "ReusePort"))
- s->reuse_port = b;
- else if (streq(name, "RemoveOnStop"))
- s->remove_on_stop = b;
- else /* "SELinuxContextFromNet" */
- s->selinux_context_from_net = b;
-
- unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
- }
+ if (streq(name, "Writable"))
+ return bus_set_transient_bool(u, name, &s->writable, message, flags, error);
- return 1;
+ if (streq(name, "KeepAlive"))
+ return bus_set_transient_bool(u, name, &s->keep_alive, message, flags, error);
- } else if (STR_IN_SET(name, "Priority", "IPTTL", "Mark")) {
- int32_t i;
+ if (streq(name, "NoDelay"))
+ return bus_set_transient_bool(u, name, &s->no_delay, message, flags, error);
- r = sd_bus_message_read(message, "i", &i);
- if (r < 0)
- return r;
+ if (streq(name, "FreeBind"))
+ return bus_set_transient_bool(u, name, &s->free_bind, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "Priority"))
- s->priority = i;
- else if (streq(name, "IPTTL"))
- s->ip_ttl = i;
- else /* "Mark" */
- s->mark = i;
-
- unit_write_settingf(u, flags, name, "%s=%i", name, i);
- }
+ if (streq(name, "Transparent"))
+ return bus_set_transient_bool(u, name, &s->transparent, message, flags, error);
- return 1;
+ if (streq(name, "Broadcast"))
+ return bus_set_transient_bool(u, name, &s->broadcast, message, flags, error);
- } else if (streq(name, "IPTOS")) {
- _cleanup_free_ char *str = NULL;
- int32_t i;
+ if (streq(name, "PassCredentials"))
+ return bus_set_transient_bool(u, name, &s->pass_cred, message, flags, error);
- r = sd_bus_message_read(message, "i", &i);
- if (r < 0)
- return r;
+ if (streq(name, "PassSecurity"))
+ return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error);
- r = ip_tos_to_string_alloc(i, &str);
- if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
+ if (streq(name, "ReusePort"))
+ return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->ip_tos = i;
+ if (streq(name, "RemoveOnStop"))
+ return bus_set_transient_bool(u, name, &s->remove_on_stop, message, flags, error);
- unit_write_settingf(u, flags, name, "%s=%s", name, str);
- }
+ if (streq(name, "SELinuxContextFromNet"))
+ return bus_set_transient_bool(u, name, &s->selinux_context_from_net, message, flags, error);
- return 1;
+ if (streq(name, "Priority"))
+ return bus_set_transient_int(u, name, &s->priority, message, flags, error);
- } else if (streq(name, "SocketProtocol")) {
- const char *p;
- int32_t i;
+ if (streq(name, "IPTTL"))
+ return bus_set_transient_int(u, name, &s->ip_ttl, message, flags, error);
- r = sd_bus_message_read(message, "i", &i);
- if (r < 0)
- return r;
+ if (streq(name, "Mark"))
+ return bus_set_transient_int(u, name, &s->mark, message, flags, error);
- p = socket_protocol_to_name(i);
- if (!p)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
+ if (streq(name, "Backlog"))
+ return bus_set_transient_unsigned(u, name, &s->backlog, message, flags, error);
- if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported socket protocol: %s", p);
+ if (streq(name, "MaxConnections"))
+ return bus_set_transient_unsigned(u, name, &s->max_connections, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->socket_protocol = i;
- unit_write_settingf(u, flags, name, "%s=%s", name, p);
- }
+ if (streq(name, "MaxConnectionsPerSource"))
+ return bus_set_transient_unsigned(u, name, &s->max_connections_per_source, message, flags, error);
- return 1;
+ if (streq(name, "KeepAliveProbes"))
+ return bus_set_transient_unsigned(u, name, &s->keep_alive_cnt, message, flags, error);
- } else if (STR_IN_SET(name, "Backlog", "MaxConnections", "MaxConnectionsPerSource", "KeepAliveProbes", "TriggerLimitBurst")) {
- uint32_t n;
+ if (streq(name, "TriggerLimitBurst"))
+ return bus_set_transient_unsigned(u, name, &s->trigger_limit.burst, message, flags, error);
- r = sd_bus_message_read(message, "u", &n);
- if (r < 0)
- return r;
+ if (streq(name, "SocketMode"))
+ return bus_set_transient_mode_t(u, name, &s->socket_mode, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "Backlog"))
- s->backlog = n;
- else if (streq(name, "MaxConnections"))
- s->max_connections = n;
- else if (streq(name, "MaxConnectionsPerSource"))
- s->max_connections_per_source = n;
- else if (streq(name, "KeepAliveProbes"))
- s->keep_alive_cnt = n;
- else /* "TriggerLimitBurst" */
- s->trigger_limit.burst = n;
-
- unit_write_settingf(u, flags, name, "%s=%u", name, n);
- }
+ if (streq(name, "DirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &s->directory_mode, message, flags, error);
- return 1;
+ if (streq(name, "MessageQueueMaxMessages"))
+ return bus_set_transient_message_queue(u, name, &s->mq_maxmsg, message, flags, error);
- } else if (STR_IN_SET(name, "SocketMode", "DirectoryMode")) {
- mode_t m;
+ if (streq(name, "MessageQueueMessageSize"))
+ return bus_set_transient_message_queue(u, name, &s->mq_msgsize, message, flags, error);
- r = sd_bus_message_read(message, "u", &m);
- if (r < 0)
- return r;
+ if (streq(name, "TimeoutUSec"))
+ return bus_set_transient_usec_fix_0(u, name, &s->timeout_usec, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "SocketMode"))
- s->socket_mode = m;
- else /* "DirectoryMode" */
- s->directory_mode = m;
+ if (streq(name, "KeepAliveTimeUSec"))
+ return bus_set_transient_usec(u, name, &s->keep_alive_time, message, flags, error);
- unit_write_settingf(u, flags, name, "%s=%040o", name, m);
- }
+ if (streq(name, "KeepAliveIntervalUSec"))
+ return bus_set_transient_usec(u, name, &s->keep_alive_interval, message, flags, error);
- return 1;
+ if (streq(name, "DeferAcceptUSec"))
+ return bus_set_transient_usec(u, name, &s->defer_accept, message, flags, error);
- } else if (STR_IN_SET(name, "MessageQueueMaxMessages", "MessageQueueMessageSize")) {
- int64_t n;
+ if (streq(name, "TriggerLimitIntervalUSec"))
+ return bus_set_transient_usec(u, name, &s->trigger_limit.interval, message, flags, error);
- r = sd_bus_message_read(message, "x", &n);
- if (r < 0)
- return r;
+ if (streq(name, "SmackLabel"))
+ return bus_set_transient_string(u, name, &s->smack, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "MessageQueueMaxMessages"))
- s->mq_maxmsg = (long) n;
- else /* "MessageQueueMessageSize" */
- s->mq_msgsize = (long) n;
+ if (streq(name, "SmackLabelIPin"))
+ return bus_set_transient_string(u, name, &s->smack_ip_in, message, flags, error);
- unit_write_settingf(u, flags, name, "%s=%" PRIi64, name, n);
- }
+ if (streq(name, "SmackLabelIPOut"))
+ return bus_set_transient_string(u, name, &s->smack_ip_out, message, flags, error);
- return 1;
+ if (streq(name, "TCPCongestion"))
+ return bus_set_transient_string(u, name, &s->tcp_congestion, message, flags, error);
- } else if (STR_IN_SET(name, "TimeoutUSec", "KeepAliveTimeUSec", "KeepAliveIntervalUSec", "DeferAcceptUSec", "TriggerLimitIntervalUSec")) {
- usec_t t;
+ if (streq(name, "FileDescriptorName"))
+ return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error);
- r = sd_bus_message_read(message, "t", &t);
- if (r < 0)
- return r;
+ if (streq(name, "SocketUser"))
+ return bus_set_transient_user(u, name, &s->user, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "TimeoutUSec"))
- s->timeout_usec = t ?: USEC_INFINITY;
- else if (streq(name, "KeepAliveTimeUSec"))
- s->keep_alive_time = t;
- else if (streq(name, "KeepAliveIntervalUSec"))
- s->keep_alive_interval = t;
- else if (streq(name, "DeferAcceptUSec"))
- s->defer_accept = t;
- else /* "TriggerLimitIntervalUSec" */
- s->trigger_limit.interval = t;
-
- unit_write_settingf(u, flags, name, "%s=" USEC_FMT, name, t);
- }
+ if (streq(name, "SocketGroup"))
+ return bus_set_transient_user(u, name, &s->group, message, flags, error);
- return 1;
+ if (streq(name, "BindIPv6Only"))
+ return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error);
- } else if (STR_IN_SET(name, "ReceiveBuffer", "SendBuffer", "PipeSize")) {
- uint64_t t;
+ if (streq(name, "ReceiveBuffer"))
+ return bus_set_transient_size_t_check_truncation(u, name, &s->receive_buffer, message, flags, error);
- r = sd_bus_message_read(message, "t", &t);
- if (r < 0)
- return r;
+ if (streq(name, "SendBuffer"))
+ return bus_set_transient_size_t_check_truncation(u, name, &s->send_buffer, message, flags, error);
- if ((uint64_t) (size_t) t != t)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %" PRIu64, name, t);
+ if (streq(name, "PipeSize"))
+ return bus_set_transient_size_t_check_truncation(u, name, &s->pipe_size, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "ReceiveBuffer"))
- s->receive_buffer = t;
- else if (streq(name, "SendBuffer"))
- s->send_buffer = t;
- else /* "PipeSize" */
- s->pipe_size = t;
-
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, t);
- }
+ if (streq(name, "BindToDevice"))
+ return bus_set_transient_ifname(u, name, &s->bind_to_device, message, flags, error);
- return 1;
+ if (streq(name, "IPTOS"))
+ return bus_set_transient_ip_tos(u, name, &s->ip_tos, message, flags, error);
- } else if (STR_IN_SET(name, "SmackLabel", "SmackLabelIPIn", "SmackLabelIPOut", "TCPCongestion")) {
- const char *n;
+ if (streq(name, "SocketProtocol"))
+ return bus_set_transient_socket_protocol(u, name, &s->socket_protocol, message, flags, error);
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
+ if ((ci = socket_exec_command_from_string(name)) >= 0)
+ return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- if (streq(name, "SmackLabel"))
- r = free_and_strdup(&s->smack, empty_to_null(n));
- else if (streq(name, "SmackLabelIPin"))
- r = free_and_strdup(&s->smack_ip_in, empty_to_null(n));
- else if (streq(name, "SmackLabelIPOut"))
- r = free_and_strdup(&s->smack_ip_out, empty_to_null(n));
- else /* "TCPCongestion" */
- r = free_and_strdup(&s->tcp_congestion, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (streq(name, "BindToDevice")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (n[0] && !streq(n, "*")) {
- if (!ifname_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface name for %s: %s", name, n);
- } else
- n = NULL;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- r = free_and_strdup(&s->bind_to_device, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (streq(name, "BindIPv6Only")) {
- SocketAddressBindIPv6Only b;
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- b = socket_address_bind_ipv6_only_from_string(n);
- if (b < 0) {
- r = parse_boolean(n);
- if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
-
- b = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
- }
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->bind_ipv6_only = b;
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, n);
- }
-
- return 1;
-
- } else if (streq(name, "FileDescriptorName")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (!isempty(n) && !fdname_is_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- r = free_and_strdup(&s->fdname, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "SocketUser", "SocketGroup")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (!isempty(n) && !valid_user_group_name_or_id(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- if (streq(name, "SocketUser"))
- r = free_and_strdup(&s->user, empty_to_null(n));
- else /* "SocketGroup" */
- r = free_and_strdup(&s->user, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (streq(name, "Symlinks")) {
+ if (streq(name, "Symlinks")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
@@ -523,9 +348,6 @@ static int bus_socket_set_transient_property(
return r;
STRV_FOREACH(p, l) {
- if (!utf8_is_valid(*p))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "String is not UTF-8 clean, ignoring assignment: %s", *p);
-
if (!path_is_absolute(*p))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Symlink path is not absolute: %s", *p);
}
@@ -623,9 +445,7 @@ static int bus_socket_set_transient_property(
}
return 1;
-
- } else if ((ci = socket_exec_command_from_string(name)) >= 0)
- return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
+ }
return 0;
}
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 12cebc2ccc..900ed369dd 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -21,6 +21,7 @@
#include "alloc-util.h"
#include "bus-util.h"
#include "dbus-timer.h"
+#include "dbus-util.h"
#include "strv.h"
#include "timer.h"
#include "unit.h"
@@ -179,6 +180,7 @@ static int bus_timer_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
+ Unit *u = UNIT(t);
int r;
assert(t);
@@ -187,7 +189,130 @@ static int bus_timer_set_transient_property(
flags |= UNIT_PRIVATE;
- if (STR_IN_SET(name,
+ if (streq(name, "AccuracyUSec"))
+ return bus_set_transient_usec(u, name, &t->accuracy_usec, message, flags, error);
+
+ if (streq(name, "AccuracySec")) {
+ log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead.");
+ return bus_set_transient_usec(u, "AccuracyUSec", &t->accuracy_usec, message, flags, error);
+ }
+
+ if (streq(name, "RandomizedDelayUSec"))
+ return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error);
+
+ if (streq(name, "WakeSystem"))
+ return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error);
+
+ if (streq(name, "Persistent"))
+ return bus_set_transient_bool(u, name, &t->persistent, message, flags, error);
+
+ if (streq(name, "RemainAfterElapse"))
+ return bus_set_transient_bool(u, name, &t->remain_after_elapse, message, flags, error);
+
+ if (streq(name, "TimersMonotonic")) {
+ const char *base_name;
+ usec_t usec = 0;
+ bool empty = true;
+
+ r = sd_bus_message_enter_container(message, 'a', "(st)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(message, "(st)", &base_name, &usec)) > 0) {
+ TimerBase b;
+
+ b = timer_base_from_string(base_name);
+ if (b < 0 || b == TIMER_CALENDAR)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid timer base: %s", base_name);
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ char ts[FORMAT_TIMESPAN_MAX];
+ TimerValue *v;
+
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", base_name,
+ format_timespan(ts, sizeof(ts), usec, USEC_PER_MSEC));
+
+ v = new0(TimerValue, 1);
+ if (!v)
+ return -ENOMEM;
+
+ v->base = b;
+ v->value = usec;
+
+ LIST_PREPEND(value, t->values, v);
+ }
+
+ empty = false;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
+ timer_free_values(t);
+ unit_write_setting(u, flags, name, "OnActiveSec=");
+ }
+
+ return 1;
+
+ } else if (streq(name, "TimersCalendar")) {
+ const char *base_name, *str;
+ bool empty = true;
+
+ r = sd_bus_message_enter_container(message, 'a', "(ss)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(message, "(ss)", &base_name, &str)) > 0) {
+ _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
+ TimerBase b;
+
+ b = timer_base_from_string(base_name);
+ if (b != TIMER_CALENDAR)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid timer base: %s", base_name);
+
+ r = calendar_spec_from_string(str, &c);
+ if (r == -EINVAL)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid calendar spec: %s", str);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ TimerValue *v;
+
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", base_name, str);
+
+ v = new0(TimerValue, 1);
+ if (!v)
+ return -ENOMEM;
+
+ v->base = b;
+ v->calendar_spec = c;
+ c = NULL;
+
+ LIST_PREPEND(value, t->values, v);
+ }
+
+ empty = false;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
+ timer_free_values(t);
+ unit_write_setting(u, flags, name, "OnCalendar=");
+ }
+
+ return 1;
+
+ } else if (STR_IN_SET(name,
"OnActiveSec",
"OnBootSec",
"OnStartupSec",
@@ -196,27 +321,30 @@ static int bus_timer_set_transient_property(
TimerValue *v;
TimerBase b = _TIMER_BASE_INVALID;
- usec_t u = 0;
+ usec_t usec = 0;
+
+ log_notice("Client is using obsolete %s= transient property, please use TimersMonotonic= instead.", name);
b = timer_base_from_string(name);
if (b < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown timer base");
- r = sd_bus_message_read(message, "t", &u);
+ r = sd_bus_message_read(message, "t", &usec);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
char time[FORMAT_TIMESPAN_MAX];
- unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name,
+ format_timespan(time, sizeof(time), usec, USEC_PER_MSEC));
v = new0(TimerValue, 1);
if (!v)
return -ENOMEM;
v->base = b;
- v->value = u;
+ v->value = usec;
LIST_PREPEND(value, t->values, v);
}
@@ -226,9 +354,11 @@ static int bus_timer_set_transient_property(
} else if (streq(name, "OnCalendar")) {
TimerValue *v;
- CalendarSpec *c = NULL;
+ _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
const char *str;
+ log_notice("Client is using obsolete %s= transient property, please use TimersCalendar= instead.", name);
+
r = sd_bus_message_read(message, "s", &str);
if (r < 0)
return r;
@@ -240,7 +370,7 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
- unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, str);
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, str);
v = new0(TimerValue, 1);
if (!v) {
@@ -250,62 +380,12 @@ static int bus_timer_set_transient_property(
v->base = TIMER_CALENDAR;
v->calendar_spec = c;
+ c = NULL;
LIST_PREPEND(value, t->values, v);
}
return 1;
-
- } else if (STR_IN_SET(name, "AccuracyUSec", "AccuracySec")) {
- usec_t u = 0;
-
- if (streq(name, "AccuracySec"))
- log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead.");
-
- r = sd_bus_message_read(message, "t", &u);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- t->accuracy_usec = u;
- unit_write_settingf(UNIT(t), flags, name, "AccuracySec=" USEC_FMT "us", u);
- }
-
- return 1;
-
- } else if (streq(name, "RandomizedDelayUSec")) {
- usec_t u = 0;
-
- r = sd_bus_message_read(message, "t", &u);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- t->random_usec = u;
- unit_write_settingf(UNIT(t), flags, name, "RandomizedDelaySec=" USEC_FMT "us", u);
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "WakeSystem", "Persistent", "RemainAfterElapse")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "WakeSystem"))
- t->wake_system = b;
- else if (streq(name, "Persistent"))
- t->persistent = b;
- else /* RemainAfterElapse */
- t->remain_after_elapse = b;
-
- unit_write_settingf(UNIT(t), flags, name, "%s=%s", name, yes_no(b));
- }
-
- return 1;
}
return 0;
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index cdab461d58..7085eee930 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -24,12 +24,15 @@
#include "bpf-firewall.h"
#include "bus-common-errors.h"
#include "cgroup-util.h"
+#include "condition.h"
#include "dbus-job.h"
#include "dbus-unit.h"
+#include "dbus-util.h"
#include "dbus.h"
#include "fd-util.h"
#include "locale-util.h"
#include "log.h"
+#include "path-util.h"
#include "process-util.h"
#include "selinux-access.h"
#include "signal-util.h"
@@ -37,6 +40,7 @@
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
+#include "web-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
@@ -795,7 +799,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -823,6 +827,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_VTABLE_END
};
@@ -1352,6 +1357,81 @@ static int bus_unit_set_live_property(
return 0;
}
+static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(emergency_action, EmergencyAction, emergency_action_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string);
+
+static int bus_set_transient_conditions(
+ Unit *u,
+ const char *name,
+ Condition **list,
+ bool is_condition,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+
+ const char *type_name, *param;
+ int trigger, negate, r;
+ bool empty = true;
+
+ assert(list);
+
+ r = sd_bus_message_enter_container(message, 'a', "(sbbs)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(message, "(sbbs)", &type_name, &trigger, &negate, &param)) > 0) {
+ ConditionType t;
+
+ t = is_condition ? condition_type_from_string(type_name) : assert_type_from_string(type_name);
+ if (t < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name);
+
+ if (t != CONDITION_NULL) {
+ if (isempty(param))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);
+
+ if (condition_takes_path(t) && !path_is_absolute(param))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);
+ } else
+ param = NULL;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ Condition *c;
+
+ c = condition_new(t, param, trigger, negate);
+ if (!c)
+ return -ENOMEM;
+
+ LIST_PREPEND(conditions, *list, c);
+
+ if (t != CONDITION_NULL)
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,
+ "%s=%s%s%s", type_name,
+ trigger ? "|" : "", negate ? "!" : "", param);
+ else
+ unit_write_settingf(u, flags, name,
+ "%s=%s%s", type_name,
+ trigger ? "|" : "", yes_no(!negate));
+ }
+
+ empty = false;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
+ *list = condition_free_list(*list);
+ unit_write_settingf(u, flags, name, "%sNull=", is_condition ? "Condition" : "Assert");
+ }
+
+ return 1;
+}
+
static int bus_unit_set_transient_property(
Unit *u,
const char *name,
@@ -1359,6 +1439,7 @@ static int bus_unit_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
+ UnitDependency d = _UNIT_DEPENDENCY_INVALID;
int r;
assert(u);
@@ -1368,35 +1449,100 @@ static int bus_unit_set_transient_property(
/* Handles settings when transient units are created. This settings cannot be altered anymore after the unit
* has been created. */
- if (streq(name, "DefaultDependencies")) {
- int b;
+ if (streq(name, "SourcePath"))
+ return bus_set_transient_path(u, name, &u->source_path, message, flags, error);
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
+ if (streq(name, "StopWhenUnneeded"))
+ return bus_set_transient_bool(u, name, &u->stop_when_unneeded, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- u->default_dependencies = b;
- unit_write_settingf(u, flags, name, "DefaultDependencies=%s", yes_no(b));
- }
+ if (streq(name, "RefuseManualStart"))
+ return bus_set_transient_bool(u, name, &u->refuse_manual_start, message, flags, error);
- return 1;
+ if (streq(name, "RefuseManualStop"))
+ return bus_set_transient_bool(u, name, &u->refuse_manual_stop, message, flags, error);
- } else if (streq(name, "CollectMode")) {
- const char *s;
- CollectMode m;
+ if (streq(name, "AllowIsolate"))
+ return bus_set_transient_bool(u, name, &u->allow_isolate, message, flags, error);
- r = sd_bus_message_read(message, "s", &s);
+ if (streq(name, "DefaultDependencies"))
+ return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error);
+
+ if (streq(name, "OnFailureJobMode"))
+ return bus_set_transient_job_mode(u, name, &u->on_failure_job_mode, message, flags, error);
+
+ if (streq(name, "IgnoreOnIsolate"))
+ return bus_set_transient_bool(u, name, &u->ignore_on_isolate, message, flags, error);
+
+ if (streq(name, "JobTimeoutUSec")) {
+ r = bus_set_transient_usec_fix_0(u, name, &u->job_timeout, message, flags, error);
+ if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags) && !u->job_running_timeout_set)
+ u->job_running_timeout = u->job_timeout;
+ }
+
+ if (streq(name, "JobRunningTimeoutUSec")) {
+ r = bus_set_transient_usec_fix_0(u, name, &u->job_running_timeout, message, flags, error);
+ if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags))
+ u->job_running_timeout_set = true;
+
+ return r;
+ }
+
+ if (streq(name, "JobTimeoutAction"))
+ return bus_set_transient_emergency_action(u, name, &u->job_timeout_action, message, flags, error);
+
+ if (streq(name, "JobTimeoutRebootArgument"))
+ return bus_set_transient_string(u, name, &u->job_timeout_reboot_arg, message, flags, error);
+
+ if (streq(name, "StartLimitIntervalUSec"))
+ return bus_set_transient_usec(u, name, &u->start_limit.interval, message, flags, error);
+
+ if (streq(name, "StartLimitBurst"))
+ return bus_set_transient_unsigned(u, name, &u->start_limit.burst, message, flags, error);
+
+ if (streq(name, "StartLimitAction"))
+ return bus_set_transient_emergency_action(u, name, &u->start_limit_action, message, flags, error);
+
+ if (streq(name, "FailureAction"))
+ return bus_set_transient_emergency_action(u, name, &u->failure_action, message, flags, error);
+
+ if (streq(name, "SuccessAction"))
+ return bus_set_transient_emergency_action(u, name, &u->success_action, message, flags, error);
+
+ if (streq(name, "RebootArgument"))
+ return bus_set_transient_string(u, name, &u->reboot_arg, message, flags, error);
+
+ if (streq(name, "CollectMode"))
+ return bus_set_transient_collect_mode(u, name, &u->collect_mode, message, flags, error);
+
+ if (streq(name, "Conditions"))
+ return bus_set_transient_conditions(u, name, &u->conditions, true, message, flags, error);
+
+ if (streq(name, "Asserts"))
+ return bus_set_transient_conditions(u, name, &u->asserts, false, message, flags, error);
+
+ if (streq(name, "Documentation")) {
+ _cleanup_strv_free_ char **l = NULL;
+ char **p;
+
+ r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
- m = collect_mode_from_string(s);
- if (m < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
+ STRV_FOREACH(p, l) {
+ if (!documentation_url_is_valid(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid URL in %s: %s", name, *p);
+ }
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- u->collect_mode = m;
- unit_write_settingf(u, flags, name, "CollectMode=%s", collect_mode_to_string(m));
+ if (strv_isempty(l)) {
+ u->documentation = strv_free(u->documentation);
+ unit_write_settingf(u, flags, name, "%s=", name);
+ } else {
+ strv_extend_strv(&u->documentation, l, false);
+
+ STRV_FOREACH(p, l)
+ unit_write_settingf(u, flags, name, "%s=%s", name, *p);
+ }
}
return 1;
@@ -1439,30 +1585,40 @@ static int bus_unit_set_transient_property(
return 1;
- } else if (STR_IN_SET(name,
- "Requires", "RequiresOverridable",
- "Requisite", "RequisiteOverridable",
- "Wants",
- "BindsTo",
- "Conflicts",
- "Before", "After",
- "OnFailure",
- "PropagatesReloadTo", "ReloadPropagatedFrom",
- "PartOf")) {
-
- UnitDependency d;
- const char *other;
+ } else if (streq(name, "RequiresMountsFor")) {
+ _cleanup_strv_free_ char **l = NULL;
+ char **p;
- if (streq(name, "RequiresOverridable"))
- d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
- else if (streq(name, "RequisiteOverridable"))
- d = UNIT_REQUISITE; /* same here */
- else {
- d = unit_dependency_from_string(name);
- if (d < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit dependency: %s", name);
+ r = sd_bus_message_read_strv(message, &l);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(p, l) {
+ if (!path_is_absolute(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p);
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE);
+ if (r < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add required mount \"%s\": %m", *p);
+
+ unit_write_settingf(u, flags, name, "%s=%s", name, *p);
+ }
}
+ return 1;
+ }
+
+ if (streq(name, "RequiresOverridable"))
+ d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
+ else if (streq(name, "RequisiteOverridable"))
+ d = UNIT_REQUISITE; /* same here */
+ else
+ d = unit_dependency_from_string(name);
+
+ if (d >= 0) {
+ const char *other;
+
r = sd_bus_message_enter_container(message, 'a', "s");
if (r < 0)
return r;
@@ -1482,7 +1638,7 @@ static int bus_unit_set_transient_property(
if (!label)
return -ENOMEM;
- unit_write_settingf(u, flags, label, "%s=%s", name, other);
+ unit_write_settingf(u, flags, label, "%s=%s", unit_dependency_to_string(d), other);
}
}
@@ -1495,30 +1651,6 @@ static int bus_unit_set_transient_property(
return 1;
- } else if (STR_IN_SET(name, "FailureAction", "SuccessAction")) {
- EmergencyAction action;
- const char *s;
-
- r = sd_bus_message_read(message, "s", &s);
- if (r < 0)
- return r;
-
- action = emergency_action_from_string(s);
- if (action < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid emergency action: %s", s);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- if (streq(name, "FailureAction"))
- u->failure_action = action;
- else
- u->success_action = action;
-
- unit_write_settingf(u, flags, name, "%s=%s", name, emergency_action_to_string(action));
- }
-
- return 1;
-
} else if (streq(name, "AddRef")) {
int b;
diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c
new file mode 100644
index 0000000000..ed83a0e5f4
--- /dev/null
+++ b/src/core/dbus-util.c
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ 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/>.
+***/
+
+#include "bus-util.h"
+#include "dbus-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "unit-printf.h"
+#include "user-util.h"
+#include "unit.h"
+
+BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o");
+BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32);
+BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user, valid_user_group_name_or_id);
+BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(path, path_is_absolute);
+
+int bus_set_transient_string(
+ Unit *u,
+ const char *name,
+ char **p,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+
+ const char *v;
+ int r;
+
+ assert(p);
+
+ r = sd_bus_message_read(message, "s", &v);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ r = free_and_strdup(p, empty_to_null(v));
+ if (r < 0)
+ return r;
+
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,
+ "%s=%s", name, strempty(v));
+ }
+
+ return 1;
+}
+
+int bus_set_transient_bool(
+ Unit *u,
+ const char *name,
+ bool *p,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+
+ int v, r;
+
+ assert(p);
+
+ r = sd_bus_message_read(message, "b", &v);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ *p = v;
+ unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(v));
+ }
+
+ return 1;
+}
+
+int bus_set_transient_usec_internal(
+ Unit *u,
+ const char *name,
+ usec_t *p,
+ bool fix_0,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+
+ usec_t v;
+ int r;
+
+ assert(p);
+
+ r = sd_bus_message_read(message, "u", &v);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ char *n, ts[FORMAT_TIMESPAN_MAX];
+
+ if (fix_0)
+ *p = v ?: USEC_INFINITY;
+ else
+ *p = v;
+
+ n = strndupa(name, strlen(name) - 4);
+ unit_write_settingf(u, flags, name, "%sSec=%s", n,
+ format_timespan(ts, sizeof(ts), v, USEC_PER_MSEC));
+ }
+
+ return 1;
+}
diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h
new file mode 100644
index 0000000000..8260298577
--- /dev/null
+++ b/src/core/dbus-util.h
@@ -0,0 +1,351 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/***
+ 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/>.
+***/
+
+#include "sd-bus.h"
+#include "unit.h"
+
+#define BUS_DEFINE_SET_TRANSIENT(function, bus_type, type, cast_type, fmt) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ cast_type *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ type v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, bus_type, &v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = (cast_type) v; \
+ unit_write_settingf(u, flags, name, \
+ "%s=" fmt, name, v); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_TRANSIENT_IS_VALID(function, bus_type, type, cast_type, fmt, check) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ cast_type *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ type v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, bus_type, &v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (!check(v)) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Invalid %s setting: " fmt, name, v); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = (cast_type) v; \
+ unit_write_settingf(u, flags, name, \
+ "%s=" fmt, name, v); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_TRANSIENT_TO_STRING(function, bus_type, type, cast_type, fmt, to_string) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ cast_type *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ const char *s; \
+ type v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, bus_type, &v); \
+ if (r < 0) \
+ return r; \
+ \
+ s = to_string(v); \
+ if (!s) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Invalid %s setting: " fmt, name, v); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = (cast_type) v; \
+ unit_write_settingf(u, flags, name, \
+ "%s=%s", name, s); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(function, bus_type, type, cast_type, fmt, to_string) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ cast_type *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ _cleanup_free_ char *s = NULL; \
+ type v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, bus_type, &v); \
+ if (r < 0) \
+ return r; \
+ \
+ r = to_string(v, &s); \
+ if (r == -EINVAL) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Invalid %s setting: " fmt, name, v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = (cast_type) v; \
+ unit_write_settingf(u, flags, name, \
+ "%s=%s", name, s); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_TRANSIENT_PARSE(function, type, parse) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ type *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ const char *s; \
+ type v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "s", &s); \
+ if (r < 0) \
+ return r; \
+ \
+ v = parse(s); \
+ if (v < 0) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Invalid %s setting: %s", name, s); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = v; \
+ unit_write_settingf(u, flags, name, \
+ "%s=%s", name, s); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(function, type, parse) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ type *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ const char *s; \
+ type v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "s", &s); \
+ if (r < 0) \
+ return r; \
+ \
+ r = parse(s, &v); \
+ if (r < 0) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Invalid %s setting: %s", name, s); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = v; \
+ unit_write_settingf(u, flags, name, \
+ "%s=%s", name, strempty(s)); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(function, check) \
+ int bus_set_transient_##function( \
+ Unit *u, \
+ const char *name, \
+ char **p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ const char *v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "s", &v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (!isempty(v) && !check(v)) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Invalid %s setting: %s", name, v); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ r = free_and_strdup(p, empty_to_null(v)); \
+ if (r < 0) \
+ return r; \
+ \
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, \
+ "%s=%s", name, strempty(v)); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val, str) \
+ int bus_cgroup_set_##function( \
+ Unit *u, \
+ const char *name, \
+ uint64_t *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ uint64_t v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "t", &v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (!check(v)) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Value specified in %s is out of range", name); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = v; \
+ unit_invalidate_cgroup(u, (mask)); \
+ \
+ if (v == (val)) \
+ unit_write_settingf(u, flags, name, \
+ "%s=" str, name); \
+ else \
+ unit_write_settingf(u, flags, name, \
+ "%s=%" PRIu64, name, v); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_DEFINE_SET_CGROUP_SCALE(function, mask, scale) \
+ int bus_cgroup_set_##function##_scale( \
+ Unit *u, \
+ const char *name, \
+ uint64_t *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ uint64_t v; \
+ uint32_t raw; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "u", &raw); \
+ if (r < 0) \
+ return r; \
+ \
+ v = scale(raw, UINT32_MAX); \
+ if (v <= 0 || v >= UINT64_MAX) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Value specified in %s is out of range", name); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ const char *e; \
+ \
+ *p = v; \
+ unit_invalidate_cgroup(u, (mask)); \
+ \
+ /* Chop off suffix */ \
+ assert_se(e = endswith(name, "Scale")); \
+ name = strndupa(name, e - name); \
+ \
+ unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
+ (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
+ } \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+int bus_set_transient_mode_t(Unit *u, const char *name, mode_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_unsigned(Unit *u, const char *name, unsigned *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_user(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_usec_internal(Unit *u, const char *name, usec_t *p, bool fix_0, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+static inline int bus_set_transient_usec(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) {
+ return bus_set_transient_usec_internal(u, name, p, false, message, flags, error);
+}
+static inline int bus_set_transient_usec_fix_0(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) {
+ return bus_set_transient_usec_internal(u, name, p, true, message, flags, error);
+}
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 549c7eb4d6..dde5010e02 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -214,6 +214,7 @@ Unit.RefuseManualStop, config_parse_bool, 0,
Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate)
Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies)
Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode)
+m4_dnl The following is a legacy alias name for compatibility
Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, offsetof(Unit, on_failure_job_mode)
Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate)
Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index f9c2acc53a..00408c4b84 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -497,19 +497,13 @@ int config_parse_socket_bind(const char *unit,
s = SOCKET(data);
- b = socket_address_bind_ipv6_only_from_string(rvalue);
+ b = parse_socket_address_bind_ipv6_only_or_bool(rvalue);
if (b < 0) {
- int r;
-
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
- return 0;
- }
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
+ return 0;
+ }
- s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
- } else
- s->bind_ipv6_only = b;
+ s->bind_ipv6_only = b;
return 0;
}
@@ -3955,6 +3949,8 @@ int config_parse_job_mode_isolate(
return 0;
}
+ log_notice("%s is deprecated. Please use OnFailureJobMode= instead", lvalue);
+
*m = r ? JOB_ISOLATE : JOB_REPLACE;
return 0;
}
@@ -4365,7 +4361,7 @@ int config_parse_protect_home(
void *userdata) {
ExecContext *c = data;
- int k;
+ ProtectHome h;
assert(filename);
assert(lvalue);
@@ -4375,23 +4371,14 @@ int config_parse_protect_home(
/* Our enum shall be a superset of booleans, hence first try
* to parse as boolean, and then as enum */
- k = parse_boolean(rvalue);
- if (k > 0)
- c->protect_home = PROTECT_HOME_YES;
- else if (k == 0)
- c->protect_home = PROTECT_HOME_NO;
- else {
- ProtectHome h;
-
- h = protect_home_from_string(rvalue);
- if (h < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->protect_home = h;
+ h = parse_protect_home_or_bool(rvalue);
+ if (h < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
+ return 0;
}
+ c->protect_home = h;
+
return 0;
}
@@ -4408,7 +4395,7 @@ int config_parse_protect_system(
void *userdata) {
ExecContext *c = data;
- int k;
+ ProtectSystem s;
assert(filename);
assert(lvalue);
@@ -4418,23 +4405,14 @@ int config_parse_protect_system(
/* Our enum shall be a superset of booleans, hence first try
* to parse as boolean, and then as enum */
- k = parse_boolean(rvalue);
- if (k > 0)
- c->protect_system = PROTECT_SYSTEM_YES;
- else if (k == 0)
- c->protect_system = PROTECT_SYSTEM_NO;
- else {
- ProtectSystem s;
-
- s = protect_system_from_string(rvalue);
- if (s < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->protect_system = s;
+ s = parse_protect_system_or_bool(rvalue);
+ if (s < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
+ return 0;
}
+ c->protect_system = s;
+
return 0;
}
diff --git a/src/core/meson.build b/src/core/meson.build
index 535ccde468..bc034082a5 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -60,6 +60,8 @@ libcore_la_sources = '''
dbus-timer.h
dbus-unit.c
dbus-unit.h
+ dbus-util.c
+ dbus-util.h
dbus.c
dbus.h
device.c
diff --git a/src/core/namespace.c b/src/core/namespace.c
index a3262fcc4d..aed11c18ee 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1450,6 +1450,18 @@ static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(protect_home, ProtectHome);
+ProtectHome parse_protect_home_or_bool(const char *s) {
+ int r;
+
+ r = parse_boolean(s);
+ if (r > 0)
+ return PROTECT_HOME_YES;
+ if (r == 0)
+ return PROTECT_HOME_NO;
+
+ return protect_home_from_string(s);
+}
+
static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
[PROTECT_SYSTEM_NO] = "no",
[PROTECT_SYSTEM_YES] = "yes",
@@ -1459,6 +1471,18 @@ static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(protect_system, ProtectSystem);
+ProtectSystem parse_protect_system_or_bool(const char *s) {
+ int r;
+
+ r = parse_boolean(s);
+ if (r > 0)
+ return PROTECT_SYSTEM_YES;
+ if (r == 0)
+ return PROTECT_SYSTEM_NO;
+
+ return protect_system_from_string(s);
+}
+
static const char* const namespace_type_table[] = {
[NAMESPACE_MOUNT] = "mnt",
[NAMESPACE_CGROUP] = "cgroup",
diff --git a/src/core/namespace.h b/src/core/namespace.h
index f0f198362c..42d841c4d2 100644
--- a/src/core/namespace.h
+++ b/src/core/namespace.h
@@ -101,9 +101,11 @@ int setup_netns(int netns_storage_socket[2]);
const char* protect_home_to_string(ProtectHome p) _const_;
ProtectHome protect_home_from_string(const char *s) _pure_;
+ProtectHome parse_protect_home_or_bool(const char *s);
const char* protect_system_to_string(ProtectSystem p) _const_;
ProtectSystem protect_system_from_string(const char *s) _pure_;
+ProtectSystem parse_protect_system_or_bool(const char *s);
void bind_mount_free_many(BindMount *b, unsigned n);
int bind_mount_add(BindMount **b, unsigned *n, const BindMount *item);
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 6940f35482..a46fa62c2c 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -24,6 +24,7 @@
#include "bus-util.h"
#include "cap-list.h"
#include "cgroup-util.h"
+#include "condition.h"
#include "cpu-set-util.h"
#include "env-util.h"
#include "errno-list.h"
@@ -72,62 +73,71 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
&u->job_path);
}
-#define DEFINE_BUS_APPEND_PARSE_PTR(bus_type, cast_type, type, parse_func) \
- static int bus_append_##parse_func(sd_bus_message *m, const char *field, const char *eq) { \
- type val; \
- int r; \
- \
- r = parse_func(eq, &val); \
- if (r < 0) \
- return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); \
- \
- r = sd_bus_message_append(m, "(sv)", field, bus_type, (cast_type) val); \
- if (r < 0) \
- return bus_log_create_error(r); \
- \
- return 1; \
- }
-
-#define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \
- static int bus_append_##parse_func(sd_bus_message *m, const char *field, const char *eq) { \
- int r; \
- \
- r = parse_func(eq); \
- if (r < 0) { \
- log_error("Failed to parse %s: %s", field, eq); \
- return -EINVAL; \
- } \
- \
- r = sd_bus_message_append(m, "(sv)", field, bus_type, (int32_t) r); \
- if (r < 0) \
- return bus_log_create_error(r); \
- \
- return 1; \
- }
-
-DEFINE_BUS_APPEND_PARSE("b", parse_boolean)
-DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string)
-DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string)
-DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string)
-DEFINE_BUS_APPEND_PARSE("i", log_level_from_string)
-DEFINE_BUS_APPEND_PARSE("i", parse_errno)
-DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string)
-DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string)
-DEFINE_BUS_APPEND_PARSE("i", signal_from_string_try_harder)
-DEFINE_BUS_APPEND_PARSE("i", socket_protocol_from_name)
-DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority)
-DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice)
-DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, safe_atoi)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, nsec_t, parse_nsec)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_blkio_weight_parse)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_shares_parse)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_weight_parse)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, unsigned long, mount_propagation_flags_from_string)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, usec_t, parse_sec)
-DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64)
-DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode)
-DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou)
-DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64)
+#define DEFINE_BUS_APPEND_PARSE_PTR(bus_type, cast_type, type, parse_func) \
+ static int bus_append_##parse_func( \
+ sd_bus_message *m, \
+ const char *field, \
+ const char *eq) { \
+ type val; \
+ int r; \
+ \
+ r = parse_func(eq, &val); \
+ if (r < 0) \
+ return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); \
+ \
+ r = sd_bus_message_append(m, "(sv)", field, \
+ bus_type, (cast_type) val); \
+ if (r < 0) \
+ return bus_log_create_error(r); \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \
+ static int bus_append_##parse_func( \
+ sd_bus_message *m, \
+ const char *field, \
+ const char *eq) { \
+ int r; \
+ \
+ r = parse_func(eq); \
+ if (r < 0) { \
+ log_error("Failed to parse %s: %s", field, eq); \
+ return -EINVAL; \
+ } \
+ \
+ r = sd_bus_message_append(m, "(sv)", field, \
+ bus_type, (int32_t) r); \
+ if (r < 0) \
+ return bus_log_create_error(r); \
+ \
+ return 1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+DEFINE_BUS_APPEND_PARSE("b", parse_boolean);
+DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string);
+DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string);
+DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string);
+DEFINE_BUS_APPEND_PARSE("i", log_level_from_string);
+DEFINE_BUS_APPEND_PARSE("i", parse_errno);
+DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string);
+DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string);
+DEFINE_BUS_APPEND_PARSE("i", signal_from_string_try_harder);
+DEFINE_BUS_APPEND_PARSE("i", socket_protocol_from_name);
+DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority);
+DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice);
+DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, safe_atoi);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, nsec_t, parse_nsec);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_blkio_weight_parse);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_shares_parse);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_weight_parse);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, unsigned long, mount_propagation_flags_from_string);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64);
+DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode);
+DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou);
+DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64);
static inline int bus_append_string(sd_bus_message *m, const char *field, const char *eq) {
int r;
@@ -672,6 +682,23 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
return 0;
}
+static int bus_append_automount_property(sd_bus_message *m, const char *field, const char *eq) {
+
+ if (streq(field, "Where"))
+
+ return bus_append_string(m, field, eq);
+
+ if (streq(field, "DirectoryMode"))
+
+ return bus_append_parse_mode(m, field, eq);
+
+ if (streq(field, "TimeoutIdleSec"))
+
+ return bus_append_parse_sec_rename(m, field, eq);
+
+ return 0;
+}
+
static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) {
int r, rl;
@@ -1128,14 +1155,30 @@ static int bus_append_kill_property(sd_bus_message *m, const char *field, const
return 0;
}
-static int bus_append_path_property(sd_bus_message *m, const char *field, const char *eq) {
+static int bus_append_mount_property(sd_bus_message *m, const char *field, const char *eq) {
- if (STR_IN_SET(field,
- "PathExists", "PathExistsGlob", "PathChanged",
- "PathModified", "DirectoryNotEmpty"))
+ if (STR_IN_SET(field, "What", "Where", "Options", "Type"))
return bus_append_string(m, field, eq);
+ if (streq(field, "TimeoutSec"))
+
+ return bus_append_parse_sec_rename(m, field, eq);
+
+ if (streq(field, "DirectoryMode"))
+
+ return bus_append_parse_mode(m, field, eq);
+
+ if (STR_IN_SET(field, "SloppyOptions", "LazyUnmount", "ForceUnmount"))
+
+ return bus_append_parse_boolean(m, field, eq);
+
+ return 0;
+}
+
+static int bus_append_path_property(sd_bus_message *m, const char *field, const char *eq) {
+ int r;
+
if (streq(field, "MakeDirectory"))
return bus_append_parse_boolean(m, field, eq);
@@ -1144,23 +1187,49 @@ static int bus_append_path_property(sd_bus_message *m, const char *field, const
return bus_append_parse_mode(m, field, eq);
+ if (STR_IN_SET(field,
+ "PathExists", "PathExistsGlob", "PathChanged",
+ "PathModified", "DirectoryNotEmpty")) {
+
+ if (isempty(eq))
+ r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 0);
+ else
+ r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 1, field, eq);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
+
return 0;
}
static int bus_append_service_property(sd_bus_message *m, const char *field, const char *eq) {
+ int r;
- if (STR_IN_SET(field, "Type", "Restart", "NotifyAccess"))
+ if (STR_IN_SET(field,
+ "PIDFile", "Type", "Restart", "BusName", "NotifyAccess",
+ "USBFunctionDescriptors", "USBFunctionStrings"))
return bus_append_string(m, field, eq);
- if (streq(field, "RemainAfterExit"))
+ if (STR_IN_SET(field, "PermissionsStartOnly", "RootDirectoryStartOnly", "RemainAfterExit", "GuessMainPID"))
return bus_append_parse_boolean(m, field, eq);
- if (streq(field, "RuntimeMaxSec"))
+ if (STR_IN_SET(field, "RestartSec", "TimeoutStartSec", "TimeoutStopSec", "RuntimeMaxSec", "WatchdogSec"))
return bus_append_parse_sec_rename(m, field, eq);
+ if (streq(field, "TimeoutSec")) {
+
+ r = bus_append_parse_sec_rename(m, "TimeoutStartSec", eq);
+ if (r < 0)
+ return r;
+
+ return bus_append_parse_sec_rename(m, "TimeoutStopSec", eq);
+ }
+
if (streq(field, "FileDescriptorStoreMax"))
return bus_append_safe_atou(m, field, eq);
@@ -1171,6 +1240,82 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
return bus_append_exec_command(m, field, eq);
+ if (STR_IN_SET(field, "RestartPreventExitStatus", "RestartForceExitStatus", "SuccessExitStatus")) {
+ _cleanup_free_ int *status = NULL, *signal = NULL;
+ size_t sz_status = 0, sz_signal = 0;
+ const char *p;
+
+ for (p = eq;;) {
+ _cleanup_free_ char *word = NULL;
+ int val;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0)
+ return log_error_errno(r, "Invalid syntax in %s: %s", field, eq);
+
+ r = safe_atoi(word, &val);
+ if (r < 0) {
+ val = signal_from_string_try_harder(word);
+ if (val < 0)
+ return log_error_errno(r, "Invalid status or signal %s in %s: %m", word, field);
+
+ signal = realloc_multiply(signal, sizeof(int), sz_signal + 1);
+ if (!signal)
+ return log_oom();
+
+ signal[sz_signal++] = val;
+ } else {
+ status = realloc_multiply(status, sizeof(int), sz_status + 1);
+ if (!status)
+ return log_oom();
+
+ status[sz_status++] = val;
+ }
+ }
+
+ r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'v', "(aiai)");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'r', "aiai");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_array(m, 'i', status, sz_status);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_array(m, 'i', signal, sz_signal);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
+
return 0;
}
@@ -1234,7 +1379,10 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
"ListenStream", "ListenDatagram", "ListenSequentialPacket", "ListenNetlink",
"ListenSpecial", "ListenMessageQueue", "ListenFIFO", "ListenUSBFunction")) {
- r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 1, field + strlen("Listen"), eq);
+ if (isempty(eq))
+ r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 0);
+ else
+ r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 1, field + strlen("Listen"), eq);
if (r < 0)
return bus_log_create_error(r);
@@ -1244,42 +1392,112 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
return 0;
}
static int bus_append_timer_property(sd_bus_message *m, const char *field, const char *eq) {
-
- if (streq(field, "OnCalendar"))
-
- return bus_append_string(m, field, eq);
+ int r;
if (STR_IN_SET(field, "WakeSystem", "RemainAfterElapse", "Persistent"))
return bus_append_parse_boolean(m, field, eq);
+ if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec"))
+
+ return bus_append_parse_sec_rename(m, field, eq);
+
if (STR_IN_SET(field,
"OnActiveSec", "OnBootSec", "OnStartupSec",
- "OnUnitActiveSec","OnUnitInactiveSec"))
+ "OnUnitActiveSec","OnUnitInactiveSec")) {
- return bus_append_parse_sec(m, field, eq);
+ if (isempty(eq))
+ r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 0);
+ else {
+ usec_t t;
+ r = parse_sec(eq, &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
- if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec"))
+ r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 1, field, t);
+ }
+ if (r < 0)
+ return bus_log_create_error(r);
- return bus_append_parse_sec_rename(m, field, eq);
+ return 1;
+ }
+
+ if (streq(field, "OnCalendar")) {
+
+ if (isempty(eq))
+ r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 0);
+ else
+ r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 1, field, eq);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
return 0;
}
static int bus_append_unit_property(sd_bus_message *m, const char *field, const char *eq) {
+ ConditionType t = _CONDITION_TYPE_INVALID;
+ bool is_condition = false;
+ int r;
- if (STR_IN_SET(field, "Description", "CollectMode", "FailureAction", "SuccessAction"))
+ if (STR_IN_SET(field,
+ "Description", "SourcePath", "OnFailureJobMode",
+ "JobTimeoutAction", "JobTimeoutRebootArgument",
+ "StartLimitAction", "FailureAction", "SuccessAction",
+ "RebootArgument", "CollectMode"))
return bus_append_string(m, field, eq);
- if (streq(field, "DefaultDependencies"))
+ if (STR_IN_SET(field,
+ "StopWhenUnneeded", "RefuseManualStart", "RefuseManualStop",
+ "AllowIsolate", "IgnoreOnIsolate", "DefaultDependencies"))
return bus_append_parse_boolean(m, field, eq);
- if (unit_dependency_from_string(field) >= 0)
+ if (STR_IN_SET(field, "JobTimeoutSec", "JobRunningTimeoutSec", "StartLimitIntervalSec"))
+
+ return bus_append_parse_sec_rename(m, field, eq);
+
+ if (streq(field, "StartLimitBurst"))
+
+ return bus_append_safe_atou(m, field, eq);
+
+ if (unit_dependency_from_string(field) >= 0 ||
+ STR_IN_SET(field, "Documentation", "RequiresMountsFor"))
return bus_append_strv(m, field, eq, EXTRACT_QUOTES);
+ t = condition_type_from_string(field);
+ if (t >= 0)
+ is_condition = true;
+ else
+ t = assert_type_from_string(field);
+ if (t >= 0) {
+ if (isempty(eq))
+ r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 0);
+ else {
+ const char *p = eq;
+ int trigger, negate;
+
+ trigger = *p == '|';
+ if (trigger)
+ p++;
+
+ negate = *p == '!';
+ if (negate)
+ p++;
+
+ r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 1,
+ field, trigger, negate, p);
+ }
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
+
return 0;
}
@@ -1355,6 +1573,10 @@ int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const cha
break;
case UNIT_SCOPE:
+
+ if (streq(field, "TimeoutStopSec"))
+ return bus_append_parse_sec_rename(m, field, eq);
+
r = bus_append_cgroup_property(m, field, eq);
if (r != 0)
return r;
@@ -1365,7 +1587,29 @@ int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const cha
break;
case UNIT_MOUNT:
+ r = bus_append_cgroup_property(m, field, eq);
+ if (r != 0)
+ return r;
+
+ r = bus_append_execute_property(m, field, eq);
+ if (r != 0)
+ return r;
+
+ r = bus_append_kill_property(m, field, eq);
+ if (r != 0)
+ return r;
+
+ r = bus_append_mount_property(m, field, eq);
+ if (r != 0)
+ return r;
+
+ break;
+
case UNIT_AUTOMOUNT:
+ r = bus_append_automount_property(m, field, eq);
+ if (r != 0)
+ return r;
+
break;
case UNIT_TARGET:
diff --git a/src/shared/condition.h b/src/shared/condition.h
index 98af2daaee..a84d993370 100644
--- a/src/shared/condition.h
+++ b/src/shared/condition.h
@@ -99,3 +99,17 @@ ConditionType assert_type_from_string(const char *s) _pure_;
const char* condition_result_to_string(ConditionResult r) _const_;
ConditionResult condition_result_from_string(const char *s) _pure_;
+
+static inline bool condition_takes_path(ConditionType t) {
+ return IN_SET(t,
+ CONDITION_PATH_EXISTS,
+ CONDITION_PATH_EXISTS_GLOB,
+ CONDITION_PATH_IS_DIRECTORY,
+ CONDITION_PATH_IS_SYMBOLIC_LINK,
+ CONDITION_PATH_IS_MOUNT_POINT,
+ CONDITION_PATH_IS_READ_WRITE,
+ CONDITION_DIRECTORY_NOT_EMPTY,
+ CONDITION_FILE_NOT_EMPTY,
+ CONDITION_FILE_IS_EXECUTABLE,
+ CONDITION_NEEDS_UPDATE);
+}
diff --git a/src/shared/nsflags.h b/src/shared/nsflags.h
index dcac6cd0b2..51bc590621 100644
--- a/src/shared/nsflags.h
+++ b/src/shared/nsflags.h
@@ -42,6 +42,13 @@ unsigned long namespace_flag_from_string(const char *name);
int namespace_flag_from_string_many(const char *name, unsigned long *ret);
int namespace_flag_to_string_many(unsigned long flags, char **ret);
+static inline int namespace_flag_to_string_many_with_check(unsigned long n, char **s) {
+ if ((n & NAMESPACE_FLAGS_ALL) != n)
+ return -EINVAL;
+
+ return namespace_flag_to_string_many(n, s);
+}
+
struct namespace_flag_map {
unsigned long flag;
const char *name;