Merge pull request #7444 from poettering/dbus-no-spec

unit writing escaping fixes + related fixes and additions
This commit is contained in:
Yu Watanabe 2017-11-30 14:50:36 +09:00 committed by GitHub
commit 191e9ef87d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
65 changed files with 1703 additions and 919 deletions

View file

@ -434,3 +434,8 @@
that interrupted system calls are automatically restarted, and we minimize
hassles with handling EINTR (in particular as EINTR handling is pretty broken
on Linux).
- When applying C-style unescaping as well as specifier expansion on the same
string, always apply the C-style unescaping fist, followed by the specifier
expansion. When doing the reverse, make sure to escape '%' in specifier-style
first (i.e. '%' → '%%'), and then do C-style escaping where necessary.

37
TODO
View file

@ -30,6 +30,10 @@ Features:
systemd-journald writes to /var/log/journal, which could be useful when we
doing disk usage calculations and so on.
* taint systemd if the overflowuid/overflowgid is not 65534
* deprecate PermissionsStartOnly= and RootDirectoryStartOnly= in favour of the ExecStart= prefix chars
* add a new RuntimeDirectoryPreserve= mode that defines a similar lifecycle for
the runtime dir as we maintain for the fdstore: i.e. keep it around as long
as the unit is running or has a job queued.
@ -67,9 +71,6 @@ Features:
suitable for processing with rrdtool. Add bus API to access this data, and
possibly implement a CPULoad property based on it.
* In journalctl add a way how "-o verbose" and suchlike can be tweaked to show
only a specific set of properties
* beef up pam_systemd to take unit file settings such as cgroups properties as
parameters
@ -116,12 +117,6 @@ Features:
taken if multiple dirs are configured. Maybe avoid setting the env vars in
that case?
* introduce SuccessAction= that permits shutting down the system when a service
succeeds. This is useful to replace "ExecPost=/usr/bin/systemctl poweroff" and
similar constructs, which are frequently used. This is particularly nice for
implementation of a systemd.run= kernel command line option that runs some
command and immediately shuts down.
* expose IO accounting data on the bus, show it in systemd-run --wait and log
about it in the resource log message
@ -145,10 +140,6 @@ Features:
ReadWritePaths=:/var/lib/foobar
* sort generated hwdb files alphabetically when we import them, so that git
diffs remain minimal (in particular: the OUI databases we import are not
sorted, and not stable)
* maybe add call sd_journal_set_block_timeout() or so to set SO_SNDTIMEO for
the sd-journal logging socket, and, if the timeout is set to 0, sets
O_NONBLOCK on it. That way people can control if and when to block for
@ -208,17 +199,12 @@ Features:
partition, that is mounted to / and is writable, and where the actual root's
/usr is mounted into.
* machined: add apis to query /etc/machine-info data of a container
* .mount and .swap units: add Format=yes|no option that formats the partition before mounting/enabling it, implicitly
* gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file
* drop nss-myhostname in favour of nss-resolve?
* drop internal dlopen() based nss-dns fallback in nss-resolve, and rely on the
external nsswitch.conf based one
* add a percentage syntax for TimeoutStopSec=, e.g. TimeoutStopSec=150%, and
then use that for the setting used in user@.service. It should be understood
relative to the configured default value.
@ -229,8 +215,6 @@ Features:
* Permit masking specific netlink APIs with RestrictAddressFamily=
* nspawn: start UID allocation loop from hash of container name
* nspawn: support that /proc, /sys/, /dev are pre-mounted
* define gpt header bits to select volatility mode
@ -268,8 +252,6 @@ Features:
a user/group for a service only has to exist on the host for the right
mapping to work.
* allow attaching additional journald log fields to cgroups
* add bus API for creating unit files in /etc, reusing the code for transient units
* add bus API to remove unit files from /etc
@ -570,8 +552,6 @@ Features:
* shutdown logging: store to EFI var, and store to USB stick?
* think about window-manager-run-as-user-service problem: exit 0 → activate shutdown.target; exit != 0 → restart service
* merge unit_kill_common() and unit_kill_context()
* introduce ExecCondition= in services
@ -657,7 +637,6 @@ Features:
- journald: when we drop syslog messages because the syslog socket is
full, make sure to write how many messages are lost as first thing
to syslog when it works again.
- journald: make sure ratelimit is actually really per-service with the new cgroup changes
- change systemd-journal-flush into a service that stays around during
boot, and causes the journal to be moved back to /run on shutdown,
so that we do not keep /var busy. This needs to happen synchronously,
@ -686,7 +665,6 @@ Features:
- add journalctl -H that talks via ssh to a remote peer and passes through
binary logs data
- add a version of --merge which also merges /var/log/journal/remote
- log accumulated resource usage after each service invocation
- journalctl: -m should access container journals directly by enumerating
them via machined, and also watch containers coming and going.
Benefit: nspawn --ephemeral would start working nicely with the journal.
@ -697,7 +675,6 @@ Features:
[Install] units of other units, unless those units are disabled
- man: clarify that time-sync.target is not only sysv compat but also useful otherwise. Same for similar targets
- document that service reload may be implemented as service reexec
- document in wiki how to map ical recurrence events to systemd timer unit calendar specifications
- add a man page containing packaging guidelines and recommending usage of things like Documentation=, PrivateTmp=, PrivateNetwork= and ReadOnlyDirectories=/etc /usr.
- document systemd-journal-flush.service properly
- documentation: recommend to connect the timer units of a service to the service via Also= in [Install]
@ -715,7 +692,6 @@ Features:
- add new command to systemctl: "systemctl system-reexec" which reexecs as many daemons as virtually possible
- systemctl enable: fail if target to alias into does not exist? maybe show how many units are enabled afterwards?
- systemctl: "Journal has been rotated since unit was started." message is misleading
- better error message if you run systemctl without systemd running
- systemctl status output should include list of triggering units and their status
* unit install:
@ -758,8 +734,6 @@ Features:
- should send out sd_notify("WATCHDOG=1") messages
- optionally automatically add FORWARD rules to iptables whenever nspawn is
running, remove them when shut down.
- Improve error message when --bind= is used on a non-existing source
directory
- maybe make copying of /etc/resolv.conf optional, and skip it if --read-only
is used
@ -846,7 +820,6 @@ Features:
* write blog stories about:
- hwdb: what belongs into it, lsusb
- enabling dbus services
- status update
- how to make changes to sysctl and sysfs attributes
- remote access
- how to pass throw-away units to systemd, or dynamically change properties of existing units
@ -1001,8 +974,6 @@ Regularly:
* check for strerror(r) instead of strerror(-r)
* Use PR_SET_PROCTITLE_AREA if it becomes available in the kernel
* pahole
* set_put(), hashmap_put() return values check. i.e. == 0 does not free()!

447
TRANSIENT-SETTINGS.md Normal file
View file

@ -0,0 +1,447 @@
# What settings are currently available for transient units?
Our intention is to make all settings that are available as unit file settings
also available for transient units, through the D-Bus API. At the moment, some
unit types (socket, swap, path) are not supported at all via unit types, but
most others are pretty well supported, with some notable omissions.
The lists below contain all settings currently available in unit files. The
ones currently available in transient units are prefixed with `✓`.
## Generic Unit Settings
Only the most important generic unit settings are available for transient units.
```
✓ Description=
Documentation=
SourcePath=
✓ Requires=
✓ Requisite=
✓ Wants=
✓ BindsTo=
✓ Conflicts=
✓ Before=
✓ After=
✓ OnFailure=
✓ PropagatesReloadTo=
✓ ReloadPropagatedFrom=
✓ PartOf=
JoinsNamespaceOf=
RequiresMountsFor=
StopWhenUnneeded=
RefuseManualStart=
RefuseManualStop=
AllowIsolate=
✓ DefaultDependencies=
OnFailureJobMode=
OnFailureIsolate=
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=
AssertPathExists=
AssertPathExistsGlob=
AssertPathIsDirectory=
AssertPathIsSymbolicLink=
AssertPathIsMountPoint=
AssertPathIsReadWrite=
AssertDirectoryNotEmpty=
AssertFileNotEmpty=
AssertFileIsExecutable=
AssertNeedsUpdate=
AssertFirstBoot=
AssertKernelCommandLine=
AssertArchitecture=
AssertVirtualization=
AssertSecurity=
AssertCapability=
AssertHost=
AssertACPower=
AssertUser=
AssertGroup=
✓ CollectMode=
```
## Execution-Related Settings
All execution-related settings are available for transient units.
```
✓ WorkingDirectory=
✓ RootDirectory=
✓ RootImage=
✓ User=
✓ Group=
✓ SupplementaryGroups=
✓ Nice=
✓ OOMScoreAdjust=
✓ IOSchedulingClass=
✓ IOSchedulingPriority=
✓ CPUSchedulingPolicy=
✓ CPUSchedulingPriority=
✓ CPUSchedulingResetOnFork=
✓ CPUAffinity=
✓ UMask=
✓ Environment=
✓ EnvironmentFile=
✓ PassEnvironment=
✓ UnsetEnvironment=
✓ DynamicUser=
✓ RemoveIPC=
✓ StandardInput=
✓ StandardOutput=
✓ StandardError=
✓ StandardInputText=
✓ StandardInputData=
✓ TTYPath=
✓ TTYReset=
✓ TTYVHangup=
✓ TTYVTDisallocate=
✓ SyslogIdentifier=
✓ SyslogFacility=
✓ SyslogLevel=
✓ SyslogLevelPrefix=
✓ LogLevelMax=
✓ LogExtraFields=
✓ SecureBits=
✓ CapabilityBoundingSet=
✓ AmbientCapabilities=
✓ TimerSlackNSec=
✓ NoNewPrivileges=
✓ KeyringMode=
✓ SystemCallFilter=
✓ SystemCallArchitectures=
✓ SystemCallErrorNumber=
✓ MemoryDenyWriteExecute=
✓ RestrictNamespaces=
✓ RestrictRealtime=
✓ RestrictAddressFamilies=
✓ LockPersonality=
✓ LimitCPU=
✓ LimitFSIZE=
✓ LimitDATA=
✓ LimitSTACK=
✓ LimitCORE=
✓ LimitRSS=
✓ LimitNOFILE=
✓ LimitAS=
✓ LimitNPROC=
✓ LimitMEMLOCK=
✓ LimitLOCKS=
✓ LimitSIGPENDING=
✓ LimitMSGQUEUE=
✓ LimitNICE=
✓ LimitRTPRIO=
✓ LimitRTTIME=
✓ ReadWritePaths=
✓ ReadOnlyPaths=
✓ InaccessiblePaths=
✓ BindPaths=
✓ BindReadOnlyPaths=
✓ PrivateTmp=
✓ PrivateDevices=
✓ ProtectKernelTunables=
✓ ProtectKernelModules=
✓ ProtectControlGroups=
✓ PrivateNetwork=
✓ PrivateUsers=
✓ ProtectSystem=
✓ ProtectHome=
✓ MountFlags=
✓ MountAPIVFS=
✓ Personality=
✓ RuntimeDirectoryPreserve=
✓ RuntimeDirectoryMode=
✓ RuntimeDirectory=
✓ StateDirectoryMode=
✓ StateDirectory=
✓ CacheDirectoryMode=
✓ CacheDirectory=
✓ LogsDirectoryMode=
✓ LogsDirectory=
✓ ConfigurationDirectoryMode=
✓ ConfigurationDirectory=
✓ PAMName=
✓ IgnoreSIGPIPE=
✓ UtmpIdentifier=
✓ UtmpMode=
✓ SELinuxContext=
✓ SmackProcessLabel=
✓ AppArmorProfile=
✓ Slice=
```
## Resource Control Settings
All cgroup/resource control settings are available for transient units
```
✓ CPUAccounting=
✓ CPUWeight=
✓ StartupCPUWeight=
✓ CPUShares=
✓ StartupCPUShares=
✓ CPUQuota=
✓ MemoryAccounting=
✓ MemoryLow=
✓ MemoryHigh=
✓ MemoryMax=
✓ MemorySwapMax=
✓ MemoryLimit=
✓ DeviceAllow=
✓ DevicePolicy=
✓ IOAccounting=
✓ IOWeight=
✓ StartupIOWeight=
✓ IODeviceWeight=
✓ IOReadBandwidthMax=
✓ IOWriteBandwidthMax=
✓ IOReadIOPSMax=
✓ IOWriteIOPSMax=
✓ BlockIOAccounting=
✓ BlockIOWeight=
✓ StartupBlockIOWeight=
✓ BlockIODeviceWeight=
✓ BlockIOReadBandwidth=
✓ BlockIOWriteBandwidth=
✓ TasksAccounting=
✓ TasksMax=
✓ Delegate=
✓ IPAccounting=
✓ IPAddressAllow=
✓ IPAddressDeny=
```
## Process Killing Settings
All process killing settings are available for transient units:
```
✓ SendSIGKILL=
✓ SendSIGHUP=
✓ KillMode=
✓ KillSignal=
```
## Service Unit Settings
Only the most important service settings are available for transient units.
```
PIDFile=
✓ ExecStartPre=
✓ ExecStart=
✓ ExecStartPost=
✓ ExecReload=
✓ ExecStop=
✓ ExecStopPost=
RestartSec=
TimeoutStartSec=
TimeoutStopSec=
TimeoutSec=
✓ RuntimeMaxSec=
WatchdogSec=
✓ Type=
✓ Restart=
PermissionsStartOnly=
RootDirectoryStartOnly=
✓ RemainAfterExit=
GuessMainPID=
RestartPreventExitStatus=
RestartForceExitStatus=
SuccessExitStatus=
✓ NonBlocking=
BusName=
✓ FileDescriptorStoreMax=
✓ NotifyAccess=
Sockets=
USBFunctionDescriptors=
USBFunctionStrings=
```
## Mount Unit Settings
Only the most important mount unit settings are currently available to transient units:
```
✓ What=
Where=
✓ Options=
✓ Type=
TimeoutSec=
DirectoryMode=
SloppyOptions=
LazyUnmount=
ForceUnmount=
```
## Automount Unit Settings
Only one automount unit setting is currently available to transient units:
```
Where=
DirectoryMode=
✓ TimeoutIdleSec=
```
## Timer Unit Settings
Most timer unit settings are available to transient units.
```
✓ OnCalendar=
✓ OnActiveSec=
✓ OnBootSec=
✓ OnStartupSec=
✓ OnUnitActiveSec=
✓ OnUnitInactiveSec=
Persistent=
✓ WakeSystem=
✓ RemainAfterElapse=
✓ AccuracySec=
✓ RandomizedDelaySec=
Unit=
```
## Slice Unit Settings
Slice units are fully supported as transient units, but they have no settings
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 and
resource control settings.
## Socket Unit Settings
Socket units are currently not available at all as transient units:
```
ListenStream=
ListenDatagram=
ListenSequentialPacket=
ListenFIFO=
ListenNetlink=
ListenSpecial=
ListenMessageQueue=
ListenUSBFunction=
SocketProtocol=
BindIPv6Only=
Backlog=
BindToDevice=
ExecStartPre=
ExecStartPost=
ExecStopPre=
ExecStopPost=
TimeoutSec=
SocketUser=
SocketGroup=
SocketMode=
DirectoryMode=
Accept=
Writable=
MaxConnections=
MaxConnectionsPerSource=
KeepAlive=
KeepAliveTimeSec=
KeepAliveIntervalSec=
KeepAliveProbes=
DeferAcceptSec=
NoDelay=
Priority=
ReceiveBuffer=
SendBuffer=
IPTOS=
IPTTL=
Mark=
PipeSize=
FreeBind=
Transparent=
Broadcast=
PassCredentials=
PassSecurity=
TCPCongestion=
ReusePort=
MessageQueueMaxMessages=
MessageQueueMessageSize=
RemoveOnStop=
Symlinks=
FileDescriptorName=
Service=
TriggerLimitIntervalSec=
TriggerLimitBurst=
SmackLabel=
SmackLabelIPIn=
SmackLabelIPOut=
SELinuxContextFromNet=
```
## Swap Unit Settings
Swap units are currently not available at all as transient units:
```
What=
Priority=
Options=
TimeoutSec=
```
## Path Unit Settings
Path units are currently not available at all as transient units:
```
PathExists=
PathExistsGlob=
PathChanged=
PathModified=
DirectoryNotEmpty=
Unit=
MakeDirectory=
DirectoryMode=
```
## Install Section
The `[Install]` section is currently not available at all for transient units, and it probably doesn't even make sense.
```
Alias=
WantedBy=
RequiredBy=
Also=
DefaultInstance=
```

View file

@ -1,35 +1,54 @@
@@
expression e;
identifier n1, n2, n3, n4, n5, n6;
statement s;
constant n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
@@
- e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6
+ IN_SET(e, n1, n2, n3, n4, n5, n6)
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8 || e == n9
+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9)
@@
expression e;
identifier n1, n2, n3, n4, n5;
statement s;
constant n0, n1, n2, n3, n4, n5, n6, n7, n8;
@@
- e == n1 || e == n2 || e == n3 || e == n4 || e == n5
+ IN_SET(e, n1, n2, n3, n4, n5)
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8
+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8)
@@
expression e;
identifier n1, n2, n3, n4;
statement s;
constant n0, n1, n2, n3, n4, n5, n6, n7;
@@
- e == n1 || e == n2 || e == n3 || e == n4
+ IN_SET(e, n1, n2, n3, n4)
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7
+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7)
@@
expression e;
identifier n1, n2, n3;
statement s;
constant n0, n1, n2, n3, n4, n5, n6;
@@
- e == n1 || e == n2 || e == n3
+ IN_SET(e, n1, n2, n3)
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6
+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6)
@@
expression e;
identifier n, p;
statement s;
constant n0, n1, n2, n3, n4, n5;
@@
- e == n || e == p
+ IN_SET(e, n, p)
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5
+ IN_SET(e, n0, n1, n2, n3, n4, n5)
@@
expression e;
constant n0, n1, n2, n3, n4;
@@
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4
+ IN_SET(e, n0, n1, n2, n3, n4)
@@
expression e;
constant n0, n1, n2, n3;
@@
- e == n0 || e == n1 || e == n2 || e == n3
+ IN_SET(e, n0, n1, n2, n3)
@@
expression e;
constant n0, n1, n2;
@@
- e == n0 || e == n1 || e == n2
+ IN_SET(e, n0, n1, n2)
@@
expression e;
constant n0, n1;
@@
- e == n0 || e == n1
+ IN_SET(e, n0, n1)

15
coccinelle/isempty.cocci Normal file
View file

@ -0,0 +1,15 @@
@@
expression s;
@@
- strv_length(s) == 0
+ strv_isempty(s)
@@
expression s;
@@
- strlen(s) == 0
+ isempty(s)
@@
expression s;
@@
- strlen_ptr(s) == 0
+ isempty(s)

View file

@ -1,147 +1,54 @@
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14 && e != n15 && e != n16 && e != n17 && e != n18 && e != n19 && e != n20
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14 && e != n15 && e != n16 && e != n17 && e != n18 && e != n19
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14 && e != n15 && e != n16 && e != n17 && e != n18
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14 && e != n15 && e != n16 && e != n17
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14 && e != n15 && e != n16
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14 && e != n15
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13 && e != n14
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12 && e != n13
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11 && e != n12
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10 && e != n11
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10;
statement s;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 && e != n10
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
statement s;
constant n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7, n8;
statement s;
constant n0, n1, n2, n3, n4, n5, n6, n7, n8;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6, n7;
statement s;
constant n0, n1, n2, n3, n4, n5, n6, n7;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5, n6;
statement s;
constant n0, n1, n2, n3, n4, n5, n6;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6
+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6)
@@
expression e;
identifier n0, n1, n2, n3, n4, n5;
statement s;
constant n0, n1, n2, n3, n4, n5;
@@
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5
+ !IN_SET(e, n0, n1, n2, n3, n4, n5)
@@
expression e;
identifier n1, n2, n3, n4, n5;
statement s;
constant n0, n1, n2, n3, n4;
@@
- e != n1 && e != n2 && e != n3 && e != n4 && e != n5
+ !IN_SET(e, n1, n2, n3, n4, n5)
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4
+ !IN_SET(e, n0, n1, n2, n3, n4)
@@
expression e;
identifier n1, n2, n3, n4;
statement s;
constant n0, n1, n2, n3;
@@
- e != n1 && e != n2 && e != n3 && e != n4
+ !IN_SET(e, n1, n2, n3, n4)
- e != n0 && e != n1 && e != n2 && e != n3
+ !IN_SET(e, n0, n1, n2, n3)
@@
expression e;
identifier n1, n2, n3, n4;
statement s;
constant n0, n1, n2;
@@
- e != n1 && e != n2 && e != n3 && e != n4
+ !IN_SET(e, n1, n2, n3, n4)
- e != n0 && e != n1 && e != n2
+ !IN_SET(e, n0, n1, n2)
@@
expression e;
identifier n1, n2, n3;
statement s;
constant n0, n1;
@@
- e != n1 && e != n2 && e != n3
+ !IN_SET(e, n1, n2, n3)
@@
expression e;
identifier n, p;
statement s;
@@
- e != n && e != p
+ !IN_SET(e, n, p)
- e != n0 && e != n1
+ !IN_SET(e, n0, n1)

11
coccinelle/run-coccinelle.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/bash -e
for SCRIPT in *.cocci ; do
[ "$SCRIPT" = "empty-if.cocci" ] && continue
echo "--x-- Processing $SCRIPT --x--"
TMPFILE=`mktemp`
spatch --sp-file $SCRIPT --dir $(pwd)/.. 2> "$TMPFILE" || cat "$TMPFILE"
rm "$TMPFILE"
echo "--x-- Processed $SCRIPT --x--"
echo ""
done

View file

@ -25,6 +25,10 @@
#include "fileio.h"
/* These functions are split out of fileio.h (and not for examplement just as flags to the functions they wrap) in
* order to optimize linking: This way, -lselinux is needed only for the callers of these functions that need selinux,
* but not for all */
int write_string_file_atomic_label_ts(const char *fn, const char *line, struct timespec *ts);
static inline int write_string_file_atomic_label(const char *fn, const char *line) {
return write_string_file_atomic_label_ts(fn, line, NULL);

View file

@ -30,11 +30,16 @@
#include "time-util.h"
typedef enum {
WRITE_STRING_FILE_CREATE = 1<<0,
WRITE_STRING_FILE_ATOMIC = 1<<1,
WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2,
WRITE_STRING_FILE_CREATE = 1<<0,
WRITE_STRING_FILE_ATOMIC = 1<<1,
WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2,
WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1<<3,
WRITE_STRING_FILE_SYNC = 1<<4,
WRITE_STRING_FILE_SYNC = 1<<4,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
and friends. */
} WriteStringFileFlags;
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);

View file

@ -603,26 +603,26 @@ char* strshorten(char *s, size_t l) {
}
char *strreplace(const char *text, const char *old_string, const char *new_string) {
size_t l, old_len, new_len, allocated = 0;
char *t, *ret = NULL;
const char *f;
char *t, *r;
size_t l, old_len, new_len;
assert(text);
assert(old_string);
assert(new_string);
if (!text)
return NULL;
old_len = strlen(old_string);
new_len = strlen(new_string);
l = strlen(text);
r = new(char, l+1);
if (!r)
if (!GREEDY_REALLOC(ret, allocated, l+1))
return NULL;
f = text;
t = r;
t = ret;
while (*f) {
char *a;
size_t d, nl;
if (!startswith(f, old_string)) {
@ -630,25 +630,21 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
continue;
}
d = t - r;
d = t - ret;
nl = l - old_len + new_len;
a = realloc(r, nl + 1);
if (!a)
goto oom;
if (!GREEDY_REALLOC(ret, allocated, nl + 1))
return mfree(ret);
l = nl;
r = a;
t = r + d;
t = ret + d;
t = stpcpy(t, new_string);
f += old_len;
}
*t = 0;
return r;
oom:
return mfree(r);
return ret;
}
char *strip_tab_ansi(char **ibuf, size_t *_isz) {

View file

@ -38,7 +38,7 @@ static int bus_automount_set_transient_property(
Automount *a,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
@ -47,18 +47,21 @@ static int bus_automount_set_transient_property(
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "TimeoutIdleUSec")) {
usec_t timeout_idle_usec;
r = sd_bus_message_read(message, "t", &timeout_idle_usec);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
char time[FORMAT_TIMESPAN_MAX];
a->timeout_idle_usec = timeout_idle_usec;
unit_write_drop_in_format(UNIT(a), mode, name, "[Automount]\nTimeoutIdleSec=%s\n",
format_timespan(time, sizeof(time), timeout_idle_usec, USEC_PER_MSEC));
unit_write_settingf(UNIT(a), flags, name, "TimeoutIdleSec=%s\n",
format_timespan(time, sizeof(time), timeout_idle_usec, USEC_PER_MSEC));
}
} else
return 0;
@ -70,20 +73,17 @@ int bus_automount_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Automount *a = AUTOMOUNT(u);
int r = 0;
assert(a);
assert(name);
assert(message);
if (u->transient && u->load_state == UNIT_STUB)
/* This is a transient unit, let's load a little more */
if (u->transient && u->load_state == UNIT_STUB) /* This is a transient unit? let's load a little more */
return bus_automount_set_transient_property(a, name, message, flags, error);
r = bus_automount_set_transient_property(a, name, message, mode, error);
return r;
return 0;
}

View file

@ -23,4 +23,4 @@
extern const sd_bus_vtable bus_automount_vtable[];
int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);

View file

@ -334,7 +334,7 @@ static int bus_cgroup_set_transient_property(
CGroupContext *c,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
@ -344,6 +344,8 @@ static int bus_cgroup_set_transient_property(
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "Delegate")) {
int b;
@ -351,11 +353,11 @@ static int bus_cgroup_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->delegate = b;
c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
}
return 1;
@ -379,7 +381,7 @@ static int bus_cgroup_set_transient_property(
cc = cgroup_controller_from_string(t);
if (cc < 0)
return sd_bus_error_set_errnof(error, EINVAL, "Unknown cgroup contoller '%s'", t);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup contoller '%s'", t);
mask |= CGROUP_CONTROLLER_TO_MASK(cc);
}
@ -388,7 +390,7 @@ static int bus_cgroup_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *t = NULL;
r = cg_mask_to_string(mask, &t);
@ -401,7 +403,7 @@ static int bus_cgroup_set_transient_property(
else
c->delegate_controllers |= mask;
unit_write_drop_in_private_format(u, mode, name, "Delegate=%s", strempty(t));
unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
}
return 1;
@ -415,7 +417,7 @@ int bus_cgroup_set_property(
CGroupContext *c,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
CGroupIOLimitType iol_type;
@ -426,6 +428,8 @@ int bus_cgroup_set_property(
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "CPUAccounting")) {
int b;
@ -433,10 +437,10 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->cpu_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU);
unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
unit_write_settingf(u, flags, name, "CPUAccounting=%s", yes_no(b));
}
return 1;
@ -449,16 +453,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "CPUWeight value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->cpu_weight = weight;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (weight == CGROUP_WEIGHT_INVALID)
unit_write_drop_in_private(u, mode, name, "CPUWeight=");
unit_write_setting(u, flags, name, "CPUWeight=");
else
unit_write_drop_in_private_format(u, mode, name, "CPUWeight=%" PRIu64, weight);
unit_write_settingf(u, flags, name, "CPUWeight=%" PRIu64, weight);
}
return 1;
@ -471,16 +475,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUWeight value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupCPUWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->startup_cpu_weight = weight;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (weight == CGROUP_CPU_SHARES_INVALID)
unit_write_drop_in_private(u, mode, name, "StartupCPUWeight=");
unit_write_setting(u, flags, name, "StartupCPUWeight=");
else
unit_write_drop_in_private_format(u, mode, name, "StartupCPUWeight=%" PRIu64, weight);
unit_write_settingf(u, flags, name, "StartupCPUWeight=%" PRIu64, weight);
}
return 1;
@ -493,16 +497,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_CPU_SHARES_IS_OK(shares))
return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUShares= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->cpu_shares = shares;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (shares == CGROUP_CPU_SHARES_INVALID)
unit_write_drop_in_private(u, mode, name, "CPUShares=");
unit_write_setting(u, flags, name, "CPUShares=");
else
unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
unit_write_settingf(u, flags, name, "CPUShares=%" PRIu64, shares);
}
return 1;
@ -515,16 +519,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_CPU_SHARES_IS_OK(shares))
return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupCPUShares= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->startup_cpu_shares = shares;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (shares == CGROUP_CPU_SHARES_INVALID)
unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
unit_write_setting(u, flags, name, "StartupCPUShares=");
else
unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
unit_write_settingf(u, flags, name, "StartupCPUShares=%" PRIu64, shares);
}
return 1;
@ -537,20 +541,20 @@ int bus_cgroup_set_property(
return r;
if (u64 <= 0)
return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->cpu_quota_per_sec_usec = u64;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
unit_write_drop_in_private_format(u, mode, "CPUQuota",
"CPUQuota=");
unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
else
/* config_parse_cpu_quota() requires an integer, so
* truncating division is used on purpose here. */
unit_write_drop_in_private_format(u, mode, "CPUQuota",
"CPUQuota=%0.f%%",
(double) (c->cpu_quota_per_sec_usec / 10000));
/* config_parse_cpu_quota() requires an integer, so truncating division is used on
* purpose here. */
unit_write_settingf(u, flags, "CPUQuota",
"CPUQuota=%0.f%%",
(double) (c->cpu_quota_per_sec_usec / 10000));
}
return 1;
@ -562,10 +566,10 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->io_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes" : "IOAccounting=no");
unit_write_settingf(u, flags, name, "IOAccounting=%s", yes_no(b));
}
return 1;
@ -578,16 +582,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "IOWeight value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IOWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->io_weight = weight;
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
if (weight == CGROUP_WEIGHT_INVALID)
unit_write_drop_in_private(u, mode, name, "IOWeight=");
unit_write_setting(u, flags, name, "IOWeight=");
else
unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64, weight);
unit_write_settingf(u, flags, name, "IOWeight=%" PRIu64, weight);
}
return 1;
@ -600,16 +604,16 @@ int bus_cgroup_set_property(
return r;
if (CGROUP_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "StartupIOWeight value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupIOWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->startup_io_weight = weight;
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
if (weight == CGROUP_WEIGHT_INVALID)
unit_write_drop_in_private(u, mode, name, "StartupIOWeight=");
unit_write_setting(u, flags, name, "StartupIOWeight=");
else
unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64, weight);
unit_write_settingf(u, flags, name, "StartupIOWeight=%" PRIu64, weight);
}
return 1;
@ -625,7 +629,7 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceLimit *a = NULL, *b;
LIST_FOREACH(device_limits, b, c->io_device_limits) {
@ -666,7 +670,7 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceLimit *a;
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
@ -691,7 +695,7 @@ int bus_cgroup_set_property(
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(u, mode, name, buf);
unit_write_setting(u, flags, name, buf);
}
return 1;
@ -708,9 +712,9 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
return sd_bus_error_set_errnof(error, EINVAL, "IODeviceWeight out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceWeight *a = NULL, *b;
LIST_FOREACH(device_weights, b, c->io_device_weights) {
@ -743,7 +747,7 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupIODeviceWeight *a;
@ -767,7 +771,7 @@ int bus_cgroup_set_property(
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(u, mode, name, buf);
unit_write_setting(u, flags, name, buf);
}
return 1;
@ -779,10 +783,10 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->blockio_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
unit_write_settingf(u, flags, name, "BlockIOAccounting=%s", yes_no(b));
}
return 1;
@ -795,16 +799,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIOWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->blockio_weight = weight;
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
unit_write_setting(u, flags, name, "BlockIOWeight=");
else
unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
unit_write_settingf(u, flags, name, "BlockIOWeight=%" PRIu64, weight);
}
return 1;
@ -817,16 +821,16 @@ int bus_cgroup_set_property(
return r;
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupBlockIOWeight= value out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->startup_blockio_weight = weight;
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
unit_write_setting(u, flags, name, "StartupBlockIOWeight=");
else
unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
unit_write_settingf(u, flags, name, "StartupBlockIOWeight=%" PRIu64, weight);
}
return 1;
@ -846,7 +850,7 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceBandwidth *a = NULL, *b;
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
@ -887,7 +891,7 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceBandwidth *a;
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
@ -923,7 +927,8 @@ int bus_cgroup_set_property(
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(u, mode, name, buf);
unit_write_setting(u, flags, name, buf);
}
return 1;
@ -940,9 +945,9 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceWeight *a = NULL, *b;
LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
@ -975,7 +980,7 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupBlockIODeviceWeight *a;
@ -999,7 +1004,8 @@ int bus_cgroup_set_property(
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(u, mode, name, buf);
unit_write_setting(u, flags, name, buf);
}
return 1;
@ -1011,10 +1017,10 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->memory_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
unit_write_settingf(u, flags, name, "MemoryAccounting=%s", yes_no(b));
}
return 1;
@ -1026,9 +1032,9 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (v <= 0)
return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is too small", name);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (streq(name, "MemoryLow"))
c->memory_low = v;
else if (streq(name, "MemoryHigh"))
@ -1041,14 +1047,14 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
if (v == CGROUP_LIMIT_MAX)
unit_write_drop_in_private_format(u, mode, name, "%s=infinity", name);
unit_write_settingf(u, flags, name, "%s=infinity", name);
else
unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, v);
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, v);
}
return 1;
} else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) {
} else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale", "MemorySwapMaxScale")) {
uint32_t raw;
uint64_t v;
@ -1058,9 +1064,9 @@ int bus_cgroup_set_property(
v = physical_memory_scale(raw, UINT32_MAX);
if (v <= 0 || v == UINT64_MAX)
return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is out of range", name);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
const char *e;
/* Chop off suffix */
@ -1071,12 +1077,14 @@ int bus_cgroup_set_property(
c->memory_low = v;
else if (streq(name, "MemoryHigh"))
c->memory_high = v;
else
else if (streq(name, "MemorySwapMaxScale"))
c->memory_swap_max = v;
else /* MemoryMax */
c->memory_max = v;
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name,
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name,
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
}
return 1;
@ -1088,16 +1096,16 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (limit <= 0)
return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is too small", name);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->memory_limit = limit;
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
if (limit == (uint64_t) -1)
unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
if (limit == CGROUP_LIMIT_MAX)
unit_write_setting(u, flags, name, "MemoryLimit=infinity");
else
unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
unit_write_settingf(u, flags, name, "MemoryLimit=%" PRIu64, limit);
}
return 1;
@ -1112,12 +1120,12 @@ int bus_cgroup_set_property(
limit = physical_memory_scale(raw, UINT32_MAX);
if (limit <= 0 || limit == UINT64_MAX)
return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is out of range", name);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->memory_limit = limit;
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
unit_write_settingf(u, flags, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
}
@ -1135,10 +1143,10 @@ int bus_cgroup_set_property(
if (p < 0)
return -EINVAL;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->device_policy = p;
unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
unit_write_drop_in_private_format(u, mode, name, "DevicePolicy=%s", policy);
unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
}
return 1;
@ -1158,15 +1166,15 @@ int bus_cgroup_set_property(
!startswith(path, "block-") &&
!startswith(path, "char-")) ||
strpbrk(path, WHITESPACE))
return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
if (isempty(rwm))
rwm = "rwm";
if (!in_charset(rwm, "rwm"))
return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupDeviceAllow *a = NULL, *b;
LIST_FOREACH(device_allow, b, c->device_allow) {
@ -1204,7 +1212,7 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupDeviceAllow *a;
@ -1228,7 +1236,7 @@ int bus_cgroup_set_property(
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(u, mode, name, buf);
unit_write_setting(u, flags, name, buf);
}
return 1;
@ -1240,10 +1248,10 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->tasks_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
unit_write_settingf(u, flags, name, "TasksAccounting=%s", yes_no(b));
}
return 1;
@ -1255,16 +1263,16 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (limit <= 0)
return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is too small", name);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->tasks_max = limit;
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
if (limit == (uint64_t) -1)
unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
unit_write_setting(u, flags, name, "TasksMax=infinity");
else
unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
unit_write_settingf(u, flags, name, "TasksMax=%" PRIu64, limit);
}
return 1;
@ -1279,13 +1287,13 @@ int bus_cgroup_set_property(
limit = system_tasks_max_scale(raw, UINT32_MAX);
if (limit <= 0 || limit >= UINT64_MAX)
return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is out of range", name);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->tasks_max = limit;
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu32 "%%",
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
unit_write_settingf(u, flags, name, "TasksMax=%" PRIu32 "%%",
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
}
return 1;
@ -1297,11 +1305,11 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->ip_accounting = b;
unit_invalidate_cgroup_bpf(u);
unit_write_drop_in_private(u, mode, name, b ? "IPAccounting=yes" : "IPAccounting=no");
unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
}
return 1;
@ -1333,14 +1341,14 @@ int bus_cgroup_set_property(
return r;
if (!IN_SET(family, AF_INET, AF_INET6))
return sd_bus_error_set_errnof(error, EINVAL, "%s= expects IPv4 or IPv6 addresses only.", name);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
r = sd_bus_message_read_array(message, 'y', &ap, &an);
if (r < 0)
return r;
if (an != FAMILY_ADDRESS_SIZE(family))
return sd_bus_error_set_errnof(error, EINVAL, "IP address has wrong size for family (%s, expected %zu, got %zu)",
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
r = sd_bus_message_read(message, "u", &prefixlen);
@ -1348,9 +1356,9 @@ int bus_cgroup_set_property(
return r;
if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
return sd_bus_error_set_errnof(error, EINVAL, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
IPAddressAccessItem *item;
item = new0(IPAddressAccessItem, 1);
@ -1377,7 +1385,7 @@ int bus_cgroup_set_property(
*list = ip_address_access_reduce(*list);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
IPAddressAccessItem *item;
@ -1407,7 +1415,8 @@ int bus_cgroup_set_property(
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(u, mode, name, buf);
unit_write_setting(u, flags, name, buf);
if (*list) {
r = bpf_firewall_supported();
@ -1429,7 +1438,7 @@ int bus_cgroup_set_property(
}
if (u->transient && u->load_state == UNIT_STUB) {
r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
r = bus_cgroup_set_transient_property(u, c, name, message, flags, error);
if (r != 0)
return r;

View file

@ -26,4 +26,4 @@
extern const sd_bus_vtable bus_cgroup_vtable[];
int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);

File diff suppressed because it is too large Load diff

View file

@ -43,4 +43,4 @@ int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *inte
int bus_property_get_exec_command(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_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, UnitSetPropertiesMode mode, sd_bus_error *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);

View file

@ -39,7 +39,7 @@ int bus_kill_context_set_transient_property(
KillContext *c,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
@ -49,6 +49,8 @@ int bus_kill_context_set_transient_property(
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "KillMode")) {
const char *m;
KillMode k;
@ -61,10 +63,10 @@ int bus_kill_context_set_transient_property(
if (k < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Kill mode '%s' not known.", m);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->kill_mode = k;
unit_write_drop_in_private_format(u, mode, name, "KillMode=%s", kill_mode_to_string(k));
unit_write_settingf(u, flags, name, "KillMode=%s", kill_mode_to_string(k));
}
return 1;
@ -79,10 +81,10 @@ int bus_kill_context_set_transient_property(
if (!SIGNAL_VALID(sig))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal %i out of range", sig);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->kill_signal = sig;
unit_write_drop_in_private_format(u, mode, name, "KillSignal=%s", signal_to_string(sig));
unit_write_settingf(u, flags, name, "KillSignal=%s", signal_to_string(sig));
}
return 1;
@ -94,10 +96,10 @@ int bus_kill_context_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->send_sighup = b;
unit_write_drop_in_private_format(u, mode, name, "SendSIGHUP=%s", yes_no(b));
unit_write_settingf(u, flags, name, "SendSIGHUP=%s", yes_no(b));
}
return 1;
@ -109,10 +111,10 @@ int bus_kill_context_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->send_sigkill = b;
unit_write_drop_in_private_format(u, mode, name, "SendSIGKILL=%s", yes_no(b));
unit_write_settingf(u, flags, name, "SendSIGKILL=%s", yes_no(b));
}
return 1;

View file

@ -27,4 +27,4 @@
extern const sd_bus_vtable bus_kill_vtable[];
int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);

View file

@ -126,18 +126,19 @@ static int bus_mount_set_transient_property(
Mount *m,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
const char *new_property;
char **property;
char *p;
int r;
assert(m);
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "What"))
property = &m->parameters_fragment.what;
else if (streq(name, "Options"))
@ -151,16 +152,13 @@ static int bus_mount_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
p = strdup(new_property);
if (!p)
return -ENOMEM;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
unit_write_drop_in_format(UNIT(m), mode, name, "[Mount]\n%s=%s\n",
name, new_property);
r = free_and_strdup(property, new_property);
if (r < 0)
return r;
free(*property);
*property = p;
unit_write_settingf(UNIT(m), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, new_property);
}
return 1;
@ -170,7 +168,7 @@ int bus_mount_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Mount *m = MOUNT(u);
@ -180,22 +178,22 @@ int bus_mount_set_property(
assert(name);
assert(message);
r = bus_cgroup_set_property(u, &m->cgroup_context, name, message, mode, error);
r = bus_cgroup_set_property(u, &m->cgroup_context, name, message, flags, error);
if (r != 0)
return r;
if (u->transient && u->load_state == UNIT_STUB) {
/* This is a transient unit, let's load a little more */
r = bus_mount_set_transient_property(m, name, message, mode, error);
r = bus_mount_set_transient_property(m, name, message, flags, error);
if (r != 0)
return r;
r = bus_exec_context_set_transient_property(u, &m->exec_context, name, message, mode, error);
r = bus_exec_context_set_transient_property(u, &m->exec_context, name, message, flags, error);
if (r != 0)
return r;
r = bus_kill_context_set_transient_property(u, &m->kill_context, name, message, mode, error);
r = bus_kill_context_set_transient_property(u, &m->kill_context, name, message, flags, error);
if (r != 0)
return r;
}

View file

@ -26,5 +26,5 @@
extern const sd_bus_vtable bus_mount_vtable[];
int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_mount_commit_properties(Unit *u);

View file

@ -73,7 +73,7 @@ static int bus_scope_set_transient_property(
Scope *s,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
@ -82,6 +82,8 @@ static int bus_scope_set_transient_property(
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "PIDs")) {
unsigned n = 0;
uint32_t pid;
@ -95,7 +97,7 @@ static int bus_scope_set_transient_property(
if (pid <= 1)
return -EINVAL;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = unit_watch_pid(UNIT(s), pid);
if (r < 0 && r != -EEXIST)
return r;
@ -117,7 +119,6 @@ static int bus_scope_set_transient_property(
} else if (streq(name, "Controller")) {
const char *controller;
char *c;
/* We can't support direct connections with this, as direct connections know no service or unique name
* concept, but the Controller field stores exactly that. */
@ -131,33 +132,25 @@ static int bus_scope_set_transient_property(
if (!isempty(controller) && !service_name_is_valid(controller))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
if (mode != UNIT_CHECK) {
if (isempty(controller))
c = NULL;
else {
c = strdup(controller);
if (!c)
return -ENOMEM;
}
free(s->controller);
s->controller = c;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = free_and_strdup(&s->controller, empty_to_null(controller));
if (r < 0)
return r;
}
return 1;
} else if (streq(name, "TimeoutStopUSec")) {
uint64_t t;
if (mode != UNIT_CHECK) {
r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
if (r < 0)
return r;
r = sd_bus_message_read(message, "t", &t);
if (r < 0)
return r;
unit_write_drop_in_private_format(UNIT(s), mode, name, "TimeoutStopSec="USEC_FMT"us", s->timeout_stop_usec);
} else {
r = sd_bus_message_skip(message, "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;
@ -170,7 +163,7 @@ int bus_scope_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Scope *s = SCOPE(u);
@ -180,18 +173,18 @@ int bus_scope_set_property(
assert(name);
assert(message);
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
if (r != 0)
return r;
if (u->load_state == UNIT_STUB) {
/* While we are created we still accept PIDs */
r = bus_scope_set_transient_property(s, name, message, mode, error);
r = bus_scope_set_transient_property(s, name, message, flags, error);
if (r != 0)
return r;
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
if (r != 0)
return r;
}

View file

@ -26,7 +26,7 @@
extern const sd_bus_vtable bus_scope_vtable[];
int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
int bus_scope_commit_properties(Unit *u);
int bus_scope_send_request_stop(Scope *s);

View file

@ -90,15 +90,18 @@ static int bus_service_set_transient_property(
Service *s,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
ServiceExecCommand ci;
int r;
assert(s);
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (streq(name, "RemainAfterExit")) {
int b;
@ -106,9 +109,9 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->remain_after_exit = b;
unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s", yes_no(b));
unit_write_settingf(UNIT(s), flags, name, "RemainAfterExit=%s", yes_no(b));
}
return 1;
@ -125,9 +128,9 @@ static int bus_service_set_transient_property(
if (k < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->type = k;
unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s", service_type_to_string(s->type));
unit_write_settingf(UNIT(s), flags, name, "Type=%s", service_type_to_string(s->type));
}
return 1;
@ -138,9 +141,9 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->runtime_max_usec = u;
unit_write_drop_in_private_format(UNIT(s), mode, name, "RuntimeMaxSec=" USEC_FMT "us", u);
unit_write_settingf(UNIT(s), flags, name, "RuntimeMaxSec=" USEC_FMT "us", u);
}
return 1;
@ -161,9 +164,9 @@ static int bus_service_set_transient_property(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid restart setting: %s", v);
}
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->restart = sr;
unit_write_drop_in_private_format(UNIT(s), mode, name, "Restart=%s", service_restart_to_string(sr));
unit_write_settingf(UNIT(s), flags, name, "Restart=%s", service_restart_to_string(sr));
}
return 1;
@ -178,7 +181,7 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
int copy;
copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
@ -208,9 +211,9 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->n_fd_store_max = (unsigned) u;
unit_write_drop_in_private_format(UNIT(s), mode, name, "FileDescriptorStoreMax=%" PRIu32, u);
unit_write_settingf(UNIT(s), flags, name, "FileDescriptorStoreMax=%" PRIu32, u);
}
return 1;
@ -227,14 +230,14 @@ static int bus_service_set_transient_property(
if (k < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid notify access setting %s", t);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
s->notify_access = k;
unit_write_drop_in_private_format(UNIT(s), mode, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
unit_write_settingf(UNIT(s), flags, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
}
return 1;
} else if (streq(name, "ExecStart")) {
} else if ((ci = service_exec_command_from_string(name)) >= 0) {
unsigned n = 0;
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
@ -251,7 +254,7 @@ static int bus_service_set_transient_property(
return r;
if (!path_is_absolute(path))
return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
r = sd_bus_message_read_strv(message, &argv);
if (r < 0)
@ -265,7 +268,7 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
ExecCommand *c;
c = new0(ExecCommand, 1);
@ -284,7 +287,7 @@ static int bus_service_set_transient_property(
c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
path_kill_slashes(c->path);
exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
exec_command_append_list(&s->exec_command[ci], c);
}
n++;
@ -297,14 +300,14 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
ExecCommand *c;
size_t size = 0;
if (n == 0)
s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
s->exec_command[ci] = exec_command_free_list(s->exec_command[ci]);
f = open_memstream(&buf, &size);
if (!f)
@ -312,23 +315,30 @@ static int bus_service_set_transient_property(
fputs_unlocked("ExecStart=\n", f);
LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
_cleanup_free_ char *a;
LIST_FOREACH(command, c, s->exec_command[ci]) {
_cleanup_free_ char *a = NULL, *t = NULL;
const char *p;
a = strv_join_quoted(c->argv);
p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
if (!p)
return -ENOMEM;
a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
if (!a)
return -ENOMEM;
fprintf(f, "ExecStart=%s@%s %s\n",
fprintf(f, "%s=%s@%s %s\n",
name,
c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
c->path,
p,
a);
}
r = fflush_and_check(f);
if (r < 0)
return r;
unit_write_drop_in_private(UNIT(s), mode, name, buf);
unit_write_setting(UNIT(s), flags, name, buf);
}
return 1;
@ -341,7 +351,7 @@ int bus_service_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Service *s = SERVICE(u);
@ -351,22 +361,22 @@ int bus_service_set_property(
assert(name);
assert(message);
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
if (r != 0)
return r;
if (u->transient && u->load_state == UNIT_STUB) {
/* This is a transient unit, let's load a little more */
r = bus_service_set_transient_property(s, name, message, mode, error);
r = bus_service_set_transient_property(s, name, message, flags, error);
if (r != 0)
return r;
r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error);
if (r != 0)
return r;
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
if (r != 0)
return r;
}

View file

@ -26,5 +26,5 @@
extern const sd_bus_vtable bus_service_vtable[];
int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
int bus_service_commit_properties(Unit *u);

View file

@ -32,7 +32,7 @@ int bus_slice_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Slice *s = SLICE(u);
@ -40,7 +40,7 @@ int bus_slice_set_property(
assert(name);
assert(u);
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
}
int bus_slice_commit_properties(Unit *u) {

View file

@ -26,5 +26,5 @@
extern const sd_bus_vtable bus_slice_vtable[];
int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_slice_commit_properties(Unit *u);

View file

@ -166,7 +166,7 @@ int bus_socket_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Socket *s = SOCKET(u);
@ -175,7 +175,7 @@ int bus_socket_set_property(
assert(name);
assert(message);
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
}
int bus_socket_commit_properties(Unit *u) {

View file

@ -26,5 +26,5 @@
extern const sd_bus_vtable bus_socket_vtable[];
int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_socket_commit_properties(Unit *u);

View file

@ -96,7 +96,7 @@ int bus_swap_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
Swap *s = SWAP(u);
@ -105,7 +105,7 @@ int bus_swap_set_property(
assert(name);
assert(message);
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
}
int bus_swap_commit_properties(Unit *u) {

View file

@ -27,5 +27,5 @@
extern const sd_bus_vtable bus_swap_vtable[];
int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_swap_commit_properties(Unit *u);

View file

@ -176,7 +176,7 @@ static int bus_timer_set_transient_property(
Timer *t,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
@ -185,6 +185,8 @@ static int bus_timer_set_transient_property(
assert(name);
assert(message);
flags |= UNIT_PRIVATE;
if (STR_IN_SET(name,
"OnActiveSec",
"OnBootSec",
@ -204,10 +206,10 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
char time[FORMAT_TIMESPAN_MAX];
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
v = new0(TimerValue, 1);
if (!v)
@ -231,12 +233,12 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = calendar_spec_from_string(str, &c);
if (r < 0)
return r;
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, str);
unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, str);
v = new0(TimerValue, 1);
if (!v) {
@ -262,9 +264,9 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
t->accuracy_usec = u;
unit_write_drop_in_private_format(UNIT(t), mode, name, "AccuracySec=" USEC_FMT "us", u);
unit_write_settingf(UNIT(t), flags, name, "AccuracySec=" USEC_FMT "us", u);
}
return 1;
@ -276,9 +278,9 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
t->random_usec = u;
unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=" USEC_FMT "us", u);
unit_write_settingf(UNIT(t), flags, name, "RandomizedDelaySec=" USEC_FMT "us", u);
}
return 1;
@ -290,9 +292,9 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
t->wake_system = b;
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, yes_no(b));
unit_write_settingf(UNIT(t), flags, name, "%s=%s", name, yes_no(b));
}
return 1;
@ -304,9 +306,9 @@ static int bus_timer_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
t->remain_after_elapse = b;
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, yes_no(b));
unit_write_settingf(UNIT(t), flags, name, "%s=%s", name, yes_no(b));
}
return 1;
@ -319,21 +321,17 @@ int bus_timer_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags mode,
sd_bus_error *error) {
Timer *t = TIMER(u);
int r;
assert(t);
assert(name);
assert(message);
if (u->transient && u->load_state == UNIT_STUB) {
r = bus_timer_set_transient_property(t, name, message, mode, error);
if (r != 0)
return r;
}
if (u->transient && u->load_state == UNIT_STUB)
return bus_timer_set_transient_property(t, name, message, mode, error);
return 0;
}

View file

@ -26,4 +26,4 @@
extern const sd_bus_vtable bus_timer_vtable[];
int bus_timer_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
int bus_timer_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);

View file

@ -1315,11 +1315,11 @@ int bus_unit_queue_job(
return sd_bus_reply_method_return(message, "o", path);
}
static int bus_unit_set_transient_property(
static int bus_unit_set_live_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
@ -1328,6 +1328,9 @@ static int bus_unit_set_transient_property(
assert(name);
assert(message);
/* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for transient
* units that are being created). */
if (streq(name, "Description")) {
const char *d;
@ -1335,26 +1338,46 @@ static int bus_unit_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = unit_set_description(u, d);
if (r < 0)
return r;
unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s", d);
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d);
}
return 1;
}
} else if (streq(name, "DefaultDependencies")) {
return 0;
}
static int bus_unit_set_transient_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
int r;
assert(u);
assert(name);
assert(message);
/* 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;
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
u->default_dependencies = b;
unit_write_drop_in_format(u, mode, name, "[Unit]\nDefaultDependencies=%s", yes_no(b));
unit_write_settingf(u, flags, name, "DefaultDependencies=%s", yes_no(b));
}
return 1;
@ -1371,9 +1394,9 @@ static int bus_unit_set_transient_property(
if (m < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
u->collect_mode = m;
unit_write_drop_in_format(u, mode, name, "[Unit]\nCollectMode=%s", collect_mode_to_string(m));
unit_write_settingf(u, flags, name, "CollectMode=%s", collect_mode_to_string(m));
}
return 1;
@ -1406,12 +1429,12 @@ static int bus_unit_set_transient_property(
if (slice->type != UNIT_SLICE)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = unit_set_slice(u, slice);
if (r < 0)
return r;
unit_write_drop_in_private_format(u, mode, name, "Slice=%s", s);
unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s);
}
return 1;
@ -1448,7 +1471,7 @@ static int bus_unit_set_transient_property(
if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *label = NULL;
r = unit_add_dependency_by_name(u, d, other, NULL, true, UNIT_DEPENDENCY_FILE);
@ -1459,7 +1482,7 @@ static int bus_unit_set_transient_property(
if (!label)
return -ENOMEM;
unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s", name, other);
unit_write_settingf(u, flags, label, "%s=%s", name, other);
}
}
@ -1484,14 +1507,14 @@ static int bus_unit_set_transient_property(
if (action < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid emergency action: %s", s);
if (mode != UNIT_CHECK) {
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (streq(name, "FailureAction"))
u->failure_action = action;
else
u->success_action = action;
unit_write_drop_in_format(u, mode, name, "%s=%s", name, emergency_action_to_string(action));
unit_write_settingf(u, flags, name, "%s=%s", name, emergency_action_to_string(action));
}
return 1;
@ -1514,7 +1537,7 @@ static int bus_unit_set_transient_property(
if (r < 0)
return r;
if (mode != UNIT_CHECK)
if (!UNIT_WRITE_FLAGS_NOOP(flags))
u->bus_track_add = b;
return 1;
@ -1526,7 +1549,7 @@ static int bus_unit_set_transient_property(
int bus_unit_set_properties(
Unit *u,
sd_bus_message *message,
UnitSetPropertiesMode mode,
UnitWriteFlags flags,
bool commit,
sd_bus_error *error) {
@ -1548,12 +1571,13 @@ int bus_unit_set_properties(
for (;;) {
const char *name;
UnitWriteFlags f;
r = sd_bus_message_enter_container(message, 'r', "sv");
if (r < 0)
return r;
if (r == 0) {
if (for_real || mode == UNIT_CHECK)
if (for_real || UNIT_WRITE_FLAGS_NOOP(flags))
break;
/* Reached EOF. Let's try again, and this time for realz... */
@ -1576,11 +1600,17 @@ int bus_unit_set_properties(
if (r < 0)
return r;
r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
/* If not for real, then mask out the two target flags */
f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT));
r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error);
if (r == 0 && u->transient && u->load_state == UNIT_STUB)
r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
r = bus_unit_set_transient_property(u, name, message, f, error);
if (r == 0)
r = bus_unit_set_live_property(u, name, message, f, error);
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);

View file

@ -34,7 +34,7 @@ int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_
int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitWriteFlags flags, bool commit, sd_bus_error *error);
int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error);

View file

@ -189,7 +189,7 @@ $1.NetClass, config_parse_warn_compat, DISABLED_LE
)m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
Unit.SourcePath, config_parse_path, 0, offsetof(Unit, source_path)
Unit.SourcePath, config_parse_unit_path_printf, 0, offsetof(Unit, source_path)
Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0
@ -291,7 +291,7 @@ Service.StartLimitInterval, config_parse_sec, 0,
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg)
Service.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
@ -382,9 +382,9 @@ CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
m4_dnl
Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
Mount.Where, config_parse_path, 0, offsetof(Mount, where)
Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where)
Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype)
Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype)
Mount.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Mount, timeout_usec)
Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options)
@ -394,11 +394,11 @@ EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
m4_dnl
Automount.Where, config_parse_path, 0, offsetof(Automount, where)
Automount.Where, config_parse_unit_path_printf, 0, offsetof(Automount, where)
Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode)
Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec)
m4_dnl
Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what)
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec)

View file

@ -2474,7 +2474,7 @@ int config_parse_unset_environ(
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
r = extract_first_word(&rvalue, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)

View file

@ -1336,13 +1336,6 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
if (r < 0)
return r;
/* Make sure the transient directory always exists, so that it remains
* in the search path */
r = mkdir_p_label(m->lookup_paths.transient, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create transient generator directory \"%s\": %m",
m->lookup_paths.transient);
dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_GENERATORS_START);
r = manager_run_generators(m);
dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_GENERATORS_FINISH);
@ -3546,14 +3539,16 @@ ManagerState manager_state(Manager *m) {
if (u && unit_active_or_pending(u))
return MANAGER_STOPPING;
/* Are the rescue or emergency targets active or queued? If so we are in maintenance state */
u = manager_get_unit(m, SPECIAL_RESCUE_TARGET);
if (u && unit_active_or_pending(u))
return MANAGER_MAINTENANCE;
if (MANAGER_IS_SYSTEM(m)) {
/* Are the rescue or emergency targets active or queued? If so we are in maintenance state */
u = manager_get_unit(m, SPECIAL_RESCUE_TARGET);
if (u && unit_active_or_pending(u))
return MANAGER_MAINTENANCE;
u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET);
if (u && unit_active_or_pending(u))
return MANAGER_MAINTENANCE;
u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET);
if (u && unit_active_or_pending(u))
return MANAGER_MAINTENANCE;
}
/* Are there any failed units? If so, we are in degraded mode */
if (set_size(m->failed_units) > 0)

View file

@ -158,46 +158,6 @@ static int specifier_special_directory(char specifier, void *data, void *userdat
return 0;
}
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
char *t;
/* If we are UID 0 (root), this will not result in NSS,
* otherwise it might. This is good, as we want to be able to
* run this in PID 1, where our user ID is 0, but where NSS
* lookups are not allowed. */
t = getusername_malloc();
if (!t)
return -ENOMEM;
*ret = t;
return 0;
}
static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
if (asprintf(ret, UID_FMT, getuid()) < 0)
return -ENOMEM;
return 0;
}
static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
/* On PID 1 (which runs as root) this will not result in NSS,
* which is good. See above */
return get_home_dir(ret);
}
static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
/* On PID 1 (which runs as root) this will not result in NSS,
* which is good. See above */
return get_shell(ret);
}
int unit_name_printf(Unit *u, const char* format, char **ret) {
/*

View file

@ -55,6 +55,7 @@
#include "signal-util.h"
#include "sparse-endian.h"
#include "special.h"
#include "specifier.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-table.h"
@ -117,6 +118,8 @@ Unit *unit_new(Manager *m, size_t size) {
u->ipv4_deny_map_fd = -1;
u->ipv6_deny_map_fd = -1;
u->last_section_private = -1;
RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst);
RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16);
@ -568,8 +571,7 @@ void unit_free(Unit *u) {
if (!u)
return;
if (u->transient_file)
fclose(u->transient_file);
u->transient_file = safe_fclose(u->transient_file);
if (!MANAGER_IS_RELOADING(u->manager))
unit_remove_transient(u);
@ -1502,9 +1504,7 @@ int unit_load(Unit *u) {
if (r < 0)
goto fail;
fclose(u->transient_file);
u->transient_file = NULL;
u->transient_file = safe_fclose(u->transient_file);
u->fragment_mtime = now(CLOCK_REALTIME);
}
@ -4120,43 +4120,156 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) {
return *(ExecRuntime**) ((uint8_t*) u + offset);
}
static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) {
static const char* unit_drop_in_dir(Unit *u, UnitWriteFlags flags) {
assert(u);
if (!IN_SET(mode, UNIT_RUNTIME, UNIT_PERSISTENT))
if (UNIT_WRITE_FLAGS_NOOP(flags))
return NULL;
if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */
return u->manager->lookup_paths.transient;
if (mode == UNIT_RUNTIME)
return u->manager->lookup_paths.runtime_control;
if (mode == UNIT_PERSISTENT)
if (flags & UNIT_PERSISTENT)
return u->manager->lookup_paths.persistent_control;
if (flags & UNIT_RUNTIME)
return u->manager->lookup_paths.runtime_control;
return NULL;
}
int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
_cleanup_free_ char *p = NULL, *q = NULL;
char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf) {
char *ret = NULL;
if (!s)
return NULL;
/* Escapes the input string as requested. Returns the escaped string. If 'buf' is specified then the allocated
* return buffer pointer is also written to *buf, except if no escaping was necessary, in which case *buf is
* set to NULL, and the input pointer is returned as-is. This means the return value always contains a properly
* escaped version, but *buf when passed only contains a pointer if an allocation was necessary. If *buf is
* not specified, then the return value always needs to be freed. Callers can use this to optimize memory
* allocations. */
if (flags & UNIT_ESCAPE_SPECIFIERS) {
ret = specifier_escape(s);
if (!ret)
return NULL;
s = ret;
}
if (flags & UNIT_ESCAPE_C) {
char *a;
a = cescape(s);
free(ret);
if (!a)
return NULL;
ret = a;
}
if (buf) {
*buf = ret;
return ret ?: (char*) s;
}
return ret ?: strdup(s);
}
char* unit_concat_strv(char **l, UnitWriteFlags flags) {
_cleanup_free_ char *result = NULL;
size_t n = 0, allocated = 0;
char **i, *ret;
/* Takes a list of strings, escapes them, and concatenates them. This may be used to format command lines in a
* way suitable for ExecStart= stanzas */
STRV_FOREACH(i, l) {
_cleanup_free_ char *buf = NULL;
const char *p;
size_t a;
char *q;
p = unit_escape_setting(*i, flags, &buf);
if (!p)
return NULL;
a = (n > 0) + 1 + strlen(p) + 1; /* separating space + " + entry + " */
if (!GREEDY_REALLOC(result, allocated, n + a + 1))
return NULL;
q = result + n;
if (n > 0)
*(q++) = ' ';
*(q++) = '"';
q = stpcpy(q, p);
*(q++) = '"';
n += a;
}
if (!GREEDY_REALLOC(result, allocated, n + 1))
return NULL;
result[n] = 0;
ret = result;
result = NULL;
return ret;
}
int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data) {
_cleanup_free_ char *p = NULL, *q = NULL, *escaped = NULL;
const char *dir, *wrapped;
int r;
assert(u);
assert(name);
assert(data);
if (UNIT_WRITE_FLAGS_NOOP(flags))
return 0;
data = unit_escape_setting(data, flags, &escaped);
if (!data)
return -ENOMEM;
/* Prefix the section header. If we are writing this out as transient file, then let's suppress this if the
* previous section header is the same */
if (flags & UNIT_PRIVATE) {
if (!UNIT_VTABLE(u)->private_section)
return -EINVAL;
if (!u->transient_file || u->last_section_private < 0)
data = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data);
else if (u->last_section_private == 0)
data = strjoina("\n[", UNIT_VTABLE(u)->private_section, "]\n", data);
} else {
if (!u->transient_file || u->last_section_private < 0)
data = strjoina("[Unit]\n", data);
else if (u->last_section_private > 0)
data = strjoina("\n[Unit]\n", data);
}
if (u->transient_file) {
/* When this is a transient unit file in creation, then let's not create a new drop-in but instead
* write to the transient unit file. */
fputs(data, u->transient_file);
fputc('\n', u->transient_file);
if (!endswith(data, "\n"))
fputc('\n', u->transient_file);
/* Remember which section we wrote this entry to */
u->last_section_private = !!(flags & UNIT_PRIVATE);
return 0;
}
if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
return 0;
dir = unit_drop_in_dir(u, mode);
dir = unit_drop_in_dir(u, flags);
if (!dir)
return -EINVAL;
@ -4169,7 +4282,7 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co
if (r < 0)
return r;
(void) mkdir_p(p, 0755);
(void) mkdir_p_label(p, 0755);
r = write_string_file_atomic_label(q, wrapped);
if (r < 0)
return r;
@ -4186,7 +4299,7 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co
return 0;
}
int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
int unit_write_settingf(Unit *u, UnitWriteFlags flags, const char *name, const char *format, ...) {
_cleanup_free_ char *p = NULL;
va_list ap;
int r;
@ -4195,7 +4308,7 @@ int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *n
assert(name);
assert(format);
if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
if (UNIT_WRITE_FLAGS_NOOP(flags))
return 0;
va_start(ap, format);
@ -4205,58 +4318,20 @@ int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *n
if (r < 0)
return -ENOMEM;
return unit_write_drop_in(u, mode, name, p);
}
int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
const char *ndata;
assert(u);
assert(name);
assert(data);
if (!UNIT_VTABLE(u)->private_section)
return -EINVAL;
if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
return 0;
ndata = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data);
return unit_write_drop_in(u, mode, name, ndata);
}
int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
_cleanup_free_ char *p = NULL;
va_list ap;
int r;
assert(u);
assert(name);
assert(format);
if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
return 0;
va_start(ap, format);
r = vasprintf(&p, format, ap);
va_end(ap);
if (r < 0)
return -ENOMEM;
return unit_write_drop_in_private(u, mode, name, p);
return unit_write_setting(u, flags, name, p);
}
int unit_make_transient(Unit *u) {
_cleanup_free_ char *path = NULL;
FILE *f;
char *path;
assert(u);
if (!UNIT_VTABLE(u)->can_transient)
return -EOPNOTSUPP;
(void) mkdir_p_label(u->manager->lookup_paths.transient, 0755);
path = strjoin(u->manager->lookup_paths.transient, "/", u->id);
if (!path)
return -ENOMEM;
@ -4266,18 +4341,14 @@ int unit_make_transient(Unit *u) {
RUN_WITH_UMASK(0022) {
f = fopen(path, "we");
if (!f) {
free(path);
if (!f)
return -errno;
}
}
if (u->transient_file)
fclose(u->transient_file);
safe_fclose(u->transient_file);
u->transient_file = f;
free(u->fragment_path);
u->fragment_path = path;
free_and_replace(u->fragment_path, path);
u->source_path = mfree(u->source_path);
u->dropin_paths = strv_free(u->dropin_paths);

View file

@ -360,6 +360,10 @@ struct Unit {
bool exported_invocation_id:1;
bool exported_log_level_max:1;
bool exported_log_extra_fields:1;
/* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If
* == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */
int last_section_private:2;
};
struct UnitStatusMessageFormats {
@ -368,11 +372,26 @@ struct UnitStatusMessageFormats {
const char *finished_stop_job[_JOB_RESULT_MAX];
};
typedef enum UnitSetPropertiesMode {
UNIT_CHECK = 0,
UNIT_RUNTIME = 1,
UNIT_PERSISTENT = 2,
} UnitSetPropertiesMode;
/* Flags used when writing drop-in files or transient unit files */
typedef enum UnitWriteFlags {
/* Write a runtime unit file or drop-in (i.e. one below /run) */
UNIT_RUNTIME = 1 << 0,
/* Write a persistent drop-in (i.e. one below /etc) */
UNIT_PERSISTENT = 1 << 1,
/* Place this item in the per-unit-type private section, instead of [Unit] */
UNIT_PRIVATE = 1 << 2,
/* Apply specifier escaping before writing */
UNIT_ESCAPE_SPECIFIERS = 1 << 3,
/* Apply C escaping before writing */
UNIT_ESCAPE_C = 1 << 4,
} UnitWriteFlags;
/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
#define UNIT_WRITE_FLAGS_NOOP(flags) (((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0)
#include "automount.h"
#include "device.h"
@ -490,7 +509,7 @@ struct UnitVTable {
void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
/* Called for each property that is being set */
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
/* Called after at least one property got changed to apply the necessary change */
int (*bus_commit_properties)(Unit *u);
@ -713,11 +732,11 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_;
int unit_setup_exec_runtime(Unit *u);
int unit_setup_dynamic_creds(Unit *u);
int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5);
char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf);
char* unit_concat_strv(char **l, UnitWriteFlags flags);
int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5);
int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data);
int unit_write_settingf(Unit *u, UnitWriteFlags mode, const char *name, const char *format, ...) _printf_(4,5);
int unit_kill_context(Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien);

View file

@ -32,6 +32,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@ -60,7 +61,7 @@ static int create_disk(
const char *options) {
_cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*filtered = NULL;
*filtered = NULL, *u_escaped = NULL, *password_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *dmname;
bool noauto, nofail, tmp, swap, netdev;
@ -80,6 +81,10 @@ static int create_disk(
return -EINVAL;
}
name_escaped = specifier_escape(name);
if (!name_escaped)
return log_oom();
e = unit_name_escape(name);
if (!e)
return log_oom();
@ -96,10 +101,18 @@ static int create_disk(
if (!u)
return log_oom();
u_escaped = specifier_escape(u);
if (!u_escaped)
return log_oom();
r = unit_name_from_path(u, ".device", &d);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
password_escaped = specifier_escape(password);
if (!password_escaped)
return log_oom();
f = fopen(p, "wxe");
if (!f)
return log_error_errno(errno, "Failed to create unit file %s: %m", p);
@ -142,7 +155,7 @@ static int create_disk(
fprintf(f, "After=%1$s\nRequires=%1$s\n", dd);
} else
fprintf(f, "RequiresMountsFor=%s\n", password);
fprintf(f, "RequiresMountsFor=%s\n", password_escaped);
}
}
}
@ -160,12 +173,17 @@ static int create_disk(
} else
fprintf(f,
"RequiresMountsFor=%s\n",
u);
u_escaped);
r = generator_write_timeouts(arg_dest, device, name, options, &filtered);
if (r < 0)
return r;
filtered_escaped = specifier_escape(filtered);
if (!filtered_escaped)
return log_oom();
fprintf(f,
"\n[Service]\n"
"Type=oneshot\n"
@ -174,18 +192,18 @@ static int create_disk(
"KeyringMode=shared\n" /* make sure we can share cached keys among instances */
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
name, u, strempty(password), strempty(filtered),
name);
name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped),
name_escaped);
if (tmp)
fprintf(f,
"ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
name);
name_escaped);
if (swap)
fprintf(f,
"ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
name);
name_escaped);
r = fflush_and_check(f);
if (r < 0)

View file

@ -26,8 +26,8 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "fstab-util.h"
#include "generator.h"
#include "log.h"
@ -38,6 +38,7 @@
#include "path-util.h"
#include "proc-cmdline.h"
#include "special.h"
#include "specifier.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@ -68,7 +69,7 @@ static int write_options(FILE *f, const char *options) {
if (streq(options, "defaults"))
return 0;
o = strreplace(options, "%", "%%");
o = specifier_escape(options);
if (!o)
return log_oom();
@ -79,7 +80,7 @@ static int write_options(FILE *f, const char *options) {
static int write_what(FILE *f, const char *what) {
_cleanup_free_ char *w = NULL;
w = strreplace(what, "%", "%%");
w = specifier_escape(what);
if (!w)
return log_oom();
@ -262,7 +263,7 @@ static int write_before(FILE *f, const char *opts) {
}
static int write_requires_mounts_for(FILE *f, const char *opts) {
_cleanup_strv_free_ char **paths = NULL;
_cleanup_strv_free_ char **paths = NULL, **paths_escaped = NULL;
_cleanup_free_ char *res = NULL;
int r;
@ -275,7 +276,11 @@ static int write_requires_mounts_for(FILE *f, const char *opts) {
if (r == 0)
return 0;
res = strv_join(paths, " ");
r = specifier_escape_strv(paths, &paths_escaped);
if (r < 0)
return log_error_errno(r, "Failed to escape paths: %m");
res = strv_join(paths_escaped, " ");
if (!res)
return log_oom();
@ -301,7 +306,8 @@ static int add_mount(
_cleanup_free_ char
*name = NULL, *unit = NULL,
*automount_name = NULL, *automount_unit = NULL,
*filtered = NULL;
*filtered = NULL,
*where_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@ -398,14 +404,25 @@ static int add_mount(
fprintf(f, "\n[Mount]\n");
if (original_where)
fprintf(f, "# Canonicalized from %s\n", original_where);
fprintf(f, "Where=%s\n", where);
where_escaped = specifier_escape(where);
if (!where_escaped)
return log_oom();
fprintf(f, "Where=%s\n", where_escaped);
r = write_what(f, what);
if (r < 0)
return r;
if (!isempty(fstype) && !streq(fstype, "auto"))
fprintf(f, "Type=%s\n", fstype);
if (!isempty(fstype) && !streq(fstype, "auto")) {
_cleanup_free_ char *t;
t = specifier_escape(fstype);
if (!t)
return -ENOMEM;
fprintf(f, "Type=%s\n", t);
}
r = generator_write_timeouts(dest, what, where, opts, &filtered);
if (r < 0)
@ -476,7 +493,7 @@ static int add_mount(
"\n"
"[Automount]\n"
"Where=%s\n",
where);
where_escaped);
r = write_idle_timeout(f, where, opts);
if (r < 0)

View file

@ -44,6 +44,7 @@
#include "path-util.h"
#include "proc-cmdline.h"
#include "special.h"
#include "specifier.h"
#include "stat-util.h"
#include "string-util.h"
#include "udev-util.h"
@ -57,7 +58,7 @@ static bool arg_root_enabled = true;
static bool arg_root_rw = false;
static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
_cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL;
_cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
char *ret;
int r;
@ -77,6 +78,14 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
id_escaped = specifier_escape(id);
if (!id_escaped)
return log_oom();
what_escaped = specifier_escape(what);
if (!what_escaped)
return log_oom();
p = strjoin(arg_dest, "/", n);
if (!p)
return log_oom();
@ -104,8 +113,8 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
d, d,
id, what, rw ? "" : "read-only",
id);
id_escaped, what_escaped, rw ? "" : "read-only",
id_escaped);
r = fflush_and_check(f);
if (r < 0)
@ -165,6 +174,10 @@ static int add_mount(
_cleanup_fclose_ FILE *f = NULL;
int r;
/* Note that we don't apply specifier escaping on the input strings here, since we know they are not configured
* externally, but all originate from our own sources here, and hence we know they contain no % characters that
* could potentially be understood as specifiers. */
assert(id);
assert(what);
assert(where);

View file

@ -381,7 +381,7 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro
if ((keymap && (!filename_is_valid(keymap) || !string_is_safe(keymap))) ||
(keymap_toggle && (!filename_is_valid(keymap_toggle) || !string_is_safe(keymap_toggle))))
return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keymap data");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keymap data");
r = bus_verify_polkit_async(
m,
@ -560,7 +560,7 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err
(model && !string_is_safe(model)) ||
(variant && !string_is_safe(variant)) ||
(options && !string_is_safe(options)))
return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keyboard data");
r = bus_verify_polkit_async(
m,

View file

@ -1282,7 +1282,7 @@ static int trigger_device(Manager *m, struct udev_device *d) {
if (!t)
return -ENOMEM;
write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
(void) write_string_file(t, "change", 0);
}
return 0;

View file

@ -467,12 +467,12 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
if (r < 0)
return r;
return bus_log_create_error(r);
if (arg_aggressive_gc) {
r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
if (r < 0)
return r;
return bus_log_create_error(r);
}
r = bus_append_unit_property_assignment_many(m, properties);
@ -487,27 +487,32 @@ static int transient_cgroup_set_properties(sd_bus_message *m) {
assert(m);
if (!isempty(arg_slice)) {
_cleanup_free_ char *slice;
_cleanup_free_ char *slice = NULL;
r = unit_name_mangle_with_suffix(arg_slice, UNIT_NAME_NOGLOB, ".slice", &slice);
if (r < 0)
return r;
return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice);
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
if (r < 0)
return r;
return bus_log_create_error(r);
}
return 0;
}
static int transient_kill_set_properties(sd_bus_message *m) {
int r;
assert(m);
if (arg_send_sighup)
return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
else
return 0;
if (arg_send_sighup) {
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
if (r < 0)
return bus_log_create_error(r);
}
return 0;
}
static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
@ -531,37 +536,37 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_remain_after_exit) {
r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_service_type) {
r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_exec_user) {
r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_exec_group) {
r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_nice_set) {
r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (pty_path) {
@ -572,7 +577,7 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
"StandardError", "s", "tty",
"TTYPath", "s", pty_path);
if (r < 0)
return r;
return bus_log_create_error(r);
send_term = true;
@ -583,7 +588,7 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
"StandardOutputFileDescriptor", "h", STDOUT_FILENO,
"StandardErrorFileDescriptor", "h", STDERR_FILENO);
if (r < 0)
return r;
return bus_log_create_error(r);
send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO);
}
@ -600,85 +605,85 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
"(sv)",
"Environment", "as", 1, n);
if (r < 0)
return r;
return bus_log_create_error(r);
}
}
if (!strv_isempty(arg_environment)) {
r = sd_bus_message_open_container(m, 'r', "sv");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", "Environment");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'v', "as");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_append_strv(m, arg_environment);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return bus_log_create_error(r);
}
/* Exec container */
{
r = sd_bus_message_open_container(m, 'r', "sv");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", "ExecStart");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'v', "a(sasb)");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "(sasb)");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'r', "sasb");
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", argv[0]);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_append_strv(m, argv);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_append(m, "b", false);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return bus_log_create_error(r);
}
return 0;
@ -703,7 +708,7 @@ static int transient_scope_set_properties(sd_bus_message *m) {
r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached());
if (r < 0)
return r;
return bus_log_create_error(r);
return 0;
}
@ -720,42 +725,42 @@ static int transient_timer_set_properties(sd_bus_message *m) {
/* Automatically clean up our transient timers */
r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false);
if (r < 0)
return r;
return bus_log_create_error(r);
if (arg_on_active) {
r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_on_boot) {
r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_on_startup) {
r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_on_unit_active) {
r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_on_unit_inactive) {
r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive);
if (r < 0)
return r;
return bus_log_create_error(r);
}
if (arg_on_calendar) {
r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar);
if (r < 0)
return r;
return bus_log_create_error(r);
}
return 0;
@ -1018,7 +1023,7 @@ static int start_transient_service(
r = transient_service_set_properties(m, argv, pty_path);
if (r < 0)
return bus_log_create_error(r);
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
@ -1217,7 +1222,7 @@ static int start_transient_scope(
r = transient_scope_set_properties(m);
if (r < 0)
return bus_log_create_error(r);
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
@ -1398,7 +1403,7 @@ static int start_transient_timer(
r = transient_timer_set_properties(m);
if (r < 0)
return bus_log_create_error(r);
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
@ -1423,7 +1428,7 @@ static int start_transient_timer(
r = transient_service_set_properties(m, argv, NULL);
if (r < 0)
return bus_log_create_error(r);
return r;
r = sd_bus_message_close_container(m);
if (r < 0)

View file

@ -134,9 +134,12 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
} else if (streq(field, "EnvironmentFile")) {
r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
eq[0] == '-' ? eq + 1 : eq,
eq[0] == '-');
if (isempty(eq))
r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 0);
else
r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
eq[0] == '-' ? eq + 1 : eq,
eq[0] == '-');
goto finish;
} else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec", "RuntimeMaxSec")) {
@ -183,7 +186,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
r = sd_bus_message_close_container(m);
goto finish;
} else if (STR_IN_SET(field, "MemoryLow", "MemoryHigh", "MemoryMax", "MemoryLimit")) {
} else if (STR_IN_SET(field, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit")) {
uint64_t bytes;
if (isempty(eq) || streq(eq, "infinity"))
@ -1205,8 +1208,96 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
return r;
r = sd_bus_message_close_container(m);
} else if (STR_IN_SET(field, "ExecStartPre", "ExecStart", "ExecStartPost",
"ExecReload", "ExecStop", "ExecStopPost")) {
bool ignore_failure = false, explicit_path = false, done = false;
_cleanup_strv_free_ char **l = NULL;
_cleanup_free_ char *path = NULL;
do {
switch (*eq) {
case '-':
if (ignore_failure)
done = true;
else {
ignore_failure = true;
eq++;
}
break;
case '@':
if (explicit_path)
done = true;
else {
explicit_path = true;
eq++;
}
break;
case '+':
case '!':
/* The bus API doesn't support +, ! and !! currently, unfortunately. :-( */
log_error("Sorry, but +, ! and !! are currently not supported for transient services.");
return -EOPNOTSUPP;
default:
done = true;
break;
}
} while(!done);
if (explicit_path) {
r = extract_first_word(&eq, &path, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
if (r < 0)
return log_error_errno(r, "Failed to parse path: %m");
}
r = strv_split_extract(&l, eq, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
if (r < 0)
return log_error_errno(r, "Failed to parse command line: %m");
r = sd_bus_message_open_container(m, 'v', "a(sasb)");
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "(sasb)");
if (r < 0)
return r;
if (strv_length(l) > 0) {
r = sd_bus_message_open_container(m, 'r', "sasb");
if (r < 0)
return r;
r = sd_bus_message_append(m, "s", path ?: l[0]);
if (r < 0)
return r;
r = sd_bus_message_append_strv(m, l);
if (r < 0)
return r;
r = sd_bus_message_append(m, "b", ignore_failure);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
} else {
log_error("Unknown assignment %s.", assignment);
log_error("Unknown assignment: %s", assignment);
return -EINVAL;
}

View file

@ -33,6 +33,7 @@
#include "mkdir.h"
#include "path-util.h"
#include "special.h"
#include "specifier.h"
#include "string-util.h"
#include "time-util.h"
#include "unit-name.h"
@ -55,15 +56,19 @@ int generator_add_symlink(const char *root, const char *dst, const char *dep_typ
}
static int write_fsck_sysroot_service(const char *dir, const char *what) {
_cleanup_free_ char *device = NULL, *escaped = NULL;
_cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *unit;
int r;
escaped = cescape(what);
escaped = specifier_escape(what);
if (!escaped)
return log_oom();
escaped2 = cescape(escaped);
if (!escaped2)
return log_oom();
unit = strjoina(dir, "/systemd-fsck-root.service");
log_debug("Creating %s", unit);
@ -91,9 +96,9 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
"ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n"
"TimeoutSec=0\n",
program_invocation_short_name,
what,
escaped,
device,
escaped);
escaped2);
r = fflush_and_check(f);
if (r < 0)

View file

@ -103,34 +103,6 @@ static int specifier_instance(char specifier, void *data, void *userdata, char *
return 0;
}
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
char *t;
/* If we are UID 0 (root), this will not result in NSS,
* otherwise it might. This is good, as we want to be able to
* run this in PID 1, where our user ID is 0, but where NSS
* lookups are not allowed.
* We don't user getusername_malloc() here, because we don't want to look
* at $USER, to remain consistent with specifer_user_id() below.
*/
t = uid_to_name(getuid());
if (!t)
return -ENOMEM;
*ret = t;
return 0;
}
static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
if (asprintf(ret, UID_FMT, getuid()) < 0)
return -ENOMEM;
return 0;
}
int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) {
/* This is similar to unit_full_printf() but does not support

View file

@ -736,6 +736,14 @@ int lookup_paths_reduce(LookupPaths *p) {
struct stat st;
unsigned k;
/* Never strip the transient and control directories from the path */
if (path_equal_ptr(p->search_path[c], p->transient) ||
path_equal_ptr(p->search_path[c], p->persistent_control) ||
path_equal_ptr(p->search_path[c], p->runtime_control)) {
c++;
continue;
}
if (p->root_dir)
r = lstat(p->search_path[c], &st);
else

View file

@ -28,8 +28,8 @@ typedef struct LookupPaths LookupPaths;
#include "macro.h"
typedef enum LookupPathsFlags {
LOOKUP_PATHS_EXCLUDE_GENERATED = 1,
LOOKUP_PATHS_TEMPORARY_GENERATED,
LOOKUP_PATHS_EXCLUDE_GENERATED = 1 << 0,
LOOKUP_PATHS_TEMPORARY_GENERATED = 1 << 1,
} LookupPathsFlags;
struct LookupPaths {

View file

@ -32,6 +32,8 @@
#include "macro.h"
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
/*
* Generic infrastructure for replacing %x style specifiers in
@ -191,3 +193,74 @@ int specifier_kernel_release(char specifier, void *data, void *userdata, char **
*ret = n;
return 0;
}
int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
char *t;
/* If we are UID 0 (root), this will not result in NSS, otherwise it might. This is good, as we want to be able
* to run this in PID 1, where our user ID is 0, but where NSS lookups are not allowed.
* We don't user getusername_malloc() here, because we don't want to look at $USER, to remain consistent with
* specifer_user_id() below.
*/
t = uid_to_name(getuid());
if (!t)
return -ENOMEM;
*ret = t;
return 0;
}
int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
if (asprintf(ret, UID_FMT, getuid()) < 0)
return -ENOMEM;
return 0;
}
int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
/* On PID 1 (which runs as root) this will not result in NSS,
* which is good. See above */
return get_home_dir(ret);
}
int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
/* On PID 1 (which runs as root) this will not result in NSS,
* which is good. See above */
return get_shell(ret);
}
int specifier_escape_strv(char **l, char ***ret) {
char **z, **p, **q;
assert(ret);
if (strv_isempty(l)) {
*ret = NULL;
return 0;
}
z = new(char*, strv_length(l)+1);
if (!z)
return -ENOMEM;
for (p = l, q = z; *p; p++, q++) {
*q = specifier_escape(*p);
if (!*q) {
strv_free(z);
return -ENOMEM;
}
}
*q = NULL;
*ret = z;
return 0;
}

View file

@ -20,6 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "string-util.h"
typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret);
typedef struct Specifier {
@ -36,3 +38,14 @@ int specifier_machine_id(char specifier, void *data, void *userdata, char **ret)
int specifier_boot_id(char specifier, void *data, void *userdata, char **ret);
int specifier_host_name(char specifier, void *data, void *userdata, char **ret);
int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret);
int specifier_user_name(char specifier, void *data, void *userdata, char **ret);
int specifier_user_id(char specifier, void *data, void *userdata, char **ret);
int specifier_user_home(char specifier, void *data, void *userdata, char **ret);
int specifier_user_shell(char specifier, void *data, void *userdata, char **ret);
static inline char* specifier_escape(const char *string) {
return strreplace(string, "%", "%%");
}
int specifier_escape_strv(char **l, char ***ret);

View file

@ -2466,7 +2466,7 @@ static int need_daemon_reload(sd_bus *bus, const char *unit) {
static void warn_unit_file_changed(const char *name) {
assert(name);
log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
log_warning("%sWarning:%s The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
ansi_highlight_red(),
ansi_normal(),
name,

View file

@ -39,6 +39,7 @@
#include "path-util.h"
#include "set.h"
#include "special.h"
#include "specifier.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@ -119,6 +120,7 @@ static int add_alias(const char *service, const char *alias) {
}
static int generate_unit_file(SysvStub *s) {
_cleanup_free_ char *path_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *unit;
char **p;
@ -129,6 +131,10 @@ static int generate_unit_file(SysvStub *s) {
if (!s->loaded)
return 0;
path_escaped = specifier_escape(s->path);
if (!path_escaped)
return log_oom();
unit = strjoina(arg_dest, "/", s->name);
/* We might already have a symlink with the same name from a Provides:,
@ -148,10 +154,17 @@ static int generate_unit_file(SysvStub *s) {
"[Unit]\n"
"Documentation=man:systemd-sysv-generator(8)\n"
"SourcePath=%s\n",
s->path);
path_escaped);
if (s->description)
fprintf(f, "Description=%s\n", s->description);
if (s->description) {
_cleanup_free_ char *t;
t = specifier_escape(s->description);
if (!t)
return log_oom();
fprintf(f, "Description=%s\n", t);
}
STRV_FOREACH(p, s->before)
fprintf(f, "Before=%s\n", *p);
@ -171,8 +184,15 @@ static int generate_unit_file(SysvStub *s) {
"RemainAfterExit=%s\n",
yes_no(!s->pid_file));
if (s->pid_file)
fprintf(f, "PIDFile=%s\n", s->pid_file);
if (s->pid_file) {
_cleanup_free_ char *t;
t = specifier_escape(s->pid_file);
if (!t)
return log_oom();
fprintf(f, "PIDFile=%s\n", t);
}
/* Consider two special LSB exit codes a clean exit */
if (s->has_lsb)
@ -184,10 +204,10 @@ static int generate_unit_file(SysvStub *s) {
fprintf(f,
"ExecStart=%s start\n"
"ExecStop=%s stop\n",
s->path, s->path);
path_escaped, path_escaped);
if (s->reload)
fprintf(f, "ExecReload=%s reload\n", s->path);
fprintf(f, "ExecReload=%s reload\n", path_escaped);
r = fflush_and_check(f);
if (r < 0)

View file

@ -249,6 +249,10 @@ tests += [
[],
[]],
[['src/test/test-specifier.c'],
[],
[]],
[['src/test/test-string-util.c'],
[],
[]],

View file

@ -47,7 +47,7 @@ static void test_paths(UnitFileScope scope) {
assert_se(strv_length(lp_with_env.search_path) == 1);
assert_se(streq(lp_with_env.search_path[0], systemd_unit_path));
assert_se(lookup_paths_reduce(&lp_with_env) >= 0);
assert_se(strv_length(lp_with_env.search_path) == 0);
assert_se(strv_isempty(lp_with_env.search_path));
assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}

66
src/test/test-specifier.c Normal file
View file

@ -0,0 +1,66 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
Copyright 2017 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 "alloc-util.h"
#include "log.h"
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
static void test_specifier_escape_one(const char *a, const char *b) {
_cleanup_free_ char *x = NULL;
x = specifier_escape(a);
assert_se(streq_ptr(x, b));
}
static void test_specifier_escape(void) {
test_specifier_escape_one(NULL, NULL);
test_specifier_escape_one("", "");
test_specifier_escape_one("%", "%%");
test_specifier_escape_one("foo bar", "foo bar");
test_specifier_escape_one("foo%bar", "foo%%bar");
test_specifier_escape_one("%%%%%", "%%%%%%%%%%");
}
static void test_specifier_escape_strv_one(char **a, char **b) {
_cleanup_strv_free_ char **x = NULL;
assert_se(specifier_escape_strv(a, &x) >= 0);
assert_se(strv_equal(x, b));
}
static void test_specifier_escape_strv(void) {
test_specifier_escape_strv_one(NULL, NULL);
test_specifier_escape_strv_one(STRV_MAKE(NULL), STRV_MAKE(NULL));
test_specifier_escape_strv_one(STRV_MAKE(""), STRV_MAKE(""));
test_specifier_escape_strv_one(STRV_MAKE("foo"), STRV_MAKE("foo"));
test_specifier_escape_strv_one(STRV_MAKE("%"), STRV_MAKE("%%"));
test_specifier_escape_strv_one(STRV_MAKE("foo", "%", "foo%", "%foo", "foo%foo", "quux", "%%%"), STRV_MAKE("foo", "%%", "foo%%", "%%foo", "foo%%foo", "quux", "%%%%%%"));
}
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
test_specifier_escape();
test_specifier_escape_strv();
return 0;
}

View file

@ -207,7 +207,7 @@ static int test_unit_printf(void) {
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
assert_se(host = gethostname_malloc());
assert_se(user = getusername_malloc());
assert_se(user = uid_to_name(getuid()));
assert_se(asprintf(&uid, UID_FMT, getuid()));
assert_se(get_home_dir(&home) >= 0);
assert_se(get_shell(&shell) >= 0);

View file

@ -1788,7 +1788,7 @@ static bool should_include_path(const char *path) {
/* no matches, so we should include this path only if we
* have no whitelist at all */
if (strv_length(arg_include_prefixes) == 0)
if (strv_isempty(arg_include_prefixes))
return true;
log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);

View file

@ -721,7 +721,7 @@ static int ask_on_this_console(const char *tty, pid_t *pid, int argc, char *argv
for (ac = 0; ac < argc; ac++) {
if (streq(argv[ac], "--console")) {
argv[ac] = strjoina("--console=", tty, NULL);
argv[ac] = strjoina("--console=", tty);
break;
}
}

View file

@ -162,7 +162,7 @@ static int checkout(int fd)
if (ptr) {
*ptr = '\0';
ptr++;
if (!strlen(word))
if (isempty(word))
continue;
if (debug)

View file

@ -1715,7 +1715,7 @@ int main(int argc, char *argv[]) {
by PID1. otherwise we are not guaranteed to have a dedicated cgroup */
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
if (r < 0) {
if (r == -ENOENT || r == -ENOMEDIUM)
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
log_debug_errno(r, "did not find dedicated cgroup: %m");
else
log_warning_errno(r, "failed to get cgroup: %m");

View file

@ -32,6 +32,7 @@
#include "mkdir.h"
#include "parse-util.h"
#include "proc-cmdline.h"
#include "specifier.h"
#include "string-util.h"
#include "unit-name.h"
@ -42,7 +43,7 @@ static char *arg_data_what = NULL;
static char *arg_hash_what = NULL;
static int create_device(void) {
_cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL;
_cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, *root_hash_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *p, *to;
int r;
@ -75,6 +76,13 @@ static int create_device(void) {
if (!v)
return log_oom();
u_escaped = specifier_escape(u);
if (!u_escaped)
return log_oom();
v_escaped = specifier_escape(v);
if (!v_escaped)
return log_oom();
r = unit_name_from_path(u, ".device", &d);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
@ -82,6 +90,10 @@ static int create_device(void) {
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
root_hash_escaped = specifier_escape(arg_root_hash);
if (!root_hash_escaped)
return log_oom();
f = fopen(p, "wxe");
if (!f)
return log_error_errno(errno, "Failed to create unit file %s: %m", p);
@ -105,7 +117,7 @@ static int create_device(void) {
"ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n",
d, e,
d, e,
u, v, arg_root_hash);
u_escaped, v_escaped, root_hash_escaped);
r = fflush_and_check(f);
if (r < 0)

View file

@ -2,7 +2,7 @@
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -e
TEST_DESCRIPTION="Basic systemd setup"
TEST_DESCRIPTION="/etc/machine-id testing"
TEST_NO_NSPAWN=1
SKIP_INITRD=yes
. $TEST_BASE_DIR/test-functions