Merge pull request #7759 from yuwata/dbus-api

DBus-API: add more options in transient units
This commit is contained in:
Lennart Poettering 2018-01-03 18:41:32 +01:00 committed by GitHub
commit fb92330ccc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 2071 additions and 1769 deletions

View file

@ -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

View file

@ -100,8 +100,6 @@
late system shutdown should disable
<varname>DefaultDependencies=</varname> option.</para></listitem>
</itemizedlist>
<para></para>
</refsect1>
<refsect1>

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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_;

View file

@ -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(

View file

@ -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);
} else if (streq(name, "CPUQuotaPerSecUSec")) {
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);
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;

View file

@ -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);
} else if (streq(name, "SupplementaryGroups")) {
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);
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;
@ -1735,22 +1764,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")) {
@ -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;

View file

@ -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);

View file

@ -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;
if (streq(name, "KillMode"))
return bus_set_transient_kill_mode(u, name, &c->kill_mode, message, flags, error);
r = sd_bus_message_read(message, "s", &m);
if (r < 0)
return r;
if (streq(name, "SendSIGHUP"))
return bus_set_transient_bool(u, name, &c->send_sighup, message, flags, error);
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 (streq(name, "SendSIGKILL"))
return bus_set_transient_bool(u, name, &c->send_sigkill, message, flags, error);
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;
unit_write_settingf(u, flags, name, "SendSIGKILL=%s", yes_no(b));
}
return 1;
}
if (streq(name, "KillSignal"))
return bus_set_transient_kill_signal(u, name, &c->kill_signal, message, flags, error);
return 0;
}

View file

@ -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),

View file

@ -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;
return bus_set_transient_string(u, name, &m->parameters_fragment.what, message, flags, error);
r = sd_bus_message_read(message, "s", &new_property);
if (r < 0)
return r;
if (streq(name, "Options"))
return bus_set_transient_string(u, name, &m->parameters_fragment.options, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (streq(name, "Type"))
return bus_set_transient_string(u, name, &m->parameters_fragment.fstype, message, flags, error);
r = free_and_strdup(property, new_property);
if (r < 0)
return r;
if (streq(name, "TimeoutUSec"))
return bus_set_transient_usec_fix_0(u, name, &m->timeout_usec, message, flags, error);
unit_write_settingf(UNIT(m), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, new_property);
}
if (streq(name, "DirectoryMode"))
return bus_set_transient_mode_t(u, name, &m->directory_mode, message, flags, error);
return 1;
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(

View file

@ -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;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (isempty(str)) {
path_free_specs(p);
unit_write_settingf(u, flags, name, "%s=", name);
} else {
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)) {
_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);
}
empty = false;
}
return 1;
} else if (streq(name, "MakeDirectory")) {
int b;
r = sd_bus_message_read(message, "b", &b);
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;

View file

@ -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;
@ -138,21 +142,6 @@ static int bus_scope_set_transient_property(
return r;
}
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;
}

View file

@ -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,6 +161,117 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_VTABLE_END
};
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) {
const int *status, *signal;
size_t sz_status, sz_signal, i;
int r;
r = sd_bus_message_enter_container(message, 'r', "aiai");
if (r < 0)
return r;
r = sd_bus_message_read_array(message, 'i', (const void **) &status, &sz_status);
if (r < 0)
return r;
r = sd_bus_message_read_array(message, 'i', (const void **) &signal, &sz_signal);
if (r < 0)
return r;
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;
}
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]);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = set_ensure_allocated(&status_set->status, NULL);
if (r < 0)
return r;
r = set_put(status_set->status, INT_TO_PTR(status[i]));
if (r < 0)
return r;
unit_write_settingf(u, flags, name, "%s=%i", name, status[i]);
}
}
for (i = 0; i < sz_signal; i++) {
const char *str;
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)) {
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;
}
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) {
int fd, r;
assert(p);
assert(b);
r = sd_bus_message_read(message, "h", &fd);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
int copy;
copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (copy < 0)
return -errno;
asynchronous_close(*p);
*p = copy;
*b = 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);
static int bus_service_set_transient_property(
Service *s,
const char *name,
@ -95,6 +279,7 @@ static int bus_service_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
Unit *u = UNIT(s);
ServiceExecCommand ci;
int r;
@ -104,143 +289,82 @@ static int bus_service_set_transient_property(
flags |= UNIT_PRIVATE;
if (streq(name, "RemainAfterExit")) {
int b;
if (streq(name, "PermissionsStartOnly"))
return bus_set_transient_bool(u, name, &s->permissions_start_only, message, flags, error);
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
if (streq(name, "RootDirectoryStartOnly"))
return bus_set_transient_bool(u, name, &s->root_directory_start_only, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->remain_after_exit = b;
unit_write_settingf(UNIT(s), flags, name, "RemainAfterExit=%s", yes_no(b));
}
if (streq(name, "RemainAfterExit"))
return bus_set_transient_bool(u, name, &s->remain_after_exit, message, flags, error);
return 1;
if (streq(name, "GuessMainPID"))
return bus_set_transient_bool(u, name, &s->guess_main_pid, message, flags, error);
} else if (streq(name, "Type")) {
const char *t;
ServiceType k;
if (streq(name, "Type"))
return bus_set_transient_service_type(u, name, &s->type, message, flags, error);
r = sd_bus_message_read(message, "s", &t);
if (r < 0)
return r;
if (streq(name, "RestartUSec"))
return bus_set_transient_usec(u, name, &s->restart_usec, message, flags, error);
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);
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;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->type = k;
unit_write_settingf(UNIT(s), flags, name, "Type=%s", service_type_to_string(s->type));
}
return r;
}
return 1;
} else if (streq(name, "RuntimeMaxUSec")) {
usec_t u;
if (streq(name, "TimeoutStopUSec"))
return bus_set_transient_usec(u, name, &s->timeout_stop_usec, message, flags, error);
r = sd_bus_message_read(message, "t", &u);
if (r < 0)
return r;
if (streq(name, "RuntimeMaxUSec"))
return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->runtime_max_usec = u;
unit_write_settingf(UNIT(s), flags, name, "RuntimeMaxSec=" USEC_FMT "us", u);
}
if (streq(name, "WatchdogUSec"))
return bus_set_transient_usec(u, name, &s->watchdog_usec, message, flags, error);
return 1;
if (streq(name, "FileDescriptorStoreMax"))
return bus_set_transient_unsigned(u, name, &s->n_fd_store_max, message, flags, error);
} else if (streq(name, "Restart")) {
ServiceRestart sr;
const char *v;
if (streq(name, "NotifyAccess"))
return bus_set_transient_notify_access(u, name, &s->notify_access, message, flags, error);
r = sd_bus_message_read(message, "s", &v);
if (r < 0)
return r;
if (streq(name, "PIDFile"))
return bus_set_transient_path(u, name, &s->pid_file, message, flags, error);
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);
}
if (streq(name, "USBFunctionDescriptors"))
return bus_set_transient_path(u, name, &s->usb_function_descriptors, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->restart = sr;
unit_write_settingf(UNIT(s), flags, name, "Restart=%s", service_restart_to_string(sr));
}
if (streq(name, "USBFunctionStrings"))
return bus_set_transient_path(u, name, &s->usb_function_strings, message, flags, error);
return 1;
if (streq(name, "BusName"))
return bus_set_transient_bus_name(u, name, &s->bus_name, message, flags, error);
} else if (STR_IN_SET(name,
"StandardInputFileDescriptor",
"StandardOutputFileDescriptor",
"StandardErrorFileDescriptor")) {
int fd;
if (streq(name, "Restart"))
return bus_set_transient_service_restart(u, name, &s->restart, message, flags, error);
r = sd_bus_message_read(message, "h", &fd);
if (r < 0)
return r;
if (streq(name, "RestartPreventExitStatus"))
return bus_set_transient_exit_status(u, name, &s->restart_prevent_status, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
int copy;
if (streq(name, "RestartForceExitStatus"))
return bus_set_transient_exit_status(u, name, &s->restart_force_status, message, flags, error);
copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (copy < 0)
return -errno;
if (streq(name, "SuccessExitStatus"))
return bus_set_transient_exit_status(u, name, &s->success_status, message, flags, error);
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;
}
if ((ci = service_exec_command_from_string(name)) >= 0)
return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
s->exec_context.stdio_as_fds = true;
}
if (streq(name, "StandardInputFileDescriptor"))
return bus_set_transient_std_fd(u, name, &s->stdin_fd, &s->exec_context.stdio_as_fds, message, flags, error);
return 1;
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 (streq(name, "FileDescriptorStoreMax")) {
uint32_t u;
r = sd_bus_message_read(message, "u", &u);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->n_fd_store_max = (unsigned) u;
unit_write_settingf(UNIT(s), flags, name, "FileDescriptorStoreMax=%" PRIu32, u);
}
return 1;
} else if (streq(name, "NotifyAccess")) {
const char *t;
NotifyAccess k;
r = sd_bus_message_read(message, "s", &t);
if (r < 0)
return r;
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 (!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));
}
return 1;
} 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;
}

View file

@ -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 (!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));
}
return 1;
} else if (STR_IN_SET(name, "Priority", "IPTTL", "Mark")) {
int32_t i;
r = sd_bus_message_read(message, "i", &i);
if (r < 0)
return r;
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);
}
return 1;
} else if (streq(name, "IPTOS")) {
_cleanup_free_ char *str = NULL;
int32_t i;
r = sd_bus_message_read(message, "i", &i);
if (r < 0)
return r;
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 (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->ip_tos = i;
unit_write_settingf(u, flags, name, "%s=%s", name, str);
}
return 1;
} else if (streq(name, "SocketProtocol")) {
const char *p;
int32_t i;
r = sd_bus_message_read(message, "i", &i);
if (r < 0)
return r;
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 (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported socket protocol: %s", p);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->socket_protocol = i;
unit_write_settingf(u, flags, name, "%s=%s", name, p);
}
return 1;
} else if (STR_IN_SET(name, "Backlog", "MaxConnections", "MaxConnectionsPerSource", "KeepAliveProbes", "TriggerLimitBurst")) {
uint32_t n;
r = sd_bus_message_read(message, "u", &n);
if (r < 0)
return r;
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);
}
return 1;
} else if (STR_IN_SET(name, "SocketMode", "DirectoryMode")) {
mode_t m;
if (streq(name, "Accept"))
return bus_set_transient_bool(u, name, &s->accept, message, flags, error);
r = sd_bus_message_read(message, "u", &m);
if (r < 0)
return r;
if (streq(name, "Writable"))
return bus_set_transient_bool(u, name, &s->writable, 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, "KeepAlive"))
return bus_set_transient_bool(u, name, &s->keep_alive, message, flags, error);
unit_write_settingf(u, flags, name, "%s=%040o", name, m);
}
if (streq(name, "NoDelay"))
return bus_set_transient_bool(u, name, &s->no_delay, message, flags, error);
return 1;
if (streq(name, "FreeBind"))
return bus_set_transient_bool(u, name, &s->free_bind, message, flags, error);
} else if (STR_IN_SET(name, "MessageQueueMaxMessages", "MessageQueueMessageSize")) {
int64_t n;
if (streq(name, "Transparent"))
return bus_set_transient_bool(u, name, &s->transparent, message, flags, error);
r = sd_bus_message_read(message, "x", &n);
if (r < 0)
return r;
if (streq(name, "Broadcast"))
return bus_set_transient_bool(u, name, &s->broadcast, 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, "PassCredentials"))
return bus_set_transient_bool(u, name, &s->pass_cred, message, flags, error);
unit_write_settingf(u, flags, name, "%s=%" PRIi64, name, n);
}
if (streq(name, "PassSecurity"))
return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error);
return 1;
if (streq(name, "ReusePort"))
return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error);
} else if (STR_IN_SET(name, "TimeoutUSec", "KeepAliveTimeUSec", "KeepAliveIntervalUSec", "DeferAcceptUSec", "TriggerLimitIntervalUSec")) {
usec_t t;
if (streq(name, "RemoveOnStop"))
return bus_set_transient_bool(u, name, &s->remove_on_stop, message, flags, error);
r = sd_bus_message_read(message, "t", &t);
if (r < 0)
return r;
if (streq(name, "SELinuxContextFromNet"))
return bus_set_transient_bool(u, name, &s->selinux_context_from_net, 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;
if (streq(name, "Priority"))
return bus_set_transient_int(u, name, &s->priority, message, flags, error);
unit_write_settingf(u, flags, name, "%s=" USEC_FMT, name, t);
}
if (streq(name, "IPTTL"))
return bus_set_transient_int(u, name, &s->ip_ttl, message, flags, error);
return 1;
if (streq(name, "Mark"))
return bus_set_transient_int(u, name, &s->mark, message, flags, error);
} else if (STR_IN_SET(name, "ReceiveBuffer", "SendBuffer", "PipeSize")) {
uint64_t t;
if (streq(name, "Backlog"))
return bus_set_transient_unsigned(u, name, &s->backlog, message, flags, error);
r = sd_bus_message_read(message, "t", &t);
if (r < 0)
return r;
if (streq(name, "MaxConnections"))
return bus_set_transient_unsigned(u, name, &s->max_connections, 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, "MaxConnectionsPerSource"))
return bus_set_transient_unsigned(u, name, &s->max_connections_per_source, 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;
if (streq(name, "KeepAliveProbes"))
return bus_set_transient_unsigned(u, name, &s->keep_alive_cnt, message, flags, error);
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, t);
}
if (streq(name, "TriggerLimitBurst"))
return bus_set_transient_unsigned(u, name, &s->trigger_limit.burst, message, flags, error);
return 1;
if (streq(name, "SocketMode"))
return bus_set_transient_mode_t(u, name, &s->socket_mode, message, flags, error);
} else if (STR_IN_SET(name, "SmackLabel", "SmackLabelIPIn", "SmackLabelIPOut", "TCPCongestion")) {
const char *n;
if (streq(name, "DirectoryMode"))
return bus_set_transient_mode_t(u, name, &s->directory_mode, message, flags, error);
r = sd_bus_message_read(message, "s", &n);
if (r < 0)
return r;
if (streq(name, "MessageQueueMaxMessages"))
return bus_set_transient_message_queue(u, name, &s->mq_maxmsg, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (streq(name, "MessageQueueMessageSize"))
return bus_set_transient_message_queue(u, name, &s->mq_msgsize, message, flags, error);
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;
if (streq(name, "TimeoutUSec"))
return bus_set_transient_usec_fix_0(u, name, &s->timeout_usec, message, flags, error);
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
}
if (streq(name, "KeepAliveTimeUSec"))
return bus_set_transient_usec(u, name, &s->keep_alive_time, message, flags, error);
return 1;
if (streq(name, "KeepAliveIntervalUSec"))
return bus_set_transient_usec(u, name, &s->keep_alive_interval, message, flags, error);
} else if (streq(name, "BindToDevice")) {
const char *n;
if (streq(name, "DeferAcceptUSec"))
return bus_set_transient_usec(u, name, &s->defer_accept, message, flags, error);
r = sd_bus_message_read(message, "s", &n);
if (r < 0)
return r;
if (streq(name, "TriggerLimitIntervalUSec"))
return bus_set_transient_usec(u, name, &s->trigger_limit.interval, message, flags, error);
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 (streq(name, "SmackLabel"))
return bus_set_transient_string(u, name, &s->smack, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (streq(name, "SmackLabelIPin"))
return bus_set_transient_string(u, name, &s->smack_ip_in, message, flags, error);
r = free_and_strdup(&s->bind_to_device, empty_to_null(n));
if (r < 0)
return r;
if (streq(name, "SmackLabelIPOut"))
return bus_set_transient_string(u, name, &s->smack_ip_out, message, flags, error);
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
}
if (streq(name, "TCPCongestion"))
return bus_set_transient_string(u, name, &s->tcp_congestion, message, flags, error);
return 1;
if (streq(name, "FileDescriptorName"))
return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error);
} else if (streq(name, "BindIPv6Only")) {
SocketAddressBindIPv6Only b;
const char *n;
if (streq(name, "SocketUser"))
return bus_set_transient_user(u, name, &s->user, message, flags, error);
r = sd_bus_message_read(message, "s", &n);
if (r < 0)
return r;
if (streq(name, "SocketGroup"))
return bus_set_transient_user(u, name, &s->group, message, flags, error);
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);
if (streq(name, "BindIPv6Only"))
return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error);
b = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
}
if (streq(name, "ReceiveBuffer"))
return bus_set_transient_size_t_check_truncation(u, name, &s->receive_buffer, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->bind_ipv6_only = b;
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, n);
}
if (streq(name, "SendBuffer"))
return bus_set_transient_size_t_check_truncation(u, name, &s->send_buffer, message, flags, error);
return 1;
if (streq(name, "PipeSize"))
return bus_set_transient_size_t_check_truncation(u, name, &s->pipe_size, message, flags, error);
} else if (streq(name, "FileDescriptorName")) {
const char *n;
if (streq(name, "BindToDevice"))
return bus_set_transient_ifname(u, name, &s->bind_to_device, message, flags, error);
r = sd_bus_message_read(message, "s", &n);
if (r < 0)
return r;
if (streq(name, "IPTOS"))
return bus_set_transient_ip_tos(u, name, &s->ip_tos, message, flags, error);
if (!isempty(n) && !fdname_is_valid(n))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
if (streq(name, "SocketProtocol"))
return bus_set_transient_socket_protocol(u, name, &s->socket_protocol, message, flags, error);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = free_and_strdup(&s->fdname, empty_to_null(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);
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;
}

View file

@ -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,61 +380,11 @@ 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;
}

View file

@ -24,12 +24,15 @@
#include "bpf-firewall.h"
#include "bus-common-errors.h"
#include "cgroup-util.h"
#include "condition.h"
#include "dbus-job.h"
#include "dbus-unit.h"
#include "dbus-util.h"
#include "dbus.h"
#include "fd-util.h"
#include "locale-util.h"
#include "log.h"
#include "path-util.h"
#include "process-util.h"
#include "selinux-access.h"
#include "signal-util.h"
@ -37,6 +40,7 @@
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
#include "web-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
@ -795,7 +799,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
@ -823,6 +827,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_VTABLE_END
};
@ -1352,6 +1357,81 @@ static int bus_unit_set_live_property(
return 0;
}
static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(emergency_action, EmergencyAction, emergency_action_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string);
static int bus_set_transient_conditions(
Unit *u,
const char *name,
Condition **list,
bool is_condition,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
const char *type_name, *param;
int trigger, negate, r;
bool empty = true;
assert(list);
r = sd_bus_message_enter_container(message, 'a', "(sbbs)");
if (r < 0)
return r;
while ((r = sd_bus_message_read(message, "(sbbs)", &type_name, &trigger, &negate, &param)) > 0) {
ConditionType t;
t = is_condition ? condition_type_from_string(type_name) : assert_type_from_string(type_name);
if (t < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name);
if (t != CONDITION_NULL) {
if (isempty(param))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);
if (condition_takes_path(t) && !path_is_absolute(param))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);
} else
param = NULL;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
Condition *c;
c = condition_new(t, param, trigger, negate);
if (!c)
return -ENOMEM;
LIST_PREPEND(conditions, *list, c);
if (t != CONDITION_NULL)
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,
"%s=%s%s%s", type_name,
trigger ? "|" : "", negate ? "!" : "", param);
else
unit_write_settingf(u, flags, name,
"%s=%s%s", type_name,
trigger ? "|" : "", yes_no(!negate));
}
empty = false;
}
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
*list = condition_free_list(*list);
unit_write_settingf(u, flags, name, "%sNull=", is_condition ? "Condition" : "Assert");
}
return 1;
}
static int bus_unit_set_transient_property(
Unit *u,
const char *name,
@ -1359,6 +1439,7 @@ static int bus_unit_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
UnitDependency d = _UNIT_DEPENDENCY_INVALID;
int r;
assert(u);
@ -1368,35 +1449,100 @@ static int bus_unit_set_transient_property(
/* Handles settings when transient units are created. This settings cannot be altered anymore after the unit
* has been created. */
if (streq(name, "DefaultDependencies")) {
int b;
if (streq(name, "SourcePath"))
return bus_set_transient_path(u, name, &u->source_path, message, flags, error);
r = sd_bus_message_read(message, "b", &b);
if (streq(name, "StopWhenUnneeded"))
return bus_set_transient_bool(u, name, &u->stop_when_unneeded, message, flags, error);
if (streq(name, "RefuseManualStart"))
return bus_set_transient_bool(u, name, &u->refuse_manual_start, message, flags, error);
if (streq(name, "RefuseManualStop"))
return bus_set_transient_bool(u, name, &u->refuse_manual_stop, message, flags, error);
if (streq(name, "AllowIsolate"))
return bus_set_transient_bool(u, name, &u->allow_isolate, message, flags, error);
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;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
u->default_dependencies = b;
unit_write_settingf(u, flags, name, "DefaultDependencies=%s", yes_no(b));
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);
}
return 1;
} else if (streq(name, "CollectMode")) {
const char *s;
CollectMode m;
r = sd_bus_message_read(message, "s", &s);
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);
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")) {
} else if (streq(name, "RequiresMountsFor")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
UnitDependency d;
const char *other;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
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);
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;

119
src/core/dbus-util.c Normal file
View file

@ -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;
}

351
src/core/dbus-util.h Normal file
View file

@ -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);
}

View file

@ -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

View file

@ -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;
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
return 0;
}
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;
}
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;
}

View file

@ -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

View file

@ -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",

View file

@ -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);

View file

@ -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_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; \
}
#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, 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_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,
"OnActiveSec", "OnBootSec", "OnStartupSec",
"OnUnitActiveSec","OnUnitInactiveSec"))
return bus_append_parse_sec(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")) {
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);
r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 1, field, t);
}
if (r < 0)
return bus_log_create_error(r);
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:

View file

@ -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);
}

View file

@ -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;