diff options
author | Lennart Poettering <lennart@poettering.net> | 2018-01-03 18:41:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-03 18:41:32 +0100 |
commit | fb92330cccb5c0e9ca30249ff4da800d5d068825 (patch) | |
tree | ec8afe44461bba060e202ebe46aedc7877aabb54 | |
parent | 7f9ac71c76f8157707fb36e1b316961aa4db0ac8 (diff) | |
parent | 681ae88e06f2acbfb3b7adf681a681c32c1d5843 (diff) | |
download | systemd-fb92330cccb5c0e9ca30249ff4da800d5d068825.tar.gz |
Merge pull request #7759 from yuwata/dbus-api
DBus-API: add more options in transient units
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, ¶m)) > 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; |