summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyze/analyze-verify.c8
-rw-r--r--src/analyze/analyze.c12
-rw-r--r--src/basic/af-list.c6
-rw-r--r--src/basic/arphrd-list.c4
-rw-r--r--src/basic/async.c4
-rw-r--r--src/basic/btrfs-util.c71
-rw-r--r--src/basic/btrfs-util.h4
-rw-r--r--src/basic/calendarspec.c2
-rw-r--r--src/basic/cap-list.c2
-rw-r--r--src/basic/env-util.c15
-rw-r--r--src/basic/env-util.h1
-rw-r--r--src/basic/errno-list.c4
-rw-r--r--src/basic/exit-status.c4
-rw-r--r--src/basic/extract-word.c4
-rw-r--r--src/basic/extract-word.h9
-rw-r--r--src/basic/fd-util.h4
-rw-r--r--src/basic/fdset.c6
-rw-r--r--src/basic/fileio-label.c4
-rw-r--r--src/basic/fileio.c119
-rw-r--r--src/basic/fileio.h7
-rw-r--r--src/basic/fs-util.c24
-rw-r--r--src/basic/fs-util.h1
-rw-r--r--src/basic/hashmap.c2
-rw-r--r--src/basic/json.c2
-rw-r--r--src/basic/label.c2
-rw-r--r--src/basic/lockfile-util.c8
-rw-r--r--src/basic/login-util.c2
-rw-r--r--src/basic/mempool.c2
-rw-r--r--src/basic/missing.h23
-rw-r--r--src/basic/mkdir-label.c2
-rw-r--r--src/basic/mkdir.c2
-rw-r--r--src/basic/selinux-util.c6
-rw-r--r--src/basic/sigbus.c2
-rw-r--r--src/basic/siphash24.c112
-rw-r--r--src/basic/siphash24.h16
-rw-r--r--src/basic/strv.c2
-rw-r--r--src/basic/strxcpyx.c1
-rw-r--r--src/basic/time-util.c71
-rw-r--r--src/basic/unaligned.h47
-rw-r--r--src/basic/unit-name.c13
-rw-r--r--src/basic/unit-name.h15
-rw-r--r--src/basic/user-util.c2
-rw-r--r--src/basic/utf8.c4
-rw-r--r--src/basic/util.c12
-rw-r--r--src/basic/virt.c2
-rw-r--r--src/boot/efi/boot.c6
-rw-r--r--src/boot/efi/console.c2
-rw-r--r--src/boot/efi/graphics.c2
-rw-r--r--src/boot/efi/linux.c2
-rw-r--r--src/boot/efi/pefile.c2
-rw-r--r--src/boot/efi/splash.c2
-rw-r--r--src/boot/efi/stub.c6
-rw-r--r--src/bootchart/svg.c14
-rw-r--r--src/bus-proxyd/bus-xml-policy.c14
-rw-r--r--src/bus-proxyd/stdio-bridge.c2
-rw-r--r--src/core/audit-fd.c5
-rw-r--r--src/core/automount.c16
-rw-r--r--src/core/busname.c2
-rw-r--r--src/core/cgroup.c24
-rw-r--r--src/core/dbus-automount.c2
-rw-r--r--src/core/dbus-busname.c2
-rw-r--r--src/core/dbus-device.c4
-rw-r--r--src/core/dbus-execute.c33
-rw-r--r--src/core/dbus-kill.c5
-rw-r--r--src/core/dbus-manager.c91
-rw-r--r--src/core/dbus-mount.c3
-rw-r--r--src/core/dbus-path.c2
-rw-r--r--src/core/dbus-slice.c4
-rw-r--r--src/core/dbus-snapshot.c55
-rw-r--r--src/core/dbus-snapshot.h28
-rw-r--r--src/core/dbus-swap.c2
-rw-r--r--src/core/dbus-target.c2
-rw-r--r--src/core/dbus-unit.c39
-rw-r--r--src/core/dbus.c2
-rw-r--r--src/core/device.c36
-rw-r--r--src/core/execute.c43
-rw-r--r--src/core/execute.h1
-rw-r--r--src/core/failure-action.c22
-rw-r--r--src/core/hostname-setup.c2
-rw-r--r--src/core/ima-setup.c2
-rw-r--r--src/core/job.c15
-rw-r--r--src/core/job.h1
-rw-r--r--src/core/kmod-setup.c6
-rw-r--r--src/core/load-dropin.c6
-rw-r--r--src/core/load-fragment-gperf.gperf.m410
-rw-r--r--src/core/load-fragment.c114
-rw-r--r--src/core/load-fragment.h2
-rw-r--r--src/core/locale-setup.c2
-rw-r--r--src/core/main.c17
-rw-r--r--src/core/manager.c70
-rw-r--r--src/core/manager.h10
-rw-r--r--src/core/mount-setup.c4
-rw-r--r--src/core/mount.c115
-rw-r--r--src/core/mount.h1
-rw-r--r--src/core/path.c23
-rw-r--r--src/core/scope.c39
-rw-r--r--src/core/selinux-access.c4
-rw-r--r--src/core/selinux-setup.c2
-rw-r--r--src/core/service.c102
-rw-r--r--src/core/slice.c28
-rw-r--r--src/core/snapshot.c303
-rw-r--r--src/core/snapshot.h39
-rw-r--r--src/core/socket.c19
-rw-r--r--src/core/swap.c34
-rw-r--r--src/core/system.conf3
-rw-r--r--src/core/target.c2
-rw-r--r--src/core/timer.c18
-rw-r--r--src/core/transaction.c52
-rw-r--r--src/core/transaction.h1
-rw-r--r--src/core/unit-printf.c168
-rw-r--r--src/core/unit.c92
-rw-r--r--src/core/unit.h15
-rw-r--r--src/firstboot/firstboot.c2
-rw-r--r--src/fsck/fsck.c8
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c4
-rw-r--r--src/hibernate-resume/hibernate-resume.c2
-rw-r--r--src/hostname/hostnamed.c2
-rw-r--r--src/import/aufs-util.c2
-rw-r--r--src/import/curl-util.c18
-rw-r--r--src/import/export-raw.c4
-rw-r--r--src/import/pull-common.c2
-rw-r--r--src/import/pull-tar.c2
-rw-r--r--src/initctl/initctl.c6
-rw-r--r--src/journal-remote/journal-upload-journal.c3
-rw-r--r--src/journal-remote/microhttpd-util.c2
-rw-r--r--src/journal/audit-type.c5
-rw-r--r--src/journal/coredump-vacuum.c15
-rw-r--r--src/journal/journal-authenticate.c2
-rw-r--r--src/journal/journal-qrcode.c7
-rw-r--r--src/journal/journal-verify.c4
-rw-r--r--src/journal/journalctl.c224
-rw-r--r--src/journal/journald-console.c2
-rw-r--r--src/journal/journald-native.c30
-rw-r--r--src/journal/journald-rate-limit.c6
-rw-r--r--src/journal/journald-server.c67
-rw-r--r--src/journal/journald-server.h1
-rw-r--r--src/journal/journald-wall.c2
-rw-r--r--src/journal/journald.c7
-rw-r--r--src/journal/lookup3.c4
-rw-r--r--src/journal/mmap-cache.c17
-rw-r--r--src/journal/test-catalog.c4
-rw-r--r--src/journal/test-journal-enum.c2
-rw-r--r--src/journal/test-journal-interleaving.c2
-rw-r--r--src/journal/test-journal-verify.c2
-rw-r--r--src/journal/test-journal.c6
-rw-r--r--src/libsystemd-network/dhcp-identifier.c12
-rw-r--r--src/libsystemd-network/dhcp-option.c4
-rw-r--r--src/libsystemd-network/dhcp-packet.c5
-rw-r--r--src/libsystemd-network/dhcp6-option.c2
-rw-r--r--src/libsystemd-network/lldp-port.c4
-rw-r--r--src/libsystemd-network/lldp-tlv.c2
-rw-r--r--src/libsystemd-network/network-internal.c6
-rw-r--r--src/libsystemd-network/network-internal.h2
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c2
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c12
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c11
-rw-r--r--src/libsystemd-network/sd-ndisc.c119
-rw-r--r--src/libsystemd-network/test-acd.c8
-rw-r--r--src/libsystemd-network/test-dhcp-client.c2
-rw-r--r--src/libsystemd-network/test-dhcp-option.c4
-rw-r--r--src/libsystemd-network/test-dhcp-server.c4
-rw-r--r--src/libsystemd-network/test-ndisc-rs.c27
-rw-r--r--src/libsystemd/sd-bus/bus-bloom.c10
-rw-r--r--src/libsystemd/sd-bus/bus-bloom.h1
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.c3
-rw-r--r--src/libsystemd/sd-bus/bus-container.c2
-rw-r--r--src/libsystemd/sd-bus/bus-control.c8
-rw-r--r--src/libsystemd/sd-bus/bus-error.c2
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.c2
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c2
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c2
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c9
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c8
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c6
-rw-r--r--src/libsystemd/sd-bus/test-bus-creds.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-error.c3
-rw-r--r--src/libsystemd/sd-bus/test-bus-introspect.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c4
-rw-r--r--src/libsystemd/sd-bus/test-bus-match.c7
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-signature.c6
-rw-r--r--src/libsystemd/sd-bus/test-bus-zero-copy.c2
-rw-r--r--src/libsystemd/sd-event/sd-event.c7
-rw-r--r--src/libsystemd/sd-id128/sd-id128.c2
-rw-r--r--src/libsystemd/sd-netlink/local-addresses.c4
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c54
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.h2
-rw-r--r--src/libsystemd/sd-netlink/netlink-util.c2
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c29
-rw-r--r--src/libsystemd/sd-netlink/test-local-addresses.c2
-rw-r--r--src/libsystemd/sd-utf8/sd-utf8.c2
-rw-r--r--src/libudev/libudev-queue.c6
-rw-r--r--src/login/logind-core.c11
-rw-r--r--src/login/logind-dbus.c132
-rw-r--r--src/login/logind-gperf.gperf1
-rw-r--r--src/login/logind-session.c27
-rw-r--r--src/login/logind-user.c255
-rw-r--r--src/login/logind-user.h12
-rw-r--r--src/login/logind-utmp.c2
-rw-r--r--src/login/logind.c1
-rw-r--r--src/login/logind.conf1
-rw-r--r--src/login/logind.h4
-rw-r--r--src/login/pam_systemd.c30
-rw-r--r--src/login/test-login-shared.c2
-rw-r--r--src/login/test-login-tables.c1
-rw-r--r--src/machine-id-setup/machine-id-setup-main.c2
-rw-r--r--src/machine/machine.c7
-rw-r--r--src/machine/machined-dbus.c5
-rw-r--r--src/machine/test-machine-tables.c1
-rw-r--r--src/network/networkctl.c22
-rw-r--r--src/network/networkd-address.c17
-rw-r--r--src/network/networkd-address.h1
-rw-r--r--src/network/networkd-dhcp4.c4
-rw-r--r--src/network/networkd-dhcp6.c96
-rw-r--r--src/network/networkd-fdb.c2
-rw-r--r--src/network/networkd-ipv4ll.c8
-rw-r--r--src/network/networkd-link-bus.c5
-rw-r--r--src/network/networkd-link.c301
-rw-r--r--src/network/networkd-link.h13
-rw-r--r--src/network/networkd-manager.c19
-rw-r--r--src/network/networkd-ndisc.c191
-rw-r--r--src/network/networkd-netdev-bond.c21
-rw-r--r--src/network/networkd-netdev-bridge.c2
-rw-r--r--src/network/networkd-netdev-tuntap.c2
-rw-r--r--src/network/networkd-netdev-veth.c1
-rw-r--r--src/network/networkd-netdev-vxlan.c5
-rw-r--r--src/network/networkd-netdev.c6
-rw-r--r--src/network/networkd-route.c8
-rw-r--r--src/network/networkd-route.h2
-rw-r--r--src/network/networkd-util.c10
-rw-r--r--src/network/test-network-tables.c9
-rw-r--r--src/network/test-network.c4
-rw-r--r--src/nspawn/nspawn-gperf.gperf43
-rw-r--r--src/nspawn/nspawn-network.c165
-rw-r--r--src/nspawn/nspawn-network.h3
-rw-r--r--src/nspawn/nspawn-register.c4
-rw-r--r--src/nspawn/nspawn-settings.c39
-rw-r--r--src/nspawn/nspawn-settings.h2
-rw-r--r--src/nspawn/nspawn.c35
-rw-r--r--src/quotacheck/quotacheck.c2
-rw-r--r--src/remount-fs/remount-fs.c70
-rw-r--r--src/resolve-host/resolve-host.c2
-rw-r--r--src/resolve/resolved-llmnr.c2
-rw-r--r--src/run/run.c2
-rw-r--r--src/shared/acl-util.c2
-rw-r--r--src/shared/acpi-fpdt.c2
-rw-r--r--src/shared/architecture.c2
-rw-r--r--src/shared/boot-timestamps.c2
-rw-r--r--src/shared/bus-util.c15
-rw-r--r--src/shared/clean-ipc.c2
-rw-r--r--src/shared/efivars.c4
-rw-r--r--src/shared/firewall-util.c2
-rw-r--r--src/shared/generator.c4
-rw-r--r--src/shared/install-printf.c52
-rw-r--r--src/shared/install.c2006
-rw-r--r--src/shared/install.h50
-rw-r--r--src/shared/path-lookup.c12
-rw-r--r--src/shared/ptyfwd.c2
-rw-r--r--src/shared/seccomp-util.c2
-rw-r--r--src/shared/spawn-ask-password-agent.c2
-rw-r--r--src/shared/spawn-polkit-agent.c6
-rw-r--r--src/shared/sysctl-util.c2
-rw-r--r--src/shared/watchdog.c6
-rw-r--r--src/systemctl/systemctl.c135
-rw-r--r--src/systemd/sd-dhcp6-client.h1
-rw-r--r--src/systemd/sd-ndisc.h24
-rw-r--r--src/systemd/sd-netlink.h2
-rw-r--r--src/sysv-generator/sysv-generator.c10
-rw-r--r--src/test/test-architecture.c4
-rw-r--r--src/test/test-boot-timestamps.c6
-rw-r--r--src/test/test-cgroup-mask.c14
-rw-r--r--src/test/test-conf-files.c3
-rw-r--r--src/test/test-engine.c24
-rw-r--r--src/test/test-execute.c35
-rw-r--r--src/test/test-extract-word.c12
-rw-r--r--src/test/test-fileio.c23
-rw-r--r--src/test/test-firewall-util.c2
-rw-r--r--src/test/test-hashmap.c2
-rw-r--r--src/test/test-install-root.c665
-rw-r--r--src/test/test-install.c73
-rw-r--r--src/test/test-job-type.c2
-rw-r--r--src/test/test-locale-util.c2
-rw-r--r--src/test/test-log.c2
-rw-r--r--src/test/test-loopback.c4
-rw-r--r--src/test/test-ns.c2
-rw-r--r--src/test/test-parse-util.c43
-rw-r--r--src/test/test-ratelimit.c2
-rw-r--r--src/test/test-sched-prio.c2
-rw-r--r--src/test/test-siphash24.c43
-rw-r--r--src/test/test-sleep.c2
-rw-r--r--src/test/test-socket-util.c41
-rw-r--r--src/test/test-tables.c7
-rw-r--r--src/test/test-terminal-util.c2
-rw-r--r--src/test/test-time.c2
-rw-r--r--src/test/test-unaligned.c76
-rw-r--r--src/test/test-unit-file.c90
-rw-r--r--src/test/test-unit-name.c27
-rw-r--r--src/test/test-utf8.c2
-rw-r--r--src/test/test-watchdog.c2
-rw-r--r--src/tmpfiles/tmpfiles.c28
-rw-r--r--src/udev/mtd_probe/mtd_probe.c8
-rw-r--r--src/udev/mtd_probe/probe_smartmedia.c9
-rw-r--r--src/udev/net/link-config.c6
-rw-r--r--src/udev/udev-builtin-path_id.c57
-rw-r--r--src/udev/udev-builtin-uaccess.c2
-rw-r--r--src/udev/udev-ctrl.c6
-rw-r--r--src/udev/udev-watch.c6
-rw-r--r--src/udev/udevadm-control.c6
-rw-r--r--src/udev/udevadm-monitor.c12
-rw-r--r--src/udev/udevadm-settle.c10
-rw-r--r--src/udev/udevd.c8
-rw-r--r--src/udev/v4l_id/v4l_id.c14
312 files changed, 5145 insertions, 3547 deletions
diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c
index a377996a37..deb102c22c 100644
--- a/src/analyze/analyze-verify.c
+++ b/src/analyze/analyze-verify.c
@@ -23,6 +23,7 @@
#include "alloc-util.h"
#include "analyze-verify.h"
+#include "bus-error.h"
#include "bus-util.h"
#include "log.h"
#include "manager.h"
@@ -164,7 +165,6 @@ static int verify_documentation(Unit *u, bool check_man) {
static int verify_unit(Unit *u, bool check_man) {
_cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
- Job *j;
int r, k;
assert(u);
@@ -173,11 +173,9 @@ static int verify_unit(Unit *u, bool check_man) {
unit_dump(u, stdout, "\t");
log_unit_debug(u, "Creating %s/start job", u->id);
- r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, false, &err, &j);
- if (sd_bus_error_is_set(&err))
- log_unit_error(u, "Error: %s: %s", err.name, err.message);
+ r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, &err, NULL);
if (r < 0)
- log_unit_error_errno(u, r, "Failed to create %s/start: %m", u->id);
+ log_unit_error_errno(u, r, "Failed to create %s/start: %s", u->id, bus_error_message(&err, r));
k = verify_socket(u);
if (k < 0 && r == 0)
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 27ead903e9..e922d6fb32 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -1066,20 +1066,17 @@ static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *fro
assert(bus);
assert(u);
- if (arg_dot == DEP_ORDER ||arg_dot == DEP_ALL) {
+ if (IN_SET(arg_dot, DEP_ORDER, DEP_ALL)) {
r = graph_one_property(bus, u, "After", "green", patterns, from_patterns, to_patterns);
if (r < 0)
return r;
}
- if (arg_dot == DEP_REQUIRE ||arg_dot == DEP_ALL) {
+ if (IN_SET(arg_dot, DEP_REQUIRE, DEP_ALL)) {
r = graph_one_property(bus, u, "Requires", "black", patterns, from_patterns, to_patterns);
if (r < 0)
return r;
- r = graph_one_property(bus, u, "RequiresOverridable", "black", patterns, from_patterns, to_patterns);
- if (r < 0)
- return r;
- r = graph_one_property(bus, u, "RequisiteOverridable", "darkblue", patterns, from_patterns, to_patterns);
+ r = graph_one_property(bus, u, "Requisite", "darkblue", patterns, from_patterns, to_patterns);
if (r < 0)
return r;
r = graph_one_property(bus, u, "Wants", "grey66", patterns, from_patterns, to_patterns);
@@ -1088,9 +1085,6 @@ static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *fro
r = graph_one_property(bus, u, "Conflicts", "red", patterns, from_patterns, to_patterns);
if (r < 0)
return r;
- r = graph_one_property(bus, u, "ConflictedBy", "red", patterns, from_patterns, to_patterns);
- if (r < 0)
- return r;
}
return 0;
diff --git a/src/basic/af-list.c b/src/basic/af-list.c
index f396115a34..07dfff6ad4 100644
--- a/src/basic/af-list.c
+++ b/src/basic/af-list.c
@@ -19,16 +19,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
#include <string.h>
+#include <sys/socket.h>
-#include "util.h"
#include "af-list.h"
+#include "util.h"
static const struct af_name* lookup_af(register const char *str, register unsigned int len);
-#include "af-to-name.h"
#include "af-from-name.h"
+#include "af-to-name.h"
const char *af_to_name(int id) {
diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c
index 284043cd90..03d8ad7403 100644
--- a/src/basic/arphrd-list.c
+++ b/src/basic/arphrd-list.c
@@ -22,13 +22,13 @@
#include <net/if_arp.h>
#include <string.h>
-#include "util.h"
#include "arphrd-list.h"
+#include "util.h"
static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
-#include "arphrd-to-name.h"
#include "arphrd-from-name.h"
+#include "arphrd-to-name.h"
const char *arphrd_to_name(int id) {
diff --git a/src/basic/async.c b/src/basic/async.c
index c3135f0efe..cfc5d224e1 100644
--- a/src/basic/async.c
+++ b/src/basic/async.c
@@ -68,7 +68,7 @@ int asynchronous_sync(void) {
}
static void *close_thread(void *p) {
- assert_se(close_nointr(PTR_TO_INT(p)) != -EBADF);
+ assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF);
return NULL;
}
@@ -84,7 +84,7 @@ int asynchronous_close(int fd) {
if (fd >= 0) {
PROTECT_ERRNO;
- r = asynchronous_job(close_thread, INT_TO_PTR(fd));
+ r = asynchronous_job(close_thread, FD_TO_PTR(fd));
if (r < 0)
assert_se(close_nointr(fd) != -EBADF);
}
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index 4c90bc0c80..be40dc5702 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -105,7 +105,7 @@ int btrfs_is_filesystem(int fd) {
return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
}
-int btrfs_is_subvol(int fd) {
+int btrfs_is_subvol_fd(int fd) {
struct stat st;
assert(fd >= 0);
@@ -121,6 +121,18 @@ int btrfs_is_subvol(int fd) {
return btrfs_is_filesystem(fd);
}
+int btrfs_is_subvol(const char *path) {
+ _cleanup_close_ int fd = -1;
+
+ assert(path);
+
+ fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (fd < 0)
+ return -errno;
+
+ return btrfs_is_subvol_fd(fd);
+}
+
int btrfs_subvol_make(const char *path) {
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -1;
@@ -575,8 +587,12 @@ int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
unsigned i;
args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
+ if (errno == ENOENT) /* quota tree is missing: quota disabled */
+ break;
+
return -errno;
+ }
if (args.key.nr_items <= 0)
break;
@@ -1006,6 +1022,10 @@ static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {
for (c = 0;; c++) {
if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) {
+ /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
+ if (errno == EINVAL)
+ return -ENOPROTOOPT;
+
if (errno == EBUSY && c < 10) {
(void) btrfs_quota_scan_wait(fd);
continue;
@@ -1335,8 +1355,12 @@ int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupi
unsigned i;
args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
+ if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */
+ break;
+
return -errno;
+ }
if (args.key.nr_items <= 0)
break;
@@ -1411,12 +1435,16 @@ static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_sub
return n_old_qgroups;
r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id);
- if (r < 0)
+ if (r == -ENXIO)
+ /* We have no parent, hence nothing to copy. */
+ n_old_parent_qgroups = 0;
+ else if (r < 0)
return r;
-
- n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
- if (n_old_parent_qgroups < 0)
- return n_old_parent_qgroups;
+ else {
+ n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
+ if (n_old_parent_qgroups < 0)
+ return n_old_parent_qgroups;
+ }
for (i = 0; i < n_old_qgroups; i++) {
uint64_t id;
@@ -1670,7 +1698,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag
assert(old_fd >= 0);
assert(new_path);
- r = btrfs_is_subvol(old_fd);
+ r = btrfs_is_subvol_fd(old_fd);
if (r < 0)
return r;
if (r == 0) {
@@ -1766,8 +1794,12 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
unsigned i;
args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
+ if (errno == ENOENT) /* quota tree missing: quota is disabled */
+ break;
+
return -errno;
+ }
if (args.key.nr_items <= 0)
break;
@@ -1852,7 +1884,7 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
*/
if (subvol_id == 0) {
- r = btrfs_is_subvol(fd);
+ r = btrfs_is_subvol_fd(fd);
if (r < 0)
return r;
if (!r)
@@ -1869,14 +1901,19 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
if (n > 0) /* already parent qgroups set up, let's bail */
return 0;
+ qgroups = mfree(qgroups);
+
r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
- if (r < 0)
+ if (r == -ENXIO)
+ /* No parent, hence no qgroup memberships */
+ n = 0;
+ else if (r < 0)
return r;
-
- qgroups = mfree(qgroups);
- n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
- if (n < 0)
- return n;
+ else {
+ n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
+ if (n < 0)
+ return n;
+ }
if (insert_intermediary_qgroup) {
uint64_t lowest = 256, new_qgroupid;
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index fc9efd72d5..8c11ce35d2 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -56,7 +56,9 @@ typedef enum BtrfsRemoveFlags {
} BtrfsRemoveFlags;
int btrfs_is_filesystem(int fd);
-int btrfs_is_subvol(int fd);
+
+int btrfs_is_subvol_fd(int fd);
+int btrfs_is_subvol(const char *path);
int btrfs_reflink(int infd, int outfd);
int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz);
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 7151fc3d0c..157ae1fb74 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -23,9 +23,9 @@
#include <string.h>
#include "alloc-util.h"
-#include "string-util.h"
#include "calendarspec.h"
#include "fileio.h"
+#include "string-util.h"
#define BITS_WEEKDAYS 127
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
index 4d391510bc..f0974900cd 100644
--- a/src/basic/cap-list.c
+++ b/src/basic/cap-list.c
@@ -28,8 +28,8 @@
static const struct capability_name* lookup_capability(register const char *str, register unsigned int len);
-#include "cap-to-name.h"
#include "cap-from-name.h"
+#include "cap-to-name.h"
const char *capability_to_name(int id) {
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index 9ddac5d6a1..441169db31 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -138,6 +138,21 @@ bool strv_env_is_valid(char **e) {
return true;
}
+bool strv_env_name_is_valid(char **l) {
+ char **p, **q;
+
+ STRV_FOREACH(p, l) {
+ if (!env_name_is_valid(*p))
+ return false;
+
+ STRV_FOREACH(q, p + 1)
+ if (streq(*p, *q))
+ return false;
+ }
+
+ return true;
+}
+
bool strv_env_name_or_assignment_is_valid(char **l) {
char **p, **q;
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index 6485dade18..5efffa3dc7 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -36,6 +36,7 @@ bool strv_env_is_valid(char **e);
#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
+bool strv_env_name_is_valid(char **l);
bool strv_env_name_or_assignment_is_valid(char **l);
char **strv_env_merge(unsigned n_lists, ...);
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
index 34d1331486..22869e4136 100644
--- a/src/basic/errno-list.c
+++ b/src/basic/errno-list.c
@@ -21,14 +21,14 @@
#include <string.h>
-#include "util.h"
#include "errno-list.h"
+#include "util.h"
static const struct errno_name* lookup_errno(register const char *str,
register unsigned int len);
-#include "errno-to-name.h"
#include "errno-from-name.h"
+#include "errno-to-name.h"
const char *errno_to_name(int id) {
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
index fcff753ada..4c83731540 100644
--- a/src/basic/exit-status.c
+++ b/src/basic/exit-status.c
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <signal.h>
+#include <stdlib.h>
#include "exit-status.h"
-#include "set.h"
#include "macro.h"
+#include "set.h"
const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index ff6d211ef4..fd495692fa 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -128,7 +128,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
} else if (c == quote) { /* found the end quote */
quote = 0;
break;
- } else if (c == '\\') {
+ } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
backslash = true;
break;
} else {
@@ -146,7 +146,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
quote = c;
break;
- } else if (c == '\\') {
+ } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
backslash = true;
break;
} else if (strchr(separators, c)) {
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
index ddc1c4f463..9606ab64b3 100644
--- a/src/basic/extract-word.h
+++ b/src/basic/extract-word.h
@@ -24,11 +24,12 @@
#include "macro.h"
typedef enum ExtractFlags {
- EXTRACT_RELAX = 1,
- EXTRACT_CUNESCAPE = 2,
- EXTRACT_CUNESCAPE_RELAX = 4,
- EXTRACT_QUOTES = 8,
+ EXTRACT_RELAX = 1,
+ EXTRACT_CUNESCAPE = 2,
+ EXTRACT_CUNESCAPE_RELAX = 4,
+ EXTRACT_QUOTES = 8,
EXTRACT_DONT_COALESCE_SEPARATORS = 16,
+ EXTRACT_RETAIN_ESCAPE = 32,
} ExtractFlags;
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index 1ca10f0383..0e9182d75b 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -28,6 +28,10 @@
#include "macro.h"
+/* Make sure we can distinguish fd 0 and NULL */
+#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
+#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
+
int close_nointr(int fd);
int safe_close(int fd);
void safe_close_pair(int p[]);
diff --git a/src/basic/fdset.c b/src/basic/fdset.c
index 42b0b2b98f..e5452f3bb0 100644
--- a/src/basic/fdset.c
+++ b/src/basic/fdset.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <errno.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include "sd-daemon.h"
@@ -36,10 +36,6 @@
#define MAKE_SET(s) ((Set*) s)
#define MAKE_FDSET(s) ((FDSet*) s)
-/* Make sure we can distinguish fd 0 and NULL */
-#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
-#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
-
FDSet *fdset_new(void) {
return MAKE_FDSET(set_new(NULL));
}
diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c
index f596f1d11f..0405822ce0 100644
--- a/src/basic/fileio-label.c
+++ b/src/basic/fileio-label.c
@@ -20,9 +20,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "selinux-util.h"
#include "fileio-label.h"
+#include "selinux-util.h"
+#include "util.h"
int write_string_file_atomic_label(const char *fn, const char *line) {
int r;
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 619dafb517..10aacdc56d 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -28,8 +28,10 @@
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
+#include "parse-util.h"
#include "path-util.h"
#include "random-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "umask-util.h"
@@ -76,6 +78,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
_cleanup_fclose_ FILE *f = NULL;
+ int q, r;
assert(fn);
assert(line);
@@ -83,30 +86,58 @@ int write_string_file(const char *fn, const char *line, WriteStringFileFlags fla
if (flags & WRITE_STRING_FILE_ATOMIC) {
assert(flags & WRITE_STRING_FILE_CREATE);
- return write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ if (r < 0)
+ goto fail;
+
+ return r;
}
if (flags & WRITE_STRING_FILE_CREATE) {
f = fopen(fn, "we");
- if (!f)
- return -errno;
+ if (!f) {
+ r = -errno;
+ goto fail;
+ }
} else {
int fd;
/* We manually build our own version of fopen(..., "we") that
* works without O_CREAT */
fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
+ if (fd < 0) {
+ r = -errno;
+ goto fail;
+ }
f = fdopen(fd, "we");
if (!f) {
+ r = -errno;
safe_close(fd);
- return -errno;
+ goto fail;
}
}
- return write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ if (r < 0)
+ goto fail;
+
+ return 0;
+
+fail:
+ if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
+ return r;
+
+ f = safe_fclose(f);
+
+ /* OK, the operation failed, but let's see if the right
+ * contents in place already. If so, eat up the error. */
+
+ q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ if (q <= 0)
+ return r;
+
+ return 0;
}
int read_one_line_file(const char *fn, char **line) {
@@ -137,15 +168,41 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
-int verify_one_line_file(const char *fn, const char *line) {
- _cleanup_free_ char *value = NULL;
- int r;
+int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *buf = NULL;
+ size_t l, k;
- r = read_one_line_file(fn, &value);
- if (r < 0)
- return r;
+ assert(fn);
+ assert(blob);
- return streq(value, line);
+ l = strlen(blob);
+
+ if (accept_extra_nl && endswith(blob, "\n"))
+ accept_extra_nl = false;
+
+ buf = malloc(l + accept_extra_nl + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ f = fopen(fn, "re");
+ if (!f)
+ return -errno;
+
+ /* We try to read one byte more than we need, so that we know whether we hit eof */
+ errno = 0;
+ k = fread(buf, 1, l + accept_extra_nl + 1, f);
+ if (ferror(f))
+ return errno > 0 ? -errno : -EIO;
+
+ if (k != l && k != l + accept_extra_nl)
+ return 0;
+ if (memcmp(buf, blob, l) != 0)
+ return 0;
+ if (k > l && buf[l] != '\n')
+ return 0;
+
+ return 1;
}
int read_full_stream(FILE *f, char **contents, size_t *size) {
@@ -1149,3 +1206,37 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
*ret = path_kill_slashes(t);
return 0;
}
+
+int write_timestamp_file_atomic(const char *fn, usec_t n) {
+ char ln[DECIMAL_STR_MAX(n)+2];
+
+ /* Creates a "timestamp" file, that contains nothing but a
+ * usec_t timestamp, formatted in ASCII. */
+
+ if (n <= 0 || n >= USEC_INFINITY)
+ return -ERANGE;
+
+ xsprintf(ln, USEC_FMT "\n", n);
+
+ return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+}
+
+int read_timestamp_file(const char *fn, usec_t *ret) {
+ _cleanup_free_ char *ln = NULL;
+ uint64_t t;
+ int r;
+
+ r = read_one_line_file(fn, &ln);
+ if (r < 0)
+ return r;
+
+ r = safe_atou64(ln, &t);
+ if (r < 0)
+ return r;
+
+ if (t <= 0 || t >= (uint64_t) USEC_INFINITY)
+ return -ERANGE;
+
+ *ret = (usec_t) t;
+ return 0;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index fa7f192331..95e8698941 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -28,11 +28,13 @@
#include <sys/types.h>
#include "macro.h"
+#include "time-util.h"
typedef enum {
WRITE_STRING_FILE_CREATE = 1,
WRITE_STRING_FILE_ATOMIC = 2,
WRITE_STRING_FILE_AVOID_NEWLINE = 4,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
} WriteStringFileFlags;
int write_string_stream(FILE *f, const char *line, bool enforce_newline);
@@ -42,7 +44,7 @@ int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
-int verify_one_line_file(const char *fn, const char *line);
+int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
@@ -77,3 +79,6 @@ int open_tmpfile(const char *path, int flags);
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
int tempfn_random(const char *p, const char *extra, char **ret);
int tempfn_random_child(const char *p, const char *extra, char **ret);
+
+int write_timestamp_file_atomic(const char *fn, usec_t n);
+int read_timestamp_file(const char *fn, usec_t *ret);
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index 7aee404bfc..2b6189ad90 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -233,6 +233,26 @@ int readlink_and_canonicalize(const char *p, char **r) {
return 0;
}
+int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
+ _cleanup_free_ char *target = NULL, *t = NULL;
+ const char *full;
+ int r;
+
+ full = prefix_roota(root, path);
+ r = readlink_malloc(full, &target);
+ if (r < 0)
+ return r;
+
+ t = file_in_same_dir(path, target);
+ if (!t)
+ return -ENOMEM;
+
+ *ret = t;
+ t = NULL;
+
+ return 0;
+}
+
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
assert(path);
@@ -311,7 +331,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
if (fd < 0)
return -errno;
- if (mode > 0) {
+ if (mode != MODE_INVALID) {
r = fchmod(fd, mode);
if (r < 0)
return -errno;
@@ -338,7 +358,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
}
int touch(const char *path) {
- return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
+ return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
}
int symlink_idempotent(const char *from, const char *to) {
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index b94873e65b..902c7e295b 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -40,6 +40,7 @@ int readlink_malloc(const char *p, char **r);
int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r);
+int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 4109a08c6c..6e501ef6ff 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -380,7 +380,7 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
h->hash_ops->hash(p, &state);
- siphash24_finalize((uint8_t*)&hash, &state);
+ hash = siphash24_finalize(&state);
return (unsigned) (hash % n_buckets(h));
}
diff --git a/src/basic/json.c b/src/basic/json.c
index 716705e5ff..9d5dedb934 100644
--- a/src/basic/json.c
+++ b/src/basic/json.c
@@ -23,9 +23,9 @@
#include <sys/types.h>
#include "alloc-util.h"
+#include "hexdecoct.h"
#include "json.h"
#include "macro.h"
-#include "hexdecoct.h"
#include "string-util.h"
#include "utf8.h"
diff --git a/src/basic/label.c b/src/basic/label.c
index 82f10b21bd..f33502f90f 100644
--- a/src/basic/label.c
+++ b/src/basic/label.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "label.h"
#include "selinux-util.h"
#include "smack-util.h"
#include "util.h"
-#include "label.h"
int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
int r, q;
diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c
index 87c3aef7af..0bdbae480b 100644
--- a/src/basic/lockfile-util.c
+++ b/src/basic/lockfile-util.c
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
-#include <stdbool.h>
#include <errno.h>
-#include <string.h>
-#include <stdio.h>
#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/file.h>
#include "alloc-util.h"
diff --git a/src/basic/login-util.c b/src/basic/login-util.c
index 832f477bd2..41cef14e73 100644
--- a/src/basic/login-util.c
+++ b/src/basic/login-util.c
@@ -20,8 +20,8 @@
***/
#include "def.h"
-#include "string-util.h"
#include "login-util.h"
+#include "string-util.h"
bool session_id_valid(const char *id) {
diff --git a/src/basic/mempool.c b/src/basic/mempool.c
index d5d98d8829..9ee6e6a76d 100644
--- a/src/basic/mempool.c
+++ b/src/basic/mempool.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "mempool.h"
#include "macro.h"
+#include "mempool.h"
#include "util.h"
struct pool {
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 306c56a156..d539ed00e4 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -23,19 +23,20 @@
/* Missing glibc definitions to access certain kernel APIs */
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
-#include <linux/oom.h>
-#include <linux/input.h>
-#include <linux/if_link.h>
-#include <linux/loop.h>
+#include <fcntl.h>
#include <linux/audit.h>
#include <linux/capability.h>
+#include <linux/if_link.h>
+#include <linux/input.h>
+#include <linux/loop.h>
#include <linux/neighbour.h>
+#include <linux/oom.h>
+#include <linux/rtnetlink.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <unistd.h>
#ifdef HAVE_AUDIT
#include <libaudit.h>
@@ -900,6 +901,10 @@ static inline int setns(int fd, int nstype) {
#define NDA_MAX (__NDA_MAX - 1)
#endif
+#ifndef RTA_PREF
+#define RTA_PREF 20
+#endif
+
#ifndef IPV6_UNICAST_IF
#define IPV6_UNICAST_IF 76
#endif
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
index 76bbc1edda..c241ef6064 100644
--- a/src/basic/mkdir-label.c
+++ b/src/basic/mkdir-label.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <stdio.h>
+#include <unistd.h>
#include "label.h"
#include "mkdir.h"
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
index 0214c4627e..5d7fb9a12d 100644
--- a/src/basic/mkdir.c
+++ b/src/basic/mkdir.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include "fs-util.h"
#include "mkdir.h"
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index a821a3d5bb..e8ce5cfd96 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -24,15 +24,15 @@
#include <sys/un.h>
#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#include <selinux/label.h>
#include <selinux/context.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
#endif
#include "alloc-util.h"
-#include "strv.h"
#include "path-util.h"
#include "selinux-util.h"
+#include "strv.h"
#ifdef HAVE_SELINUX
DEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon);
diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c
index 0108603fe8..c535c89d52 100644
--- a/src/basic/sigbus.c
+++ b/src/basic/sigbus.c
@@ -23,8 +23,8 @@
#include <sys/mman.h>
#include "macro.h"
-#include "util.h"
#include "sigbus.h"
+#include "util.h"
#define SIGBUS_QUEUE_MAX 64
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
index 3b61961389..10fc56da69 100644
--- a/src/basic/siphash24.c
+++ b/src/basic/siphash24.c
@@ -17,9 +17,9 @@
coding style)
*/
-#include "sparse-endian.h"
-
#include "siphash24.h"
+#include "sparse-endian.h"
+#include "unaligned.h"
#include "util.h"
static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
@@ -53,37 +53,40 @@ void siphash24_init(struct siphash *state, const uint8_t k[16]) {
assert(state);
assert(k);
- k0 = le64toh(*(le64_t*) k);
- k1 = le64toh(*(le64_t*) (k + 8));
-
- /* "somepseudorandomlygeneratedbytes" */
- state->v0 = 0x736f6d6570736575ULL ^ k0;
- state->v1 = 0x646f72616e646f6dULL ^ k1;
- state->v2 = 0x6c7967656e657261ULL ^ k0;
- state->v3 = 0x7465646279746573ULL ^ k1;
- state->padding = 0;
- state->inlen = 0;
+ k0 = unaligned_read_le64(k);
+ k1 = unaligned_read_le64(k + 8);
+
+ *state = (struct siphash) {
+ /* "somepseudorandomlygeneratedbytes" */
+ .v0 = 0x736f6d6570736575ULL ^ k0,
+ .v1 = 0x646f72616e646f6dULL ^ k1,
+ .v2 = 0x6c7967656e657261ULL ^ k0,
+ .v3 = 0x7465646279746573ULL ^ k1,
+ .padding = 0,
+ .inlen = 0,
+ };
}
void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
- uint64_t m;
+
const uint8_t *in = _in;
const uint8_t *end = in + inlen;
- unsigned left = state->inlen & 7;
+ size_t left = state->inlen & 7;
+ uint64_t m;
assert(in);
assert(state);
- /* update total length */
+ /* Update total length */
state->inlen += inlen;
- /* if padding exists, fill it out */
+ /* If padding exists, fill it out */
if (left > 0) {
- for ( ; in < end && left < 8; in ++, left ++ )
- state->padding |= ( ( uint64_t )*in ) << (left * 8);
+ for ( ; in < end && left < 8; in ++, left ++)
+ state->padding |= ((uint64_t) *in) << (left * 8);
if (in == end && left < 8)
- /* we did not have enough input to fill out the padding completely */
+ /* We did not have enough input to fill out the padding completely */
return;
#ifdef DEBUG
@@ -93,6 +96,7 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
#endif
+
state->v3 ^= state->padding;
sipround(state);
sipround(state);
@@ -101,10 +105,10 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
state->padding = 0;
}
- end -= ( state->inlen % sizeof (uint64_t) );
+ end -= (state->inlen % sizeof(uint64_t));
- for ( ; in < end; in += 8 ) {
- m = le64toh(*(le64_t*) in);
+ for ( ; in < end; in += 8) {
+ m = unaligned_read_le64(in);
#ifdef DEBUG
printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
@@ -119,38 +123,41 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
}
left = state->inlen & 7;
-
- switch(left)
- {
- case 7: state->padding |= ((uint64_t) in[6]) << 48;
-
- case 6: state->padding |= ((uint64_t) in[5]) << 40;
-
- case 5: state->padding |= ((uint64_t) in[4]) << 32;
-
- case 4: state->padding |= ((uint64_t) in[3]) << 24;
-
- case 3: state->padding |= ((uint64_t) in[2]) << 16;
-
- case 2: state->padding |= ((uint64_t) in[1]) << 8;
-
- case 1: state->padding |= ((uint64_t) in[0]); break;
-
- case 0: break;
+ switch (left) {
+ case 7:
+ state->padding |= ((uint64_t) in[6]) << 48;
+ case 6:
+ state->padding |= ((uint64_t) in[5]) << 40;
+ case 5:
+ state->padding |= ((uint64_t) in[4]) << 32;
+ case 4:
+ state->padding |= ((uint64_t) in[3]) << 24;
+ case 3:
+ state->padding |= ((uint64_t) in[2]) << 16;
+ case 2:
+ state->padding |= ((uint64_t) in[1]) << 8;
+ case 1:
+ state->padding |= ((uint64_t) in[0]);
+ case 0:
+ break;
}
}
-void siphash24_finalize(uint8_t out[8], struct siphash *state) {
+uint64_t siphash24_finalize(struct siphash *state) {
uint64_t b;
- b = state->padding | (( ( uint64_t )state->inlen ) << 56);
+ assert(state);
+
+ b = state->padding | (((uint64_t) state->inlen) << 56);
+
#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3);
+ printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
+ printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
+ printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
+ printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
#endif
+
state->v3 ^= b;
sipround(state);
sipround(state);
@@ -169,14 +176,17 @@ void siphash24_finalize(uint8_t out[8], struct siphash *state) {
sipround(state);
sipround(state);
- *(le64_t*)out = htole64(state->v0 ^ state->v1 ^ state->v2 ^ state->v3);
+ return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
}
-/* SipHash-2-4 */
-void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) {
+uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
struct siphash state;
+ assert(in);
+ assert(k);
+
siphash24_init(&state, k);
- siphash24_compress(_in, inlen, &state);
- siphash24_finalize(out, &state);
+ siphash24_compress(in, inlen, &state);
+
+ return siphash24_finalize(&state);
}
diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h
index 6c5cd98ee8..ba4f7d01b6 100644
--- a/src/basic/siphash24.h
+++ b/src/basic/siphash24.h
@@ -4,16 +4,16 @@
#include <sys/types.h>
struct siphash {
- uint64_t v0;
- uint64_t v1;
- uint64_t v2;
- uint64_t v3;
- uint64_t padding;
- size_t inlen;
+ uint64_t v0;
+ uint64_t v1;
+ uint64_t v2;
+ uint64_t v3;
+ uint64_t padding;
+ size_t inlen;
};
void siphash24_init(struct siphash *state, const uint8_t k[16]);
void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
-void siphash24_finalize(uint8_t out[8], struct siphash *state);
+uint64_t siphash24_finalize(struct siphash *state);
-void siphash24(uint8_t out[8], const void *in, size_t inlen, const uint8_t k[16]);
+uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
diff --git a/src/basic/strv.c b/src/basic/strv.c
index ba6df716a7..771781f9fc 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -27,8 +27,8 @@
#include "alloc-util.h"
#include "escape.h"
#include "string-util.h"
-#include "util.h"
#include "strv.h"
+#include "util.h"
char *strv_find(char **l, const char *name) {
char **i;
diff --git a/src/basic/strxcpyx.c b/src/basic/strxcpyx.c
index 6542c0abf5..088ba53c29 100644
--- a/src/basic/strxcpyx.c
+++ b/src/basic/strxcpyx.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
+
#include "strxcpyx.h"
size_t strpcpy(char **dest, size_t size, const char *src) {
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index b36fbe4f09..647763a230 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -323,15 +323,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
const char *suffix;
usec_t usec;
} table[] = {
- { "y", USEC_PER_YEAR },
- { "month", USEC_PER_MONTH },
- { "w", USEC_PER_WEEK },
- { "d", USEC_PER_DAY },
- { "h", USEC_PER_HOUR },
- { "min", USEC_PER_MINUTE },
- { "s", USEC_PER_SEC },
- { "ms", USEC_PER_MSEC },
- { "us", 1 },
+ { "y", USEC_PER_YEAR },
+ { "month", USEC_PER_MONTH },
+ { "w", USEC_PER_WEEK },
+ { "d", USEC_PER_DAY },
+ { "h", USEC_PER_HOUR },
+ { "min", USEC_PER_MINUTE },
+ { "s", USEC_PER_SEC },
+ { "ms", USEC_PER_MSEC },
+ { "us", 1 },
};
unsigned i;
@@ -711,33 +711,34 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
const char *suffix;
usec_t usec;
} table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
+ { "seconds", USEC_PER_SEC },
+ { "second", USEC_PER_SEC },
+ { "sec", USEC_PER_SEC },
+ { "s", USEC_PER_SEC },
{ "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
+ { "minute", USEC_PER_MINUTE },
+ { "min", USEC_PER_MINUTE },
+ { "months", USEC_PER_MONTH },
+ { "month", USEC_PER_MONTH },
+ { "M", USEC_PER_MONTH },
+ { "msec", USEC_PER_MSEC },
+ { "ms", USEC_PER_MSEC },
+ { "m", USEC_PER_MINUTE },
+ { "hours", USEC_PER_HOUR },
+ { "hour", USEC_PER_HOUR },
+ { "hr", USEC_PER_HOUR },
+ { "h", USEC_PER_HOUR },
+ { "days", USEC_PER_DAY },
+ { "day", USEC_PER_DAY },
+ { "d", USEC_PER_DAY },
+ { "weeks", USEC_PER_WEEK },
+ { "week", USEC_PER_WEEK },
+ { "w", USEC_PER_WEEK },
+ { "years", USEC_PER_YEAR },
+ { "year", USEC_PER_YEAR },
+ { "y", USEC_PER_YEAR },
+ { "usec", 1ULL },
+ { "us", 1ULL },
};
const char *p, *s;
diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h
index d6181dd9a9..a8115eaa1f 100644
--- a/src/basic/unaligned.h
+++ b/src/basic/unaligned.h
@@ -21,8 +21,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <endian.h>
#include <stdint.h>
+/* BE */
+
static inline uint16_t unaligned_read_be16(const void *_u) {
const uint8_t *u = _u;
@@ -64,3 +67,47 @@ static inline void unaligned_write_be64(void *_u, uint64_t a) {
unaligned_write_be32(u, (uint32_t) (a >> 32));
unaligned_write_be32(u + 4, (uint32_t) a);
}
+
+/* LE */
+
+static inline uint16_t unaligned_read_le16(const void *_u) {
+ const uint8_t *u = _u;
+
+ return (((uint16_t) u[1]) << 8) |
+ ((uint16_t) u[0]);
+}
+
+static inline uint32_t unaligned_read_le32(const void *_u) {
+ const uint8_t *u = _u;
+
+ return (((uint32_t) unaligned_read_le16(u + 2)) << 16) |
+ ((uint32_t) unaligned_read_le16(u));
+}
+
+static inline uint64_t unaligned_read_le64(const void *_u) {
+ const uint8_t *u = _u;
+
+ return (((uint64_t) unaligned_read_le32(u + 4)) << 32) |
+ ((uint64_t) unaligned_read_le32(u));
+}
+
+static inline void unaligned_write_le16(void *_u, uint16_t a) {
+ uint8_t *u = _u;
+
+ u[0] = (uint8_t) a;
+ u[1] = (uint8_t) (a >> 8);
+}
+
+static inline void unaligned_write_le32(void *_u, uint32_t a) {
+ uint8_t *u = _u;
+
+ unaligned_write_le16(u, (uint16_t) a);
+ unaligned_write_le16(u + 2, (uint16_t) (a >> 16));
+}
+
+static inline void unaligned_write_le64(void *_u, uint64_t a) {
+ uint8_t *u = _u;
+
+ unaligned_write_le32(u, (uint32_t) a);
+ unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
+}
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 710421508c..9a55eacbfb 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -597,7 +597,6 @@ const char* unit_dbus_interface_from_type(UnitType t) {
[UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
[UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName",
[UNIT_TARGET] = "org.freedesktop.systemd1.Target",
- [UNIT_SNAPSHOT] = "org.freedesktop.systemd1.Snapshot",
[UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
[UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
[UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
@@ -819,7 +818,6 @@ static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
[UNIT_SOCKET] = "socket",
[UNIT_BUSNAME] = "busname",
[UNIT_TARGET] = "target",
- [UNIT_SNAPSHOT] = "snapshot",
[UNIT_DEVICE] = "device",
[UNIT_MOUNT] = "mount",
[UNIT_AUTOMOUNT] = "automount",
@@ -950,13 +948,6 @@ static const char* const slice_state_table[_SLICE_STATE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
-static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
- [SNAPSHOT_DEAD] = "dead",
- [SNAPSHOT_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
-
static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = "dead",
[SOCKET_START_PRE] = "start-pre",
@@ -1009,16 +1000,12 @@ DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
[UNIT_REQUIRES] = "Requires",
- [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
[UNIT_REQUISITE] = "Requisite",
- [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
[UNIT_WANTS] = "Wants",
[UNIT_BINDS_TO] = "BindsTo",
[UNIT_PART_OF] = "PartOf",
[UNIT_REQUIRED_BY] = "RequiredBy",
- [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
[UNIT_REQUISITE_OF] = "RequisiteOf",
- [UNIT_REQUISITE_OF_OVERRIDABLE] = "RequisiteOfOverridable",
[UNIT_WANTED_BY] = "WantedBy",
[UNIT_BOUND_BY] = "BoundBy",
[UNIT_CONSISTS_OF] = "ConsistsOf",
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
index 65b55d9554..03c1a6e4ac 100644
--- a/src/basic/unit-name.h
+++ b/src/basic/unit-name.h
@@ -32,7 +32,6 @@ typedef enum UnitType {
UNIT_SOCKET,
UNIT_BUSNAME,
UNIT_TARGET,
- UNIT_SNAPSHOT,
UNIT_DEVICE,
UNIT_MOUNT,
UNIT_AUTOMOUNT,
@@ -165,13 +164,6 @@ typedef enum SliceState {
_SLICE_STATE_INVALID = -1
} SliceState;
-typedef enum SnapshotState {
- SNAPSHOT_DEAD,
- SNAPSHOT_ACTIVE,
- _SNAPSHOT_STATE_MAX,
- _SNAPSHOT_STATE_INVALID = -1
-} SnapshotState;
-
typedef enum SocketState {
SOCKET_DEAD,
SOCKET_START_PRE,
@@ -226,18 +218,14 @@ typedef enum TimerState {
typedef enum UnitDependency {
/* Positive dependencies */
UNIT_REQUIRES,
- UNIT_REQUIRES_OVERRIDABLE,
UNIT_REQUISITE,
- UNIT_REQUISITE_OVERRIDABLE,
UNIT_WANTS,
UNIT_BINDS_TO,
UNIT_PART_OF,
/* Inverse of the above */
UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */
- UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' is 'required_by_overridable' */
UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */
- UNIT_REQUISITE_OF_OVERRIDABLE,/* inverse of 'requisite_overridable' is 'requisite_of_overridable' */
UNIT_WANTED_BY, /* inverse of 'wants' */
UNIT_BOUND_BY, /* inverse of 'binds_to' */
UNIT_CONSISTS_OF, /* inverse of 'part_of' */
@@ -366,9 +354,6 @@ ServiceState service_state_from_string(const char *s) _pure_;
const char* slice_state_to_string(SliceState i) _const_;
SliceState slice_state_from_string(const char *s) _pure_;
-const char* snapshot_state_to_string(SnapshotState i) _const_;
-SnapshotState snapshot_state_from_string(const char *s) _pure_;
-
const char* socket_state_to_string(SocketState i) _const_;
SocketState socket_state_from_string(const char *s) _pure_;
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index d6c936db37..397880b0b1 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <pwd.h>
#include <grp.h>
+#include <pwd.h>
#include "alloc-util.h"
#include "fd-util.h"
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
index 7600d99903..b4063a4cec 100644
--- a/src/basic/utf8.c
+++ b/src/basic/utf8.c
@@ -44,10 +44,10 @@
*/
#include <errno.h>
-#include <stdlib.h>
#include <inttypes.h>
-#include <string.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
#include "alloc-util.h"
#include "hexdecoct.h"
diff --git a/src/basic/util.c b/src/basic/util.c
index 08bdcd28f2..58617b354a 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -73,6 +73,7 @@
#include "build.h"
#include "def.h"
#include "device-nodes.h"
+#include "dirent-util.h"
#include "env-util.h"
#include "escape.h"
#include "exit-status.h"
@@ -81,19 +82,20 @@
#include "formats-util.h"
#include "gunicode.h"
#include "hashmap.h"
+#include "hexdecoct.h"
#include "hostname-util.h"
#include "ioprio.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
-#include "hexdecoct.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "signal-util.h"
#include "sparse-endian.h"
+#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
@@ -102,8 +104,6 @@
#include "utf8.h"
#include "util.h"
#include "virt.h"
-#include "dirent-util.h"
-#include "stat-util.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -206,7 +206,7 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) {
log_debug("Spawned %s as " PID_FMT ".", path, pid);
- r = hashmap_put(pids, UINT_TO_PTR(pid), path);
+ r = hashmap_put(pids, PID_TO_PTR(pid), path);
if (r < 0)
return log_oom();
path = NULL;
@@ -224,10 +224,10 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) {
_cleanup_free_ char *path = NULL;
pid_t pid;
- pid = PTR_TO_UINT(hashmap_first_key(pids));
+ pid = PTR_TO_PID(hashmap_first_key(pids));
assert(pid > 0);
- path = hashmap_remove(pids, UINT_TO_PTR(pid));
+ path = hashmap_remove(pids, PID_TO_PTR(pid));
assert(path);
wait_for_terminate_and_warn(path, pid, true);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index d088b7a804..1e5d6eea6e 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -24,6 +24,8 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "dirent-util.h"
+#include "fd-util.h"
#include "fileio.h"
#include "process-util.h"
#include "stat-util.h"
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 38b79da886..6d35adc0e2 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -18,12 +18,12 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "console.h"
-#include "graphics.h"
-#include "pefile.h"
#include "disk.h"
+#include "graphics.h"
#include "linux.h"
+#include "pefile.h"
+#include "util.h"
#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
index 66aa88f32e..2151d34432 100644
--- a/src/boot/efi/console.c
+++ b/src/boot/efi/console.c
@@ -18,8 +18,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "console.h"
+#include "util.h"
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
diff --git a/src/boot/efi/graphics.c b/src/boot/efi/graphics.c
index f732428216..efa91fa7ac 100644
--- a/src/boot/efi/graphics.c
+++ b/src/boot/efi/graphics.c
@@ -20,8 +20,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "graphics.h"
+#include "util.h"
EFI_STATUS graphics_mode(BOOLEAN on) {
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
index 809c69310e..e9d097c132 100644
--- a/src/boot/efi/linux.c
+++ b/src/boot/efi/linux.c
@@ -17,8 +17,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "linux.h"
+#include "util.h"
#define SETUP_MAGIC 0x53726448 /* "HdrS" */
struct SetupHeader {
diff --git a/src/boot/efi/pefile.c b/src/boot/efi/pefile.c
index e6fedbc929..efb3271ee3 100644
--- a/src/boot/efi/pefile.c
+++ b/src/boot/efi/pefile.c
@@ -17,8 +17,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "pefile.h"
+#include "util.h"
struct DosFileHeader {
UINT8 Magic[2];
diff --git a/src/boot/efi/splash.c b/src/boot/efi/splash.c
index 470ea3e2cc..b584b5e6a9 100644
--- a/src/boot/efi/splash.c
+++ b/src/boot/efi/splash.c
@@ -18,9 +18,9 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "graphics.h"
#include "splash.h"
+#include "util.h"
struct bmp_file {
CHAR8 signature[2];
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index 0c5ee4e9ff..2cd5c33cb6 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -16,12 +16,12 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
-#include "pefile.h"
#include "disk.h"
#include "graphics.h"
-#include "splash.h"
#include "linux.h"
+#include "pefile.h"
+#include "splash.h"
+#include "util.h"
/* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " VERSION " ####";
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index 05330c0577..2bf473ffc1 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -22,25 +22,25 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
+#include <sys/utsname.h>
#include <time.h>
-#include <limits.h>
#include <unistd.h>
-#include <sys/utsname.h>
-#include <fcntl.h>
#include "alloc-util.h"
#include "architecture.h"
-#include "util.h"
+#include "bootchart.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "list.h"
#include "macro.h"
#include "store.h"
#include "svg.h"
-#include "bootchart.h"
-#include "list.h"
#include "utf8.h"
-#include "fd-util.h"
+#include "util.h"
#define time_to_graph(t) ((t) * arg_scale_x)
#define ps_to_graph(n) ((n) * arg_scale_y)
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index f0834e9525..debd58ce8b 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -392,11 +392,11 @@ static int file_load(Policy *p, const char *path) {
} else {
PolicyItem *first;
- first = hashmap_get(p->user_items, UINT32_TO_PTR(i->uid));
+ first = hashmap_get(p->user_items, UID_TO_PTR(i->uid));
item_append(i, &first);
i->uid_valid = true;
- r = hashmap_replace(p->user_items, UINT32_TO_PTR(i->uid), first);
+ r = hashmap_replace(p->user_items, UID_TO_PTR(i->uid), first);
if (r < 0) {
LIST_REMOVE(items, first, i);
return log_oom();
@@ -424,11 +424,11 @@ static int file_load(Policy *p, const char *path) {
} else {
PolicyItem *first;
- first = hashmap_get(p->group_items, UINT32_TO_PTR(i->gid));
+ first = hashmap_get(p->group_items, GID_TO_PTR(i->gid));
item_append(i, &first);
i->gid_valid = true;
- r = hashmap_replace(p->group_items, UINT32_TO_PTR(i->gid), first);
+ r = hashmap_replace(p->group_items, GID_TO_PTR(i->gid), first);
if (r < 0) {
LIST_REMOVE(items, first, i);
return log_oom();
@@ -787,7 +787,7 @@ static int policy_check(Policy *p, const struct policy_check_filter *filter) {
verdict = check_policy_items(p->default_items, filter);
if (filter->gid != GID_INVALID) {
- items = hashmap_get(p->group_items, UINT32_TO_PTR(filter->gid));
+ items = hashmap_get(p->group_items, GID_TO_PTR(filter->gid));
if (items) {
v = check_policy_items(items, filter);
if (v != DUNNO)
@@ -796,7 +796,7 @@ static int policy_check(Policy *p, const struct policy_check_filter *filter) {
}
if (filter->uid != UID_INVALID) {
- items = hashmap_get(p->user_items, UINT32_TO_PTR(filter->uid));
+ items = hashmap_get(p->user_items, UID_TO_PTR(filter->uid));
if (items) {
v = check_policy_items(items, filter);
if (v != DUNNO)
@@ -1155,7 +1155,7 @@ static void dump_hashmap_items(Hashmap *h) {
void *k;
HASHMAP_FOREACH_KEY(i, k, h, j) {
- printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW), PTR_TO_UINT(k));
+ printf("\t%s Item for " UID_FMT ":\n", draw_special_char(DRAW_ARROW), PTR_TO_UID(k));
dump_items(i, "\t\t");
}
}
diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c
index 6e47884209..2dc5fe631b 100644
--- a/src/bus-proxyd/stdio-bridge.c
+++ b/src/bus-proxyd/stdio-bridge.c
@@ -27,8 +27,8 @@
#include <string.h>
#include <unistd.h>
-#include "sd-daemon.h"
#include "sd-bus.h"
+#include "sd-daemon.h"
#include "alloc-util.h"
#include "bus-internal.h"
diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c
index 3ae46d8cfb..0a484d89fc 100644
--- a/src/core/audit-fd.c
+++ b/src/core/audit-fd.c
@@ -21,16 +21,17 @@
#include <errno.h>
+
#include "audit-fd.h"
#ifdef HAVE_AUDIT
-#include <stdbool.h>
#include <libaudit.h>
+#include <stdbool.h>
+#include "fd-util.h"
#include "log.h"
#include "util.h"
-#include "fd-util.h"
static bool initialized = false;
static int audit_fd;
diff --git a/src/core/automount.c b/src/core/automount.c
index 4c229247c5..85b7b4e842 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -148,6 +148,9 @@ static int automount_add_default_dependencies(Automount *a) {
assert(a);
+ if (!UNIT(a)->default_dependencies)
+ return 0;
+
if (UNIT(a)->manager->running_as != MANAGER_SYSTEM)
return 0;
@@ -219,11 +222,9 @@ static int automount_load(Unit *u) {
if (r < 0)
return r;
- if (UNIT(a)->default_dependencies) {
- r = automount_add_default_dependencies(a);
- if (r < 0)
- return r;
- }
+ r = automount_add_default_dependencies(a);
+ if (r < 0)
+ return r;
}
return automount_verify(a);
@@ -727,8 +728,7 @@ static void automount_enter_runnning(Automount *a) {
if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
log_unit_info(UNIT(a), "Automount point already active?");
else {
- r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
- JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
goto fail;
@@ -973,7 +973,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
break;
}
- r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
goto fail;
diff --git a/src/core/busname.c b/src/core/busname.c
index 68508e20d2..04fa12a4da 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -596,7 +596,7 @@ static void busname_enter_running(BusName *n) {
goto fail;
}
- r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
}
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index bed01fde21..d122175417 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -217,7 +217,7 @@ static int whitelist_device(const char *path, const char *node, const char *acc)
r = cg_set_attribute("devices", path, "devices.allow", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set devices.allow on %s: %m", path);
return r;
@@ -288,7 +288,7 @@ static int whitelist_major(const char *path, const char *name, char type, const
r = cg_set_attribute("devices", path, "devices.allow", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set devices.allow on %s: %m", path);
}
@@ -328,13 +328,13 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT);
r = cg_set_attribute("cpu", path, "cpu.shares", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set cpu.shares on %s: %m", path);
sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set cpu.cfs_period_us on %s: %m", path);
if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
@@ -343,7 +343,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
} else
r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set cpu.cfs_quota_us on %s: %m", path);
}
@@ -359,7 +359,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT);
r = cg_set_attribute("blkio", path, "blkio.weight", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.weight on %s: %m", path);
/* FIXME: no way to reset this list */
@@ -373,7 +373,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.weight_device on %s: %m", path);
}
}
@@ -392,7 +392,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
r = cg_set_attribute("blkio", path, a, buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set %s on %s: %m", a, path);
}
}
@@ -416,7 +416,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
}
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set memory.limit_in_bytes/memory.max on %s: %m", path);
}
@@ -432,7 +432,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
else
r = cg_set_attribute("devices", path, "devices.allow", "a");
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to reset devices.list on %s: %m", path);
if (c->device_policy == CGROUP_CLOSED ||
@@ -494,7 +494,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
r = cg_set_attribute("pids", path, "pids.max", "max");
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set pids.max on %s: %m", path);
}
@@ -505,7 +505,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
r = cg_set_attribute("net_cls", path, "net_cls.classid", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set net_cls.classid on %s: %m", path);
}
}
diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c
index 45f2c2ffd6..54830a515b 100644
--- a/src/core/dbus-automount.c
+++ b/src/core/dbus-automount.c
@@ -21,8 +21,8 @@
#include "automount.h"
#include "bus-util.h"
-#include "string-util.h"
#include "dbus-automount.h"
+#include "string-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult);
diff --git a/src/core/dbus-busname.c b/src/core/dbus-busname.c
index 05ac89c3c0..445b237643 100644
--- a/src/core/dbus-busname.c
+++ b/src/core/dbus-busname.c
@@ -21,9 +21,9 @@
#include "bus-util.h"
#include "busname.h"
+#include "dbus-busname.h"
#include "string-util.h"
#include "unit.h"
-#include "dbus-busname.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, busname_result, BusNameResult);
diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c
index cb156fd37c..97e4a47556 100644
--- a/src/core/dbus-device.c
+++ b/src/core/dbus-device.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unit.h"
-#include "device.h"
#include "dbus-device.h"
+#include "device.h"
+#include "unit.h"
const sd_bus_vtable bus_device_vtable[] = {
SD_BUS_VTABLE_START(0),
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index db4206a523..093179c003 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -629,6 +629,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1289,6 +1290,38 @@ int bus_exec_context_set_transient_property(
return 1;
+ } else if (streq(name, "PassEnvironment")) {
+
+ _cleanup_strv_free_ char **l = NULL;
+
+ r = sd_bus_message_read_strv(message, &l);
+ if (r < 0)
+ return r;
+
+ if (!strv_env_name_is_valid(l))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block.");
+
+ if (mode != UNIT_CHECK) {
+ if (strv_isempty(l)) {
+ c->pass_environment = strv_free(c->pass_environment);
+ unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=\n");
+ } else {
+ _cleanup_free_ char *joined = NULL;
+
+ r = strv_extend_strv(&c->pass_environment, l, true);
+ if (r < 0)
+ return r;
+
+ joined = strv_join_quoted(c->pass_environment);
+ if (!joined)
+ return -ENOMEM;
+
+ unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s\n", joined);
+ }
+ }
+
+ return 1;
+
} else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
_cleanup_strv_free_ char **l = NULL;
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index 3b8116281c..c633eb1b76 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -19,11 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "signal-util.h"
#include "bus-util.h"
-
-#include "kill.h"
#include "dbus-kill.h"
+#include "kill.h"
+#include "signal-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 1f9f25093d..67e4e8b218 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -31,7 +31,6 @@
#include "dbus-execute.h"
#include "dbus-job.h"
#include "dbus-manager.h"
-#include "dbus-snapshot.h"
#include "dbus-unit.h"
#include "dbus.h"
#include "env-util.h"
@@ -656,7 +655,18 @@ static int transient_unit_from_message(
if (r < 0)
return r;
- if (u->load_state != UNIT_NOT_FOUND ||
+ /* Check if the unit already exists or is already referenced,
+ * in a number of different ways. Note that to cater for unit
+ * types such as slice, we are generally fine with units that
+ * are marked UNIT_LOADED even even though nothing was
+ * actually loaded, as those unit types don't require a file
+ * on disk to validly load. */
+
+ if (!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) ||
+ u->fragment_path ||
+ u->source_path ||
+ !strv_isempty(u->dropin_paths) ||
+ u->refs ||
set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
@@ -1101,66 +1111,8 @@ static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *er
return sd_bus_reply_method_return(message, "s", dump);
}
-static int method_create_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_free_ char *path = NULL;
- Manager *m = userdata;
- const char *name;
- int cleanup;
- Snapshot *s = NULL;
- int r;
-
- assert(message);
- assert(m);
-
- r = mac_selinux_access_check(message, "start", error);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(message, "sb", &name, &cleanup);
- if (r < 0)
- return r;
-
- if (isempty(name))
- name = NULL;
-
- r = bus_verify_manage_units_async(m, message, error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
-
- r = snapshot_create(m, name, cleanup, error, &s);
- if (r < 0)
- return r;
-
- path = unit_dbus_path(UNIT(s));
- if (!path)
- return -ENOMEM;
-
- return sd_bus_reply_method_return(message, "o", path);
-}
-
-static int method_remove_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- const char *name;
- Unit *u;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- u = manager_get_unit(m, name);
- if (!u)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
-
- if (u->type != UNIT_SNAPSHOT)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
-
- return bus_snapshot_method_remove(message, u, error);
+static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
}
static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -1580,9 +1532,9 @@ static int method_get_unit_file_state(sd_bus_message *message, void *userdata, s
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
- state = unit_file_get_state(scope, NULL, name);
- if (state < 0)
- return state;
+ r = unit_file_get_state(scope, NULL, name, &state);
+ if (r < 0)
+ return r;
return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
}
@@ -1710,6 +1662,8 @@ static int method_enable_unit_files_generic(
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
+ if (r == -ESHUTDOWN)
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked");
if (r < 0)
return r;
@@ -1944,6 +1898,8 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
+ if (r == -ESHUTDOWN)
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked");
if (r < 0)
return r;
@@ -2015,6 +1971,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2042,8 +1999,8 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 0c91850c52..bc5751a10d 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -23,10 +23,10 @@
#include "dbus-cgroup.h"
#include "dbus-execute.h"
#include "dbus-kill.h"
+#include "dbus-mount.h"
#include "mount.h"
#include "string-util.h"
#include "unit.h"
-#include "dbus-mount.h"
static int property_get_what(
sd_bus *bus,
@@ -118,7 +118,6 @@ const sd_bus_vtable bus_mount_vtable[] = {
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SmackFileSystemRootLabel", "s", NULL, offsetof(Mount, smack_fs_root_label), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c
index 9e32b5fb06..e0544e9161 100644
--- a/src/core/dbus-path.c
+++ b/src/core/dbus-path.c
@@ -20,10 +20,10 @@
***/
#include "bus-util.h"
+#include "dbus-path.h"
#include "path.h"
#include "string-util.h"
#include "unit.h"
-#include "dbus-path.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult);
diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c
index 09e78d1f33..469e3e1c93 100644
--- a/src/core/dbus-slice.c
+++ b/src/core/dbus-slice.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unit.h"
-#include "slice.h"
#include "dbus-cgroup.h"
#include "dbus-slice.h"
+#include "slice.h"
+#include "unit.h"
const sd_bus_vtable bus_slice_vtable[] = {
SD_BUS_VTABLE_START(0),
diff --git a/src/core/dbus-snapshot.c b/src/core/dbus-snapshot.c
deleted file mode 100644
index cfe44c9c15..0000000000
--- a/src/core/dbus-snapshot.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "selinux-access.h"
-#include "unit.h"
-#include "dbus.h"
-#include "snapshot.h"
-#include "dbus-snapshot.h"
-
-int bus_snapshot_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Snapshot *s = userdata;
- int r;
-
- assert(message);
- assert(s);
-
- r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error);
- if (r < 0)
- return r;
-
- r = bus_verify_manage_units_async(UNIT(s)->manager, message, error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
-
- snapshot_remove(s);
-
- return sd_bus_reply_method_return(message, NULL);
-}
-
-const sd_bus_vtable bus_snapshot_vtable[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("Cleanup", "b", bus_property_get_bool, offsetof(Snapshot, cleanup), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_METHOD("Remove", NULL, NULL, bus_snapshot_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_VTABLE_END
-};
diff --git a/src/core/dbus-snapshot.h b/src/core/dbus-snapshot.h
deleted file mode 100644
index 9288f44e15..0000000000
--- a/src/core/dbus-snapshot.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-extern const sd_bus_vtable bus_snapshot_vtable[];
-
-int bus_snapshot_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
index 603ca95fd9..f2a0f1d172 100644
--- a/src/core/dbus-swap.c
+++ b/src/core/dbus-swap.c
@@ -23,10 +23,10 @@
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
+#include "dbus-swap.h"
#include "string-util.h"
#include "swap.h"
#include "unit.h"
-#include "dbus-swap.h"
static int property_get_priority(
sd_bus *bus,
diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c
index 350f5c3ed2..654bcf1a29 100644
--- a/src/core/dbus-target.c
+++ b/src/core/dbus-target.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unit.h"
#include "dbus-target.h"
+#include "unit.h"
const sd_bus_vtable bus_target_vtable[] = {
SD_BUS_VTABLE_START(0),
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 6320cd1aa9..d9b7382c82 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -118,6 +118,22 @@ static int property_get_dependencies(
return sd_bus_message_close_container(reply);
}
+static int property_get_obsolete_dependencies(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ assert(bus);
+ assert(reply);
+
+ /* For dependency types we don't support anymore always return an empty array */
+ return sd_bus_message_append(reply, "as", 0);
+}
+
static int property_get_description(
sd_bus *bus,
const char *path,
@@ -621,16 +637,12 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -644,6 +656,10 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -671,7 +687,6 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -993,7 +1008,7 @@ int bus_unit_queue_job(
(type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
- r = manager_add_job(u->manager, type, u, mode, true, error, &j);
+ r = manager_add_job(u->manager, type, u, mode, error, &j);
if (r < 0)
return r;
@@ -1109,9 +1124,15 @@ static int bus_unit_set_transient_property(
UnitDependency d;
const char *other;
- d = unit_dependency_from_string(name);
- if (d < 0)
- return -EINVAL;
+ if (streq(name, "RequiresOverridable"))
+ d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
+ else if (streq(name, "RequisiteOverridable"))
+ d = UNIT_REQUISITE; /* same here */
+ else {
+ d = unit_dependency_from_string(name);
+ if (d < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit dependency: %s", name);
+ }
r = sd_bus_message_enter_container(message, 'a', "s");
if (r < 0)
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 6c44b28adf..7932130036 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -177,7 +177,7 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd
goto failed;
}
- r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, NULL);
if (r < 0)
goto failed;
diff --git a/src/core/device.c b/src/core/device.c
index 23ee7aee7e..bcd4d1146b 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -117,7 +117,6 @@ static void device_init(Unit *u) {
u->job_timeout = u->manager->default_timeout_start_usec;
u->ignore_on_isolate = true;
- u->ignore_on_snapshot = true;
}
static void device_done(Unit *u) {
@@ -602,7 +601,7 @@ static void device_shutdown(Manager *m) {
m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs);
}
-static int device_enumerate(Manager *m) {
+static void device_enumerate(Manager *m) {
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
@@ -612,7 +611,7 @@ static int device_enumerate(Manager *m) {
if (!m->udev_monitor) {
m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_monitor) {
- r = -ENOMEM;
+ log_oom();
goto fail;
}
@@ -622,37 +621,49 @@ static int device_enumerate(Manager *m) {
(void) udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to add udev tag match: %m");
goto fail;
+ }
r = udev_monitor_enable_receiving(m->udev_monitor);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to enable udev event reception: %m");
goto fail;
+ }
r = sd_event_add_io(m->event, &m->udev_event_source, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to watch udev file descriptor: %m");
goto fail;
+ }
(void) sd_event_source_set_description(m->udev_event_source, "device");
}
e = udev_enumerate_new(m->udev);
if (!e) {
- r = -ENOMEM;
+ log_oom();
goto fail;
}
r = udev_enumerate_add_match_tag(e, "systemd");
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to create udev tag enumeration: %m");
goto fail;
+ }
r = udev_enumerate_add_match_is_initialized(e);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to install initialization match into enumeration: %m");
goto fail;
+ }
r = udev_enumerate_scan_devices(e);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to enumerate devices: %m");
goto fail;
+ }
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
@@ -675,13 +686,10 @@ static int device_enumerate(Manager *m) {
device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false);
}
- return 0;
+ return;
fail:
- log_error_errno(r, "Failed to enumerate devices: %m");
-
device_shutdown(m);
- return r;
}
static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
diff --git a/src/core/execute.c b/src/core/execute.c
index d751065af0..07979bf8b3 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1332,6 +1332,34 @@ static int build_environment(
return 0;
}
+static int build_pass_environment(const ExecContext *c, char ***ret) {
+ _cleanup_strv_free_ char **pass_env = NULL;
+ size_t n_env = 0, n_bufsize = 0;
+ char **i;
+
+ STRV_FOREACH(i, c->pass_environment) {
+ _cleanup_free_ char *x = NULL;
+ char *v;
+
+ v = getenv(*i);
+ if (!v)
+ continue;
+ x = strjoin(*i, "=", v, NULL);
+ if (!x)
+ return -ENOMEM;
+ if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2))
+ return -ENOMEM;
+ pass_env[n_env++] = x;
+ pass_env[n_env] = NULL;
+ x = NULL;
+ }
+
+ *ret = pass_env;
+ pass_env = NULL;
+
+ return 0;
+}
+
static bool exec_needs_mount_namespace(
const ExecContext *context,
const ExecParameters *params,
@@ -1412,7 +1440,7 @@ static int exec_child(
char **files_env,
int *exit_status) {
- _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
+ _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
_cleanup_free_ char *mac_selinux_context_net = NULL;
const char *username = NULL, *home = NULL, *shell = NULL, *wd;
uid_t uid = UID_INVALID;
@@ -1928,9 +1956,16 @@ static int exec_child(
return r;
}
- final_env = strv_env_merge(5,
+ r = build_pass_environment(context, &pass_env);
+ if (r < 0) {
+ *exit_status = EXIT_MEMORY;
+ return r;
+ }
+
+ final_env = strv_env_merge(6,
params->environment,
our_env,
+ pass_env,
context->environment,
files_env,
pam_env,
@@ -2088,6 +2123,7 @@ void exec_context_done(ExecContext *c) {
c->environment = strv_free(c->environment);
c->environment_files = strv_free(c->environment_files);
+ c->pass_environment = strv_free(c->pass_environment);
for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
c->rlimit[l] = mfree(c->rlimit[l]);
@@ -2358,6 +2394,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
STRV_FOREACH(e, c->environment_files)
fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
+ STRV_FOREACH(e, c->pass_environment)
+ fprintf(f, "%sPassEnvironment: %s\n", prefix, *e);
+
fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode);
STRV_FOREACH(d, c->runtime_directory)
diff --git a/src/core/execute.h b/src/core/execute.h
index f8995a4203..1faff160cb 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -99,6 +99,7 @@ struct ExecRuntime {
struct ExecContext {
char **environment;
char **environment_files;
+ char **pass_environment;
struct rlimit *rlimit[_RLIMIT_MAX];
char *working_directory, *root_directory;
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index c7c95984b7..f67fb05af0 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -42,8 +42,6 @@ int failure_action(
FailureAction action,
const char *reboot_arg) {
- int r;
-
assert(m);
assert(action >= 0);
assert(action < _FAILURE_ACTION_MAX);
@@ -62,18 +60,13 @@ int failure_action(
switch (action) {
- case FAILURE_ACTION_REBOOT: {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-
+ case FAILURE_ACTION_REBOOT:
log_and_status(m, "Rebooting as result of failure.");
update_reboot_param_file(reboot_arg);
- r = manager_add_job_by_name(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, true, &error, NULL);
- if (r < 0)
- log_error("Failed to reboot: %s.", bus_error_message(&error, r));
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, NULL);
break;
- }
case FAILURE_ACTION_REBOOT_FORCE:
log_and_status(m, "Forcibly rebooting as result of failure.");
@@ -96,17 +89,10 @@ int failure_action(
reboot(RB_AUTOBOOT);
break;
- case FAILURE_ACTION_POWEROFF: {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-
+ case FAILURE_ACTION_POWEROFF:
log_and_status(m, "Powering off as result of failure.");
-
- r = manager_add_job_by_name(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, true, &error, NULL);
- if (r < 0)
- log_error("Failed to poweroff: %s.", bus_error_message(&error, r));
-
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, NULL);
break;
- }
case FAILURE_ACTION_POWEROFF_FORCE:
log_and_status(m, "Forcibly powering off as result of failure.");
diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c
index 3645f9c515..d92a9a764f 100644
--- a/src/core/hostname-setup.c
+++ b/src/core/hostname-setup.c
@@ -25,12 +25,12 @@
#include "alloc-util.h"
#include "fileio.h"
+#include "hostname-setup.h"
#include "hostname-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "util.h"
-#include "hostname-setup.h"
int hostname_setup(void) {
int r;
diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c
index 9572fa17d9..4f42ae6f31 100644
--- a/src/core/ima-setup.c
+++ b/src/core/ima-setup.c
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <errno.h>
+#include <unistd.h>
#include "fd-util.h"
#include "fileio.h"
diff --git a/src/core/job.c b/src/core/job.c
index 120381fc3b..53e0947215 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -175,7 +175,6 @@ static void job_merge_into_installed(Job *j, Job *other) {
else
assert(other->type == JOB_NOP);
- j->override = j->override || other->override;
j->irreversible = j->irreversible || other->irreversible;
j->ignore_order = j->ignore_order || other->ignore_order;
}
@@ -307,12 +306,10 @@ void job_dump(Job *j, FILE*f, const char *prefix) {
"%s-> Job %u:\n"
"%s\tAction: %s -> %s\n"
"%s\tState: %s\n"
- "%s\tForced: %s\n"
"%s\tIrreversible: %s\n",
prefix, j->id,
prefix, j->unit->id, job_type_to_string(j->type),
prefix, job_state_to_string(j->state),
- prefix, yes_no(j->override),
prefix, yes_no(j->irreversible));
}
@@ -841,8 +838,6 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
job_fail_dependencies(u, UNIT_REQUIRED_BY);
job_fail_dependencies(u, UNIT_REQUISITE_OF);
job_fail_dependencies(u, UNIT_BOUND_BY);
- job_fail_dependencies(u, UNIT_REQUIRED_BY_OVERRIDABLE);
- job_fail_dependencies(u, UNIT_REQUISITE_OF_OVERRIDABLE);
} else if (t == JOB_STOP)
job_fail_dependencies(u, UNIT_CONFLICTED_BY);
}
@@ -967,7 +962,6 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
fprintf(f, "job-id=%u\n", j->id);
fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
- fprintf(f, "job-override=%s\n", yes_no(j->override));
fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
@@ -1035,15 +1029,6 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
else
job_set_state(j, s);
- } else if (streq(l, "job-override")) {
- int b;
-
- b = parse_boolean(v);
- if (b < 0)
- log_debug("Failed to parse job override flag %s", v);
- else
- j->override = j->override || b;
-
} else if (streq(l, "job-irreversible")) {
int b;
diff --git a/src/core/job.h b/src/core/job.h
index 350e9f385f..60d8bd4f3e 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -162,7 +162,6 @@ struct Job {
bool installed:1;
bool in_run_queue:1;
bool matters_to_anchor:1;
- bool override:1;
bool in_dbus_queue:1;
bool sent_dbus_new_signal:1;
bool ignore_order:1;
diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
index 651f79a1fe..a6ab8cf4b3 100644
--- a/src/core/kmod-setup.c
+++ b/src/core/kmod-setup.c
@@ -19,17 +19,17 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <string.h>
+#include <unistd.h>
#ifdef HAVE_KMOD
#include <libkmod.h>
#endif
-#include "macro.h"
-#include "capability-util.h"
#include "bus-util.h"
+#include "capability-util.h"
#include "kmod-setup.h"
+#include "macro.h"
#ifdef HAVE_KMOD
static void systemd_kmod_log(
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index 11566af51b..3fa66f91aa 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -20,13 +20,13 @@
***/
-#include "unit.h"
+#include "conf-parser.h"
#include "load-dropin.h"
+#include "load-fragment.h"
#include "log.h"
#include "strv.h"
#include "unit-name.h"
-#include "conf-parser.h"
-#include "load-fragment.h"
+#include "unit.h"
static int add_dependency_consumer(
UnitDependency dependency,
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 75388659e3..799418033d 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -33,6 +33,7 @@ $1.CPUAffinity, config_parse_exec_cpu_affinity, 0,
$1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask)
$1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment)
$1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files)
+$1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment)
$1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input)
$1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output)
$1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error)
@@ -125,7 +126,7 @@ $1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0,
$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting)
-$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context)
+$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max)
$1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate)
$1.NetClass, config_parse_netclass, 0, offsetof($1, cgroup_context)'
)m4_dnl
@@ -133,9 +134,7 @@ Unit.Description, config_parse_unit_string_printf, 0,
Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
Unit.SourcePath, config_parse_path, 0, offsetof(Unit, source_path)
Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
-Unit.RequiresOverridable, config_parse_unit_deps, UNIT_REQUIRES_OVERRIDABLE, 0
Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
-Unit.RequisiteOverridable, config_parse_unit_deps, UNIT_REQUISITE_OVERRIDABLE, 0
Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0
Unit.BindsTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
Unit.BindTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
@@ -149,6 +148,8 @@ Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD
Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0
Unit.JoinsNamespaceOf, config_parse_unit_deps, UNIT_JOINS_NAMESPACE_OF, 0
+Unit.RequiresOverridable, config_parse_obsolete_unit_deps, UNIT_REQUIRES, 0
+Unit.RequisiteOverridable, config_parse_obsolete_unit_deps, UNIT_REQUISITE, 0
Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0
Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded)
Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start)
@@ -158,7 +159,7 @@ Unit.DefaultDependencies, config_parse_bool, 0,
Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode)
Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, offsetof(Unit, on_failure_job_mode)
Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate)
-Unit.IgnoreOnSnapshot, config_parse_bool, 0, offsetof(Unit, ignore_on_snapshot)
+Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
Unit.JobTimeoutSec, config_parse_sec, 0, offsetof(Unit, job_timeout)
Unit.JobTimeoutAction, config_parse_failure_action, 0, offsetof(Unit, job_timeout_action)
Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg)
@@ -319,7 +320,6 @@ Mount.Type, config_parse_string, 0,
Mount.TimeoutSec, config_parse_sec, 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)
-Mount.SmackFileSystemRootLabel, config_parse_string, 0, offsetof(Mount, smack_fs_root_label)
EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 79cabd26e7..dda79267f7 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -32,8 +32,8 @@
#include <sys/resource.h>
#include <sys/stat.h>
-#include "alloc-util.h"
#include "af-list.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-util.h"
@@ -98,16 +98,17 @@ int config_parse_warn_compat(
return 0;
}
-int config_parse_unit_deps(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_unit_deps(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
UnitDependency d = ltype;
Unit *u = userdata;
@@ -122,7 +123,7 @@ int config_parse_unit_deps(const char *unit,
_cleanup_free_ char *word = NULL, *k = NULL;
int r;
- r = extract_first_word(&p, &word, NULL, 0);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
if (r == 0)
break;
if (r == -ENOMEM)
@@ -146,6 +147,24 @@ int config_parse_unit_deps(const char *unit,
return 0;
}
+int config_parse_obsolete_unit_deps(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Unit dependency type %s= is obsolete, replacing by %s=, please update your unit file", lvalue, unit_dependency_to_string(ltype));
+
+ return config_parse_unit_deps(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
+}
+
int config_parse_unit_string_printf(
const char *unit,
const char *filename,
@@ -2196,6 +2215,70 @@ int config_parse_environ(const char *unit,
return 0;
}
+int config_parse_pass_environ(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const char *whole_rvalue = rvalue;
+ char*** passenv = data;
+ _cleanup_strv_free_ char **n = NULL;
+ size_t nlen = 0, nbufsize = 0;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ *passenv = strv_free(*passenv);
+ return 0;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue);
+ break;
+ }
+
+ if (!env_name_is_valid(word)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Invalid environment name for %s, ignoring: %s", lvalue, word);
+ continue;
+ }
+
+ if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
+ return log_oom();
+ n[nlen++] = word;
+ n[nlen] = NULL;
+ word = NULL;
+ }
+
+ if (n) {
+ r = strv_extend_strv(passenv, n, true);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
int config_parse_ip_tos(const char *unit,
const char *filename,
unsigned line,
@@ -2908,12 +2991,11 @@ int config_parse_tasks_max(
void *data,
void *userdata) {
- CGroupContext *c = data;
- uint64_t u;
+ uint64_t *tasks_max = data, u;
int r;
if (isempty(rvalue) || streq(rvalue, "infinity")) {
- c->tasks_max = (uint64_t) -1;
+ *tasks_max = (uint64_t) -1;
return 0;
}
@@ -2923,7 +3005,7 @@ int config_parse_tasks_max(
return 0;
}
- c->tasks_max = u;
+ *tasks_max = u;
return 0;
}
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 0cf821289c..62300c10f9 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -31,6 +31,7 @@ void unit_dump_config_items(FILE *f);
int config_parse_warn_compat(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_obsolete_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_string_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_path_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
@@ -84,6 +85,7 @@ int config_parse_syscall_filter(const char *unit, const char *filename, unsigned
int config_parse_syscall_archs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_syscall_errno(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_pass_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c
index bd632131b9..4c8d920389 100644
--- a/src/core/locale-setup.c
+++ b/src/core/locale-setup.c
@@ -24,12 +24,12 @@
#include "env-util.h"
#include "fileio.h"
+#include "locale-setup.h"
#include "locale-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
#include "virt.h"
-#include "locale-setup.h"
int locale_setup(char ***environment) {
char **add;
diff --git a/src/core/main.c b/src/core/main.c
index a86080642d..97f904b031 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -37,8 +37,8 @@
#include <valgrind/valgrind.h>
#endif
-#include "sd-daemon.h"
#include "sd-bus.h"
+#include "sd-daemon.h"
#include "alloc-util.h"
#include "architecture.h"
@@ -125,7 +125,8 @@ static FILE* arg_serialization = NULL;
static bool arg_default_cpu_accounting = false;
static bool arg_default_blockio_accounting = false;
static bool arg_default_memory_accounting = false;
-static bool arg_default_tasks_accounting = false;
+static bool arg_default_tasks_accounting = true;
+static uint64_t arg_default_tasks_max = UINT64_C(512);
static void pager_open_if_enabled(void) {
@@ -657,7 +658,7 @@ static int parse_config_file(void) {
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
- { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
+ { "Manager", "DefaultLimitCPU", config_parse_sec_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
{ "Manager", "DefaultLimitFSIZE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] },
{ "Manager", "DefaultLimitDATA", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_DATA] },
{ "Manager", "DefaultLimitSTACK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_STACK] },
@@ -672,11 +673,12 @@ static int parse_config_file(void) {
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE] },
{ "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE] },
{ "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO] },
- { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
+ { "Manager", "DefaultLimitRTTIME", config_parse_usec_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
+ { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
{}
};
@@ -712,6 +714,7 @@ static void manager_set_defaults(Manager *m) {
m->default_blockio_accounting = arg_default_blockio_accounting;
m->default_memory_accounting = arg_default_memory_accounting;
m->default_tasks_accounting = arg_default_tasks_accounting;
+ m->default_tasks_max = arg_default_tasks_max;
manager_set_default_rlimits(m, arg_default_rlimit);
manager_environment_add(m, NULL, arg_default_environment);
@@ -1744,11 +1747,13 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
}
- r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, false, &error, &default_unit_job);
+ r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &default_unit_job);
if (r == -EPERM) {
log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
- r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
+ sd_bus_error_free(&error);
+
+ r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &default_unit_job);
if (r < 0) {
log_emergency("Failed to start default target: %s", bus_error_message(&error, r));
error_message = "Failed to start default target";
diff --git a/src/core/manager.c b/src/core/manager.c
index 7c3a020c4a..edff6758c5 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -486,7 +486,7 @@ static int manager_setup_signals(Manager *m) {
* later than notify_fd processing, so that the notify
* processing can still figure out to which process/service a
* message belongs, before we reap the process. */
- r = sd_event_source_set_priority(m->signal_event_source, -5);
+ r = sd_event_source_set_priority(m->signal_event_source, SD_EVENT_PRIORITY_NORMAL-5);
if (r < 0)
return r;
@@ -577,6 +577,8 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
m->running_as = running_as;
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
m->default_timer_accuracy_usec = USEC_PER_MINUTE;
+ m->default_tasks_accounting = true;
+ m->default_tasks_max = UINT64_C(512);
/* Prepare log fields we can use for structured logging */
m->unit_log_field = unit_log_fields[running_as];
@@ -734,7 +736,7 @@ static int manager_setup_notify(Manager *m) {
/* Process signals a bit earlier than SIGCHLD, so that we can
* still identify to which service an exit message belongs */
- r = sd_event_source_set_priority(m->notify_event_source, -7);
+ r = sd_event_source_set_priority(m->notify_event_source, SD_EVENT_PRIORITY_NORMAL-7);
if (r < 0)
return log_error_errno(r, "Failed to set priority of notify event source: %m");
@@ -993,8 +995,7 @@ Manager* manager_free(Manager *m) {
return NULL;
}
-int manager_enumerate(Manager *m) {
- int r = 0;
+void manager_enumerate(Manager *m) {
UnitType c;
assert(m);
@@ -1002,8 +1003,6 @@ int manager_enumerate(Manager *m) {
/* Let's ask every type to load all units from disk/kernel
* that it might know */
for (c = 0; c < _UNIT_TYPE_MAX; c++) {
- int q;
-
if (!unit_type_supported(c)) {
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue;
@@ -1012,13 +1011,10 @@ int manager_enumerate(Manager *m) {
if (!unit_vtable[c]->enumerate)
continue;
- q = unit_vtable[c]->enumerate(m);
- if (q < 0)
- r = q;
+ unit_vtable[c]->enumerate(m);
}
manager_dispatch_load_queue(m);
- return r;
}
static void manager_coldplug(Manager *m) {
@@ -1100,10 +1096,9 @@ fail:
}
-static int manager_distribute_fds(Manager *m, FDSet *fds) {
- Unit *u;
+static void manager_distribute_fds(Manager *m, FDSet *fds) {
Iterator i;
- int r;
+ Unit *u;
assert(m);
@@ -1112,14 +1107,11 @@ static int manager_distribute_fds(Manager *m, FDSet *fds) {
if (fdset_size(fds) <= 0)
break;
- if (UNIT_VTABLE(u)->distribute_fds) {
- r = UNIT_VTABLE(u)->distribute_fds(u, fds);
- if (r < 0)
- return r;
- }
- }
+ if (!UNIT_VTABLE(u)->distribute_fds)
+ continue;
- return 0;
+ UNIT_VTABLE(u)->distribute_fds(u, fds);
+ }
}
int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
@@ -1152,7 +1144,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
/* First, enumerate what we can from all config files */
dual_timestamp_get(&m->units_load_start_timestamp);
- r = manager_enumerate(m);
+ manager_enumerate(m);
dual_timestamp_get(&m->units_load_finish_timestamp);
/* Second, deserialize if there is something to deserialize */
@@ -1163,11 +1155,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
* useful to allow container managers to pass some file
* descriptors to us pre-initialized. This enables
* socket-based activation of entire containers. */
- if (fdset_size(fds) > 0) {
- q = manager_distribute_fds(m, fds);
- if (q < 0 && r == 0)
- r = q;
- }
+ manager_distribute_fds(m, fds);
/* We might have deserialized the notify fd, but if we didn't
* then let's create the bus now */
@@ -1197,7 +1185,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
return r;
}
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret) {
int r;
Transaction *tr;
@@ -1220,7 +1208,7 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
if (!tr)
return -ENOMEM;
- r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
+ r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, false,
mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
mode == JOB_IGNORE_DEPENDENCIES, e);
if (r < 0)
@@ -1252,7 +1240,7 @@ tr_abort:
return r;
}
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) {
Unit *unit;
int r;
@@ -1265,7 +1253,23 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode
if (r < 0)
return r;
- return manager_add_job(m, type, unit, mode, override, e, _ret);
+ return manager_add_job(m, type, unit, mode, e, ret);
+}
+
+int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(m);
+ assert(type < _JOB_TYPE_MAX);
+ assert(name);
+ assert(mode < _JOB_MODE_MAX);
+
+ r = manager_add_job_by_name(m, type, name, mode, &error, ret);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r));
+
+ return r;
}
Job *manager_get_job(Manager *m, uint32_t id) {
@@ -1701,7 +1705,7 @@ static int manager_start_target(Manager *m, const char *name, JobMode mode) {
log_debug("Activating special unit %s", name);
- r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL);
+ r = manager_add_job_by_name(m, JOB_START, name, mode, &error, NULL);
if (r < 0)
log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
@@ -2554,9 +2558,7 @@ int manager_reload(Manager *m) {
manager_build_unit_path_cache(m);
/* First, enumerate what we can from all config files */
- q = manager_enumerate(m);
- if (q < 0 && r >= 0)
- r = q;
+ manager_enumerate(m);
/* Second, deserialize our stored data */
q = manager_deserialize(m, f, fds);
diff --git a/src/core/manager.h b/src/core/manager.h
index 38d2770e97..b5b258f909 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -141,8 +141,6 @@ struct Manager {
sd_event_source *jobs_in_progress_event_source;
- unsigned n_snapshots;
-
LookupPaths lookup_paths;
Set *unit_path_cache;
@@ -262,6 +260,7 @@ struct Manager {
bool default_blockio_accounting;
bool default_tasks_accounting;
+ uint64_t default_tasks_max;
usec_t default_timer_accuracy_usec;
struct rlimit *rlimit[_RLIMIT_MAX];
@@ -316,7 +315,7 @@ struct Manager {
int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m);
Manager* manager_free(Manager *m);
-int manager_enumerate(Manager *m);
+void manager_enumerate(Manager *m);
int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
Job *manager_get_job(Manager *m, uint32_t id);
@@ -328,8 +327,9 @@ int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd
int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, sd_bus_error *e, Job **_ret);
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool force, sd_bus_error *e, Job **_ret);
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret);
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **_ret);
+int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret);
void manager_dump_units(Manager *s, FILE *f, const char *prefix);
void manager_dump_jobs(Manager *s, FILE *f, const char *prefix);
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index b2596d1cd1..2b8d590ed1 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -19,11 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/mount.h>
#include <errno.h>
+#include <ftw.h>
#include <stdlib.h>
+#include <sys/mount.h>
#include <unistd.h>
-#include <ftw.h>
#include "alloc-util.h"
#include "bus-util.h"
diff --git a/src/core/mount.c b/src/core/mount.c
index 950d5d76d5..9b44357e90 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -41,7 +41,6 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
-#include "smack-util.h"
#include "special.h"
#include "string-table.h"
#include "string-util.h"
@@ -211,7 +210,6 @@ static void mount_done(Unit *u) {
assert(m);
m->where = mfree(m->where);
- m->smack_fs_root_label = mfree(m->smack_fs_root_label);
mount_parameters_done(&m->parameters_proc_self_mountinfo);
mount_parameters_done(&m->parameters_fragment);
@@ -387,12 +385,15 @@ static bool should_umount(Mount *m) {
}
static int mount_add_default_dependencies(Mount *m) {
- const char *after, *after2, *online;
MountParameters *p;
+ const char *after;
int r;
assert(m);
+ if (!UNIT(m)->default_dependencies)
+ return 0;
+
if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
return 0;
@@ -413,30 +414,34 @@ static int mount_add_default_dependencies(Mount *m) {
return 0;
if (mount_is_network(p)) {
- after = SPECIAL_REMOTE_FS_PRE_TARGET;
- after2 = SPECIAL_NETWORK_TARGET;
- online = SPECIAL_NETWORK_ONLINE_TARGET;
- } else {
- after = SPECIAL_LOCAL_FS_PRE_TARGET;
- after2 = NULL;
- online = NULL;
- }
+ /* We order ourselves after network.target. This is
+ * primarily useful at shutdown: services that take
+ * down the network should order themselves before
+ * network.target, so that they are shut down only
+ * after this mount unit is stopped. */
- r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
- if (r < 0)
- return r;
-
- if (after2) {
- r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after2, NULL, true);
+ r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true);
if (r < 0)
return r;
- }
- if (online) {
- r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, online, NULL, true);
+ /* We pull in network-online.target, and order
+ * ourselves after it. This is useful at start-up to
+ * actively pull in tools that want to be started
+ * before we start mounting network file systems, and
+ * whose purpose it is to delay this until the network
+ * is "up". */
+
+ r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true);
if (r < 0)
return r;
- }
+
+ after = SPECIAL_REMOTE_FS_PRE_TARGET;
+ } else
+ after = SPECIAL_LOCAL_FS_PRE_TARGET;
+
+ r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
+ if (r < 0)
+ return r;
if (should_umount(m)) {
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
@@ -533,11 +538,9 @@ static int mount_add_extras(Mount *m) {
if (r < 0)
return r;
- if (u->default_dependencies) {
- r = mount_add_default_dependencies(m);
- if (r < 0)
- return r;
- }
+ r = mount_add_default_dependencies(m);
+ if (r < 0)
+ return r;
return 0;
}
@@ -677,8 +680,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
"%sOptions: %s\n"
"%sFrom /proc/self/mountinfo: %s\n"
"%sFrom fragment: %s\n"
- "%sDirectoryMode: %04o\n"
- "%sSmackFileSystemRootLabel: %s\n",
+ "%sDirectoryMode: %04o\n",
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
prefix, m->where,
@@ -687,8 +689,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
prefix, p ? strna(p->options) : "n/a",
prefix, yes_no(m->from_proc_self_mountinfo),
prefix, yes_no(m->from_fragment),
- prefix, m->directory_mode,
- prefix, strna(m->smack_fs_root_label));
+ prefix, m->directory_mode);
if (m->control_pid > 0)
fprintf(f,
@@ -865,29 +866,9 @@ fail:
mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
}
-static int mount_get_opts(Mount *m, char **_opts) {
- int r;
- char *o = NULL, *opts = NULL;
-
- r = fstab_filter_options(m->parameters_fragment.options,
- "nofail\0" "noauto\0" "auto\0", NULL, NULL, &o);
- if (r < 0)
- return r;
-
- if (mac_smack_use() && m->smack_fs_root_label) {
- if (!isempty(o)) {
- opts = strjoin(o, ",", "smackfsroot=", m->smack_fs_root_label, NULL);
- free(o);
- } else
- opts = strjoin("smackfsroot=", m->smack_fs_root_label, NULL);
-
- if (!opts)
- return -ENOMEM;
- } else
- opts = o;
-
- *_opts = opts;
- return 0;
+static int mount_get_opts(Mount *m, char **ret) {
+ return fstab_filter_options(m->parameters_fragment.options,
+ "nofail\0" "noauto\0" "auto\0", NULL, NULL, ret);
}
static void mount_enter_mounting(Mount *m) {
@@ -1596,7 +1577,7 @@ static int mount_get_timeout(Unit *u, uint64_t *timeout) {
return 1;
}
-static int mount_enumerate(Manager *m) {
+static void mount_enumerate(Manager *m) {
int r;
assert(m);
@@ -1608,29 +1589,40 @@ static int mount_enumerate(Manager *m) {
m->mount_monitor = mnt_new_monitor();
if (!m->mount_monitor) {
- r = -ENOMEM;
+ log_oom();
goto fail;
}
r = mnt_monitor_enable_kernel(m->mount_monitor, 1);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to enable watching of kernel mount events: %m");
goto fail;
+ }
+
r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to enable watching of userspace mount events: %m");
goto fail;
+ }
/* mnt_unref_monitor() will close the fd */
fd = r = mnt_monitor_get_fd(m->mount_monitor);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to acquire watch file descriptor: %m");
goto fail;
+ }
r = sd_event_add_io(m->event, &m->mount_event_source, fd, EPOLLIN, mount_dispatch_io, m);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to watch mount file descriptor: %m");
goto fail;
+ }
r = sd_event_source_set_priority(m->mount_event_source, -10);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to adjust mount watch priority: %m");
goto fail;
+ }
(void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");
}
@@ -1639,11 +1631,10 @@ static int mount_enumerate(Manager *m) {
if (r < 0)
goto fail;
- return 0;
+ return;
fail:
mount_shutdown(m);
- return r;
}
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
diff --git a/src/core/mount.h b/src/core/mount.h
index b344b5aa13..83d14ae713 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -71,7 +71,6 @@ struct Mount {
bool reset_cpu_usage:1;
bool sloppy_options;
- char *smack_fs_root_label;
MountResult result;
MountResult reload_result;
diff --git a/src/core/path.c b/src/core/path.c
index 35e1753583..02fb134bb9 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -315,20 +315,20 @@ static int path_add_default_dependencies(Path *p) {
assert(p);
- r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE,
- SPECIAL_PATHS_TARGET, NULL, true);
+ if (!UNIT(p)->default_dependencies)
+ return 0;
+
+ r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_PATHS_TARGET, NULL, true);
if (r < 0)
return r;
if (UNIT(p)->manager->running_as == MANAGER_SYSTEM) {
- r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_SYSINIT_TARGET, NULL, true);
+ r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
if (r < 0)
return r;
}
- return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS,
- SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
}
static int path_load(Unit *u) {
@@ -360,11 +360,9 @@ static int path_load(Unit *u) {
if (r < 0)
return r;
- if (UNIT(p)->default_dependencies) {
- r = path_add_default_dependencies(p);
- if (r < 0)
- return r;
- }
+ r = path_add_default_dependencies(p);
+ if (r < 0)
+ return r;
}
return path_verify(p);
@@ -476,8 +474,7 @@ static void path_enter_running(Path *p) {
if (unit_stop_pending(UNIT(p)))
return;
- r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)),
- JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
diff --git a/src/core/scope.c b/src/core/scope.c
index 6bacb226e8..1953af1f88 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -54,7 +54,6 @@ static void scope_init(Unit *u) {
s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
UNIT(s)->ignore_on_isolate = true;
- UNIT(s)->ignore_on_snapshot = true;
}
static void scope_done(Unit *u) {
@@ -123,6 +122,9 @@ static int scope_add_default_dependencies(Scope *s) {
assert(s);
+ if (!UNIT(s)->default_dependencies)
+ return 0;
+
/* Make sure scopes are unloaded on shutdown */
r = unit_add_two_dependencies_by_name(
UNIT(s),
@@ -174,11 +176,9 @@ static int scope_load(Unit *u) {
if (r < 0)
return r;
- if (u->default_dependencies) {
- r = scope_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ r = scope_add_default_dependencies(s);
+ if (r < 0)
+ return r;
return scope_verify(s);
}
@@ -402,15 +402,10 @@ static bool scope_check_gc(Unit *u) {
/* Never clean up scopes that still have a process around,
* even if the scope is formally dead. */
- if (u->cgroup_path) {
- int r;
+ if (!u->cgroup_path)
+ return false;
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
- if (r <= 0)
- return true;
- }
-
- return false;
+ return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path) <= 0;
}
static void scope_notify_cgroup_empty_event(Unit *u) {
@@ -510,7 +505,7 @@ _pure_ static const char *scope_sub_state_to_string(Unit *u) {
return scope_state_to_string(SCOPE(u)->state);
}
-static int scope_enumerate(Manager *m) {
+static void scope_enumerate(Manager *m) {
Unit *u;
int r;
@@ -524,13 +519,16 @@ static int scope_enumerate(Manager *m) {
u = manager_get_unit(m, SPECIAL_INIT_SCOPE);
if (!u) {
u = unit_new(m, sizeof(Scope));
- if (!u)
- return log_oom();
+ if (!u) {
+ log_oom();
+ return;
+ }
r = unit_add_name(u, SPECIAL_INIT_SCOPE);
if (r < 0) {
unit_free(u);
- return log_error_errno(r, "Failed to add init.scope name");
+ log_error_errno(r, "Failed to add init.scope name");
+ return;
}
}
@@ -551,8 +549,6 @@ static int scope_enumerate(Manager *m) {
unit_add_to_load_queue(u);
unit_add_to_dbus_queue(u);
-
- return 0;
}
static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
@@ -576,6 +572,7 @@ const UnitVTable scope_vtable = {
.no_alias = true,
.no_instances = true,
+ .can_transient = true,
.init = scope_init,
.load = scope_load,
@@ -610,7 +607,5 @@ const UnitVTable scope_vtable = {
.bus_set_property = bus_scope_set_property,
.bus_commit_properties = bus_scope_commit_properties,
- .can_transient = true,
-
.enumerate = scope_enumerate,
};
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index 4bcdd27389..8856927c88 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -23,10 +23,10 @@
#ifdef HAVE_SELINUX
-#include <stdio.h>
#include <errno.h>
-#include <selinux/selinux.h>
#include <selinux/avc.h>
+#include <selinux/selinux.h>
+#include <stdio.h>
#ifdef HAVE_AUDIT
#include <libaudit.h>
#endif
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index d9b00fb95c..d4757e0853 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -29,10 +29,10 @@
#include "log.h"
#include "macro.h"
+#include "selinux-setup.h"
#include "selinux-util.h"
#include "string-util.h"
#include "util.h"
-#include "selinux-setup.h"
#ifdef HAVE_SELINUX
_printf_(2,3)
diff --git a/src/core/service.c b/src/core/service.c
index 586eddd99a..c27b70fa3c 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -515,15 +515,38 @@ static int service_add_default_dependencies(Service *s) {
assert(s);
+ if (!UNIT(s)->default_dependencies)
+ return 0;
+
/* Add a number of automatic dependencies useful for the
* majority of services. */
- /* First, pull in base system */
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true);
+ if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) {
+ /* First, pull in the really early boot stuff, and
+ * require it, so that we fail if we can't acquire
+ * it. */
+
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
+ if (r < 0)
+ return r;
+ } else {
+
+ /* In the --user instance there's no sysinit.target,
+ * in that case require basic.target instead. */
+
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true);
+ if (r < 0)
+ return r;
+ }
+
+ /* Second, if the rest of the base system is in the same
+ * transaction, order us after it, but do not pull it in or
+ * even require it. */
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, NULL, true);
if (r < 0)
return r;
- /* Second, activate normal shutdown */
+ /* Third, add us in for normal shutdown. */
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
}
@@ -545,6 +568,43 @@ static void service_fix_output(Service *s) {
s->exec_context.std_output = UNIT(s)->manager->default_std_output;
}
+static int service_setup_bus_name(Service *s) {
+ int r;
+
+ assert(s);
+
+ if (!s->bus_name)
+ return 0;
+
+ if (is_kdbus_available()) {
+ const char *n;
+
+ n = strjoina(s->bus_name, ".busname");
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, n, NULL, true);
+ if (r < 0)
+ return log_unit_error_errno(UNIT(s), r, "Failed to add dependency to .busname unit: %m");
+
+ } else {
+ /* If kdbus is not available, we know the dbus socket is required, hence pull it in, and require it */
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true);
+ if (r < 0)
+ return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
+ }
+
+ /* Regardless if kdbus is used or not, we always want to be ordered against dbus.socket if both are in the transaction. */
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true);
+ if (r < 0)
+ return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
+
+ r = unit_watch_bus_name(UNIT(s), s->bus_name);
+ if (r == -EEXIST)
+ return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name);
+ if (r < 0)
+ return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name);
+
+ return 0;
+}
+
static int service_add_extras(Service *s) {
int r;
@@ -584,26 +644,13 @@ static int service_add_extras(Service *s) {
if (s->watchdog_usec > 0 && s->notify_access == NOTIFY_NONE)
s->notify_access = NOTIFY_MAIN;
- if (s->bus_name) {
- const char *n;
-
- n = strjoina(s->bus_name, ".busname");
- r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, n, NULL, true);
- if (r < 0)
- return r;
-
- r = unit_watch_bus_name(UNIT(s), s->bus_name);
- if (r == -EEXIST)
- return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name);
- if (r < 0)
- return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name);
- }
+ r = service_add_default_dependencies(s);
+ if (r < 0)
+ return r;
- if (UNIT(s)->default_dependencies) {
- r = service_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ r = service_setup_bus_name(s);
+ if (r < 0)
+ return r;
return 0;
}
@@ -1802,7 +1849,7 @@ static void service_enter_restart(Service *s) {
* restarted. We use JOB_RESTART (instead of the more obvious
* JOB_START) here so that those dependency jobs will be added
* as well. */
- r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_FAIL, false, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_FAIL, &error, NULL);
if (r < 0)
goto fail;
@@ -2365,14 +2412,6 @@ static bool service_check_gc(Unit *u) {
return false;
}
-_pure_ static bool service_check_snapshot(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- return s->socket_fd < 0;
-}
-
static int service_retry_pid_file(Service *s) {
int r;
@@ -3294,7 +3333,6 @@ const UnitVTable service_vtable = {
.sub_state_to_string = service_sub_state_to_string,
.check_gc = service_check_gc,
- .check_snapshot = service_check_snapshot,
.sigchld_event = service_sigchld_event,
diff --git a/src/core/slice.c b/src/core/slice.c
index 4602144150..06ac6f8450 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -24,12 +24,12 @@
#include "alloc-util.h"
#include "dbus-slice.h"
#include "log.h"
+#include "slice.h"
#include "special.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
#include "unit.h"
-#include "slice.h"
static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
[SLICE_DEAD] = UNIT_INACTIVE,
@@ -85,6 +85,9 @@ static int slice_add_default_dependencies(Slice *s) {
assert(s);
+ if (!UNIT(s)->default_dependencies)
+ return 0;
+
/* Make sure slices are unloaded on shutdown */
r = unit_add_two_dependencies_by_name(
UNIT(s),
@@ -96,7 +99,6 @@ static int slice_add_default_dependencies(Slice *s) {
return 0;
}
-
static int slice_verify(Slice *s) {
_cleanup_free_ char *parent = NULL;
int r;
@@ -144,11 +146,9 @@ static int slice_load(Unit *u) {
if (r < 0)
return r;
- if (u->default_dependencies) {
- r = slice_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ r = slice_add_default_dependencies(s);
+ if (r < 0)
+ return r;
}
return slice_verify(s);
@@ -255,7 +255,7 @@ _pure_ static const char *slice_sub_state_to_string(Unit *u) {
return slice_state_to_string(SLICE(u)->state);
}
-static int slice_enumerate(Manager *m) {
+static void slice_enumerate(Manager *m) {
Unit *u;
int r;
@@ -264,13 +264,16 @@ static int slice_enumerate(Manager *m) {
u = manager_get_unit(m, SPECIAL_ROOT_SLICE);
if (!u) {
u = unit_new(m, sizeof(Slice));
- if (!u)
- return log_oom();
+ if (!u) {
+ log_oom();
+ return;
+ }
r = unit_add_name(u, SPECIAL_ROOT_SLICE);
if (r < 0) {
unit_free(u);
- return log_error_errno(r, "Failed to add -.slice name");
+ log_error_errno(r, "Failed to add -.slice name");
+ return;
}
}
@@ -288,8 +291,6 @@ static int slice_enumerate(Manager *m) {
unit_add_to_load_queue(u);
unit_add_to_dbus_queue(u);
-
- return 0;
}
const UnitVTable slice_vtable = {
@@ -304,6 +305,7 @@ const UnitVTable slice_vtable = {
.no_alias = true,
.no_instances = true,
+ .can_transient = true,
.load = slice_load,
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
deleted file mode 100644
index ba3135f401..0000000000
--- a/src/core/snapshot.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-
-#include "alloc-util.h"
-#include "bus-common-errors.h"
-#include "dbus-snapshot.h"
-#include "parse-util.h"
-#include "parse-util.h"
-#include "snapshot.h"
-#include "string-util.h"
-#include "unit-name.h"
-#include "unit.h"
-
-static const UnitActiveState state_translation_table[_SNAPSHOT_STATE_MAX] = {
- [SNAPSHOT_DEAD] = UNIT_INACTIVE,
- [SNAPSHOT_ACTIVE] = UNIT_ACTIVE
-};
-
-static void snapshot_init(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(UNIT(s)->load_state == UNIT_STUB);
-
- UNIT(s)->ignore_on_isolate = true;
- UNIT(s)->ignore_on_snapshot = true;
- UNIT(s)->allow_isolate = true;
-}
-
-static void snapshot_set_state(Snapshot *s, SnapshotState state) {
- SnapshotState old_state;
- assert(s);
-
- old_state = s->state;
- s->state = state;
-
- if (state != old_state)
- log_unit_debug(UNIT(s), "Changed %s -> %s", snapshot_state_to_string(old_state), snapshot_state_to_string(state));
-
- unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static int snapshot_load(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- /* Make sure that only snapshots created via snapshot_create()
- * can be loaded */
- if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
- return -ENOENT;
-
- u->load_state = UNIT_LOADED;
- return 0;
-}
-
-static int snapshot_coldplug(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(s->state == SNAPSHOT_DEAD);
-
- if (s->deserialized_state != s->state)
- snapshot_set_state(s, s->deserialized_state);
-
- return 0;
-}
-
-static void snapshot_dump(Unit *u, FILE *f, const char *prefix) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(f);
-
- fprintf(f,
- "%sSnapshot State: %s\n"
- "%sClean Up: %s\n",
- prefix, snapshot_state_to_string(s->state),
- prefix, yes_no(s->cleanup));
-}
-
-static int snapshot_start(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(s->state == SNAPSHOT_DEAD);
-
- snapshot_set_state(s, SNAPSHOT_ACTIVE);
-
- if (s->cleanup)
- unit_add_to_cleanup_queue(u);
-
- return 1;
-}
-
-static int snapshot_stop(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(s->state == SNAPSHOT_ACTIVE);
-
- snapshot_set_state(s, SNAPSHOT_DEAD);
- return 1;
-}
-
-static int snapshot_serialize(Unit *u, FILE *f, FDSet *fds) {
- Snapshot *s = SNAPSHOT(u);
- Unit *other;
- Iterator i;
-
- assert(s);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", snapshot_state_to_string(s->state));
- unit_serialize_item(u, f, "cleanup", yes_no(s->cleanup));
- SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
- unit_serialize_item(u, f, "wants", other->id);
-
- return 0;
-}
-
-static int snapshot_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Snapshot *s = SNAPSHOT(u);
- int r;
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- SnapshotState state;
-
- state = snapshot_state_from_string(value);
- if (state < 0)
- log_unit_debug(u, "Failed to parse state value: %s", value);
- else
- s->deserialized_state = state;
-
- } else if (streq(key, "cleanup")) {
-
- r = parse_boolean(value);
- if (r < 0)
- log_unit_debug(u, "Failed to parse cleanup value: %s", value);
- else
- s->cleanup = r;
-
- } else if (streq(key, "wants")) {
-
- r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, value, NULL, true);
- if (r < 0)
- return r;
- } else
- log_unit_debug(u, "Unknown serialization key: %s", key);
-
- return 0;
-}
-
-_pure_ static UnitActiveState snapshot_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[SNAPSHOT(u)->state];
-}
-
-_pure_ static const char *snapshot_sub_state_to_string(Unit *u) {
- assert(u);
-
- return snapshot_state_to_string(SNAPSHOT(u)->state);
-}
-
-int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **_s) {
- _cleanup_free_ char *n = NULL;
- Unit *other, *u = NULL;
- Iterator i;
- int r;
- const char *k;
-
- assert(m);
- assert(_s);
-
- if (name) {
- if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
- return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
-
- if (!endswith(name, ".snapshot"))
- return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
-
- if (manager_get_unit(m, name))
- return sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
-
- } else {
-
- for (;;) {
- if (asprintf(&n, "snapshot-%u.snapshot", ++ m->n_snapshots) < 0)
- return -ENOMEM;
-
- if (!manager_get_unit(m, n)) {
- name = n;
- break;
- }
-
- n = mfree(n);
- }
- }
-
- r = manager_load_unit_prepare(m, name, NULL, e, &u);
- if (r < 0)
- goto fail;
-
- u->transient = true;
- manager_dispatch_load_queue(m);
- assert(u->load_state == UNIT_LOADED);
-
- HASHMAP_FOREACH_KEY(other, k, m->units, i) {
-
- if (other->ignore_on_snapshot ||
- other->transient)
- continue;
-
- if (k != other->id)
- continue;
-
- if (UNIT_VTABLE(other)->check_snapshot)
- if (!UNIT_VTABLE(other)->check_snapshot(other))
- continue;
-
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- continue;
-
- r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, other, true);
- if (r < 0)
- goto fail;
- }
-
- SNAPSHOT(u)->cleanup = cleanup;
- *_s = SNAPSHOT(u);
-
- log_unit_info(u, "Created snapshot.");
-
- return 0;
-
-fail:
- if (u)
- unit_add_to_cleanup_queue(u);
-
- return r;
-}
-
-void snapshot_remove(Snapshot *s) {
- assert(s);
-
- log_unit_info(UNIT(s), "Removing snapshot.");
-
- unit_add_to_cleanup_queue(UNIT(s));
-}
-
-const UnitVTable snapshot_vtable = {
- .object_size = sizeof(Snapshot),
-
- .no_alias = true,
- .no_instances = true,
- .no_gc = true,
-
- .init = snapshot_init,
- .load = snapshot_load,
-
- .coldplug = snapshot_coldplug,
-
- .dump = snapshot_dump,
-
- .start = snapshot_start,
- .stop = snapshot_stop,
-
- .serialize = snapshot_serialize,
- .deserialize_item = snapshot_deserialize_item,
-
- .active_state = snapshot_active_state,
- .sub_state_to_string = snapshot_sub_state_to_string,
-
- .bus_vtable = bus_snapshot_vtable
-};
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
deleted file mode 100644
index bd52dea408..0000000000
--- a/src/core/snapshot.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct Snapshot Snapshot;
-
-#include "unit.h"
-
-struct Snapshot {
- Unit meta;
-
- SnapshotState state, deserialized_state;
-
- bool cleanup;
-};
-
-extern const UnitVTable snapshot_vtable;
-
-int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **s);
-void snapshot_remove(Snapshot *s);
diff --git a/src/core/socket.c b/src/core/socket.c
index 3c7f972fbc..5b9e32ce9d 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -296,6 +296,9 @@ static int socket_add_default_dependencies(Socket *s) {
int r;
assert(s);
+ if (!UNIT(s)->default_dependencies)
+ return 0;
+
r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SOCKETS_TARGET, NULL, true);
if (r < 0)
return r;
@@ -365,11 +368,9 @@ static int socket_add_extras(Socket *s) {
return r;
}
- if (u->default_dependencies) {
- r = socket_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ r = socket_add_default_dependencies(s);
+ if (r < 0)
+ return r;
return 0;
}
@@ -1920,7 +1921,7 @@ static void socket_enter_running(Socket *s, int cfd) {
goto fail;
}
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
}
@@ -1978,7 +1979,7 @@ static void socket_enter_running(Socket *s, int cfd) {
cfd = -1;
s->n_connections ++;
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
@@ -2332,7 +2333,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
return 0;
}
-static int socket_distribute_fds(Unit *u, FDSet *fds) {
+static void socket_distribute_fds(Unit *u, FDSet *fds) {
Socket *s = SOCKET(u);
SocketPort *p;
@@ -2356,8 +2357,6 @@ static int socket_distribute_fds(Unit *u, FDSet *fds) {
}
}
}
-
- return 0;
}
_pure_ static UnitActiveState socket_active_state(Unit *u) {
diff --git a/src/core/swap.c b/src/core/swap.c
index baaa27b6a3..ee0838e676 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -213,6 +213,9 @@ static int swap_add_device_links(Swap *s) {
static int swap_add_default_dependencies(Swap *s) {
assert(s);
+ if (!UNIT(s)->default_dependencies)
+ return 0;
+
if (UNIT(s)->manager->running_as != MANAGER_SYSTEM)
return 0;
@@ -331,11 +334,9 @@ static int swap_load(Unit *u) {
if (r < 0)
return r;
- if (UNIT(s)->default_dependencies) {
- r = swap_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ r = swap_add_default_dependencies(s);
+ if (r < 0)
+ return r;
}
return swap_verify(s);
@@ -1268,26 +1269,36 @@ static void swap_shutdown(Manager *m) {
m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
}
-static int swap_enumerate(Manager *m) {
+static void swap_enumerate(Manager *m) {
int r;
assert(m);
if (!m->proc_swaps) {
m->proc_swaps = fopen("/proc/swaps", "re");
- if (!m->proc_swaps)
- return errno == ENOENT ? 0 : -errno;
+ if (!m->proc_swaps) {
+ if (errno == ENOENT)
+ log_debug("Not swap enabled, skipping enumeration");
+ else
+ log_error_errno(errno, "Failed to open /proc/swaps: %m");
+
+ return;
+ }
r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to watch /proc/swaps: %m");
goto fail;
+ }
/* Dispatch this before we dispatch SIGCHLD, so that
* we always get the events from /proc/swaps before
* the SIGCHLD of /sbin/swapon. */
r = sd_event_source_set_priority(m->swap_event_source, -10);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to change /proc/swaps priority: %m");
goto fail;
+ }
(void) sd_event_source_set_description(m->swap_event_source, "swap-proc");
}
@@ -1296,11 +1307,10 @@ static int swap_enumerate(Manager *m) {
if (r < 0)
goto fail;
- return 0;
+ return;
fail:
swap_shutdown(m);
- return r;
}
int swap_process_device_new(Manager *m, struct udev_device *dev) {
diff --git a/src/core/system.conf b/src/core/system.conf
index 50668e12c4..e2ded27333 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -40,7 +40,8 @@
#DefaultCPUAccounting=no
#DefaultBlockIOAccounting=no
#DefaultMemoryAccounting=no
-#DefaultTasksAccounting=no
+#DefaultTasksAccounting=yes
+#DefaultTasksMax=512
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=
diff --git a/src/core/target.c b/src/core/target.c
index c3e79fffc8..14f9b2e26a 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -52,9 +52,7 @@ static int target_add_default_dependencies(Target *t) {
static const UnitDependency deps[] = {
UNIT_REQUIRES,
- UNIT_REQUIRES_OVERRIDABLE,
UNIT_REQUISITE,
- UNIT_REQUISITE_OVERRIDABLE,
UNIT_WANTS,
UNIT_BINDS_TO,
UNIT_PART_OF
diff --git a/src/core/timer.c b/src/core/timer.c
index c9dc97d4fb..51b1d875be 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -102,6 +102,9 @@ static int timer_add_default_dependencies(Timer *t) {
assert(t);
+ if (!UNIT(t)->default_dependencies)
+ return 0;
+
r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, NULL, true);
if (r < 0)
return r;
@@ -192,11 +195,9 @@ static int timer_load(Unit *u) {
if (r < 0)
return r;
- if (u->default_dependencies) {
- r = timer_add_default_dependencies(t);
- if (r < 0)
- return r;
- }
+ r = timer_add_default_dependencies(t);
+ if (r < 0)
+ return r;
}
return timer_verify(t);
@@ -510,15 +511,14 @@ static void timer_enter_running(Timer *t) {
if (unit_stop_pending(UNIT(t)))
return;
- r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
- JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
dual_timestamp_get(&t->last_trigger);
if (t->stamp_path)
- touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, 0);
+ touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID);
timer_set_state(t, TIMER_RUNNING);
return;
@@ -554,7 +554,7 @@ static int timer_start(Unit *u) {
/* The timer has never run before,
* make sure a stamp file exists.
*/
- touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
+ touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
}
t->result = TIMER_SUCCESS;
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 69f28c902f..15e79d00b3 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <fcntl.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "bus-common-errors.h"
@@ -99,9 +99,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
j->type = t;
j->state = JOB_WAITING;
- j->override = j->override || other->override;
j->irreversible = j->irreversible || other->irreversible;
-
j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
/* Patch us in as new owner of the JobDependency objects */
@@ -745,7 +743,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error
return 0;
}
-static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool override, bool *is_new) {
+static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool *is_new) {
Job *j, *f;
assert(tr);
@@ -774,7 +772,6 @@ static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, b
j->generation = 0;
j->marker = NULL;
j->matters_to_anchor = false;
- j->override = override;
j->irreversible = tr->irreversible;
LIST_PREPEND(transaction, f, j);
@@ -833,7 +830,6 @@ int transaction_add_job_and_dependencies(
Unit *unit,
Job *by,
bool matters,
- bool override,
bool conflicts,
bool ignore_requirements,
bool ignore_order,
@@ -895,7 +891,7 @@ int transaction_add_job_and_dependencies(
/* First add the job. */
- ret = transaction_add_one_job(tr, type, unit, override, &is_new);
+ ret = transaction_add_one_job(tr, type, unit, &is_new);
if (!ret)
return -ENOMEM;
@@ -918,7 +914,7 @@ int transaction_add_job_and_dependencies(
* add all dependencies of everybody following. */
if (unit_following_set(ret->unit, &following) > 0) {
SET_FOREACH(dep, following, i) {
- r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e);
if (r < 0) {
log_unit_warning(dep, "Cannot add dependency job for, ignoring: %s", bus_error_message(e, r));
sd_bus_error_free(e);
@@ -931,7 +927,7 @@ int transaction_add_job_and_dependencies(
/* Finally, recursively add in all dependencies. */
if (type == JOB_START || type == JOB_RESTART) {
SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e);
if (r < 0) {
if (r != -EBADR)
goto fail;
@@ -941,7 +937,7 @@ int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e);
if (r < 0) {
if (r != -EBADR)
goto fail;
@@ -950,19 +946,8 @@ int transaction_add_job_and_dependencies(
}
}
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, !override, override, false, false, ignore_order, e);
- if (r < 0) {
- log_unit_full(dep,
- r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, r,
- "Cannot add dependency job, ignoring: %s",
- bus_error_message(e, r));
- sd_bus_error_free(e);
- }
- }
-
SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e);
if (r < 0) {
log_unit_full(dep,
r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, r,
@@ -973,7 +958,7 @@ int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, false, false, ignore_order, e);
if (r < 0) {
if (r != -EBADR)
goto fail;
@@ -982,19 +967,8 @@ int transaction_add_job_and_dependencies(
}
}
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e);
- if (r < 0) {
- log_unit_full(dep,
- r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, r,
- "Cannot add dependency job, ignoring: %s",
- bus_error_message(e, r));
- sd_bus_error_free(e);
- }
- }
-
SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, true, false, ignore_order, e);
if (r < 0) {
if (r != -EBADR)
goto fail;
@@ -1004,7 +978,7 @@ int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, false, false, ignore_order, e);
if (r < 0) {
log_unit_warning(dep,
"Cannot add dependency job, ignoring: %s",
@@ -1039,7 +1013,7 @@ int transaction_add_job_and_dependencies(
if (nt == JOB_NOP)
continue;
- r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, false, false, ignore_order, e);
if (r < 0) {
if (r != -EBADR)
goto fail;
@@ -1052,7 +1026,7 @@ int transaction_add_job_and_dependencies(
if (type == JOB_RELOAD) {
SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, override, false, false, ignore_order, e);
+ r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, false, false, ignore_order, e);
if (r < 0) {
log_unit_warning(dep,
"Cannot add dependency reload job, ignoring: %s",
@@ -1097,7 +1071,7 @@ int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
if (hashmap_get(tr->jobs, u))
continue;
- r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, false, NULL);
+ r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, NULL);
if (r < 0)
log_unit_warning_errno(u, r, "Cannot add isolate job, ignoring: %m");
}
diff --git a/src/core/transaction.h b/src/core/transaction.h
index d949b21b8d..f7aa3df085 100644
--- a/src/core/transaction.h
+++ b/src/core/transaction.h
@@ -44,7 +44,6 @@ int transaction_add_job_and_dependencies(
Unit *unit,
Job *by,
bool matters,
- bool override,
bool conflicts,
bool ignore_requirements,
bool ignore_order,
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 721c8ccce9..f587a5a141 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -159,162 +159,43 @@ static int specifier_runtime(char specifier, void *data, void *userdata, char **
}
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
- char *printed = NULL;
- Unit *u = userdata;
- ExecContext *c;
- int r = 0;
-
- assert(u);
-
- c = unit_get_exec_context(u);
- if (!c)
- return -EOPNOTSUPP;
-
- if (u->manager->running_as == MANAGER_SYSTEM) {
-
- /* We cannot use NSS from PID 1, hence try to make the
- * best of it in that case, and fail if we can't help
- * it */
-
- if (!c->user || streq(c->user, "root") || streq(c->user, "0"))
- printed = strdup(specifier == 'u' ? "root" : "0");
- else {
- if (specifier == 'u')
- printed = strdup(c->user);
- else {
- uid_t uid;
+ char *t;
- r = parse_uid(c->user, &uid);
- if (r < 0)
- return -ENODATA;
-
- r = asprintf(&printed, UID_FMT, uid);
- }
- }
-
- } else {
- _cleanup_free_ char *tmp = NULL;
- const char *username = NULL;
- uid_t uid;
-
- if (c->user)
- username = c->user;
- else
- /* get USER env from env or our own uid */
- username = tmp = getusername_malloc();
-
- /* fish username from passwd */
- r = get_user_creds(&username, &uid, NULL, NULL, NULL);
- if (r < 0)
- return r;
-
- if (specifier == 'u')
- printed = strdup(username);
- else
- r = asprintf(&printed, UID_FMT, uid);
- }
+ /* 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. */
- if (r < 0 || !printed)
+ t = getusername_malloc();
+ if (!t)
return -ENOMEM;
- *ret = printed;
+ *ret = t;
return 0;
}
-static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
- Unit *u = userdata;
- ExecContext *c;
- char *n;
- int r;
-
- assert(u);
-
- c = unit_get_exec_context(u);
- if (!c)
- return -EOPNOTSUPP;
-
- if (u->manager->running_as == MANAGER_SYSTEM) {
-
- /* We cannot use NSS from PID 1, hence try to make the
- * best of it if we can, but fail if we can't */
-
- if (!c->user || streq(c->user, "root") || streq(c->user, "0"))
- n = strdup("/root");
- else
- return -EOPNOTSUPP;
-
- } else {
+static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
- /* return HOME if set, otherwise from passwd */
- if (!c || !c->user) {
- r = get_home_dir(&n);
- if (r < 0)
- return r;
- } else {
- const char *username, *home;
-
- username = c->user;
- r = get_user_creds(&username, NULL, NULL, &home, NULL);
- if (r < 0)
- return r;
-
- n = strdup(home);
- }
- }
-
- if (!n)
+ if (asprintf(ret, UID_FMT, getuid()) < 0)
return -ENOMEM;
- *ret = n;
return 0;
}
-static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
- Unit *u = userdata;
- ExecContext *c;
- char *n;
- int r;
-
- assert(u);
-
- c = unit_get_exec_context(u);
- if (!c)
- return -EOPNOTSUPP;
-
- if (u->manager->running_as == MANAGER_SYSTEM) {
-
- /* We cannot use NSS from PID 1, hence try to make the
- * best of it if we can, but fail if we can't */
-
- if (!c->user || streq(c->user, "root") || streq(c->user, "0"))
- n = strdup("/bin/sh");
- else
- return -EOPNOTSUPP;
-
- } else {
+static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
- /* return /bin/sh for root, otherwise the value from passwd */
- if (!c->user) {
- r = get_shell(&n);
- if (r < 0)
- return r;
- } else {
- const char *username, *shell;
+ /* On PID 1 (which runs as root) this will not result in NSS,
+ * which is good. See above */
- username = c->user;
- r = get_user_creds(&username, NULL, NULL, NULL, &shell);
- if (r < 0)
- return r;
+ return get_home_dir(ret);
+}
- n = strdup(shell);
- }
- }
+static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
- if (!n)
- return -ENOMEM;
+ /* On PID 1 (which runs as root) this will not result in NSS,
+ * which is good. See above */
- *ret = n;
- return 0;
+ return get_shell(ret);
}
int unit_name_printf(Unit *u, const char* format, char **ret) {
@@ -354,10 +235,10 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
* %r where units in this slice are placed in the cgroup tree
* %R the root of this systemd's instance tree
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
- * %U the UID of the configured user or running user
- * %u the username of the configured user or running user
- * %h the homedir of the configured user or running user
- * %s the shell of the configured user or running user
+ * %U the UID of the running user
+ * %u the username of the running user
+ * %h the homedir of the running user
+ * %s the shell of the running user
* %m the machine ID of the running system
* %H the host name of the running system
* %b the boot ID of the running system
@@ -377,7 +258,8 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
{ 'r', specifier_cgroup_slice, NULL },
{ 'R', specifier_cgroup_root, NULL },
{ 't', specifier_runtime, NULL },
- { 'U', specifier_user_name, NULL },
+
+ { 'U', specifier_user_id, NULL },
{ 'u', specifier_user_name, NULL },
{ 'h', specifier_user_home, NULL },
{ 's', specifier_user_shell, NULL },
diff --git a/src/core/unit.c b/src/core/unit.c
index 6c130d4cd1..d199d87bf8 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -63,7 +63,6 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SOCKET] = &socket_vtable,
[UNIT_BUSNAME] = &busname_vtable,
[UNIT_TARGET] = &target_vtable,
- [UNIT_SNAPSHOT] = &snapshot_vtable,
[UNIT_DEVICE] = &device_vtable,
[UNIT_MOUNT] = &mount_vtable,
[UNIT_AUTOMOUNT] = &automount_vtable,
@@ -133,6 +132,9 @@ static void unit_init(Unit *u) {
cc->blockio_accounting = u->manager->default_blockio_accounting;
cc->memory_accounting = u->manager->default_memory_accounting;
cc->tasks_accounting = u->manager->default_tasks_accounting;
+
+ if (u->type != UNIT_SLICE)
+ cc->tasks_max = u->manager->default_tasks_max;
}
ec = unit_get_exec_context(u);
@@ -315,9 +317,6 @@ bool unit_check_gc(Unit *u) {
if (state != UNIT_INACTIVE)
return true;
- if (UNIT_VTABLE(u)->no_gc)
- return true;
-
if (u->no_gc)
return true;
@@ -998,15 +997,13 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tRefuseManualStop: %s\n"
"%s\tDefaultDependencies: %s\n"
"%s\tOnFailureJobMode: %s\n"
- "%s\tIgnoreOnIsolate: %s\n"
- "%s\tIgnoreOnSnapshot: %s\n",
+ "%s\tIgnoreOnIsolate: %s\n",
prefix, yes_no(u->stop_when_unneeded),
prefix, yes_no(u->refuse_manual_start),
prefix, yes_no(u->refuse_manual_stop),
prefix, yes_no(u->default_dependencies),
prefix, job_mode_to_string(u->on_failure_job_mode),
- prefix, yes_no(u->ignore_on_isolate),
- prefix, yes_no(u->ignore_on_snapshot));
+ prefix, yes_no(u->ignore_on_isolate));
if (UNIT_VTABLE(u)->dump)
UNIT_VTABLE(u)->dump(u, f, prefix2);
@@ -1104,9 +1101,7 @@ static int unit_add_target_dependencies(Unit *u) {
static const UnitDependency deps[] = {
UNIT_REQUIRED_BY,
- UNIT_REQUIRED_BY_OVERRIDABLE,
UNIT_REQUISITE_OF,
- UNIT_REQUISITE_OF_OVERRIDABLE,
UNIT_WANTED_BY,
UNIT_BOUND_BY
};
@@ -1608,11 +1603,11 @@ bool unit_can_reload(Unit *u) {
static void unit_check_unneeded(Unit *u) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+
static const UnitDependency needed_dependencies[] = {
UNIT_REQUIRED_BY,
- UNIT_REQUIRED_BY_OVERRIDABLE,
UNIT_REQUISITE_OF,
- UNIT_REQUISITE_OF_OVERRIDABLE,
UNIT_WANTED_BY,
UNIT_BOUND_BY,
};
@@ -1649,12 +1644,13 @@ static void unit_check_unneeded(Unit *u) {
log_unit_info(u, "Unit not needed anymore. Stopping.");
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
if (r < 0)
- log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %m");
+ log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
}
static void unit_check_binds_to(Unit *u) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
bool stop = false;
Unit *other;
Iterator i;
@@ -1694,9 +1690,9 @@ static void unit_check_binds_to(Unit *u) {
log_unit_info(u, "Unit is bound to inactive unit %s. Stopping, too.", other->id);
/* A unit we need to run is gone. Sniff. Let's stop this. */
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
if (r < 0)
- log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %m");
+ log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
}
static void retroactively_start_dependencies(Unit *u) {
@@ -1709,30 +1705,25 @@ static void retroactively_start_dependencies(Unit *u) {
SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
if (!set_get(u->dependencies[UNIT_AFTER], other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
+ manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL);
SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
if (!set_get(u->dependencies[UNIT_AFTER], other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
- if (!set_get(u->dependencies[UNIT_AFTER], other) &&
- !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
+ manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL);
SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
if (!set_get(u->dependencies[UNIT_AFTER], other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
+ manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL);
SET_FOREACH(other, u->dependencies[UNIT_CONFLICTS], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
+ manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
+ manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
}
static void retroactively_stop_dependencies(Unit *u) {
@@ -1745,7 +1736,7 @@ static void retroactively_stop_dependencies(Unit *u) {
/* Pull down units which are bound to us recursively if enabled */
SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
+ manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
}
static void check_unneeded_dependencies(Unit *u) {
@@ -1759,18 +1750,12 @@ static void check_unneeded_dependencies(Unit *u) {
SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
unit_check_unneeded(other);
SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
unit_check_unneeded(other);
@@ -1790,7 +1775,7 @@ void unit_start_on_failure(Unit *u) {
SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) {
int r;
- r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, true, NULL, NULL);
+ r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, NULL);
if (r < 0)
log_unit_error_errno(u, r, "Failed to enqueue OnFailure= job: %m");
}
@@ -2138,16 +2123,12 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = {
[UNIT_REQUIRES] = UNIT_REQUIRED_BY,
- [UNIT_REQUIRES_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
[UNIT_WANTS] = UNIT_WANTED_BY,
[UNIT_REQUISITE] = UNIT_REQUISITE_OF,
- [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUISITE_OF_OVERRIDABLE,
[UNIT_BINDS_TO] = UNIT_BOUND_BY,
[UNIT_PART_OF] = UNIT_CONSISTS_OF,
[UNIT_REQUIRED_BY] = UNIT_REQUIRES,
- [UNIT_REQUIRED_BY_OVERRIDABLE] = UNIT_REQUIRES_OVERRIDABLE,
[UNIT_REQUISITE_OF] = UNIT_REQUISITE,
- [UNIT_REQUISITE_OF_OVERRIDABLE] = UNIT_REQUISITE_OVERRIDABLE,
[UNIT_WANTED_BY] = UNIT_WANTS,
[UNIT_BOUND_BY] = UNIT_BINDS_TO,
[UNIT_CONSISTS_OF] = UNIT_PART_OF,
@@ -2890,7 +2871,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
}
int unit_coldplug(Unit *u) {
- int r;
+ int r = 0, q = 0;
assert(u);
@@ -2901,17 +2882,16 @@ int unit_coldplug(Unit *u) {
u->coldplugged = true;
- if (UNIT_VTABLE(u)->coldplug) {
+ if (UNIT_VTABLE(u)->coldplug)
r = UNIT_VTABLE(u)->coldplug(u);
- if (r < 0)
- return r;
- }
- if (u->job) {
- r = job_coldplug(u->job);
- if (r < 0)
- return r;
- }
+ if (u->job)
+ q = job_coldplug(u->job);
+
+ if (r < 0)
+ return r;
+ if (q < 0)
+ return q;
return 0;
}
@@ -3152,12 +3132,19 @@ int unit_following_set(Unit *u, Set **s) {
}
UnitFileState unit_get_unit_file_state(Unit *u) {
+ int r;
+
assert(u);
- if (u->unit_file_state < 0 && u->fragment_path)
- u->unit_file_state = unit_file_get_state(
+ if (u->unit_file_state < 0 && u->fragment_path) {
+ r = unit_file_get_state(
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, basename(u->fragment_path));
+ NULL,
+ basename(u->fragment_path),
+ &u->unit_file_state);
+ if (r < 0)
+ u->unit_file_state = UNIT_FILE_BAD;
+ }
return u->unit_file_state;
}
@@ -3168,7 +3155,8 @@ int unit_get_unit_file_preset(Unit *u) {
if (u->unit_file_preset < 0 && u->fragment_path)
u->unit_file_preset = unit_file_query_preset(
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, basename(u->fragment_path));
+ NULL,
+ basename(u->fragment_path));
return u->unit_file_preset;
}
diff --git a/src/core/unit.h b/src/core/unit.h
index 6f775c5ce1..bcf41d2348 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -203,9 +203,6 @@ struct Unit {
/* Ignore this unit when isolating */
bool ignore_on_isolate;
- /* Ignore this unit when snapshotting */
- bool ignore_on_snapshot;
-
/* Did the last condition check succeed? */
bool condition_result;
bool assert_result;
@@ -248,7 +245,6 @@ typedef enum UnitSetPropertiesMode {
#include "socket.h"
#include "busname.h"
#include "target.h"
-#include "snapshot.h"
#include "device.h"
#include "automount.h"
#include "swap.h"
@@ -322,7 +318,7 @@ struct UnitVTable {
int (*deserialize_item)(Unit *u, const char *key, const char *data, FDSet *fds);
/* Try to match up fds with what we need for this unit */
- int (*distribute_fds)(Unit *u, FDSet *fds);
+ void (*distribute_fds)(Unit *u, FDSet *fds);
/* Boils down the more complex internal state of this unit to
* a simpler one that the engine can understand */
@@ -343,9 +339,6 @@ struct UnitVTable {
* shall release its runtime resources */
void (*release_resources)(Unit *u);
- /* Return true when this unit is suitable for snapshotting */
- bool (*check_snapshot)(Unit *u);
-
/* Invoked on every child that died */
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
@@ -389,7 +382,7 @@ struct UnitVTable {
* everything that is loaded here should still stay in
* inactive state. It is the job of the coldplug() call above
* to put the units into the initial state. */
- int (*enumerate)(Manager *m);
+ void (*enumerate)(Manager *m);
/* Type specific cleanups. */
void (*shutdown)(Manager *m);
@@ -410,9 +403,6 @@ struct UnitVTable {
/* Instances make no sense for this type */
bool no_instances:1;
- /* Exclude from automatic gc */
- bool no_gc:1;
-
/* True if transient units of this type are OK */
bool can_transient:1;
};
@@ -443,7 +433,6 @@ DEFINE_CAST(SERVICE, Service);
DEFINE_CAST(SOCKET, Socket);
DEFINE_CAST(BUSNAME, BusName);
DEFINE_CAST(TARGET, Target);
-DEFINE_CAST(SNAPSHOT, Snapshot);
DEFINE_CAST(DEVICE, Device);
DEFINE_CAST(MOUNT, Mount);
DEFINE_CAST(AUTOMOUNT, Automount);
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 642d36912c..469ee7af68 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -542,7 +542,7 @@ static int process_root_password(void) {
lock = take_etc_passwd_lock(arg_root);
if (lock < 0)
- return lock;
+ return log_error_errno(lock, "Failed to take a lock: %m");
if (arg_copy_root_password && arg_root) {
struct spwd *p;
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 5b806a1e69..e0436d794c 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -20,14 +20,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
-#include <stdbool.h>
#include <errno.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
#include <sys/file.h>
-#include <sys/stat.h>
#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include "sd-bus.h"
#include "sd-device.h"
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 34852ce381..ce8cecc5cb 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
+#include <blkid/blkid.h>
#include <stdlib.h>
#include <sys/statfs.h>
-#include <blkid/blkid.h>
+#include <unistd.h>
#include "libudev.h"
#include "sd-id128.h"
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 316a2803d3..2e1259ef68 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <errno.h>
+#include <stdio.h>
#include <sys/stat.h>
#include "alloc-util.h"
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 92061532b8..dde2baf661 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -21,8 +21,8 @@
#include <errno.h>
#include <string.h>
-#include <unistd.h>
#include <sys/utsname.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "bus-util.h"
diff --git a/src/import/aufs-util.c b/src/import/aufs-util.c
index 7b1ac134a0..82f519958c 100644
--- a/src/import/aufs-util.c
+++ b/src/import/aufs-util.c
@@ -21,10 +21,10 @@
#include <ftw.h>
+#include "aufs-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "util.h"
-#include "aufs-util.h"
static int nftw_cb(
const char *fpath,
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 4278466df1..8e531a64fa 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -48,9 +48,7 @@ static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *u
assert(s);
assert(g);
- translated_fd = PTR_TO_INT(hashmap_get(g->translate_fds, INT_TO_PTR(fd+1)));
- assert(translated_fd > 0);
- translated_fd--;
+ translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT))
action = CURL_POLL_INOUT;
@@ -79,7 +77,7 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
assert(curl);
assert(g);
- io = hashmap_get(g->ios, INT_TO_PTR(s+1));
+ io = hashmap_get(g->ios, FD_TO_PTR(s));
if (action == CURL_POLL_REMOVE) {
if (io) {
@@ -91,8 +89,8 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
sd_event_source_set_enabled(io, SD_EVENT_OFF);
sd_event_source_unref(io);
- hashmap_remove(g->ios, INT_TO_PTR(s+1));
- hashmap_remove(g->translate_fds, INT_TO_PTR(fd+1));
+ hashmap_remove(g->ios, FD_TO_PTR(s));
+ hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
safe_close(fd);
}
@@ -143,17 +141,17 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
sd_event_source_set_description(io, "curl-io");
- r = hashmap_put(g->ios, INT_TO_PTR(s+1), io);
+ r = hashmap_put(g->ios, FD_TO_PTR(s), io);
if (r < 0) {
log_oom();
sd_event_source_unref(io);
return -1;
}
- r = hashmap_put(g->translate_fds, INT_TO_PTR(fd+1), INT_TO_PTR(s+1));
+ r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
if (r < 0) {
log_oom();
- hashmap_remove(g->ios, INT_TO_PTR(s+1));
+ hashmap_remove(g->ios, FD_TO_PTR(s));
sd_event_source_unref(io);
return -1;
}
@@ -229,7 +227,7 @@ CurlGlue *curl_glue_unref(CurlGlue *g) {
fd = sd_event_source_get_io_fd(io);
assert(fd >= 0);
- hashmap_remove(g->translate_fds, INT_TO_PTR(fd+1));
+ hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
safe_close(fd);
sd_event_source_unref(io);
diff --git a/src/import/export-raw.c b/src/import/export-raw.c
index 103d45bf21..28c87594d6 100644
--- a/src/import/export-raw.c
+++ b/src/import/export-raw.c
@@ -20,6 +20,10 @@
***/
#include <sys/sendfile.h>
+
+/* When we include libgen.h because we need dirname() we immediately
+ * undefine basename() since libgen.h defines it as a macro to the POSIX
+ * version which is really broken. We prefer GNU basename(). */
#include <libgen.h>
#undef basename
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index d6567ba7ee..a83cffffa0 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -165,7 +165,7 @@ static int hash_url(const char *url, char **ret) {
assert(url);
- siphash24((uint8_t *) &h, url, strlen(url), k.bytes);
+ h = siphash24(url, strlen(url), k.bytes);
if (asprintf(ret, "%"PRIx64, h) < 0)
return -ENOMEM;
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index e7fcd293f1..2e48167c54 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/prctl.h>
#include <curl/curl.h>
+#include <sys/prctl.h>
#include "sd-daemon.h"
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index d4f8673187..a35f2b541c 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -19,11 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
+#include <ctype.h>
#include <errno.h>
-#include <unistd.h>
+#include <stdio.h>
#include <sys/epoll.h>
-#include <ctype.h>
+#include <unistd.h>
#include "sd-bus.h"
#include "sd-daemon.h"
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index 3ee6d32bf7..a6d7c3b7e8 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -19,9 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
-
#include <curl/curl.h>
+#include <stdbool.h>
#include "alloc-util.h"
#include "journal-upload.h"
diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c
index b2c398a845..09e6da0031 100644
--- a/src/journal-remote/microhttpd-util.c
+++ b/src/journal-remote/microhttpd-util.c
@@ -32,10 +32,10 @@
#include "alloc-util.h"
#include "log.h"
#include "macro.h"
+#include "microhttpd-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "microhttpd-util.h"
void microhttpd_logger(void *arg, const char *fmt, va_list ap) {
char *f;
diff --git a/src/journal/audit-type.c b/src/journal/audit-type.c
index 4888c7d05d..086bf7e7e3 100644
--- a/src/journal/audit-type.c
+++ b/src/journal/audit-type.c
@@ -25,8 +25,7 @@
# include <libaudit.h>
#endif
-#include "audit-type.h"
-#include "macro.h"
#include "missing.h"
-
+#include "audit-type.h"
#include "audit_type-to-name.h"
+#include "macro.h"
diff --git a/src/journal/coredump-vacuum.c b/src/journal/coredump-vacuum.c
index 39bc2e4270..09ab60c6c4 100644
--- a/src/journal/coredump-vacuum.c
+++ b/src/journal/coredump-vacuum.c
@@ -157,8 +157,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
if (errno == ENOENT)
return 0;
- log_error_errno(errno, "Can't open coredump directory: %m");
- return -errno;
+ return log_error_errno(errno, "Can't open coredump directory: %m");
}
for (;;) {
@@ -183,7 +182,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
if (errno == ENOENT)
continue;
- log_warning("Failed to stat /var/lib/systemd/coredump/%s", de->d_name);
+ log_warning_errno(errno, "Failed to stat /var/lib/systemd/coredump/%s: %m", de->d_name);
continue;
}
@@ -201,7 +200,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
t = timespec_load(&st.st_mtim);
- c = hashmap_get(h, UINT32_TO_PTR(uid));
+ c = hashmap_get(h, UID_TO_PTR(uid));
if (c) {
if (t < c->oldest_mtime) {
@@ -229,7 +228,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
n->oldest_mtime = t;
- r = hashmap_put(h, UINT32_TO_PTR(uid), n);
+ r = hashmap_put(h, UID_TO_PTR(uid), n);
if (r < 0)
return log_oom();
@@ -259,8 +258,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
if (errno == ENOENT)
continue;
- log_error_errno(errno, "Failed to remove file %s: %m", worst->oldest_file);
- return -errno;
+ return log_error_errno(errno, "Failed to remove file %s: %m", worst->oldest_file);
} else
log_info("Removed old coredump %s.", worst->oldest_file);
}
@@ -268,6 +266,5 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
return 0;
fail:
- log_error_errno(errno, "Failed to read directory: %m");
- return -errno;
+ return log_error_errno(errno, "Failed to read directory: %m");
}
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index 0c4ac5cdc3..aeec83da1e 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -24,10 +24,10 @@
#include "fd-util.h"
#include "fsprg.h"
+#include "hexdecoct.h"
#include "journal-authenticate.h"
#include "journal-def.h"
#include "journal-file.h"
-#include "hexdecoct.h"
static uint64_t journal_file_tag_seqnum(JournalFile *f) {
uint64_t r;
diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c
index 1db66e89c6..257ddb302b 100644
--- a/src/journal/journal-qrcode.c
+++ b/src/journal/journal-qrcode.c
@@ -20,12 +20,11 @@
***/
#include <assert.h>
-#include <stdio.h>
#include <errno.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
#include <qrencode.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "journal-qrcode.h"
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 3676cb8788..715847e018 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
-#include <sys/mman.h>
#include <fcntl.h>
#include <stddef.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "compress.h"
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 277adba904..d9a8063d31 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -133,6 +133,7 @@ static enum {
ACTION_UPDATE_CATALOG,
ACTION_LIST_BOOTS,
ACTION_FLUSH,
+ ACTION_SYNC,
ACTION_ROTATE,
ACTION_VACUUM,
} arg_action = ACTION_SHOW;
@@ -201,7 +202,7 @@ static void help(void) {
printf("%s [OPTIONS...] [MATCHES...]\n\n"
"Query the journal.\n\n"
- "Flags:\n"
+ "Options:\n"
" --system Show the system journal\n"
" --user Show the user journal for the current user\n"
" -M --machine=CONTAINER Operate on local container\n"
@@ -234,7 +235,7 @@ static void help(void) {
" -m --merge Show entries from all available journals\n"
" -D --directory=PATH Show journal files from directory\n"
" --file=PATH Show journal file\n"
- " --root=ROOT Operate on catalog files underneath the root ROOT\n"
+ " --root=ROOT Operate on catalog files below a root directory\n"
#ifdef HAVE_GCRYPT
" --interval=TIME Time interval for changing the FSS sealing key\n"
" --verify-key=KEY Specify FSS verification key\n"
@@ -244,20 +245,21 @@ static void help(void) {
" -h --help Show this help text\n"
" --version Show package version\n"
" -F --field=FIELD List all values that a specified field takes\n"
- " --new-id128 Generate a new 128-bit ID\n"
" --disk-usage Show total disk usage of all journal files\n"
" --vacuum-size=BYTES Reduce disk usage below specified size\n"
" --vacuum-files=INT Leave only the specified number of journal files\n"
" --vacuum-time=TIME Remove journal files older than specified time\n"
+ " --verify Verify journal file consistency\n"
+ " --sync Synchronize unwritten journal messages to disk\n"
" --flush Flush all journal data from /run into /var\n"
" --rotate Request immediate rotation of the journal files\n"
" --header Show journal header information\n"
" --list-catalog Show all message IDs in the catalog\n"
" --dump-catalog Show entries in the message catalog\n"
" --update-catalog Update the message catalog database\n"
+ " --new-id128 Generate a new 128-bit ID\n"
#ifdef HAVE_GCRYPT
" --setup-keys Generate a new FSS key pair\n"
- " --verify Verify journal file consistency\n"
#endif
, program_invocation_short_name);
}
@@ -289,6 +291,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_UPDATE_CATALOG,
ARG_FORCE,
ARG_UTC,
+ ARG_SYNC,
ARG_FLUSH,
ARG_ROTATE,
ARG_VACUUM_SIZE,
@@ -345,6 +348,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "machine", required_argument, NULL, 'M' },
{ "utc", no_argument, NULL, ARG_UTC },
{ "flush", no_argument, NULL, ARG_FLUSH },
+ { "sync", no_argument, NULL, ARG_SYNC },
{ "rotate", no_argument, NULL, ARG_ROTATE },
{ "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
{ "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES },
@@ -729,6 +733,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_ROTATE;
break;
+ case ARG_SYNC:
+ arg_action = ACTION_SYNC;
+ break;
+
case '?':
return -EINVAL;
@@ -1763,6 +1771,11 @@ static int flush_to_var(void) {
_cleanup_close_ int watch_fd = -1;
int r;
+ if (arg_machine) {
+ log_error("--flush is not supported in conjunction with --machine=.");
+ return -EOPNOTSUPP;
+ }
+
/* Quick exit */
if (access("/run/systemd/journal/flushed", F_OK) >= 0)
return 0;
@@ -1782,10 +1795,8 @@ static int flush_to_var(void) {
&error,
NULL,
"ssi", "systemd-journald.service", "main", SIGUSR1);
- if (r < 0) {
- log_error("Failed to kill journal service: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
mkdir_p("/run/systemd/journal", 0755);
@@ -1816,30 +1827,97 @@ static int flush_to_var(void) {
return 0;
}
-static int rotate(void) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+static int send_signal_and_wait(int sig, const char *watch_path) {
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_close_ int watch_fd = -1;
+ usec_t start;
int r;
- r = bus_connect_system_systemd(&bus);
- if (r < 0)
- return log_error_errno(r, "Failed to get D-Bus connection: %m");
+ if (arg_machine) {
+ log_error("--sync and --rotate are not supported in conjunction with --machine=.");
+ return -EOPNOTSUPP;
+ }
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "KillUnit",
- &error,
- NULL,
- "ssi", "systemd-journald.service", "main", SIGUSR2);
- if (r < 0)
- return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
+ start = now(CLOCK_MONOTONIC);
+
+ /* This call sends the specified signal to journald, and waits
+ * for acknowledgment by watching the mtime of the specified
+ * flag file. This is used to trigger syncing or rotation and
+ * then wait for the operation to complete. */
+
+ for (;;) {
+ usec_t tstamp;
+
+ /* See if a sync happened by now. */
+ r = read_timestamp_file(watch_path, &tstamp);
+ if (r < 0 && r != -ENOENT)
+ return log_error_errno(errno, "Failed to read %s: %m", watch_path);
+ if (r >= 0 && tstamp >= start)
+ return 0;
+
+ /* Let's ask for a sync, but only once. */
+ if (!bus) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+
+ r = bus_connect_system_systemd(&bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get D-Bus connection: %m");
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "KillUnit",
+ &error,
+ NULL,
+ "ssi", "systemd-journald.service", "main", sig);
+ if (r < 0)
+ return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
+
+ continue;
+ }
+
+ /* Let's install the inotify watch, if we didn't do that yet. */
+ if (watch_fd < 0) {
+
+ mkdir_p("/run/systemd/journal", 0755);
+
+ watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
+ if (watch_fd < 0)
+ return log_error_errno(errno, "Failed to create inotify watch: %m");
+
+ r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to watch journal directory: %m");
+
+ /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
+ continue;
+ }
+
+ /* OK, all preparatory steps done, let's wait until
+ * inotify reports an event. */
+
+ r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
+ if (r < 0)
+ return log_error_errno(r, "Failed to wait for event: %m");
+
+ r = flush_fd(watch_fd);
+ if (r < 0)
+ return log_error_errno(r, "Failed to flush inotify events: %m");
+ }
return 0;
}
+static int rotate(void) {
+ return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated");
+}
+
+static int sync_journal(void) {
+ return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced");
+}
+
int main(int argc, char *argv[]) {
int r;
_cleanup_journal_close_ sd_journal *j = NULL;
@@ -1865,30 +1943,19 @@ int main(int argc, char *argv[]) {
* be split up into many files. */
setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
- if (arg_action == ACTION_NEW_ID128) {
- r = generate_new_id128();
- goto finish;
- }
+ switch (arg_action) {
- if (arg_action == ACTION_FLUSH) {
- r = flush_to_var();
- goto finish;
- }
-
- if (arg_action == ACTION_ROTATE) {
- r = rotate();
+ case ACTION_NEW_ID128:
+ r = generate_new_id128();
goto finish;
- }
- if (arg_action == ACTION_SETUP_KEYS) {
+ case ACTION_SETUP_KEYS:
r = setup_keys();
goto finish;
- }
-
- if (arg_action == ACTION_UPDATE_CATALOG ||
- arg_action == ACTION_LIST_CATALOG ||
- arg_action == ACTION_DUMP_CATALOG) {
+ case ACTION_LIST_CATALOG:
+ case ACTION_DUMP_CATALOG:
+ case ACTION_UPDATE_CATALOG: {
_cleanup_free_ char *database;
database = path_join(arg_root, CATALOG_DATABASE, NULL);
@@ -1905,9 +1972,9 @@ int main(int argc, char *argv[]) {
bool oneline = arg_action == ACTION_LIST_CATALOG;
pager_open_if_enabled();
+
if (optind < argc)
- r = catalog_list_items(stdout, database,
- oneline, argv + optind);
+ r = catalog_list_items(stdout, database, oneline, argv + optind);
else
r = catalog_list(stdout, database, oneline);
if (r < 0)
@@ -1917,6 +1984,31 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ case ACTION_FLUSH:
+ r = flush_to_var();
+ goto finish;
+
+ case ACTION_SYNC:
+ r = sync_journal();
+ goto finish;
+
+ case ACTION_ROTATE:
+ r = rotate();
+ goto finish;
+
+ case ACTION_SHOW:
+ case ACTION_PRINT_HEADER:
+ case ACTION_VERIFY:
+ case ACTION_DISK_USAGE:
+ case ACTION_LIST_BOOTS:
+ case ACTION_VACUUM:
+ /* These ones require access to the journal files, continue below. */
+ break;
+
+ default:
+ assert_not_reached("Unknown action");
+ }
+
if (arg_directory)
r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
else if (arg_file)
@@ -1926,8 +2018,7 @@ int main(int argc, char *argv[]) {
else
r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
if (r < 0) {
- log_error_errno(r, "Failed to open %s: %m",
- arg_directory ? arg_directory : arg_file ? "files" : "journal");
+ log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal");
goto finish;
}
@@ -1935,18 +2026,28 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- if (arg_action == ACTION_VERIFY) {
- r = verify(j);
- goto finish;
- }
+ switch (arg_action) {
+
+ case ACTION_NEW_ID128:
+ case ACTION_SETUP_KEYS:
+ case ACTION_LIST_CATALOG:
+ case ACTION_DUMP_CATALOG:
+ case ACTION_UPDATE_CATALOG:
+ case ACTION_FLUSH:
+ case ACTION_SYNC:
+ case ACTION_ROTATE:
+ assert_not_reached("Unexpected action.");
- if (arg_action == ACTION_PRINT_HEADER) {
+ case ACTION_PRINT_HEADER:
journal_print_header(j);
r = 0;
goto finish;
- }
- if (arg_action == ACTION_DISK_USAGE) {
+ case ACTION_VERIFY:
+ r = verify(j);
+ goto finish;
+
+ case ACTION_DISK_USAGE: {
uint64_t bytes = 0;
char sbytes[FORMAT_BYTES_MAX];
@@ -1959,7 +2060,11 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (arg_action == ACTION_VACUUM) {
+ case ACTION_LIST_BOOTS:
+ r = list_boots(j);
+ goto finish;
+
+ case ACTION_VACUUM: {
Directory *d;
Iterator i;
@@ -1979,9 +2084,11 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (arg_action == ACTION_LIST_BOOTS) {
- r = list_boots(j);
- goto finish;
+ case ACTION_SHOW:
+ break;
+
+ default:
+ assert_not_reached("Unknown action");
}
/* add_boot() must be called first!
@@ -2140,7 +2247,8 @@ int main(int argc, char *argv[]) {
if (arg_follow)
need_seek = true;
else {
- printf("-- No entries --\n");
+ if (!arg_quiet)
+ printf("-- No entries --\n");
goto finish;
}
}
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 89f3d4b42f..04487c29b5 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <time.h>
#include <fcntl.h>
#include <sys/socket.h>
+#include <time.h>
#include "alloc-util.h"
#include "fd-util.h"
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
index 1e3774dafb..69a685c06f 100644
--- a/src/journal/journald-native.c
+++ b/src/journal/journald-native.c
@@ -22,6 +22,7 @@
#include <stddef.h>
#include <sys/epoll.h>
#include <sys/mman.h>
+#include <sys/statvfs.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -399,8 +400,37 @@ void server_process_native_file(
assert_se(munmap(p, ps) >= 0);
} else {
_cleanup_free_ void *p = NULL;
+ struct statvfs vfs;
ssize_t n;
+ if (fstatvfs(fd, &vfs) < 0) {
+ log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
+ return;
+ }
+
+ /* Refuse operating on file systems that have
+ * mandatory locking enabled, see:
+ *
+ * https://github.com/systemd/systemd/issues/1822
+ */
+ if (vfs.f_flag & ST_MANDLOCK) {
+ log_error("Received file descriptor from file system with mandatory locking enable, refusing.");
+ return;
+ }
+
+ /* Make the fd non-blocking. On regular files this has
+ * the effect of bypassing mandatory locking. Of
+ * course, this should normally not be necessary given
+ * the check above, but let's better be safe than
+ * sorry, after all NFS is pretty confusing regarding
+ * file system flags, and we better don't trust it,
+ * and so is SMB. */
+ r = fd_nonblock(fd, true);
+ if (r < 0) {
+ log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
+ return;
+ }
+
/* The file is not sealed, we can't map the file here, since
* clients might then truncate it and trigger a SIGBUS for
* us. So let's stupidly read it */
diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c
index 434ddc8ac9..1c406aef8e 100644
--- a/src/journal/journald-rate-limit.c
+++ b/src/journal/journald-rate-limit.c
@@ -24,11 +24,11 @@
#include "alloc-util.h"
#include "hashmap.h"
+#include "journald-rate-limit.h"
#include "list.h"
#include "random-util.h"
#include "string-util.h"
#include "util.h"
-#include "journald-rate-limit.h"
#define POOLS_MAX 5
#define BUCKETS_MAX 127
@@ -162,7 +162,7 @@ static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r,
siphash24_init(&state, r->hash_key);
string_hash_func(g->id, &state);
- siphash24_finalize((uint8_t*)&g->hash, &state);
+ g->hash = siphash24_finalize(&state);
journal_rate_limit_vacuum(r, ts);
@@ -230,7 +230,7 @@ int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, u
siphash24_init(&state, r->hash_key);
string_hash_func(id, &state);
- siphash24_finalize((uint8_t*)&h, &state);
+ h = siphash24_finalize(&state);
g = r->buckets[h % BUCKETS_MAX];
LIST_FOREACH(bucket, g, g)
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 36fe739073..7d11a568aa 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -41,6 +41,7 @@
#include "dirent-util.h"
#include "extract-word.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "fs-util.h"
#include "hashmap.h"
@@ -68,6 +69,7 @@
#include "socket-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "user-util.h"
#define USER_JOURNALS_MAX 1024
@@ -280,7 +282,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
if (r < 0)
return s->system_journal;
- f = ordered_hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
+ f = ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid));
if (f)
return f;
@@ -301,7 +303,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
server_fix_perms(s, f, uid);
- r = ordered_hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
+ r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f);
if (r < 0) {
journal_file_close(f);
return s->system_journal;
@@ -347,7 +349,7 @@ void server_rotate(Server *s) {
(void) do_rotate(s, &s->system_journal, "system", s->seal, 0);
ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
- r = do_rotate(s, &f, "user", s->seal, PTR_TO_UINT32(k));
+ r = do_rotate(s, &f, "user", s->seal, PTR_TO_UID(k));
if (r >= 0)
ordered_hashmap_replace(s->user_journals, k, f);
else if (!f)
@@ -358,7 +360,6 @@ void server_rotate(Server *s) {
void server_sync(Server *s) {
JournalFile *f;
- void *k;
Iterator i;
int r;
@@ -368,7 +369,7 @@ void server_sync(Server *s) {
log_warning_errno(r, "Failed to sync system journal, ignoring: %m");
}
- ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
+ ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) {
r = journal_file_set_offline(f);
if (r < 0)
log_warning_errno(r, "Failed to sync user journal, ignoring: %m");
@@ -1240,29 +1241,38 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
+ int r;
assert(s);
- log_info("Received request to flush runtime journal from PID %"PRIu32, si->ssi_pid);
+ log_info("Received request to flush runtime journal from PID " PID_FMT, si->ssi_pid);
server_flush_to_var(s);
server_sync(s);
server_vacuum(s, false, false);
- (void) touch("/run/systemd/journal/flushed");
+ r = touch("/run/systemd/journal/flushed");
+ if (r < 0)
+ log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
return 0;
}
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
+ int r;
assert(s);
- log_info("Received request to rotate journal from PID %"PRIu32, si->ssi_pid);
+ log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid);
server_rotate(s);
server_vacuum(s, true, true);
+ /* Let clients know when the most recent rotation happened. */
+ r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC));
+ if (r < 0)
+ log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m");
+
return 0;
}
@@ -1277,12 +1287,30 @@ static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *
return 0;
}
+static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+ Server *s = userdata;
+ int r;
+
+ assert(s);
+
+ log_debug("Received request to sync from PID " PID_FMT, si->ssi_pid);
+
+ server_sync(s);
+
+ /* Let clients know when the most recent sync happened. */
+ r = write_timestamp_file_atomic("/run/systemd/journal/synced", now(CLOCK_MONOTONIC));
+ if (r < 0)
+ log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m");
+
+ return 0;
+}
+
static int setup_signals(Server *s) {
int r;
assert(s);
- assert(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1) >= 0);
+ assert(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s);
if (r < 0)
@@ -1312,6 +1340,19 @@ static int setup_signals(Server *s) {
if (r < 0)
return r;
+ /* SIGRTMIN+1 causes an immediate sync. We process this very
+ * late, so that everything else queued at this point is
+ * really written to disk. Clients can watch
+ * /run/systemd/journal/synced with inotify until its mtime
+ * changes to see when a sync happened. */
+ r = sd_event_add_signal(s->event, &s->sigrtmin1_event_source, SIGRTMIN+1, dispatch_sigrtmin1, s);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_priority(s->sigrtmin1_event_source, SD_EVENT_PRIORITY_NORMAL+15);
+ if (r < 0)
+ return r;
+
return 0;
}
@@ -1484,11 +1525,6 @@ static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents,
assert(s->notify_event_source == es);
assert(s->notify_fd == fd);
- if (revents != EPOLLOUT) {
- log_error("Invalid events on notify file descriptor.");
- return -EINVAL;
- }
-
/* The $NOTIFY_SOCKET is writable again, now send exactly one
* message on it. Either it's the wtachdog event, the initial
* READY=1 event or an stdout stream event. If there's nothing
@@ -1634,7 +1670,7 @@ static int server_connect_notify(Server *s) {
if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) {
s->send_watchdog = true;
- r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec*3/4, dispatch_watchdog, s);
+ r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s);
if (r < 0)
return log_error_errno(r, "Failed to add watchdog time event: %m");
}
@@ -1874,6 +1910,7 @@ void server_done(Server *s) {
sd_event_source_unref(s->sigusr2_event_source);
sd_event_source_unref(s->sigterm_event_source);
sd_event_source_unref(s->sigint_event_source);
+ sd_event_source_unref(s->sigrtmin1_event_source);
sd_event_source_unref(s->hostname_event_source);
sd_event_source_unref(s->notify_event_source);
sd_event_source_unref(s->watchdog_event_source);
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 03a61bd2ed..dcc21bb7c3 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -72,6 +72,7 @@ struct Server {
sd_event_source *sigusr2_event_source;
sd_event_source *sigterm_event_source;
sd_event_source *sigint_event_source;
+ sd_event_source *sigrtmin1_event_source;
sd_event_source *hostname_event_source;
sd_event_source *notify_event_source;
sd_event_source *watchdog_event_source;
diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c
index 69540f1141..88bea3b86e 100644
--- a/src/journal/journald-wall.c
+++ b/src/journal/journald-wall.c
@@ -22,10 +22,10 @@
#include "alloc-util.h"
#include "formats-util.h"
#include "journald-server.h"
+#include "journald-wall.h"
#include "process-util.h"
#include "string-util.h"
#include "utmp-wtmp.h"
-#include "journald-wall.h"
void server_forward_wall(
Server *s,
diff --git a/src/journal/journald.c b/src/journal/journald.c
index b137e3c7be..b9f5c099e1 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -21,16 +21,15 @@
#include <unistd.h>
-#include "sd-messages.h"
#include "sd-daemon.h"
+#include "sd-messages.h"
+#include "formats-util.h"
#include "journal-authenticate.h"
-#include "journald-server.h"
#include "journald-kmsg.h"
+#include "journald-server.h"
#include "journald-syslog.h"
-
#include "sigbus.h"
-#include "formats-util.h"
int main(int argc, char *argv[]) {
Server server;
diff --git a/src/journal/lookup3.c b/src/journal/lookup3.c
index 52ffdf7b1d..3d791234f4 100644
--- a/src/journal/lookup3.c
+++ b/src/journal/lookup3.c
@@ -40,10 +40,10 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
*/
/* #define SELF_TEST 1 */
-#include <stdio.h> /* defines printf for tests */
-#include <time.h> /* defines time_t for timings in the test */
#include <stdint.h> /* defines uint32_t etc */
+#include <stdio.h> /* defines printf for tests */
#include <sys/param.h> /* attempt to define endianness */
+#include <time.h> /* defines time_t for timings in the test */
#ifdef linux
# include <endian.h> /* attempt to define endianness */
#endif
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 3cb1dfa986..5a07ddda76 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -24,13 +24,14 @@
#include <sys/mman.h>
#include "alloc-util.h"
+#include "fd-util.h"
#include "hashmap.h"
#include "list.h"
#include "log.h"
-#include "util.h"
#include "macro.h"
-#include "sigbus.h"
#include "mmap-cache.h"
+#include "sigbus.h"
+#include "util.h"
typedef struct Window Window;
typedef struct Context Context;
@@ -289,7 +290,7 @@ static void fd_free(FileDescriptor *f) {
window_free(f->windows);
if (f->cache)
- assert_se(hashmap_remove(f->cache->fds, INT_TO_PTR(f->fd + 1)));
+ assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd)));
free(f);
}
@@ -301,7 +302,7 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
assert(m);
assert(fd >= 0);
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
+ f = hashmap_get(m->fds, FD_TO_PTR(fd));
if (f)
return f;
@@ -316,7 +317,7 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
f->cache = m;
f->fd = fd;
- r = hashmap_put(m->fds, UINT_TO_PTR(fd + 1), f);
+ r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
if (r < 0) {
free(f);
return NULL;
@@ -429,7 +430,7 @@ static int find_mmap(
assert(fd >= 0);
assert(size > 0);
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
+ f = hashmap_get(m->fds, FD_TO_PTR(fd));
if (!f)
return 0;
@@ -679,7 +680,7 @@ bool mmap_cache_got_sigbus(MMapCache *m, int fd) {
mmap_cache_process_sigbus(m);
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
+ f = hashmap_get(m->fds, FD_TO_PTR(fd));
if (!f)
return false;
@@ -698,7 +699,7 @@ void mmap_cache_close_fd(MMapCache *m, int fd) {
mmap_cache_process_sigbus(m);
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
+ f = hashmap_get(m->fds, FD_TO_PTR(fd));
if (!f)
return;
diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c
index aea8fd15e6..25980b7744 100644
--- a/src/journal/test-catalog.c
+++ b/src/journal/test-catalog.c
@@ -20,10 +20,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <locale.h>
-#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
+#include <locale.h>
+#include <unistd.h>
#include "sd-messages.h"
diff --git a/src/journal/test-journal-enum.c b/src/journal/test-journal-enum.c
index 040c7d58fb..8f56ea1907 100644
--- a/src/journal/test-journal-enum.c
+++ b/src/journal/test-journal-enum.c
@@ -23,9 +23,9 @@
#include "sd-journal.h"
+#include "journal-internal.h"
#include "log.h"
#include "macro.h"
-#include "journal-internal.h"
int main(int argc, char *argv[]) {
unsigned n = 0;
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index 4ad89fe4b6..5c055ef748 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <fcntl.h>
+#include <unistd.h>
#include "sd-journal.h"
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index 887a83efe1..a7abb11fba 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
-#include <fcntl.h>
#include "fd-util.h"
#include "journal-file.h"
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
index 01d4bc968a..266e0d5473 100644
--- a/src/journal/test-journal.c
+++ b/src/journal/test-journal.c
@@ -22,11 +22,11 @@
#include <fcntl.h>
#include <unistd.h>
-#include "log.h"
-#include "rm-rf.h"
-#include "journal-file.h"
#include "journal-authenticate.h"
+#include "journal-file.h"
#include "journal-vacuum.h"
+#include "log.h"
+#include "rm-rf.h"
static bool arg_keep = false;
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 51ee7bcce4..d7ae865557 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -35,6 +35,7 @@
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
sd_id128_t machine_id;
+ uint64_t hash;
int r;
assert(duid);
@@ -50,8 +51,9 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
*len = sizeof(duid->type) + sizeof(duid->en);
/* a bit of snake-oil perhaps, but no need to expose the machine-id
- directly */
- siphash24(duid->en.id, &machine_id, sizeof(machine_id), HASH_KEY.bytes);
+ directly; duid->en.id might not be aligned, so we need to copy */
+ hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
+ memcpy(duid->en.id, &hash, sizeof(duid->en.id));
return 0;
}
@@ -84,10 +86,12 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
}
if (name)
- siphash24((uint8_t*)&id, name, strlen(name), HASH_KEY.bytes);
+ id = siphash24(name, strlen(name), HASH_KEY.bytes);
else
/* fall back to MAC address if no predictable name available */
- siphash24((uint8_t*)&id, mac, mac_len, HASH_KEY.bytes);
+ id = siphash24(mac, mac_len, HASH_KEY.bytes);
+
+ id = htole64(id);
/* fold into 32 bits */
unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 36be7d54ed..a6c410ba91 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdint.h>
-#include <string.h>
#include <errno.h>
+#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include "dhcp-internal.h"
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index cd7f5095ca..9ff42b155e 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -19,13 +19,12 @@
***/
#include <errno.h>
-#include <string.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
+#include <string.h>
-
-#include "dhcp-protocol.h"
#include "dhcp-internal.h"
+#include "dhcp-protocol.h"
#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index 0f46df6a1b..62023a9e49 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <netinet/in.h>
#include <errno.h>
+#include <netinet/in.h>
#include <string.h>
#include "alloc-util.h"
diff --git a/src/libsystemd-network/lldp-port.c b/src/libsystemd-network/lldp-port.c
index 97b6b485d2..1f1a49adbf 100644
--- a/src/libsystemd-network/lldp-port.c
+++ b/src/libsystemd-network/lldp-port.c
@@ -22,9 +22,9 @@
#include "alloc-util.h"
#include "async.h"
-#include "lldp-port.h"
-#include "lldp-network.h"
#include "lldp-internal.h"
+#include "lldp-network.h"
+#include "lldp-port.h"
int lldp_port_start(lldp_port *p) {
int r;
diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c
index 7890160497..66343147a1 100644
--- a/src/libsystemd-network/lldp-tlv.c
+++ b/src/libsystemd-network/lldp-tlv.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <net/ethernet.h>
#include <arpa/inet.h>
+#include <net/ethernet.h>
#include "alloc-util.h"
#include "lldp-tlv.h"
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 52d76e443e..a4d4f1ae2f 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -29,9 +29,9 @@
#include "condition.h"
#include "conf-parser.h"
#include "dhcp-lease-internal.h"
+#include "hexdecoct.h"
#include "log.h"
#include "network-internal.h"
-#include "hexdecoct.h"
#include "parse-util.h"
#include "siphash24.h"
#include "string-util.h"
@@ -56,7 +56,7 @@ const char *net_get_name(struct udev_device *device) {
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
-int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
+int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result) {
size_t l, sz = 0;
const char *name = NULL;
int r;
@@ -81,7 +81,7 @@ int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8
/* Let's hash the machine ID plus the device name. We
* use a fixed, but originally randomly created hash
* key here. */
- siphash24(result, v, sz, HASH_KEY.bytes);
+ *result = htole64(siphash24(v, sz, HASH_KEY.bytes));
return 0;
}
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index d5d4ef42f2..d516f2dafd 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -62,7 +62,7 @@ int config_parse_ifalias(const char *unit, const char *filename, unsigned line,
const char *section, unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data, void *userdata);
-int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]);
+int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 8d0d9955c3..277c88e2b9 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -753,7 +753,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
siphash24_init(&state, HASH_KEY.bytes);
client_id_hash_func(&req->client_id, &state);
- siphash24_finalize((uint8_t*)&hash, &state);
+ hash = htole64(siphash24_finalize(&state));
next_offer = hash % server->pool_size;
for (i = 0; i < server->pool_size; i++) {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index e29de60d24..a443bb3a7a 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -259,12 +259,12 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
assert_return(client, -EINVAL);
- assert_return(ret, -EINVAL);
if (!client->lease)
return -ENOMSG;
- *ret = client->lease;
+ if (ret)
+ *ret = client->lease;
return 0;
}
@@ -1115,11 +1115,19 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
}
int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
+ assert_return(client, -EINVAL);
+
client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP);
return 0;
}
+int sd_dhcp6_client_is_running(sd_dhcp6_client *client) {
+ assert_return(client, -EINVAL);
+
+ return client->state != DHCP6_STATE_STOPPED;
+}
+
int sd_dhcp6_client_start(sd_dhcp6_client *client) {
int r = 0;
enum DHCP6State state = DHCP6_STATE_SOLICITATION;
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index 0d915e20e7..30a7ef5785 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -101,6 +101,8 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {
if (!ll)
return -ENOMEM;
+ ll->n_ref = 1;
+
r = sd_ipv4acd_new(&ll->acd);
if (r < 0)
return r;
@@ -109,8 +111,6 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {
if (r < 0)
return r;
- ll->n_ref = 1;
-
*ret = ll;
ll = NULL;
@@ -143,15 +143,14 @@ int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
assert_return(ll, -EINVAL);
if (!ll->random_data) {
- uint8_t seed[8];
+ uint64_t seed;
/* If no random data is set, generate some from the MAC */
- siphash24(seed, &addr->ether_addr_octet,
- ETH_ALEN, HASH_KEY.bytes);
+ seed = siphash24(&addr->ether_addr_octet, ETH_ALEN, HASH_KEY.bytes);
assert_cc(sizeof(unsigned) <= 8);
- r = sd_ipv4ll_set_address_seed(ll, *(unsigned*)seed);
+ r = sd_ipv4ll_set_address_seed(ll, (unsigned) htole64(seed));
if (r < 0)
return r;
}
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index c494b9d6d8..0881973e7f 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -29,6 +29,7 @@
#include "alloc-util.h"
#include "async.h"
#include "icmp6-util.h"
+#include "in-addr-util.h"
#include "list.h"
#include "socket-util.h"
@@ -47,6 +48,12 @@ enum NDiscState {
#define ICMP6_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
#define NDISC_OPT_LEN_UNITS 8
+#define ND_RA_FLAG_PREF 0x18
+#define ND_RA_FLAG_PREF_LOW 0x03
+#define ND_RA_FLAG_PREF_MEDIUM 0x0
+#define ND_RA_FLAG_PREF_HIGH 0x1
+#define ND_RA_FLAG_PREF_INVALID 0x2
+
typedef struct NDiscPrefix NDiscPrefix;
struct NDiscPrefix {
@@ -75,6 +82,9 @@ struct sd_ndisc {
sd_event_source *recv;
sd_event_source *timeout;
int nd_sent;
+ sd_ndisc_router_callback_t router_callback;
+ sd_ndisc_prefix_autonomous_callback_t prefix_autonomous_callback;
+ sd_ndisc_prefix_onlink_callback_t prefix_onlink_callback;
sd_ndisc_callback_t callback;
void *userdata;
};
@@ -119,15 +129,17 @@ static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) {
return 0;
}
-static void ndisc_notify(sd_ndisc *nd, int event) {
- if (nd->callback)
- nd->callback(nd, event, nd->userdata);
-}
-
-int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t callback,
- void *userdata) {
+int sd_ndisc_set_callback(sd_ndisc *nd,
+ sd_ndisc_router_callback_t router_callback,
+ sd_ndisc_prefix_onlink_callback_t prefix_onlink_callback,
+ sd_ndisc_prefix_autonomous_callback_t prefix_autonomous_callback,
+ sd_ndisc_callback_t callback,
+ void *userdata) {
assert(nd);
+ nd->router_callback = router_callback;
+ nd->prefix_onlink_callback = prefix_onlink_callback;
+ nd->prefix_autonomous_callback = prefix_autonomous_callback;
nd->callback = callback;
nd->userdata = userdata;
@@ -320,7 +332,7 @@ static int ndisc_prefix_match(sd_ndisc *nd, const struct in6_addr *addr,
static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
const struct nd_opt_prefix_info *prefix_opt) {
NDiscPrefix *prefix;
- uint32_t lifetime;
+ uint32_t lifetime_valid, lifetime_preferred;
usec_t time_now;
char time_string[FORMAT_TIMESPAN_MAX];
int r;
@@ -331,10 +343,17 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
if (len < prefix_opt->nd_opt_pi_len)
return -ENOMSG;
- if (!(prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK))
+ if (!(prefix_opt->nd_opt_pi_flags_reserved & (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO)))
+ return 0;
+
+ if (in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &prefix_opt->nd_opt_pi_prefix) > 0)
return 0;
- lifetime = be32toh(prefix_opt->nd_opt_pi_valid_time);
+ lifetime_valid = be32toh(prefix_opt->nd_opt_pi_valid_time);
+ lifetime_preferred = be32toh(prefix_opt->nd_opt_pi_preferred_time);
+
+ if (lifetime_valid < lifetime_preferred)
+ return 0;
r = ndisc_prefix_match(nd, &prefix_opt->nd_opt_pi_prefix,
prefix_opt->nd_opt_pi_prefix_len, &prefix);
@@ -357,8 +376,8 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
log_ndisc(nd, "New prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
- prefix->len, lifetime,
- format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
+ prefix->len, lifetime_valid,
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
LIST_PREPEND(prefixes, nd->prefixes, prefix);
@@ -378,17 +397,24 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
log_ndisc(nd, "Update prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
- prefix->len, lifetime,
- format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
+ prefix->len, lifetime_valid,
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
}
r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return r;
- prefix->valid_until = time_now + lifetime * USEC_PER_SEC;
+ prefix->valid_until = time_now + lifetime_valid * USEC_PER_SEC;
- return r;
+ if ((prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && nd->prefix_onlink_callback)
+ nd->prefix_onlink_callback(nd, &prefix->addr, prefix->len, prefix->valid_until, nd->userdata);
+
+ if ((prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && nd->prefix_autonomous_callback)
+ nd->prefix_autonomous_callback(nd, &prefix->addr, prefix->len, lifetime_preferred, lifetime_valid,
+ nd->userdata);
+
+ return 0;
}
static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
@@ -453,11 +479,13 @@ static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
}
static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_free_ struct nd_router_advert *ra = NULL;
sd_ndisc *nd = userdata;
- int r, buflen = 0;
+ int r, buflen = 0, pref, stateful;
+ union sockaddr_union router = {};
+ socklen_t router_len = sizeof(router);
+ unsigned lifetime;
ssize_t len;
- _cleanup_free_ struct nd_router_advert *ra = NULL;
- int event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE;
assert(s);
assert(nd);
@@ -471,9 +499,12 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
if (!ra)
return -ENOMEM;
- len = read(fd, ra, buflen);
+ len = recvfrom(fd, ra, buflen, 0, &router.sa, &router_len);
if (len < 0) {
- log_ndisc(nd, "Could not receive message from UDP socket: %m");
+ log_ndisc(nd, "Could not receive message from ICMPv6 socket: %m");
+ return 0;
+ } else if (router_len != sizeof(router.in6) && router_len != 0) {
+ log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)router_len);
return 0;
}
@@ -487,26 +518,33 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
- if (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
- event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER;
+ stateful = ra->nd_ra_flags_reserved & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER);
+ pref = (ra->nd_ra_flags_reserved & ND_RA_FLAG_PREF) >> 3;
- if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
- event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED;
+ switch (pref) {
+ case ND_RA_FLAG_PREF_LOW:
+ case ND_RA_FLAG_PREF_HIGH:
+ break;
+ default:
+ pref = ND_RA_FLAG_PREF_MEDIUM;
+ break;
+ }
- log_ndisc(nd, "Received Router Advertisement flags %s/%s",
- ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED? "MANAGED": "none",
- ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER? "OTHER": "none");
+ lifetime = be16toh(ra->nd_ra_router_lifetime);
- if (event != SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE) {
- r = ndisc_ra_parse(nd, ra, len);
- if (r < 0) {
- log_ndisc(nd, "Could not parse Router Advertisement: %s",
- strerror(-r));
- return 0;
- }
+ log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %u sec",
+ stateful & ND_RA_FLAG_MANAGED ? "MANAGED" : stateful & ND_RA_FLAG_OTHER ? "OTHER" : "none",
+ pref == ND_RA_FLAG_PREF_HIGH ? "high" : pref == ND_RA_FLAG_PREF_LOW ? "low" : "medium",
+ lifetime);
+
+ r = ndisc_ra_parse(nd, ra, len);
+ if (r < 0) {
+ log_ndisc(nd, "Could not parse Router Advertisement: %s", strerror(-r));
+ return 0;
}
- ndisc_notify(nd, event);
+ if (nd->router_callback)
+ nd->router_callback(nd, stateful, router_len != 0 ? &router.in6.sin6_addr : NULL, lifetime, pref, nd->userdata);
return 0;
}
@@ -525,7 +563,8 @@ static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
nd->timeout = sd_event_source_unref(nd->timeout);
if (nd->nd_sent >= NDISC_MAX_ROUTER_SOLICITATIONS) {
- ndisc_notify(nd, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT);
+ if (nd->callback)
+ nd->callback(nd, SD_NDISC_EVENT_TIMEOUT, nd->userdata);
nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
} else {
if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr)))
@@ -549,7 +588,8 @@ static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
next_timeout, 0,
ndisc_router_solicitation_timeout, nd);
if (r < 0) {
- ndisc_notify(nd, r);
+ /* we cannot continue if we are unable to rearm the timer */
+ sd_ndisc_stop(nd);
return 0;
}
@@ -575,6 +615,9 @@ int sd_ndisc_stop(sd_ndisc *nd) {
nd->state = NDISC_STATE_IDLE;
+ if (nd->callback)
+ nd->callback(nd, SD_NDISC_EVENT_STOP, nd->userdata);
+
return 0;
}
diff --git a/src/libsystemd-network/test-acd.c b/src/libsystemd-network/test-acd.c
index 94c31af3f3..69eff5116f 100644
--- a/src/libsystemd-network/test-acd.c
+++ b/src/libsystemd-network/test-acd.c
@@ -19,21 +19,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <errno.h>
+#include <stdlib.h>
#include <unistd.h>
#include <linux/veth.h>
#include <net/if.h>
#include "sd-event.h"
-#include "sd-netlink.h"
#include "sd-ipv4acd.h"
+#include "sd-netlink.h"
-#include "util.h"
#include "event-util.h"
-#include "netlink-util.h"
#include "in-addr-util.h"
+#include "netlink-util.h"
+#include "util.h"
static void acd_handler(sd_ipv4acd *acd, int event, void *userdata) {
assert_se(acd);
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 5b52c1cbb9..1200a7c251 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -32,8 +32,8 @@
#include "dhcp-internal.h"
#include "dhcp-protocol.h"
#include "event-util.h"
-#include "util.h"
#include "fd-util.h"
+#include "util.h"
static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c
index 2d29e28f16..3607df63af 100644
--- a/src/libsystemd-network/test-dhcp-option.c
+++ b/src/libsystemd-network/test-dhcp-option.c
@@ -1,8 +1,8 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-#include <stdio.h>
-#include <stdbool.h>
#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
#include <string.h>
#include "alloc-util.h"
diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c
index 1a5c8c4605..2b5f59e4d6 100644
--- a/src/libsystemd-network/test-dhcp-server.c
+++ b/src/libsystemd-network/test-dhcp-server.c
@@ -200,13 +200,11 @@ static void test_message_handler(void) {
static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) {
struct siphash state;
- uint64_t hash;
siphash24_init(&state, key);
client_id_hash_func(id, &state);
- siphash24_finalize((uint8_t*)&hash, &state);
- return hash;
+ return htole64(siphash24_finalize(&state));
}
static void test_client_id_hash(void) {
diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c
index 44eab94e8b..a485be704e 100644
--- a/src/libsystemd-network/test-ndisc-rs.c
+++ b/src/libsystemd-network/test-ndisc-rs.c
@@ -85,29 +85,28 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
return send_ra_function(0);
}
-static void test_rs_done(sd_ndisc *nd, int event, void *userdata) {
+static void test_rs_done(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
sd_event *e = userdata;
- static int idx = 0;
- struct {
- uint8_t flag;
- int event;
- } flag_event[] = {
- { 0, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE },
- { ND_RA_FLAG_OTHER, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER },
- { ND_RA_FLAG_MANAGED, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED }
+ static unsigned idx = 0;
+ uint8_t flags_array[] = {
+ 0,
+ 0,
+ 0,
+ ND_RA_FLAG_OTHER,
+ ND_RA_FLAG_MANAGED
};
uint32_t mtu;
assert_se(nd);
- assert_se(event == flag_event[idx].event);
+ assert_se(flags == flags_array[idx]);
idx++;
if (verbose)
- printf(" got event %d\n", event);
+ printf(" got event 0x%02x\n", flags);
- if (idx < 3) {
- send_ra(flag_event[idx].flag);
+ if (idx < ELEMENTSOF(flags_array)) {
+ send_ra(flags_array[idx]);
return;
}
@@ -135,7 +134,7 @@ static void test_rs(void) {
assert_se(sd_ndisc_set_index(nd, 42) >= 0);
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
- assert_se(sd_ndisc_set_callback(nd, test_rs_done, e) >= 0);
+ assert_se(sd_ndisc_set_callback(nd, test_rs_done, NULL, NULL, NULL, e) >= 0);
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
time_now + 2 *USEC_PER_SEC, 0,
diff --git a/src/libsystemd/sd-bus/bus-bloom.c b/src/libsystemd/sd-bus/bus-bloom.c
index 91fab90cb0..c0c5d445eb 100644
--- a/src/libsystemd/sd-bus/bus-bloom.c
+++ b/src/libsystemd/sd-bus/bus-bloom.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "siphash24.h"
#include "bus-bloom.h"
+#include "siphash24.h"
+#include "util.h"
static inline void set_bit(uint64_t filter[], unsigned long b) {
filter[b >> 6] |= 1ULL << (b & 63);
@@ -45,7 +45,7 @@ static void bloom_add_data(
const void *data, /* Data to hash */
size_t n) { /* Size of data to hash in bytes */
- uint8_t h[8];
+ uint64_t h;
uint64_t m;
unsigned w, i, c = 0;
unsigned hash_index;
@@ -72,11 +72,11 @@ static void bloom_add_data(
for (d = 0; d < w; d++) {
if (c <= 0) {
- siphash24(h, data, n, hash_keys[hash_index++].bytes);
+ h = siphash24(data, n, hash_keys[hash_index++].bytes);
c += 8;
}
- p = (p << 8ULL) | (uint64_t) h[8 - c];
+ p = (p << 8ULL) | (uint64_t) ((uint8_t *)&h)[8 - c];
c--;
}
diff --git a/src/libsystemd/sd-bus/bus-bloom.h b/src/libsystemd/sd-bus/bus-bloom.h
index a9350d7f51..38892044f1 100644
--- a/src/libsystemd/sd-bus/bus-bloom.h
+++ b/src/libsystemd/sd-bus/bus-bloom.h
@@ -22,6 +22,7 @@
***/
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
/*
diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
index 52f8dfd3be..8d486fcbbd 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/sd-bus/bus-common-errors.c
@@ -22,8 +22,9 @@
#include <errno.h>
#include "sd-bus.h"
-#include "bus-error.h"
+
#include "bus-common-errors.h"
+#include "bus-error.h"
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT),
diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
index 589a90bbff..7da6ba9903 100644
--- a/src/libsystemd/sd-bus/bus-container.c
+++ b/src/libsystemd/sd-bus/bus-container.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <fcntl.h>
+#include <unistd.h>
#include "bus-container.h"
#include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index d5bc32e757..94251fe87c 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -23,8 +23,8 @@
#include <valgrind/memcheck.h>
#endif
-#include <stddef.h>
#include <errno.h>
+#include <stddef.h>
#include "sd-bus.h"
@@ -981,8 +981,12 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **
static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
_cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
pid_t pid = 0;
+ bool do_label;
int r;
- bool do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
+
+ assert(bus);
+
+ do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
/* Avoid allocating anything if we have no chance of returning useful data */
if (!bus->ucred_valid && !do_label)
diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c
index 239d7245e6..404eaa3c89 100644
--- a/src/libsystemd/sd-bus/bus-error.c
+++ b/src/libsystemd/sd-bus/bus-error.c
@@ -29,10 +29,10 @@
#include "sd-bus.h"
#include "alloc-util.h"
+#include "bus-error.h"
#include "errno-list.h"
#include "string-util.h"
#include "util.h"
-#include "bus-error.h"
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES),
diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c
index 402d43d66d..ec027590b2 100644
--- a/src/libsystemd/sd-bus/bus-gvariant.c
+++ b/src/libsystemd/sd-bus/bus-gvariant.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "bus-type.h"
#include "bus-gvariant.h"
#include "bus-signature.h"
+#include "bus-type.h"
int bus_gvariant_get_size(const char *signature) {
const char *p;
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 8c472626a8..303e49fa84 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -23,6 +23,7 @@
#include "bus-internal.h"
#include "bus-introspect.h"
#include "bus-message.h"
+#include "bus-objects.h"
#include "bus-signature.h"
#include "bus-slot.h"
#include "bus-type.h"
@@ -30,7 +31,6 @@
#include "set.h"
#include "string-util.h"
#include "strv.h"
-#include "bus-objects.h"
static int node_vtable_get_userdata(
sd_bus *bus,
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index 550bad27ba..e405a04c53 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -24,8 +24,8 @@
#include "alloc-util.h"
#include "bus-control.h"
#include "bus-objects.h"
-#include "string-util.h"
#include "bus-slot.h"
+#include "string-util.h"
sd_bus_slot *bus_slot_allocate(
sd_bus *bus,
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index a5cb667630..25873dea1e 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -36,6 +36,7 @@
#include "hexdecoct.h"
#include "macro.h"
#include "missing.h"
+#include "selinux-util.h"
#include "signal-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -608,9 +609,11 @@ static void bus_get_peercred(sd_bus *b) {
b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
/* Get the SELinux context of the peer */
- r = getpeersec(b->input_fd, &b->label);
- if (r < 0 && r != -EOPNOTSUPP)
- log_debug_errno(r, "Failed to determine peer security context: %m");
+ if (mac_selinux_use()) {
+ r = getpeersec(b->input_fd, &b->label);
+ if (r < 0 && r != -EOPNOTSUPP)
+ log_debug_errno(r, "Failed to determine peer security context: %m");
+ }
}
static int bus_socket_start_auth_client(sd_bus *b) {
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index a8d79b01b0..99780c8cce 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -20,12 +20,12 @@
***/
#include <endian.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <netdb.h>
#include <poll.h>
-#include <sys/mman.h>
#include <pthread.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include "sd-bus.h"
@@ -46,10 +46,10 @@
#include "cgroup-util.h"
#include "def.h"
#include "fd-util.h"
+#include "hexdecoct.h"
#include "hostname-util.h"
#include "macro.h"
#include "missing.h"
-#include "hexdecoct.h"
#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index 767aef63ff..f20eced4ac 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
+#include <fcntl.h>
#include <pthread.h>
+#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
#include "sd-bus.h"
@@ -31,11 +31,11 @@
#include "bus-internal.h"
#include "bus-match.h"
#include "bus-util.h"
+#include "fd-util.h"
#include "formats-util.h"
#include "log.h"
#include "macro.h"
#include "util.h"
-#include "fd-util.h"
static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c
index 580117165a..bd0101af9e 100644
--- a/src/libsystemd/sd-bus/test-bus-creds.c
+++ b/src/libsystemd/sd-bus/test-bus-creds.c
@@ -20,6 +20,7 @@
***/
#include "sd-bus.h"
+
#include "bus-dump.h"
#include "bus-util.h"
#include "cgroup-util.h"
diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c
index 5753c04b0e..9d6c221eb0 100644
--- a/src/libsystemd/sd-bus/test-bus-error.c
+++ b/src/libsystemd/sd-bus/test-bus-error.c
@@ -20,10 +20,11 @@
***/
#include "sd-bus.h"
+
+#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
#include "errno-list.h"
-#include "bus-common-errors.h"
static void test_error(void) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c
index f39dedeb24..26ba16d119 100644
--- a/src/libsystemd/sd-bus/test-bus-introspect.c
+++ b/src/libsystemd/sd-bus/test-bus-introspect.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "log.h"
#include "bus-introspect.h"
+#include "log.h"
static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return -EINVAL;
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
index 0747d6a37c..0a6093e78b 100644
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ b/src/libsystemd/sd-bus/test-bus-marshal.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#ifdef HAVE_GLIB
#include <gio/gio.h>
@@ -38,8 +38,8 @@
#include "bus-message.h"
#include "bus-util.h"
#include "fd-util.h"
-#include "log.h"
#include "hexdecoct.h"
+#include "log.h"
#include "util.h"
static void test_bus_path_encode_unique(void) {
diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c
index 75ea28371b..94896c196a 100644
--- a/src/libsystemd/sd-bus/test-bus-match.c
+++ b/src/libsystemd/sd-bus/test-bus-match.c
@@ -19,13 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "log.h"
-#include "macro.h"
-
#include "bus-match.h"
#include "bus-message.h"
-#include "bus-util.h"
#include "bus-slot.h"
+#include "bus-util.h"
+#include "log.h"
+#include "macro.h"
static bool mask[32];
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
index 5bc72e2355..edd63f9ea7 100644
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ b/src/libsystemd/sd-bus/test-bus-objects.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <pthread.h>
+#include <stdlib.h>
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c
index 92a810a7d8..949d16e6e9 100644
--- a/src/libsystemd/sd-bus/test-bus-signature.c
+++ b/src/libsystemd/sd-bus/test-bus-signature.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "string-util.h"
-#include "log.h"
-#include "bus-signature.h"
#include "bus-internal.h"
+#include "bus-signature.h"
+#include "log.h"
+#include "string-util.h"
int main(int argc, char *argv[]) {
char prefix[256];
diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c
index ff8df61a9e..1cf8416fa4 100644
--- a/src/libsystemd/sd-bus/test-bus-zero-copy.c
+++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c
@@ -27,11 +27,11 @@
#include "bus-dump.h"
#include "bus-kernel.h"
#include "bus-message.h"
+#include "fd-util.h"
#include "log.h"
#include "memfd-util.h"
#include "string-util.h"
#include "util.h"
-#include "fd-util.h"
#define FIRST_ARRAY 17
#define SECOND_ARRAY 33
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index ee4886700e..700ac691b5 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -34,6 +34,7 @@
#include "macro.h"
#include "missing.h"
#include "prioq.h"
+#include "process-util.h"
#include "set.h"
#include "signal-util.h"
#include "string-util.h"
@@ -808,7 +809,7 @@ static void source_disconnect(sd_event_source *s) {
s->event->n_enabled_child_sources--;
}
- (void) hashmap_remove(s->event->child_sources, INT_TO_PTR(s->child.pid));
+ (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid));
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
}
@@ -1188,7 +1189,7 @@ _public_ int sd_event_add_child(
if (r < 0)
return r;
- if (hashmap_contains(e->child_sources, INT_TO_PTR(pid)))
+ if (hashmap_contains(e->child_sources, PID_TO_PTR(pid)))
return -EBUSY;
s = source_new(e, !ret, SOURCE_CHILD);
@@ -1201,7 +1202,7 @@ _public_ int sd_event_add_child(
s->userdata = userdata;
s->enabled = SD_EVENT_ONESHOT;
- r = hashmap_put(e->child_sources, INT_TO_PTR(pid), s);
+ r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s);
if (r < 0) {
source_free(s);
return r;
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index 1e17ea6a06..c12bb1e20b 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -26,9 +26,9 @@
#include "sd-id128.h"
#include "fd-util.h"
+#include "hexdecoct.h"
#include "io-util.h"
#include "macro.h"
-#include "hexdecoct.h"
#include "random-util.h"
#include "util.h"
diff --git a/src/libsystemd/sd-netlink/local-addresses.c b/src/libsystemd/sd-netlink/local-addresses.c
index a00865b56b..d431ba4be4 100644
--- a/src/libsystemd/sd-netlink/local-addresses.c
+++ b/src/libsystemd/sd-netlink/local-addresses.c
@@ -23,9 +23,9 @@
#include "sd-netlink.h"
#include "alloc-util.h"
-#include "netlink-util.h"
-#include "macro.h"
#include "local-addresses.h"
+#include "macro.h"
+#include "netlink-util.h"
static int address_compare(const void *_a, const void *_b) {
const struct local_address *a = _a, *b = _b;
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index cf0a6248d6..135354e5f3 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -83,20 +83,20 @@ static const NLTypeSystem empty_type_system = {
.types = empty_types,
};
-static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = {
+static const NLType rtnl_link_info_data_veth_types[] = {
[VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
};
-static const NLType rtnl_link_info_data_ipvlan_types[IFLA_IPVLAN_MAX + 1] = {
+static const NLType rtnl_link_info_data_ipvlan_types[] = {
[IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = {
+static const NLType rtnl_link_info_data_macvlan_types[] = {
[IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_bridge_management_types[IFLA_BRIDGE_MAX + 1] = {
+static const NLType rtnl_link_bridge_management_types[] = {
[IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
[IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 },
/*
@@ -105,7 +105,7 @@ static const NLType rtnl_link_bridge_management_types[IFLA_BRIDGE_MAX + 1] = {
*/
};
-static const NLType rtnl_link_info_data_bridge_types[IFLA_BR_MAX + 1] = {
+static const NLType rtnl_link_info_data_bridge_types[] = {
[IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 },
[IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 },
[IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 },
@@ -114,7 +114,7 @@ static const NLType rtnl_link_info_data_bridge_types[IFLA_BR_MAX + 1] = {
[IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
+static const NLType rtnl_link_info_data_vlan_types[] = {
[IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
/*
[IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) },
@@ -124,7 +124,7 @@ static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
[IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = {
+static const NLType rtnl_link_info_data_vxlan_types[] = {
[IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 },
[IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR },
[IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 },
@@ -151,7 +151,7 @@ static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = {
[IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
};
-static const NLType rtnl_bond_arp_target_types[BOND_ARP_TARGETS_MAX + 1] = {
+static const NLType rtnl_bond_arp_target_types[] = {
[BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 },
[BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 },
[BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 },
@@ -175,7 +175,7 @@ static const NLTypeSystem rtnl_bond_arp_type_system = {
.types = rtnl_bond_arp_target_types,
};
-static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = {
+static const NLType rtnl_link_info_data_bond_types[] = {
[IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 },
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 },
[IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 },
@@ -201,7 +201,7 @@ static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = {
[IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED },
};
-static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
+static const NLType rtnl_link_info_data_iptun_types[] = {
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
@@ -220,7 +220,7 @@ static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
+static const NLType rtnl_link_info_data_ipgre_types[] = {
[IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
[IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
[IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
@@ -239,7 +239,7 @@ static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
+static const NLType rtnl_link_info_data_ipvti_types[] = {
[IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 },
[IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 },
[IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 },
@@ -247,7 +247,7 @@ static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
[IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
};
-static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
+static const NLType rtnl_link_info_data_ip6tnl_types[] = {
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
@@ -259,7 +259,7 @@ static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
};
/* these strings must match the .kind entries in the kernel */
-static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = {
+static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_BOND] = "bond",
[NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge",
[NL_UNION_LINK_INFO_DATA_VLAN] = "vlan",
@@ -282,7 +282,7 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
-static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = {
+static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
[NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
.types = rtnl_link_info_data_bond_types },
[NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
@@ -328,7 +328,7 @@ static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
.match = IFLA_INFO_KIND,
};
-static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = {
+static const NLType rtnl_link_info_types[] = {
[IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING },
[IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union},
/*
@@ -343,7 +343,7 @@ static const NLTypeSystem rtnl_link_info_type_system = {
.types = rtnl_link_info_types,
};
-static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
+static const struct NLType rtnl_prot_info_bridge_port_types[] = {
[IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
[IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
[IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
@@ -357,7 +357,7 @@ static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1]
[IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
};
-static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
+static const NLTypeSystem rtnl_prot_info_type_systems[] = {
[AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types),
.types = rtnl_prot_info_bridge_port_types },
};
@@ -368,7 +368,7 @@ static const NLTypeSystemUnion rtnl_prot_info_type_system_union = {
.match_type = NL_MATCH_PROTOCOL,
};
-static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = {
+static const struct NLType rtnl_af_spec_inet6_types[] = {
[IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 },
/*
IFLA_INET6_CONF,
@@ -386,7 +386,7 @@ static const NLTypeSystem rtnl_af_spec_inet6_type_system = {
.types = rtnl_af_spec_inet6_types,
};
-static const NLType rtnl_af_spec_types[AF_MAX + 1] = {
+static const NLType rtnl_af_spec_types[] = {
[AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system },
};
@@ -395,7 +395,7 @@ static const NLTypeSystem rtnl_af_spec_type_system = {
.types = rtnl_af_spec_types,
};
-static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
+static const NLType rtnl_link_types[] = {
[IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
[IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
[IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
@@ -454,7 +454,7 @@ static const NLTypeSystem rtnl_link_type_system = {
/* IFA_FLAGS was defined in kernel 3.14, but we still support older
* kernels where IFA_MAX is lower. */
-static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, IFA_FLAGS) + 1] = {
+static const NLType rtnl_address_types[] = {
[IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR },
[IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
[IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
@@ -472,7 +472,7 @@ static const NLTypeSystem rtnl_address_type_system = {
.types = rtnl_address_types,
};
-static const NLType rtnl_route_types[RTA_MAX + 1] = {
+static const NLType rtnl_route_types[] = {
[RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
[RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
[RTA_IIF] = { .type = NETLINK_TYPE_U32 },
@@ -490,7 +490,11 @@ static const NLType rtnl_route_types[RTA_MAX + 1] = {
RTA_TABLE,
RTA_MARK,
RTA_MFC_STATS,
+ RTA_VIA,
+ RTA_NEWDST,
*/
+ [RTA_PREF] = { .type = NETLINK_TYPE_U8 },
+
};
static const NLTypeSystem rtnl_route_type_system = {
@@ -498,7 +502,7 @@ static const NLTypeSystem rtnl_route_type_system = {
.types = rtnl_route_types,
};
-static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
+static const NLType rtnl_neigh_types[] = {
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
[NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
@@ -514,7 +518,7 @@ static const NLTypeSystem rtnl_neigh_type_system = {
.types = rtnl_neigh_types,
};
-static const NLType rtnl_types[RTM_MAX + 1] = {
+static const NLType rtnl_types[] = {
[NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
[NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
[RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index bf7c641541..9e636a0b53 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -21,6 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "macro.h"
+
enum {
NETLINK_TYPE_UNSPEC,
NETLINK_TYPE_U8, /* NLA_U8 */
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index 6f9fd2993b..95690b7ff1 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -21,8 +21,8 @@
#include "sd-netlink.h"
-#include "netlink-util.h"
#include "netlink-internal.h"
+#include "netlink-util.h"
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
_cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index 7cccb9b1d5..3e605db661 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -84,6 +84,35 @@ int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope)
return 0;
}
+int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) {
+ struct rtmsg *rtm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ rtm->rtm_flags = flags;
+
+ return 0;
+}
+
+int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) {
+ struct rtmsg *rtm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(flags, -EINVAL);
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ *flags = rtm->rtm_flags;
+
+ return 0;
+}
+
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
struct rtmsg *rtm;
diff --git a/src/libsystemd/sd-netlink/test-local-addresses.c b/src/libsystemd/sd-netlink/test-local-addresses.c
index 7180175970..0b53297ab8 100644
--- a/src/libsystemd/sd-netlink/test-local-addresses.c
+++ b/src/libsystemd/sd-netlink/test-local-addresses.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "af-list.h"
#include "alloc-util.h"
#include "in-addr-util.h"
#include "local-addresses.h"
-#include "af-list.h"
static void print_local_addresses(struct local_address *a, unsigned n) {
unsigned i;
diff --git a/src/libsystemd/sd-utf8/sd-utf8.c b/src/libsystemd/sd-utf8/sd-utf8.c
index 381397cc52..9e52db3b3d 100644
--- a/src/libsystemd/sd-utf8/sd-utf8.c
+++ b/src/libsystemd/sd-utf8/sd-utf8.c
@@ -21,8 +21,8 @@
#include "sd-utf8.h"
-#include "util.h"
#include "utf8.h"
+#include "util.h"
_public_ const char *sd_utf8_is_valid(const char *s) {
assert_return(s, NULL);
diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c
index 58410b1b8f..e3dffa6925 100644
--- a/src/libudev/libudev-queue.c
+++ b/src/libudev/libudev-queue.c
@@ -18,11 +18,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
#include <sys/inotify.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "fd-util.h"
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index b3f30c8dc9..36cdbbe0f9 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
-#include <sys/ioctl.h>
#include <fcntl.h>
#include <pwd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
#include <linux/vt.h>
#include "alloc-util.h"
@@ -98,15 +98,16 @@ int manager_add_session(Manager *m, const char *id, Session **_session) {
int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
User *u;
+ int r;
assert(m);
assert(name);
u = hashmap_get(m->users, UID_TO_PTR(uid));
if (!u) {
- u = user_new(m, uid, gid, name);
- if (!u)
- return -ENOMEM;
+ r = user_new(&u, m, uid, gid, name);
+ if (r < 0)
+ return r;
}
if (_user)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 7890d68aa0..e507a19aef 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -308,8 +308,10 @@ static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd
r = sd_bus_message_read(message, "u", &pid);
if (r < 0)
return r;
+ if (pid < 0)
+ return -EINVAL;
- if (pid <= 0) {
+ if (pid == 0) {
r = manager_get_session_from_creds(m, message, NULL, error, &session);
if (r < 0)
return r;
@@ -369,8 +371,10 @@ static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bu
r = sd_bus_message_read(message, "u", &pid);
if (r < 0)
return r;
+ if (pid < 0)
+ return -EINVAL;
- if (pid <= 0) {
+ if (pid == 0) {
r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
if (r < 0)
return r;
@@ -573,12 +577,14 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu
static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
- uint32_t uid, leader, audit_id = 0;
+ uint32_t audit_id = 0;
_cleanup_free_ char *id = NULL;
Session *session = NULL;
Manager *m = userdata;
User *user = NULL;
Seat *seat = NULL;
+ pid_t leader;
+ uid_t uid;
int remote;
uint32_t vtnr = 0;
SessionType t;
@@ -588,11 +594,16 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
assert(message);
assert(m);
+ assert_cc(sizeof(pid_t) == sizeof(uint32_t));
+ assert_cc(sizeof(uid_t) == sizeof(uint32_t));
+
r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
if (r < 0)
return r;
- if (leader == 1)
+ if (!uid_is_valid(uid))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
+ if (leader < 0 || leader == 1)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
if (isempty(type))
@@ -684,7 +695,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
c = SESSION_USER;
}
- if (leader <= 0) {
+ if (leader == 0) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
@@ -1093,7 +1104,9 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r < 0)
return r;
- }
+
+ } else if (!uid_is_valid(uid))
+ return -EINVAL;
errno = 0;
pw = getpwuid(uid);
@@ -2607,11 +2620,8 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
}
session = hashmap_get(m->session_units, unit);
- if (session) {
-
- if (streq_ptr(path, session->scope_job))
- session->scope_job = mfree(session->scope_job);
-
+ if (session && streq_ptr(path, session->scope_job)) {
+ session->scope_job = mfree(session->scope_job);
session_jobs_reply(session, unit, result);
session_save(session);
@@ -2620,7 +2630,9 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
}
user = hashmap_get(m->user_units, unit);
- if (user) {
+ if (user &&
+ (streq_ptr(path, user->service_job) ||
+ streq_ptr(path, user->slice_job))) {
if (streq_ptr(path, user->service_job))
user->service_job = mfree(user->service_job);
@@ -2740,13 +2752,101 @@ int manager_send_changed(Manager *manager, const char *property, ...) {
l);
}
+int manager_start_slice(
+ Manager *manager,
+ const char *slice,
+ const char *description,
+ const char *after,
+ const char *after2,
+ uint64_t tasks_max,
+ sd_bus_error *error,
+ char **job) {
+
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ int r;
+
+ assert(manager);
+ assert(slice);
+
+ r = sd_bus_message_new_method_call(
+ manager->bus,
+ &m,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'a', "(sv)");
+ if (r < 0)
+ return r;
+
+ if (!isempty(description)) {
+ r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
+ if (r < 0)
+ return r;
+ }
+
+ if (!isempty(after)) {
+ r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
+ if (r < 0)
+ return r;
+ }
+
+ if (!isempty(after2)) {
+ r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "a(sa(sv))", 0);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call(manager->bus, m, 0, error, &reply);
+ if (r < 0)
+ return r;
+
+ if (job) {
+ const char *j;
+ char *copy;
+
+ r = sd_bus_message_read(reply, "o", &j);
+ if (r < 0)
+ return r;
+
+ copy = strdup(j);
+ if (!copy)
+ return -ENOMEM;
+
+ *job = copy;
+ }
+
+ return 1;
+}
+
int manager_start_scope(
Manager *manager,
const char *scope,
pid_t pid,
const char *slice,
const char *description,
- const char *after, const char *after2,
+ const char *after,
+ const char *after2,
+ uint64_t tasks_max,
sd_bus_error *error,
char **job) {
@@ -2814,6 +2914,10 @@ int manager_start_scope(
if (r < 0)
return r;
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
+ if (r < 0)
+ return r;
+
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
@@ -2859,7 +2963,7 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error,
"StartUnit",
error,
&reply,
- "ss", unit, "fail");
+ "ss", unit, "replace");
if (r < 0)
return r;
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index 9218d098e0..8552c464cc 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -34,3 +34,4 @@ Login.IdleAction, config_parse_handle_action, 0, offsetof(Manag
Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
+Login.UserTasksMax, config_parse_uint64, 0, offsetof(Manager, user_tasks_max)
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 1d561a6f8a..9f03a7b31e 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -36,7 +36,6 @@
#include "bus-util.h"
#include "escape.h"
#include "fd-util.h"
-#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "io-util.h"
@@ -513,25 +512,31 @@ static int session_start_scope(Session *s) {
assert(s);
assert(s->user);
- assert(s->user->slice);
if (!s->scope) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *description = NULL;
char *scope, *job = NULL;
-
- description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
- if (!description)
- return log_oom();
+ const char *description;
scope = strjoin("session-", s->id, ".scope", NULL);
if (!scope)
return log_oom();
- r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
+ description = strjoina("Session ", s->id, " of user ", s->user->name, NULL);
+
+ r = manager_start_scope(
+ s->manager,
+ scope,
+ s->leader,
+ s->user->slice,
+ description,
+ "systemd-logind.service",
+ "systemd-user-sessions.service",
+ (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
+ &error,
+ &job);
if (r < 0) {
- log_error("Failed to start session scope %s: %s %s",
- scope, bus_error_message(&error, r), error.name);
+ log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r));
free(scope);
return r;
} else {
@@ -543,7 +548,7 @@ static int session_start_scope(Session *s) {
}
if (s->scope)
- hashmap_put(s->manager->session_units, s->scope, s);
+ (void) hashmap_put(s->manager->session_units, s->scope, s);
return 0;
}
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 56bc5a010c..778f19b50d 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
#include "clean-ipc.h"
@@ -44,47 +45,68 @@
#include "rm-rf.h"
#include "smack-util.h"
#include "special.h"
+#include "stdio-util.h"
#include "string-table.h"
#include "unit-name.h"
#include "user-util.h"
#include "util.h"
-User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
- User *u;
+int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
+ _cleanup_(user_freep) User *u = NULL;
+ char lu[DECIMAL_STR_MAX(uid_t) + 1];
+ int r;
+ assert(out);
assert(m);
assert(name);
u = new0(User, 1);
if (!u)
- return NULL;
+ return -ENOMEM;
+
+ u->manager = m;
+ u->uid = uid;
+ u->gid = gid;
+ xsprintf(lu, UID_FMT, uid);
u->name = strdup(name);
if (!u->name)
- goto fail;
+ return -ENOMEM;
if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
- goto fail;
+ return -ENOMEM;
- if (hashmap_put(m->users, UID_TO_PTR(uid), u) < 0)
- goto fail;
+ if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
+ return -ENOMEM;
- u->manager = m;
- u->uid = uid;
- u->gid = gid;
+ r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
+ if (r < 0)
+ return r;
- return u;
+ r = unit_name_build("user", lu, ".service", &u->service);
+ if (r < 0)
+ return r;
-fail:
- free(u->state_file);
- free(u->name);
- free(u);
+ r = hashmap_put(m->users, UID_TO_PTR(uid), u);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(m->user_units, u->slice, u);
+ if (r < 0)
+ return r;
- return NULL;
+ r = hashmap_put(m->user_units, u->service, u);
+ if (r < 0)
+ return r;
+
+ *out = u;
+ u = NULL;
+ return 0;
}
-void user_free(User *u) {
- assert(u);
+User *user_free(User *u) {
+ if (!u)
+ return NULL;
if (u->in_gc_queue)
LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
@@ -92,26 +114,24 @@ void user_free(User *u) {
while (u->sessions)
session_free(u->sessions);
- if (u->slice) {
- hashmap_remove(u->manager->user_units, u->slice);
- free(u->slice);
- }
+ if (u->service)
+ hashmap_remove_value(u->manager->user_units, u->service, u);
- if (u->service) {
- hashmap_remove(u->manager->user_units, u->service);
- free(u->service);
- }
+ if (u->slice)
+ hashmap_remove_value(u->manager->user_units, u->slice, u);
- free(u->slice_job);
- free(u->service_job);
+ hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
- free(u->runtime_path);
+ u->slice_job = mfree(u->slice_job);
+ u->service_job = mfree(u->service_job);
- hashmap_remove(u->manager->users, UID_TO_PTR(u->uid));
+ u->service = mfree(u->service);
+ u->slice = mfree(u->slice);
+ u->runtime_path = mfree(u->runtime_path);
+ u->state_file = mfree(u->state_file);
+ u->name = mfree(u->name);
- free(u->name);
- free(u->state_file);
- free(u);
+ return mfree(u);
}
static int user_save_internal(User *u) {
@@ -139,16 +159,13 @@ static int user_save_internal(User *u) {
u->name,
user_state_to_string(user_get_state(u)));
+ /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
if (u->runtime_path)
fprintf(f, "RUNTIME=%s\n", u->runtime_path);
- if (u->service)
- fprintf(f, "SERVICE=%s\n", u->service);
if (u->service_job)
fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
- if (u->slice)
- fprintf(f, "SLICE=%s\n", u->slice);
if (u->slice_job)
fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
@@ -286,10 +303,7 @@ int user_load(User *u) {
assert(u);
r = parse_env_file(u->state_file, NEWLINE,
- "RUNTIME", &u->runtime_path,
- "SERVICE", &u->service,
"SERVICE_JOB", &u->service_job,
- "SLICE", &u->slice,
"SLICE_JOB", &u->slice_job,
"DISPLAY", &display,
"REALTIME", &realtime,
@@ -325,7 +339,6 @@ int user_load(User *u) {
}
static int user_mkdir_runtime_path(User *u) {
- char *p;
int r;
assert(u);
@@ -334,16 +347,10 @@ static int user_mkdir_runtime_path(User *u) {
if (r < 0)
return log_error_errno(r, "Failed to create /run/user: %m");
- if (!u->runtime_path) {
- if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0)
- return log_oom();
- } else
- p = u->runtime_path;
-
- if (path_is_mount_point(p, 0) <= 0) {
+ if (path_is_mount_point(u->runtime_path, 0) <= 0) {
_cleanup_free_ char *t = NULL;
- (void) mkdir_label(p, 0700);
+ (void) mkdir_label(u->runtime_path, 0700);
if (mac_smack_use())
r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
@@ -354,10 +361,10 @@ static int user_mkdir_runtime_path(User *u) {
goto fail;
}
- r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
+ r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
if (r < 0) {
if (errno != EPERM) {
- r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", p);
+ r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
goto fail;
}
@@ -365,62 +372,54 @@ static int user_mkdir_runtime_path(User *u) {
* CAP_SYS_ADMIN-less container? In this case,
* just use a normal directory. */
- r = chmod_and_chown(p, 0700, u->uid, u->gid);
+ r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
if (r < 0) {
log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
goto fail;
}
}
- r = label_fix(p, false, false);
+ r = label_fix(u->runtime_path, false, false);
if (r < 0)
- log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p);
+ log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
}
- u->runtime_path = p;
return 0;
fail:
- if (p) {
- /* Try to clean up, but ignore errors */
- (void) rmdir(p);
- free(p);
- }
-
- u->runtime_path = NULL;
+ /* Try to clean up, but ignore errors */
+ (void) rmdir(u->runtime_path);
return r;
}
static int user_start_slice(User *u) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *description;
char *job;
int r;
assert(u);
- if (!u->slice) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
- sprintf(lu, UID_FMT, u->uid);
-
- r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &slice);
- if (r < 0)
- return r;
-
- r = manager_start_unit(u->manager, slice, &error, &job);
- if (r < 0) {
- log_error("Failed to start user slice: %s", bus_error_message(&error, r));
- free(slice);
- } else {
- u->slice = slice;
-
- free(u->slice_job);
- u->slice_job = job;
- }
+ u->slice_job = mfree(u->slice_job);
+ description = strjoina("User Slice of ", u->name);
+
+ r = manager_start_slice(
+ u->manager,
+ u->slice,
+ description,
+ "systemd-logind.service",
+ "systemd-user-sessions.service",
+ u->manager->user_tasks_max,
+ &error,
+ &job);
+ if (r < 0) {
+ /* we don't fail due to this, let's try to continue */
+ if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
+ log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", u->slice, bus_error_message(&error, r), error.name);
+ } else {
+ u->slice_job = job;
}
- if (u->slice)
- hashmap_put(u->manager->user_units, u->slice, u);
-
return 0;
}
@@ -431,29 +430,20 @@ static int user_start_service(User *u) {
assert(u);
- if (!u->service) {
- char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
- sprintf(lu, UID_FMT, u->uid);
-
- r = unit_name_build("user", lu, ".service", &service);
- if (r < 0)
- return log_error_errno(r, "Failed to build service name: %m");
-
- r = manager_start_unit(u->manager, service, &error, &job);
- if (r < 0) {
- log_error("Failed to start user service: %s", bus_error_message(&error, r));
- free(service);
- } else {
- u->service = service;
+ u->service_job = mfree(u->service_job);
- free(u->service_job);
- u->service_job = job;
- }
+ r = manager_start_unit(
+ u->manager,
+ u->service,
+ &error,
+ &job);
+ if (r < 0) {
+ /* we don't fail due to this, let's try to continue */
+ log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
+ } else {
+ u->service_job = job;
}
- if (u->service)
- hashmap_put(u->manager->user_units, u->service, u);
-
return 0;
}
@@ -462,15 +452,32 @@ int user_start(User *u) {
assert(u);
- if (u->started)
+ if (u->started && !u->stopping)
return 0;
- log_debug("New user %s logged in.", u->name);
-
- /* Make XDG_RUNTIME_DIR */
- r = user_mkdir_runtime_path(u);
- if (r < 0)
- return r;
+ /*
+ * If u->stopping is set, the user is marked for removal and the slice
+ * and service stop-jobs are queued. We have to clear that flag before
+ * queing the start-jobs again. If they succeed, the user object can be
+ * re-used just fine (pid1 takes care of job-ordering and proper
+ * restart), but if they fail, we want to force another user_stop() so
+ * possibly pending units are stopped.
+ * Note that we don't clear u->started, as we have no clue what state
+ * the user is in on failure here. Hence, we pretend the user is
+ * running so it will be properly taken down by GC. However, we clearly
+ * return an error from user_start() in that case, so no further
+ * reference to the user is taken.
+ */
+ u->stopping = false;
+
+ if (!u->started) {
+ log_debug("New user %s logged in.", u->name);
+
+ /* Make XDG_RUNTIME_DIR */
+ r = user_mkdir_runtime_path(u);
+ if (r < 0)
+ return r;
+ }
/* Create cgroup */
r = user_start_slice(u);
@@ -488,16 +495,16 @@ int user_start(User *u) {
if (r < 0)
return r;
- if (!dual_timestamp_is_set(&u->timestamp))
- dual_timestamp_get(&u->timestamp);
-
- u->started = true;
+ if (!u->started) {
+ if (!dual_timestamp_is_set(&u->timestamp))
+ dual_timestamp_get(&u->timestamp);
+ user_send_signal(u, true);
+ u->started = true;
+ }
/* Save new user data */
user_save(u);
- user_send_signal(u, true);
-
return 0;
}
@@ -508,9 +515,6 @@ static int user_stop_slice(User *u) {
assert(u);
- if (!u->slice)
- return 0;
-
r = manager_stop_unit(u->manager, u->slice, &error, &job);
if (r < 0) {
log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
@@ -530,9 +534,6 @@ static int user_stop_service(User *u) {
assert(u);
- if (!u->service)
- return 0;
-
r = manager_stop_unit(u->manager, u->service, &error, &job);
if (r < 0) {
log_error("Failed to stop user service: %s", bus_error_message(&error, r));
@@ -550,9 +551,6 @@ static int user_remove_runtime_path(User *u) {
assert(u);
- if (!u->runtime_path)
- return 0;
-
r = rm_rf(u->runtime_path, 0);
if (r < 0)
log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
@@ -568,8 +566,6 @@ static int user_remove_runtime_path(User *u) {
if (r < 0)
log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
- u->runtime_path = mfree(u->runtime_path);
-
return r;
}
@@ -761,9 +757,6 @@ UserState user_get_state(User *u) {
int user_kill(User *u, int signo) {
assert(u);
- if (!u->slice)
- return -ESRCH;
-
return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
}
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 722247806b..de99cf47b4 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -39,16 +39,13 @@ typedef enum UserState {
struct User {
Manager *manager;
-
uid_t uid;
gid_t gid;
char *name;
-
char *state_file;
char *runtime_path;
-
- char *service;
char *slice;
+ char *service;
char *service_job;
char *slice_job;
@@ -65,8 +62,11 @@ struct User {
LIST_FIELDS(User, gc_queue);
};
-User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name);
-void user_free(User *u);
+int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name);
+User *user_free(User *u);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free);
+
bool user_check_gc(User *u, bool drop_not_started);
void user_add_to_gc_queue(User *u);
int user_start(User *u);
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
index 3e7a935a34..3bd61a81fd 100644
--- a/src/login/logind-utmp.c
+++ b/src/login/logind-utmp.c
@@ -20,9 +20,9 @@
***/
#include <errno.h>
+#include <pwd.h>
#include <string.h>
#include <unistd.h>
-#include <pwd.h>
#include "sd-messages.h"
diff --git a/src/login/logind.c b/src/login/logind.c
index be6bbe5b5c..7b41174c64 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -70,6 +70,7 @@ static Manager *manager_new(void) {
m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
+ m->user_tasks_max = UINT64_C(4096);
m->devices = hashmap_new(&string_hash_ops);
m->seats = hashmap_new(&string_hash_ops);
diff --git a/src/login/logind.conf b/src/login/logind.conf
index 6df6f04c77..81f6695434 100644
--- a/src/login/logind.conf
+++ b/src/login/logind.conf
@@ -32,3 +32,4 @@
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RemoveIPC=yes
+#UserTasksMax=4096
diff --git a/src/login/logind.h b/src/login/logind.h
index 44e05d8b01..f34544e64c 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -134,6 +134,7 @@ struct Manager {
sd_event_source *lid_switch_ignore_event_source;
size_t runtime_dir_size;
+ uint64_t user_tasks_max;
};
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);
@@ -171,7 +172,8 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
+int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index 0d61f528db..ed4f7c726f 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -267,29 +267,21 @@ _public_ PAM_EXTERN int pam_sm_open_session(
pam_get_item(handle, PAM_SERVICE, (const void**) &service);
if (streq_ptr(service, "systemd-user")) {
- _cleanup_free_ char *p = NULL, *rt = NULL;
+ _cleanup_free_ char *rt = NULL;
- if (asprintf(&p, "/run/systemd/users/"UID_FMT, pw->pw_uid) < 0)
+ if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0)
return PAM_BUF_ERR;
- r = parse_env_file(p, NEWLINE,
- "RUNTIME", &rt,
- NULL);
- if (r < 0 && r != -ENOENT)
- return PAM_SESSION_ERR;
-
- if (rt) {
- r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
- return r;
- }
-
- r = export_legacy_dbus_address(handle, pw->pw_uid, rt);
- if (r != PAM_SUCCESS)
- return r;
+ r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
+ if (r != PAM_SUCCESS) {
+ pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
+ return r;
}
+ r = export_legacy_dbus_address(handle, pw->pw_uid, rt);
+ if (r != PAM_SUCCESS)
+ return r;
+
return PAM_SUCCESS;
}
@@ -501,7 +493,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SESSION_ERR;
}
- r = pam_set_data(handle, "systemd.session-fd", INT_TO_PTR(session_fd+1), NULL);
+ r = pam_set_data(handle, "systemd.session-fd", FD_TO_PTR(session_fd), NULL);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to install session fd.");
safe_close(session_fd);
diff --git a/src/login/test-login-shared.c b/src/login/test-login-shared.c
index 4c4275d124..ac327f71fb 100644
--- a/src/login/test-login-shared.c
+++ b/src/login/test-login-shared.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "macro.h"
#include "login-util.h"
+#include "macro.h"
static void test_session_id_valid(void) {
assert_se(session_id_valid("c1"));
diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c
index a4196bf14b..4fbc893a9a 100644
--- a/src/login/test-login-tables.c
+++ b/src/login/test-login-tables.c
@@ -19,7 +19,6 @@
#include "logind-action.h"
#include "logind-session.h"
-
#include "test-tables.h"
int main(int argc, char **argv) {
diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c
index f1165ea09c..d805bcfdca 100644
--- a/src/machine-id-setup/machine-id-setup-main.c
+++ b/src/machine-id-setup/machine-id-setup-main.c
@@ -26,8 +26,8 @@
#include "log.h"
#include "machine-id-setup.h"
-#include "util.h"
#include "path-util.h"
+#include "util.h"
static char *arg_root = NULL;
static bool arg_commit = false;
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 196bc4b8f4..6b1fae2769 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -29,6 +29,7 @@
#include "bus-error.h"
#include "bus-util.h"
#include "escape.h"
+#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
@@ -37,12 +38,12 @@
#include "machine.h"
#include "mkdir.h"
#include "parse-util.h"
+#include "process-util.h"
#include "special.h"
#include "string-table.h"
#include "terminal-util.h"
#include "unit-name.h"
#include "util.h"
-#include "extract-word.h"
Machine* machine_new(Manager *manager, MachineClass class, const char *name) {
Machine *m;
@@ -105,7 +106,7 @@ void machine_free(Machine *m) {
m->manager->host_machine = NULL;
if (m->leader > 0)
- (void) hashmap_remove_value(m->manager->machine_leaders, UINT_TO_PTR(m->leader), m);
+ (void) hashmap_remove_value(m->manager->machine_leaders, PID_TO_PTR(m->leader), m);
sd_bus_message_unref(m->create_message);
@@ -401,7 +402,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
if (m->started)
return 0;
- r = hashmap_put(m->manager->machine_leaders, UINT_TO_PTR(m->leader), m);
+ r = hashmap_put(m->manager->machine_leaders, PID_TO_PTR(m->leader), m);
if (r < 0)
return r;
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 7827f063c1..961767c4a9 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -199,6 +199,9 @@ static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd
if (r < 0)
return r;
+ if (pid < 0)
+ return -EINVAL;
+
if (pid == 0) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
@@ -1505,7 +1508,7 @@ int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
assert(pid >= 1);
assert(machine);
- mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
+ mm = hashmap_get(m->machine_leaders, PID_TO_PTR(pid));
if (!mm) {
_cleanup_free_ char *unit = NULL;
diff --git a/src/machine/test-machine-tables.c b/src/machine/test-machine-tables.c
index 4aae426050..f851a4d37d 100644
--- a/src/machine/test-machine-tables.c
+++ b/src/machine/test-machine-tables.c
@@ -18,7 +18,6 @@
***/
#include "machine.h"
-
#include "test-tables.h"
int main(int argc, char **argv) {
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index ba7e3ba74a..6fcb3050c7 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -36,7 +36,6 @@
#include "lldp.h"
#include "local-addresses.h"
#include "locale-util.h"
-#include "locale-util.h"
#include "netlink-util.h"
#include "pager.h"
#include "parse-util.h"
@@ -910,12 +909,10 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
_cleanup_free_ LinkInfo *links = NULL;
- const char *state, *word;
-
double ttl = -1;
uint32_t capability;
int i, r, c, j;
- size_t ll;
+ const char *p;
char **s;
pager_open_if_enabled();
@@ -956,14 +953,19 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
return -ENOMEM;
STRV_FOREACH(s, l) {
- FOREACH_WORD_QUOTED(word, ll, *s, state) {
- _cleanup_free_ char *t = NULL, *a = NULL, *b = NULL;
- t = strndup(word, ll);
- if (!t)
- return -ENOMEM;
+ p = *s;
+ for (;;) {
+ _cleanup_free_ char *a = NULL, *b = NULL, *word = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse LLDP syntax \"%s\": %m", *s);
+
+ if (r == 0)
+ break;
- r = split_pair(t, "=", &a, &b);
+ r = split_pair(word, "=", &a, &b);
if (r < 0)
continue;
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 8b6acf2e1d..c0562e5788 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -248,6 +248,8 @@ static int address_add_internal(Link *link, Set **addresses,
address->family = family;
address->in_addr = *in_addr;
address->prefixlen = prefixlen;
+ /* Consider address tentative until we get the real flags from the kernel */
+ address->flags = IFA_F_TENTATIVE;
r = set_ensure_allocated(addresses, &address_hash_ops);
if (r < 0)
@@ -327,13 +329,13 @@ static int address_release(Address *address) {
int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo) {
bool ready;
+ int r;
assert(address);
assert(cinfo);
ready = address_is_ready(address);
- address->added = true;
address->flags = flags;
address->scope = scope;
address->cinfo = *cinfo;
@@ -341,8 +343,17 @@ int address_update(Address *address, unsigned char flags, unsigned char scope, s
if (address->link) {
link_update_operstate(address->link);
- if (!ready && address_is_ready(address))
+ if (!ready && address_is_ready(address)) {
link_check_ready(address->link);
+
+ if (address->family == AF_INET6 &&
+ in_addr_is_link_local(AF_INET6, &address->in_addr) &&
+ !address->link->ipv6ll_address) {
+ r = link_ipv6ll_gained(address->link);
+ if (r < 0)
+ return r;
+ }
+ }
}
return 0;
@@ -769,5 +780,5 @@ int config_parse_label(const char *unit,
bool address_is_ready(const Address *a) {
assert(a);
- return a->added && !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
+ return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
}
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 0b1f3b688b..4049a23bdc 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -52,7 +52,6 @@ struct Address {
union in_addr_union in_addr;
union in_addr_union in_addr_peer;
- bool added:1;
bool ip_masquerade_done:1;
LIST_FIELDS(Address, addresses);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index b58fc5808c..b9c60a3c77 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -34,7 +34,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
int r;
assert(link);
- assert(link->dhcp4_messages);
+ assert(link->dhcp4_messages > 0);
link->dhcp4_messages --;
@@ -44,7 +44,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
link_enter_failed(link);
}
- if (!link->dhcp4_messages) {
+ if (link->dhcp4_messages == 0) {
link->dhcp4_configured = true;
link_check_ready(link);
}
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index c3332bb1ac..f83ff54369 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -131,7 +131,8 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
case SD_DHCP6_CLIENT_EVENT_STOP:
case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE:
case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX:
- log_link_warning(link, "DHCPv6 lease lost");
+ if (sd_dhcp6_client_get_lease(client, NULL) >= 0)
+ log_link_warning(link, "DHCPv6 lease lost");
link->dhcp6_configured = false;
break;
@@ -165,83 +166,82 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
link_check_ready(link);
}
-int dhcp6_configure(Link *link, bool inf_req) {
- int r, information_request;
+int dhcp6_request_address(Link *link) {
+ int r, inf_req;
+ bool running;
- assert_return(link, -EINVAL);
+ assert(link);
+ assert(link->dhcp6_client);
- link->dhcp6_configured = false;
+ r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
+ if (r < 0)
+ return r;
- if (link->dhcp6_client) {
- r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &information_request);
- if (r < 0) {
- log_link_warning_errno(link, r, "Could not get DHCPv6 Information request setting: %m");
- goto error;
- }
+ if (!inf_req)
+ return 0;
- if (information_request && !inf_req) {
- r = sd_dhcp6_client_stop(link->dhcp6_client);
- if (r < 0) {
- log_link_warning_errno(link, r, "Could not stop DHCPv6 while setting Managed mode: %m");
- goto error;
- }
+ r = sd_dhcp6_client_is_running(link->dhcp6_client);
+ if (r < 0)
+ return r;
+ else
+ running = !!r;
- r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
- if (r < 0) {
- log_link_warning_errno(link, r, "Could not unset DHCPv6 Information request: %m");
- goto error;
- }
+ if (running) {
+ r = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (r < 0)
+ return r;
+ }
- }
+ r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
+ if (r < 0)
+ return r;
+ if (running) {
r = sd_dhcp6_client_start(link->dhcp6_client);
- if (r < 0 && r != -EALREADY) {
- log_link_warning_errno(link, r, "Could not restart DHCPv6: %m");
- goto error;
- }
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
- if (r == -EALREADY)
- link->dhcp6_configured = true;
+int dhcp6_configure(Link *link) {
+ sd_dhcp6_client *client = NULL;
+ int r;
+
+ assert(link);
+ r = sd_dhcp6_client_new(&client);
+ if (r < 0)
return r;
- }
- r = sd_dhcp6_client_new(&link->dhcp6_client);
+ r = sd_dhcp6_client_attach_event(client, NULL, 0);
if (r < 0)
goto error;
- r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
+ r = sd_dhcp6_client_set_information_request(client, true);
if (r < 0)
goto error;
- r = sd_dhcp6_client_set_mac(link->dhcp6_client,
+ r = sd_dhcp6_client_set_mac(client,
(const uint8_t *) &link->mac,
sizeof (link->mac), ARPHRD_ETHER);
if (r < 0)
goto error;
- r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
+ r = sd_dhcp6_client_set_index(client, link->ifindex);
if (r < 0)
goto error;
- r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
- link);
+ r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
if (r < 0)
goto error;
- if (inf_req) {
- r = sd_dhcp6_client_set_information_request(link->dhcp6_client, true);
- if (r < 0)
- goto error;
- }
-
- r = sd_dhcp6_client_start(link->dhcp6_client);
- if (r < 0)
- goto error;
+ link->dhcp6_client = client;
- return r;
+ return 0;
- error:
- link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+error:
+ sd_dhcp6_client_unref(client);
return r;
}
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index c9222b8cb8..6e5480ee22 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <net/if.h>
#include <net/ethernet.h>
+#include <net/if.h>
#include "alloc-util.h"
#include "conf-parser.h"
diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c
index ed0d861e7a..f4aac4bb93 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -22,8 +22,8 @@
#include <netinet/ether.h>
#include <linux/if.h>
-#include "networkd-link.h"
#include "network-internal.h"
+#include "networkd-link.h"
static int ipv4ll_address_lost(Link *link) {
_cleanup_address_free_ Address *address = NULL;
@@ -201,7 +201,7 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
}
int ipv4ll_configure(Link *link) {
- uint8_t seed[8];
+ uint64_t seed;
int r;
assert(link);
@@ -215,11 +215,11 @@ int ipv4ll_configure(Link *link) {
}
if (link->udev_device) {
- r = net_get_unique_predictable_data(link->udev_device, seed);
+ r = net_get_unique_predictable_data(link->udev_device, &seed);
if (r >= 0) {
assert_cc(sizeof(unsigned) <= 8);
- r = sd_ipv4ll_set_address_seed(link->ipv4ll, *(unsigned *)seed);
+ r = sd_ipv4ll_set_address_seed(link->ipv4ll, (unsigned)seed);
if (r < 0)
return r;
}
diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
index 11b35d6cf8..d09a3c2d07 100644
--- a/src/network/networkd-link-bus.c
+++ b/src/network/networkd-link-bus.c
@@ -19,13 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "bus-util.h"
-#include "strv.h"
-
#include "alloc-util.h"
+#include "bus-util.h"
#include "networkd-link.h"
#include "networkd.h"
#include "parse-util.h"
+#include "strv.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 13d2fc6d0d..a415035887 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -111,20 +111,56 @@ static bool link_ipv4_forward_enabled(Link *link) {
if (!link->network)
return false;
+ if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ return false;
+
return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
}
static bool link_ipv6_forward_enabled(Link *link) {
+
+ if (!socket_ipv6_is_supported())
+ return false;
+
if (link->flags & IFF_LOOPBACK)
return false;
if (!link->network)
return false;
+ if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ return false;
+
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
}
+bool link_ipv6_accept_ra_enabled(Link *link) {
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ /* If unset use system default (enabled if local forwarding is disabled.
+ * disabled if local forwarding is enabled).
+ * If set, ignore or enforce RA independent of local forwarding state.
+ */
+ if (link->network->ipv6_accept_ra < 0)
+ /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
+ return !link_ipv6_forward_enabled(link);
+ else if (link->network->ipv6_accept_ra > 0)
+ /* accept RA even if ip_forward is enabled */
+ return true;
+ else
+ /* ignore RA */
+ return false;
+}
+
static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
+
+ if (!socket_ipv6_is_supported())
+ return _IPV6_PRIVACY_EXTENSIONS_INVALID;
+
if (link->flags & IFF_LOOPBACK)
return _IPV6_PRIVACY_EXTENSIONS_INVALID;
@@ -470,9 +506,6 @@ static int link_stop_clients(Link *link) {
assert(link->manager);
assert(link->manager->event);
- if (!link->network)
- return 0;
-
if (link->dhcp_client) {
k = sd_dhcp_client_stop(link->dhcp_client);
if (k < 0)
@@ -485,13 +518,13 @@ static int link_stop_clients(Link *link) {
r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
}
- if(link->ndisc_router_discovery) {
- if (link->dhcp6_client) {
- k = sd_dhcp6_client_stop(link->dhcp6_client);
- if (k < 0)
- r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
- }
+ if (link->dhcp6_client) {
+ k = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (k < 0)
+ r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
+ }
+ if (link->ndisc_router_discovery) {
k = sd_ndisc_stop(link->ndisc_router_discovery);
if (k < 0)
r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
@@ -581,6 +614,10 @@ void link_check_ready(Link *link) {
!link->ipv4ll_route)
return;
+ if (link_ipv6ll_enabled(link))
+ if (!link->ipv6ll_address)
+ return;
+
if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
!link->dhcp4_configured) ||
(link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
@@ -589,6 +626,9 @@ void link_check_ready(Link *link) {
!link->dhcp4_configured && !link->dhcp6_configured))
return;
+ if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
+ return;
+
SET_FOREACH(a, link->addresses, i)
if (!address_is_ready(a))
return;
@@ -1213,6 +1253,34 @@ static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
}
}
+static int link_acquire_ipv6_conf(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (link_dhcp6_enabled(link)) {
+ assert(link->dhcp6_client);
+
+ log_link_debug(link, "Acquiring DHCPv6 lease");
+
+ r = sd_dhcp6_client_start(link->dhcp6_client);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
+ }
+
+ if (link_ipv6_accept_ra_enabled(link)) {
+ assert(link->ndisc_router_discovery);
+
+ log_link_debug(link, "Discovering IPv6 routers");
+
+ r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
+ }
+
+ return 0;
+}
+
static int link_acquire_conf(Link *link) {
int r;
@@ -1241,16 +1309,6 @@ static int link_acquire_conf(Link *link) {
return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
}
- if (link_dhcp6_enabled(link)) {
- assert(link->ndisc_router_discovery);
-
- log_link_debug(link, "Discovering IPv6 routers");
-
- r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
- }
-
if (link_lldp_enabled(link)) {
assert(link->lldp);
@@ -1800,55 +1858,43 @@ static int link_enter_join_netdev(Link *link) {
}
static int link_set_ipv4_forward(Link *link) {
- const char *p = NULL, *v;
int r;
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (!link_ipv4_forward_enabled(link))
return 0;
- p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
- v = one_zero(link_ipv4_forward_enabled(link));
-
- r = write_string_file(p, v, 0);
- if (r < 0) {
- /* If the right value is set anyway, don't complain */
- if (verify_one_line_file(p, v) > 0)
- return 0;
+ /* We propagate the forwarding flag from one interface to the
+ * global setting one way. This means: as long as at least one
+ * interface was configured at any time that had IP forwarding
+ * enabled the setting will stay on for good. We do this
+ * primarily to keep IPv4 and IPv6 packet forwarding behaviour
+ * somewhat in sync (see below). */
- log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
- }
+ r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
return 0;
}
static int link_set_ipv6_forward(Link *link) {
- const char *p = NULL, *v = NULL;
int r;
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
+ if (!link_ipv6_forward_enabled(link))
return 0;
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
- return 0;
-
- p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
- v = one_zero(link_ipv6_forward_enabled(link));
-
- r = write_string_file(p, v, 0);
- if (r < 0) {
- /* If the right value is set anyway, don't complain */
- if (verify_one_line_file(p, v) > 0)
- return 0;
+ /* On Linux, the IPv6 stack does not not know a per-interface
+ * packet forwarding setting: either packet forwarding is on
+ * for all, or off for all. We hence don't bother with a
+ * per-interface setting, but simply propagate the interface
+ * flag, if it is set, to the global flag, one-way. Note that
+ * while IPv4 would allow a per-interface flag, we expose the
+ * same behaviour there and also propagate the setting from
+ * one to all, to keep things simple (see above). */
- log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
- }
+ r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
return 0;
}
@@ -1859,31 +1905,22 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
const char *p = NULL;
int r;
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
- return 0;
-
s = link_ipv6_privacy_extensions(link);
- if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
+ if (s < 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
- xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
-
- r = write_string_file(p, buf, 0);
- if (r < 0) {
- /* If the right value is set anyway, don't complain */
- if (verify_one_line_file(p, buf) > 0)
- return 0;
+ xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
- }
return 0;
}
static int link_set_ipv6_accept_ra(Link *link) {
- const char *p = NULL, *v = NULL;
+ const char *p = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
@@ -1893,36 +1930,21 @@ static int link_set_ipv6_accept_ra(Link *link) {
if (link->flags & IFF_LOOPBACK)
return 0;
- /* If unset use system default (enabled if local forwarding is disabled.
- * disabled if local forwarding is enabled).
- * If set, ignore or enforce RA independent of local forwarding state.
- */
- if (link->network->ipv6_accept_ra < 0)
- /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
- v = "1";
- else if (link->network->ipv6_accept_ra > 0)
- /* "2" means accept RA even if ip_forward is enabled */
- v = "2";
- else
- /* "0" means ignore RA */
- v = "0";
+ if (!link->network)
+ return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
- r = write_string_file(p, v, 0);
- if (r < 0) {
- /* If the right value is set anyway, don't complain */
- if (verify_one_line_file(p, v) > 0)
- return 0;
-
- log_link_warning_errno(link, r, "Cannot configure IPv6 accept_ra for interface: %m");
- }
+ /* We handle router advertisments ourselves, tell the kernel to GTFO */
+ r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
return 0;
}
static int link_set_ipv6_dad_transmits(Link *link) {
- char buf[DECIMAL_STR_MAX(unsigned) + 1];
+ char buf[DECIMAL_STR_MAX(int) + 1];
const char *p = NULL;
int r;
@@ -1933,27 +1955,24 @@ static int link_set_ipv6_dad_transmits(Link *link) {
if (link->flags & IFF_LOOPBACK)
return 0;
+ if (!link->network)
+ return 0;
+
if (link->network->ipv6_dad_transmits < 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
+ xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
- xsprintf(buf, "%u", link->network->ipv6_dad_transmits);
-
- r = write_string_file(p, buf, 0);
- if (r < 0) {
- /* If the right value is set anyway, don't complain */
- if (verify_one_line_file(p, buf) > 0)
- return 0;
-
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
- }
return 0;
}
static int link_set_ipv6_hop_limit(Link *link) {
- char buf[DECIMAL_STR_MAX(unsigned) + 1];
+ char buf[DECIMAL_STR_MAX(int) + 1];
const char *p = NULL;
int r;
@@ -1964,20 +1983,46 @@ static int link_set_ipv6_hop_limit(Link *link) {
if (link->flags & IFF_LOOPBACK)
return 0;
+ if (!link->network)
+ return 0;
+
if (link->network->ipv6_hop_limit < 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
+ xsprintf(buf, "%i", link->network->ipv6_hop_limit);
- xsprintf(buf, "%u", link->network->ipv6_hop_limit);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
- r = write_string_file(p, buf, 0);
- if (r < 0) {
- /* If the right value is set anyway, don't complain */
- if (verify_one_line_file(p, buf) > 0)
- return 0;
+ return 0;
+}
- log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
+static int link_drop_foreign_config(Link *link) {
+ Address *address;
+ Route *route;
+ Iterator i;
+ int r;
+
+ SET_FOREACH(address, link->addresses_foreign, i) {
+ /* we consider IPv6LL addresses to be managed by the kernel */
+ if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1)
+ continue;
+
+ r = address_remove(address, link, link_address_remove_handler);
+ if (r < 0)
+ return r;
+ }
+
+ SET_FOREACH(route, link->routes_foreign, i) {
+ /* do not touch routes managed by the kernel */
+ if (route->protocol == RTPROT_KERNEL)
+ continue;
+
+ r = route_remove(route, link, link_address_remove_handler);
+ if (r < 0)
+ return r;
}
return 0;
@@ -1990,6 +2035,10 @@ static int link_configure(Link *link) {
assert(link->network);
assert(link->state == LINK_STATE_PENDING);
+ r = link_drop_foreign_config(link);
+ if (r < 0)
+ return r;
+
r = link_set_bridge_fdb(link);
if (r < 0)
return r;
@@ -2041,6 +2090,12 @@ static int link_configure(Link *link) {
}
if (link_dhcp6_enabled(link)) {
+ r = dhcp6_configure(link);
+ if (r < 0)
+ return r;
+ }
+
+ if (link_ipv6_accept_ra_enabled(link)) {
r = ndisc_configure(link);
if (r < 0)
return r;
@@ -2065,6 +2120,12 @@ static int link_configure(Link *link) {
r = link_acquire_conf(link);
if (r < 0)
return r;
+
+ if (link->ipv6ll_address) {
+ r = link_acquire_ipv6_conf(link);
+ if (r < 0)
+ return r;
+ }
}
return link_enter_join_netdev(link);
@@ -2411,12 +2472,33 @@ failed:
return r;
}
+int link_ipv6ll_gained(Link *link) {
+ int r;
+
+ assert(link);
+
+ log_link_info(link, "Gained IPv6LL");
+
+ link->ipv6ll_address = true;
+ link_check_ready(link);
+
+ if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+ r = link_acquire_ipv6_conf(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return r;
+ }
+ }
+
+ return 0;
+}
+
static int link_carrier_gained(Link *link) {
int r;
assert(link);
- if (link->network) {
+ if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
r = link_acquire_conf(link);
if (r < 0) {
link_enter_failed(link);
@@ -2639,9 +2721,8 @@ int link_save(Link *link) {
sd_dhcp6_lease *dhcp6_lease = NULL;
if (link->dhcp6_client) {
- r = sd_dhcp6_client_get_lease(link->dhcp6_client,
- &dhcp6_lease);
- if (r < 0)
+ r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
+ if (r < 0 && r != -ENOMSG)
log_link_debug(link, "No DHCPv6 lease");
}
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index a22041870e..b564bcbca0 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -95,10 +95,13 @@ struct Link {
unsigned dhcp4_messages;
bool dhcp4_configured;
bool dhcp6_configured;
+ unsigned ndisc_messages;
+ bool ndisc_configured;
sd_ipv4ll *ipv4ll;
- bool ipv4ll_address;
- bool ipv4ll_route;
+ bool ipv4ll_address:1;
+ bool ipv4ll_route:1;
+ bool ipv6ll_address:1;
bool static_configured;
@@ -141,13 +144,16 @@ int link_save(Link *link);
int link_carrier_reset(Link *link);
bool link_has_carrier(Link *link);
+int link_ipv6ll_gained(Link *link);
+
int link_set_mtu(Link *link, uint32_t mtu);
int link_set_hostname(Link *link, const char *hostname);
int link_set_timezone(Link *link, const char *timezone);
int ipv4ll_configure(Link *link);
int dhcp4_configure(Link *link);
-int dhcp6_configure(Link *link, bool information_request);
+int dhcp6_configure(Link *link);
+int dhcp6_request_address(Link *link);
int ndisc_configure(Link *link);
bool link_lldp_enabled(Link *link);
@@ -156,6 +162,7 @@ bool link_ipv6ll_enabled(Link *link);
bool link_dhcp4_server_enabled(Link *link);
bool link_dhcp4_enabled(Link *link);
bool link_dhcp6_enabled(Link *link);
+bool link_ipv6_accept_ra_enabled(Link *link);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index a5701001c1..42f58fed19 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -577,9 +577,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo);
if (r >= 0) {
- if (cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
- valid_str = "ever";
- else
+ if (cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
cinfo.ifa_valid * USEC_PER_SEC,
USEC_PER_SEC);
@@ -590,7 +588,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
switch (type) {
case RTM_NEWADDR:
if (address)
- log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+ log_link_debug(link, "Updating address: %s/%u (valid %s%s)", buf, prefixlen,
+ valid_str ? "for " : "forever", valid_str ?: "");
else {
/* An address appeared that we did not request */
r = address_add_foreign(link, family, &in_addr, prefixlen, &address);
@@ -598,7 +597,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen);
return 0;
} else
- log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+ log_link_debug(link, "Adding address: %s/%u (valid %s%s)", buf, prefixlen,
+ valid_str ? "for " : "forever", valid_str ?: "");
}
address_update(address, flags, scope, &cinfo);
@@ -608,10 +608,12 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
case RTM_DELADDR:
if (address) {
- log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+ log_link_debug(link, "Removing address: %s/%u (valid %s%s)", buf, prefixlen,
+ valid_str ? "for " : "forever", valid_str ?: "");
address_drop(address);
} else
- log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+ log_link_warning(link, "Removing non-existent address: %s/%u (valid %s%s)", buf, prefixlen,
+ valid_str ? "for " : "forever", valid_str ?: "");
break;
default:
@@ -1091,7 +1093,8 @@ static bool manager_check_idle(void *userdata) {
link_ipv4ll_enabled(link) ||
link_dhcp4_server_enabled(link) ||
link_dhcp4_enabled(link) ||
- link_dhcp6_enabled(link))
+ link_dhcp6_enabled(link) ||
+ link_ipv6_accept_ra_enabled(link))
return false;
}
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 33e692f97f..126f9c0fe9 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -20,14 +20,132 @@
***/
#include <netinet/ether.h>
+#include <netinet/icmp6.h>
#include <linux/if.h>
#include "sd-ndisc.h"
#include "networkd-link.h"
-static void ndisc_router_handler(sd_ndisc *nd, int event, void *userdata) {
+static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+ _cleanup_link_unref_ Link *link = userdata;
+ int r;
+
+ assert(link);
+ assert(link->ndisc_messages > 0);
+
+ link->ndisc_messages --;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST) {
+ log_link_error_errno(link, r, "Could not set NDisc route or address: %m");
+ link_enter_failed(link);
+ }
+
+ if (link->ndisc_messages == 0) {
+ link->ndisc_configured = true;
+ link_check_ready(link);
+ }
+
+ return 1;
+}
+
+static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
+ unsigned lifetime_preferred, unsigned lifetime_valid, void *userdata) {
+ _cleanup_address_free_ Address *address = NULL;
Link *link = userdata;
+ usec_t time_now;
+ int r;
+
+ assert(nd);
+ assert(link);
+ assert(link->network);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ r = address_new(&address);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Could not allocate address: %m");
+ return;
+ }
+
+ assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
+
+ address->family = AF_INET6;
+ address->in_addr.in6 = *prefix;
+ if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0)
+ memcpy(&address->in_addr.in6 + 8, &link->network->ipv6_token + 8, 8);
+ else {
+ /* see RFC4291 section 2.5.1 */
+ address->in_addr.in6.__in6_u.__u6_addr8[8] = link->mac.ether_addr_octet[0];
+ address->in_addr.in6.__in6_u.__u6_addr8[8] ^= 1 << 1;
+ address->in_addr.in6.__in6_u.__u6_addr8[9] = link->mac.ether_addr_octet[1];
+ address->in_addr.in6.__in6_u.__u6_addr8[10] = link->mac.ether_addr_octet[2];
+ address->in_addr.in6.__in6_u.__u6_addr8[11] = 0xff;
+ address->in_addr.in6.__in6_u.__u6_addr8[12] = 0xfe;
+ address->in_addr.in6.__in6_u.__u6_addr8[13] = link->mac.ether_addr_octet[3];
+ address->in_addr.in6.__in6_u.__u6_addr8[14] = link->mac.ether_addr_octet[4];
+ address->in_addr.in6.__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5];
+ }
+ address->prefixlen = prefixlen;
+ address->flags = IFA_F_NOPREFIXROUTE;
+ address->cinfo.ifa_prefered = lifetime_preferred;
+ address->cinfo.ifa_valid = lifetime_valid;
+
+ r = address_configure(address, link, ndisc_netlink_handler, true);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set SLAAC address: %m");
+ link_enter_failed(link);
+ return;
+ }
+
+ link->ndisc_messages ++;
+}
+
+static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime, void *userdata) {
+ _cleanup_route_free_ Route *route = NULL;
+ Link *link = userdata;
+ usec_t time_now;
+ int r;
+
+ assert(nd);
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ r = route_new(&route);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Could not allocate route: %m");
+ return;
+ }
+
+ assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
+
+ route->family = AF_INET6;
+ route->table = RT_TABLE_MAIN;
+ route->protocol = RTPROT_RA;
+ route->flags = RTM_F_PREFIX;
+ route->dst.in6 = *prefix;
+ route->dst_prefixlen = prefixlen;
+ route->lifetime = time_now + lifetime * USEC_PER_SEC;
+
+ r = route_configure(route, link, ndisc_netlink_handler);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set prefix route: %m");
+ link_enter_failed(link);
+ return;
+ }
+
+ link->ndisc_messages ++;
+}
+
+static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
+ _cleanup_route_free_ Route *route = NULL;
+ Link *link = userdata;
+ usec_t time_now;
+ int r;
assert(link);
assert(link->network);
@@ -36,27 +154,64 @@ static void ndisc_router_handler(sd_ndisc *nd, int event, void *userdata) {
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return;
- switch(event) {
- case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE:
+ if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) {
+ if (flags & ND_RA_FLAG_MANAGED)
+ dhcp6_request_address(link);
+
+ r = sd_dhcp6_client_start(link->dhcp6_client);
+ if (r < 0 && r != -EALREADY)
+ log_link_warning_errno(link, r, "Starting DHCPv6 client on NDisc request failed: %m");
+ }
+
+ if (!gateway)
return;
- case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER:
- dhcp6_configure(link, true);
+ r = route_new(&route);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Could not allocate route: %m");
+ return;
+ }
- break;
- case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
- case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED:
- dhcp6_configure(link, false);
+ assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
- break;
+ route->family = AF_INET6;
+ route->table = RT_TABLE_MAIN;
+ route->protocol = RTPROT_RA;
+ route->pref = pref;
+ route->gw.in6 = *gateway;
+ route->lifetime = time_now + lifetime * USEC_PER_SEC;
- default:
- if (event < 0)
- log_link_warning_errno(link, event, "IPv6 Neighbor Discover error: %m");
- else
- log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
+ r = route_configure(route, link, ndisc_netlink_handler);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set default route: %m");
+ link_enter_failed(link);
+ return;
+ }
+
+ link->ndisc_messages ++;
+}
+
+static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
+ Link *link = userdata;
+ int r;
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ switch (event) {
+ case SD_NDISC_EVENT_TIMEOUT:
+ dhcp6_request_address(link);
+
+ r = sd_dhcp6_client_start(link->dhcp6_client);
+ if (r < 0 && r != -EALREADY)
+ log_link_warning_errno(link, r, "Starting DHCPv6 client after NDisc timeout failed: %m");
break;
+ case SD_NDISC_EVENT_STOP:
+ break;
+ default:
+ log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
}
}
@@ -82,7 +237,11 @@ int ndisc_configure(Link *link) {
return r;
r = sd_ndisc_set_callback(link->ndisc_router_discovery,
- ndisc_router_handler, link);
+ ndisc_router_handler,
+ ndisc_prefix_onlink_handler,
+ ndisc_prefix_autonomous_handler,
+ ndisc_handler,
+ link);
return r;
}
diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c
index 70105b8aa0..50b9021d09 100644
--- a/src/network/networkd-netdev-bond.c
+++ b/src/network/networkd-netdev-bond.c
@@ -29,8 +29,8 @@
#include "conf-parser.h"
#include "missing.h"
#include "networkd-netdev-bond.h"
-#include "string-util.h"
#include "string-table.h"
+#include "string-util.h"
/*
* Number of seconds between instances where the bonding
@@ -340,8 +340,6 @@ int config_parse_arp_ip_target_address(const char *unit,
void *data,
void *userdata) {
Bond *b = userdata;
- const char *word, *state;
- size_t l;
int r;
assert(filename);
@@ -349,14 +347,19 @@ int config_parse_arp_ip_target_address(const char *unit,
assert(rvalue);
assert(data);
- FOREACH_WORD_QUOTED(word, l, rvalue, state) {
+ for (;;) {
_cleanup_free_ ArpIpTarget *buffer = NULL;
_cleanup_free_ char *n = NULL;
int f;
- n = strndup(word, l);
- if (!n)
- return -ENOMEM;
+ r = extract_first_word(&rvalue, &n, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Bond ARP ip target address, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ if (r == 0)
+ break;
buffer = new0(ArpIpTarget, 1);
if (!buffer)
@@ -380,7 +383,9 @@ int config_parse_arp_ip_target_address(const char *unit,
}
if (b->n_arp_ip_targets > NETDEV_BOND_ARP_TARGETS_MAX)
- log_syntax(unit, LOG_WARNING, filename, line, 0, "More than the maximum number of kernel-supported ARP ip targets specified: %d > %d", b->n_arp_ip_targets, NETDEV_BOND_ARP_TARGETS_MAX);
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "More than the maximum number of kernel-supported ARP ip targets specified: %d > %d",
+ b->n_arp_ip_targets, NETDEV_BOND_ARP_TARGETS_MAX);
return 0;
}
diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c
index 57c58d83b4..a991bdb5fb 100644
--- a/src/network/networkd-netdev-bridge.c
+++ b/src/network/networkd-netdev-bridge.c
@@ -22,9 +22,9 @@
#include <net/if.h>
-#include "networkd-netdev-bridge.h"
#include "missing.h"
#include "netlink-util.h"
+#include "networkd-netdev-bridge.h"
/* callback for brige netdev's parameter set */
static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c
index 851e83537e..3d504a8564 100644
--- a/src/network/networkd-netdev-tuntap.c
+++ b/src/network/networkd-netdev-tuntap.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/ioctl.h>
#include <net/if.h>
+#include <sys/ioctl.h>
#include <linux/if_tun.h>
#include "alloc-util.h"
diff --git a/src/network/networkd-netdev-veth.c b/src/network/networkd-netdev-veth.c
index bee1a16726..773a1ee6d1 100644
--- a/src/network/networkd-netdev-veth.c
+++ b/src/network/networkd-netdev-veth.c
@@ -23,6 +23,7 @@
#include <linux/veth.h>
#include "sd-netlink.h"
+
#include "networkd-netdev-veth.h"
static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c
index 755ad2f934..7932b93335 100644
--- a/src/network/networkd-netdev-vxlan.c
+++ b/src/network/networkd-netdev-vxlan.c
@@ -22,10 +22,11 @@
#include <net/if.h>
#include "sd-netlink.h"
-#include "networkd-netdev-vxlan.h"
-#include "networkd-link.h"
+
#include "conf-parser.h"
#include "missing.h"
+#include "networkd-link.h"
+#include "networkd-netdev-vxlan.h"
static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
VxLan *v;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index dd0b400c6a..a86a6383da 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -411,7 +411,7 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) {
int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
_cleanup_free_ struct ether_addr *mac = NULL;
- uint8_t result[8];
+ uint64_t result;
size_t l, sz;
uint8_t *v;
int r;
@@ -438,10 +438,10 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
/* Let's hash the host machine ID plus the container name. We
* use a fixed, but originally randomly created hash key here. */
- siphash24(result, v, sz, HASH_KEY.bytes);
+ result = siphash24(v, sz, HASH_KEY.bytes);
assert_cc(ETH_ALEN <= sizeof(result));
- memcpy(mac->ether_addr_octet, result, ETH_ALEN);
+ memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
/* see eth_random_addr in the kernel */
mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index f4bbd06af1..ed06c21160 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -494,10 +494,18 @@ int route_configure(Route *route, Link *link,
if (r < 0)
return log_error_errno(r, "Could not set scope: %m");
+ r = sd_rtnl_message_route_set_flags(req, route->flags);
+ if (r < 0)
+ return log_error_errno(r, "Colud not set flags: %m");
+
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
if (r < 0)
return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+ r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
+
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index d0a51838ed..b276756674 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -40,6 +40,8 @@ struct Route {
unsigned char tos;
uint32_t priority; /* note that ip(8) calls this 'metric' */
unsigned char table;
+ unsigned char pref;
+ unsigned flags;
union in_addr_union gw;
union in_addr_union dst;
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index df091393f6..2545621a93 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -79,10 +79,18 @@ int config_parse_address_family_boolean_with_kernel(
assert(rvalue);
assert(data);
+ /* This function is mostly obsolete now. It simply redirects
+ * "kernel" to "no". In older networkd versions we used to
+ * distuingish IPForward=off from IPForward=kernel, where the
+ * former would explicitly turn off forwarding while the
+ * latter would simply not touch the setting. But that logic
+ * is gone, hence silently accept the old setting, but turn it
+ * to "no". */
+
s = address_family_boolean_from_string(rvalue);
if (s < 0) {
if (streq(rvalue, "kernel"))
- s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
+ s = ADDRESS_FAMILY_NO;
else {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
return 0;
diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c
index 438214015d..ecbbe6c3c9 100644
--- a/src/network/test-network-tables.c
+++ b/src/network/test-network-tables.c
@@ -1,11 +1,10 @@
-#include "networkd.h"
-#include "networkd-netdev-bond.h"
-#include "networkd-netdev-macvlan.h"
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
-#include "netlink-internal.h"
#include "ethtool-util.h"
-
+#include "netlink-internal.h"
+#include "networkd-netdev-bond.h"
+#include "networkd-netdev-macvlan.h"
+#include "networkd.h"
#include "test-tables.h"
int main(int argc, char **argv) {
diff --git a/src/network/test-network.c b/src/network/test-network.c
index dbed3795e3..a1a77b6867 100644
--- a/src/network/test-network.c
+++ b/src/network/test-network.c
@@ -20,9 +20,9 @@
***/
#include "alloc-util.h"
-#include "networkd.h"
-#include "network-internal.h"
#include "dhcp-lease-internal.h"
+#include "network-internal.h"
+#include "networkd.h"
static void test_deserialize_in_addr(void) {
_cleanup_free_ struct in_addr *addresses = NULL;
diff --git a/src/nspawn/nspawn-gperf.gperf b/src/nspawn/nspawn-gperf.gperf
index b5127a387c..58f9f4c635 100644
--- a/src/nspawn/nspawn-gperf.gperf
+++ b/src/nspawn/nspawn-gperf.gperf
@@ -15,24 +15,25 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Exec.Boot, config_parse_tristate, 0, offsetof(Settings, boot)
-Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
-Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
-Exec.User, config_parse_string, 0, offsetof(Settings, user)
-Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
-Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
-Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
-Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
-Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
-Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
-Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
-Files.Bind, config_parse_bind, 0, 0
-Files.BindReadOnly, config_parse_bind, 1, 0
-Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
-Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
-Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
-Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
-Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
-Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
-Network.Bridge, config_parse_string, 0, offsetof(Settings, network_bridge)
-Network.Port, config_parse_expose_port, 0, 0
+Exec.Boot, config_parse_tristate, 0, offsetof(Settings, boot)
+Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
+Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
+Exec.User, config_parse_string, 0, offsetof(Settings, user)
+Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
+Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
+Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
+Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
+Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
+Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
+Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
+Files.Bind, config_parse_bind, 0, 0
+Files.BindReadOnly, config_parse_bind, 1, 0
+Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
+Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
+Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
+Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
+Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
+Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
+Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
+Network.Bridge, config_parse_string, 0, offsetof(Settings, network_bridge)
+Network.Port, config_parse_expose_port, 0, 0
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index 29384b60b2..8f74c41c71 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -29,14 +29,16 @@
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "netlink-util.h"
+#include "nspawn-network.h"
#include "siphash24.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
-#include "nspawn-network.h"
#define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1)
#define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2)
+#define VETH_EXTRA_HOST_HASH_KEY SD_ID128_MAKE(48,c7,f6,b7,ea,9d,4c,9e,b7,28,d4,de,91,d5,bf,66)
+#define VETH_EXTRA_CONTAINER_HASH_KEY SD_ID128_MAKE(af,50,17,61,ce,f9,4d,35,84,0d,2b,20,54,be,ce,59)
#define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
static int generate_mac(
@@ -45,7 +47,7 @@ static int generate_mac(
sd_id128_t hash_key,
uint64_t idx) {
- uint8_t result[8];
+ uint64_t result;
size_t l, sz;
uint8_t *v, *i;
int r;
@@ -72,10 +74,10 @@ static int generate_mac(
/* Let's hash the host machine ID plus the container name. We
* use a fixed, but originally randomly created hash key here. */
- siphash24(result, v, sz, hash_key.bytes);
+ result = htole64(siphash24(v, sz, hash_key.bytes));
assert_cc(ETH_ALEN <= sizeof(result));
- memcpy(mac->ether_addr_octet, result, ETH_ALEN);
+ memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
/* see eth_random_addr in the kernel */
mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
@@ -84,42 +86,32 @@ static int generate_mac(
return 0;
}
-int setup_veth(const char *machine_name,
- pid_t pid,
- char iface_name[IFNAMSIZ],
- bool bridge) {
+static int add_veth(
+ sd_netlink *rtnl,
+ pid_t pid,
+ const char *ifname_host,
+ const struct ether_addr *mac_host,
+ const char *ifname_container,
+ const struct ether_addr *mac_container) {
_cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- struct ether_addr mac_host, mac_container;
- int r, i;
-
- /* Use two different interface name prefixes depending whether
- * we are in bridge mode or not. */
- snprintf(iface_name, IFNAMSIZ - 1, "%s-%s",
- bridge ? "vb" : "ve", machine_name);
-
- r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m");
-
- r = generate_mac(machine_name, &mac_host, HOST_HASH_KEY, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to generate predictable MAC address for host side: %m");
+ int r;
- r = sd_netlink_open(&rtnl);
- if (r < 0)
- return log_error_errno(r, "Failed to connect to netlink: %m");
+ assert(rtnl);
+ assert(ifname_host);
+ assert(mac_host);
+ assert(ifname_container);
+ assert(mac_container);
r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0);
if (r < 0)
return log_error_errno(r, "Failed to allocate netlink message: %m");
- r = sd_netlink_message_append_string(m, IFLA_IFNAME, iface_name);
+ r = sd_netlink_message_append_string(m, IFLA_IFNAME, ifname_host);
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name: %m");
- r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, &mac_host);
+ r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, mac_host);
if (r < 0)
return log_error_errno(r, "Failed to add netlink MAC address: %m");
@@ -135,11 +127,11 @@ int setup_veth(const char *machine_name,
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
- r = sd_netlink_message_append_string(m, IFLA_IFNAME, "host0");
+ r = sd_netlink_message_append_string(m, IFLA_IFNAME, ifname_container);
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name: %m");
- r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, &mac_container);
+ r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, mac_container);
if (r < 0)
return log_error_errno(r, "Failed to add netlink MAC address: %m");
@@ -161,7 +153,44 @@ int setup_veth(const char *machine_name,
r = sd_netlink_call(rtnl, m, 0, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to add new veth interfaces (host0, %s): %m", iface_name);
+ return log_error_errno(r, "Failed to add new veth interfaces (%s:%s): %m", ifname_host, ifname_container);
+
+ return 0;
+}
+
+int setup_veth(const char *machine_name,
+ pid_t pid,
+ char iface_name[IFNAMSIZ],
+ bool bridge) {
+
+ _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ struct ether_addr mac_host, mac_container;
+ int r, i;
+
+ assert(machine_name);
+ assert(pid > 0);
+ assert(iface_name);
+
+ /* Use two different interface name prefixes depending whether
+ * we are in bridge mode or not. */
+ snprintf(iface_name, IFNAMSIZ - 1, "%s-%s",
+ bridge ? "vb" : "ve", machine_name);
+
+ r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m");
+
+ r = generate_mac(machine_name, &mac_host, HOST_HASH_KEY, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate predictable MAC address for host side: %m");
+
+ r = sd_netlink_open(&rtnl);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to netlink: %m");
+
+ r = add_veth(rtnl, pid, iface_name, &mac_host, "host0", &mac_container);
+ if (r < 0)
+ return r;
i = (int) if_nametoindex(iface_name);
if (i <= 0)
@@ -170,6 +199,47 @@ int setup_veth(const char *machine_name,
return i;
}
+int setup_veth_extra(
+ const char *machine_name,
+ pid_t pid,
+ char **pairs) {
+
+ _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ uint64_t idx = 0;
+ char **a, **b;
+ int r;
+
+ assert(machine_name);
+ assert(pid > 0);
+
+ if (strv_isempty(pairs))
+ return 0;
+
+ r = sd_netlink_open(&rtnl);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to netlink: %m");
+
+ STRV_FOREACH_PAIR(a, b, pairs) {
+ struct ether_addr mac_host, mac_container;
+
+ r = generate_mac(machine_name, &mac_container, VETH_EXTRA_CONTAINER_HASH_KEY, idx);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m");
+
+ r = generate_mac(machine_name, &mac_host, VETH_EXTRA_HOST_HASH_KEY, idx);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m");
+
+ r = add_veth(rtnl, pid, *a, &mac_host, *b, &mac_container);
+ if (r < 0)
+ return r;
+
+ idx ++;
+ }
+
+ return 0;
+}
+
int setup_bridge(const char *veth_name, const char *bridge_name) {
_cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
_cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
@@ -439,3 +509,34 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
return 0;
}
+
+int veth_extra_parse(char ***l, const char *p) {
+ _cleanup_free_ char *a = NULL, *b = NULL;
+ int r;
+
+ r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+ if (r < 0)
+ return r;
+ if (r == 0 || isempty(a))
+ return -EINVAL;
+
+ r = extract_first_word(&p, &b, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+ if (r < 0)
+ return r;
+ if (r == 0 || isempty(b)) {
+ free(b);
+ b = strdup(a);
+ if (!b)
+ return -ENOMEM;
+ }
+
+ if (p)
+ return -EINVAL;
+
+ r = strv_push_pair(l, a, b);
+ if (r < 0)
+ return -ENOMEM;
+
+ a = b = NULL;
+ return 0;
+}
diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h
index 311e6d06cb..b86effef47 100644
--- a/src/nspawn/nspawn-network.h
+++ b/src/nspawn/nspawn-network.h
@@ -27,6 +27,7 @@
#include <stdbool.h>
int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge);
+int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
int setup_bridge(const char *veth_name, const char *bridge_name);
@@ -34,3 +35,5 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces);
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces);
int move_network_interfaces(pid_t pid, char **ifaces);
+
+int veth_extra_parse(char ***l, const char *p);
diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c
index 374f958c20..50871464c5 100644
--- a/src/nspawn/nspawn-register.c
+++ b/src/nspawn/nspawn-register.c
@@ -105,6 +105,10 @@ int register_machine(
return bus_log_create_error(r);
}
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
+ if (r < 0)
+ return bus_log_create_error(r);
+
r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
if (r < 0)
return bus_log_create_error(r);
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index 6885d0641e..d6b64d8d5a 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -22,6 +22,7 @@
#include "alloc-util.h"
#include "cap-list.h"
#include "conf-parser.h"
+#include "nspawn-network.h"
#include "nspawn-settings.h"
#include "process-util.h"
#include "strv.h"
@@ -77,6 +78,7 @@ Settings* settings_free(Settings *s) {
strv_free(s->network_interfaces);
strv_free(s->network_macvlan);
strv_free(s->network_ipvlan);
+ strv_free(s->network_veth_extra);
free(s->network_bridge);
expose_port_free_all(s->expose_ports);
@@ -95,7 +97,8 @@ bool settings_private_network(Settings *s) {
s->network_bridge ||
s->network_interfaces ||
s->network_macvlan ||
- s->network_ipvlan;
+ s->network_ipvlan ||
+ s->network_veth_extra;
}
bool settings_network_veth(Settings *s) {
@@ -269,15 +272,33 @@ int config_parse_tmpfs(
return 0;
}
- if (settings->network_bridge)
- settings->network_veth = true;
+ return 0;
+}
- if (settings->network_interfaces ||
- settings->network_macvlan ||
- settings->network_ipvlan ||
- settings->network_bridge ||
- settings->network_veth)
- settings->private_network = true;
+int config_parse_veth_extra(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Settings *settings = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = veth_extra_parse(&settings->network_veth_extra, rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue);
+ return 0;
+ }
return 0;
}
diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h
index 16e8c54508..dde0d8bd45 100644
--- a/src/nspawn/nspawn-settings.h
+++ b/src/nspawn/nspawn-settings.h
@@ -69,6 +69,7 @@ typedef struct Settings {
char **network_interfaces;
char **network_macvlan;
char **network_ipvlan;
+ char **network_veth_extra;
ExposePort *expose_ports;
} Settings;
@@ -88,3 +89,4 @@ int config_parse_expose_port(const char *unit, const char *filename, unsigned li
int config_parse_volatile_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_tmpfs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_veth_extra(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 4c48681f17..f6a2c0386e 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -165,6 +165,7 @@ static char **arg_network_interfaces = NULL;
static char **arg_network_macvlan = NULL;
static char **arg_network_ipvlan = NULL;
static bool arg_network_veth = false;
+static char **arg_network_veth_extra = NULL;
static char *arg_network_bridge = NULL;
static unsigned long arg_personality = PERSONALITY_INVALID;
static char *arg_image = NULL;
@@ -212,6 +213,9 @@ static void help(void) {
" existing network interface to the container\n"
" -n --network-veth Add a virtual Ethernet connection between host\n"
" and container\n"
+ " --network-veth-extra=HOSTIF[:CONTAINERIF]\n"
+ " Add an additional virtual Ethernet link between\n"
+ " host and container\n"
" --network-bridge=INTERFACE\n"
" Add a virtual Ethernet connection between host\n"
" and container and add it to an existing bridge on\n"
@@ -334,6 +338,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NETWORK_MACVLAN,
ARG_NETWORK_IPVLAN,
ARG_NETWORK_BRIDGE,
+ ARG_NETWORK_VETH_EXTRA,
ARG_PERSONALITY,
ARG_VOLATILE,
ARG_TEMPLATE,
@@ -375,6 +380,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
{ "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN },
{ "network-veth", no_argument, NULL, 'n' },
+ { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA},
{ "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE },
{ "personality", required_argument, NULL, ARG_PERSONALITY },
{ "image", required_argument, NULL, 'i' },
@@ -449,6 +455,15 @@ static int parse_argv(int argc, char *argv[]) {
arg_settings_mask |= SETTING_NETWORK;
break;
+ case ARG_NETWORK_VETH_EXTRA:
+ r = veth_extra_parse(&arg_network_veth_extra, optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --network-veth-extra= parameter: %s", optarg);
+
+ arg_private_network = true;
+ arg_settings_mask |= SETTING_NETWORK;
+ break;
+
case ARG_NETWORK_INTERFACE:
if (strv_extend(&arg_network_interfaces, optarg) < 0)
return log_oom();
@@ -2268,7 +2283,7 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) {
static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
pid_t pid;
- pid = PTR_TO_UINT32(userdata);
+ pid = PTR_TO_PID(userdata);
if (pid > 0) {
if (kill(pid, arg_kill_signal) >= 0) {
log_info("Trying to halt container. Send SIGTERM again to trigger immediate termination.");
@@ -2964,12 +2979,13 @@ static int load_settings(void) {
settings->network_bridge ||
settings->network_interfaces ||
settings->network_macvlan ||
- settings->network_ipvlan)) {
+ settings->network_ipvlan ||
+ settings->network_veth_extra)) {
if (!arg_settings_trusted)
log_warning("Ignoring network settings, file %s is not trusted.", p);
else {
- arg_network_veth = settings_private_network(settings);
+ arg_network_veth = settings_network_veth(settings);
arg_private_network = settings_private_network(settings);
strv_free(arg_network_interfaces);
@@ -2984,6 +3000,10 @@ static int load_settings(void) {
arg_network_ipvlan = settings->network_ipvlan;
settings->network_ipvlan = NULL;
+ strv_free(arg_network_veth_extra);
+ arg_network_veth_extra = settings->network_veth_extra;
+ settings->network_veth_extra = NULL;
+
free(arg_network_bridge);
arg_network_bridge = settings->network_bridge;
settings->network_bridge = NULL;
@@ -3409,6 +3429,10 @@ int main(int argc, char *argv[]) {
}
}
+ r = setup_veth_extra(arg_machine, pid, arg_network_veth_extra);
+ if (r < 0)
+ goto finish;
+
r = setup_macvlan(arg_machine, pid, arg_network_macvlan);
if (r < 0)
goto finish;
@@ -3486,8 +3510,8 @@ int main(int argc, char *argv[]) {
if (arg_kill_signal > 0) {
/* Try to kill the init system on SIGINT or SIGTERM */
- sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, UINT32_TO_PTR(pid));
- sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, UINT32_TO_PTR(pid));
+ sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(pid));
+ sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(pid));
} else {
/* Immediately exit */
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
@@ -3610,6 +3634,7 @@ finish:
strv_free(arg_network_interfaces);
strv_free(arg_network_macvlan);
strv_free(arg_network_ipvlan);
+ strv_free(arg_network_veth_extra);
strv_free(arg_parameters);
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
expose_port_free_all(arg_expose_ports);
diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c
index dc2911e4e8..883d96608d 100644
--- a/src/quotacheck/quotacheck.c
+++ b/src/quotacheck/quotacheck.c
@@ -25,11 +25,11 @@
#include <sys/prctl.h>
#include <unistd.h>
+#include "proc-cmdline.h"
#include "process-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "util.h"
-#include "proc-cmdline.h"
static bool arg_skip = false;
static bool arg_force = false;
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
index 57f99c9ef0..9fc56284d2 100644
--- a/src/remount-fs/remount-fs.c
+++ b/src/remount-fs/remount-fs.c
@@ -19,19 +19,22 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <errno.h>
+#include <mntent.h>
#include <string.h>
+#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <mntent.h>
+#include <unistd.h>
#include "exit-status.h"
#include "log.h"
#include "mount-setup.h"
#include "mount-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "signal-util.h"
+#include "strv.h"
#include "util.h"
/* Goes through /etc/fstab and remounts all API file systems, applying
@@ -39,10 +42,10 @@
* respected */
int main(int argc, char *argv[]) {
- int ret = EXIT_FAILURE;
+ _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
_cleanup_endmntent_ FILE *f = NULL;
struct mntent* me;
- Hashmap *pids = NULL;
+ int r;
if (argc > 1) {
log_error("This program takes no argument.");
@@ -57,21 +60,21 @@ int main(int argc, char *argv[]) {
f = setmntent("/etc/fstab", "r");
if (!f) {
- if (errno == ENOENT)
- return EXIT_SUCCESS;
+ if (errno == ENOENT) {
+ r = 0;
+ goto finish;
+ }
- log_error_errno(errno, "Failed to open /etc/fstab: %m");
- return EXIT_FAILURE;
+ r = log_error_errno(errno, "Failed to open /etc/fstab: %m");
+ goto finish;
}
pids = hashmap_new(NULL);
if (!pids) {
- log_error("Failed to allocate set");
+ r = log_oom();
goto finish;
}
- ret = EXIT_SUCCESS;
-
while ((me = getmntent(f))) {
pid_t pid;
int k;
@@ -87,25 +90,18 @@ int main(int argc, char *argv[]) {
pid = fork();
if (pid < 0) {
- log_error_errno(errno, "Failed to fork: %m");
- ret = EXIT_FAILURE;
- continue;
+ r = log_error_errno(errno, "Failed to fork: %m");
+ goto finish;
}
if (pid == 0) {
- const char *arguments[5];
/* Child */
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
+ (void) prctl(PR_SET_PDEATHSIG, SIGTERM);
- arguments[0] = MOUNT_PATH;
- arguments[1] = me->mnt_dir;
- arguments[2] = "-o";
- arguments[3] = "remount";
- arguments[4] = NULL;
-
- execv(MOUNT_PATH, (char **) arguments);
+ execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, me->mnt_dir, "-o", "remount"));
log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m");
_exit(EXIT_FAILURE);
@@ -115,20 +111,19 @@ int main(int argc, char *argv[]) {
s = strdup(me->mnt_dir);
if (!s) {
- log_oom();
- ret = EXIT_FAILURE;
- continue;
+ r = log_oom();
+ goto finish;
}
-
- k = hashmap_put(pids, UINT_TO_PTR(pid), s);
+ k = hashmap_put(pids, PID_TO_PTR(pid), s);
if (k < 0) {
- log_error_errno(k, "Failed to add PID to set: %m");
- ret = EXIT_FAILURE;
- continue;
+ free(s);
+ r = log_oom();
+ goto finish;
}
}
+ r = 0;
while (!hashmap_isempty(pids)) {
siginfo_t si = {};
char *s;
@@ -138,12 +133,11 @@ int main(int argc, char *argv[]) {
if (errno == EINTR)
continue;
- log_error_errno(errno, "waitid() failed: %m");
- ret = EXIT_FAILURE;
- break;
+ r = log_error_errno(errno, "waitid() failed: %m");
+ goto finish;
}
- s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
+ s = hashmap_remove(pids, PID_TO_PTR(si.si_pid));
if (s) {
if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
if (si.si_code == CLD_EXITED)
@@ -151,7 +145,7 @@ int main(int argc, char *argv[]) {
else
log_error(MOUNT_PATH " for %s terminated by signal %s.", s, signal_to_string(si.si_status));
- ret = EXIT_FAILURE;
+ r = -ENOEXEC;
}
free(s);
@@ -159,9 +153,5 @@ int main(int argc, char *argv[]) {
}
finish:
-
- if (pids)
- hashmap_free_free(pids);
-
- return ret;
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c
index 432e62dd9f..eb4e646846 100644
--- a/src/resolve-host/resolve-host.c
+++ b/src/resolve-host/resolve-host.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <net/if.h>
#include <getopt.h>
+#include <net/if.h>
#include "sd-bus.h"
diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c
index 5c3a4a00c3..6a7ff9d245 100644
--- a/src/resolve/resolved-llmnr.c
+++ b/src/resolve/resolved-llmnr.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <resolv.h>
#include <netinet/in.h>
+#include <resolv.h>
#include "fd-util.h"
#include "resolved-llmnr.h"
diff --git a/src/run/run.c b/src/run/run.c
index 38a482bb11..df6a4f0074 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -33,6 +33,7 @@
#include "event-util.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "ptyfwd.h"
#include "signal-util.h"
@@ -41,7 +42,6 @@
#include "terminal-util.h"
#include "unit-name.h"
#include "user-util.h"
-#include "parse-util.h"
static bool arg_ask_password = true;
static bool arg_scope = false;
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 79f5a60579..35f2e1b67d 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -22,8 +22,8 @@
#include <errno.h>
#include <stdbool.h>
-#include "alloc-util.h"
#include "acl-util.h"
+#include "alloc-util.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index 8e36067f74..30e03c0652 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -25,8 +25,8 @@
#include <string.h>
#include <unistd.h>
-#include "alloc-util.h"
#include "acpi-fpdt.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "time-util.h"
diff --git a/src/shared/architecture.c b/src/shared/architecture.c
index e2efa4272b..73937bd5a7 100644
--- a/src/shared/architecture.c
+++ b/src/shared/architecture.c
@@ -21,9 +21,9 @@
#include <sys/utsname.h>
+#include "architecture.h"
#include "string-table.h"
#include "string-util.h"
-#include "architecture.h"
int uname_architecture(void) {
diff --git a/src/shared/boot-timestamps.c b/src/shared/boot-timestamps.c
index ecbe1aaa0f..879aca9374 100644
--- a/src/shared/boot-timestamps.c
+++ b/src/shared/boot-timestamps.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "boot-timestamps.h"
#include "acpi-fpdt.h"
+#include "boot-timestamps.h"
#include "efivars.h"
int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index a13991a960..73ceeba18f 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1654,7 +1654,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
r = sd_bus_message_append(m, "v", "i", i);
- } else if (streq(field, "Environment")) {
+ } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");
@@ -1678,9 +1678,16 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
if (r == 0)
break;
- if (!env_assignment_is_valid(word)) {
- log_error("Invalid environment assignment: %s", eq);
- return -EINVAL;
+ if (streq(field, "Environment")) {
+ if (!env_assignment_is_valid(word)) {
+ log_error("Invalid environment assignment: %s", word);
+ return -EINVAL;
+ }
+ } else { /* PassEnvironment */
+ if (!env_name_is_valid(word)) {
+ log_error("Invalid environment variable name: %s", word);
+ return -EINVAL;
+ }
}
r = sd_bus_message_append_basic(m, 's', word);
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index 835fe52423..71cc613704 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -29,13 +29,13 @@
#include <sys/stat.h>
#include "clean-ipc.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "dirent-util.h"
static int clean_sysvipc_shm(uid_t delete_uid) {
_cleanup_fclose_ FILE *f = NULL;
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 86bb0b57c3..89deeb9b55 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
-#include <string.h>
#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "dirent-util.h"
diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c
index e178287872..5acfb0191b 100644
--- a/src/shared/firewall-util.c
+++ b/src/shared/firewall-util.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <arpa/inet.h>
#include <net/if.h>
+#include <sys/types.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter/xt_addrtype.h>
diff --git a/src/shared/generator.c b/src/shared/generator.c
index cb4ebc606e..9998c64416 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -64,7 +64,7 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
"Description=File System Check on %2$s\n"
"DefaultDependencies=no\n"
"BindsTo=%3$s\n"
- "After=%3$s\n"
+ "After=%3$s local-fs-pre.target\n"
"Before=shutdown.target\n"
"\n"
"[Service]\n"
@@ -142,7 +142,7 @@ int generator_write_fsck_deps(
}
fprintf(f,
- "RequiresOverridable=%1$s\n"
+ "Requires=%1$s\n"
"After=%1$s\n",
fsck);
}
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index e1cb5d27ff..74b909d34d 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -67,42 +67,28 @@ static int specifier_instance(char specifier, void *data, void *userdata, char *
}
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
- UnitFileInstallInfo *i = userdata;
- const char *username;
- _cleanup_free_ char *tmp = NULL;
- char *printed = NULL;
-
- assert(i);
+ char *t;
- if (i->user)
- username = i->user;
- else
- /* get USER env from env or our own uid */
- username = tmp = getusername_malloc();
-
- switch (specifier) {
- case 'u':
- printed = strdup(username);
- break;
- case 'U': {
- /* fish username from passwd */
- uid_t uid;
- int r;
-
- r = get_user_creds(&username, &uid, NULL, NULL, NULL);
- if (r < 0)
- return r;
-
- if (asprintf(&printed, UID_FMT, uid) < 0)
- return -ENOMEM;
- break;
- }}
+ /* 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 = printed;
+ *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) {
@@ -114,8 +100,8 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret)
* %p: the prefix (foo)
* %i: the instance (bar)
- * %U the UID of the configured user or running user
- * %u the username of the configured user or running user
+ * %U the UID of the running user
+ * %u the username of running user
* %m the machine ID of the running system
* %H the host name of the running system
* %b the boot ID of the running system
@@ -128,7 +114,7 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret)
{ 'p', specifier_prefix, NULL },
{ 'i', specifier_instance, NULL },
- { 'U', specifier_user_name, NULL },
+ { 'U', specifier_user_id, NULL },
{ 'u', specifier_user_name, NULL },
{ 'm', specifier_machine_id, NULL },
diff --git a/src/shared/install.c b/src/shared/install.c
index b7d1d22505..17e03e59cd 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -30,6 +30,7 @@
#include "conf-parser.h"
#include "dirent-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "fs-util.h"
#include "hashmap.h"
#include "install-printf.h"
@@ -46,13 +47,21 @@
#include "unit-name.h"
#include "util.h"
+#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
+
+typedef enum SearchFlags {
+ SEARCH_LOAD = 1,
+ SEARCH_FOLLOW_CONFIG_SYMLINKS = 2,
+} SearchFlags;
+
typedef struct {
- OrderedHashmap *will_install;
- OrderedHashmap *have_installed;
+ OrderedHashmap *will_process;
+ OrderedHashmap *have_processed;
} InstallContext;
static int in_search_path(const char *path, char **search) {
_cleanup_free_ char *parent = NULL;
+ char **i;
assert(path);
@@ -60,7 +69,11 @@ static int in_search_path(const char *path, char **search) {
if (!parent)
return -ENOMEM;
- return strv_contains(search, parent);
+ STRV_FOREACH(i, search)
+ if (path_equal(parent, *i))
+ return true;
+
+ return false;
}
static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
@@ -71,6 +84,9 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(ret);
+ /* This determines where we shall create or remove our
+ * installation ("configuration") symlinks */
+
switch (scope) {
case UNIT_FILE_SYSTEM:
@@ -101,9 +117,10 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d
r = user_runtime_dir(&p);
else
r = user_config_home(&p);
-
- if (r <= 0)
- return r < 0 ? r : -ENOENT;
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOENT;
break;
@@ -118,6 +135,185 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d
return 0;
}
+static bool is_config_path(UnitFileScope scope, const char *path) {
+ int r;
+
+ assert(scope >= 0);
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
+ assert(path);
+
+ /* Checks whether the specified path is intended for
+ * configuration or is outside of it */
+
+ switch (scope) {
+
+ case UNIT_FILE_SYSTEM:
+ case UNIT_FILE_GLOBAL:
+ return path_startswith(path, "/etc") ||
+ path_startswith(path, SYSTEM_CONFIG_UNIT_PATH) ||
+ path_startswith(path, "/run");
+
+
+ case UNIT_FILE_USER: {
+ _cleanup_free_ char *p = NULL;
+
+ r = user_config_home(&p);
+ if (r < 0)
+ return r;
+ if (r > 0 && path_startswith(path, p))
+ return true;
+
+ p = mfree(p);
+
+ r = user_runtime_dir(&p);
+ if (r < 0)
+ return r;
+ if (r > 0 && path_startswith(path, p))
+ return true;
+
+ return false;
+ }
+
+ default:
+ assert_not_reached("Bad scope");
+ }
+}
+
+
+static int verify_root_dir(UnitFileScope scope, const char **root_dir) {
+ int r;
+
+ assert(root_dir);
+
+ /* Verifies that the specified root directory to operate on
+ * makes sense. Reset it to NULL if it is the root directory
+ * or set to empty */
+
+ if (isempty(*root_dir) || path_equal(*root_dir, "/")) {
+ *root_dir = NULL;
+ return 0;
+ }
+
+ if (scope != UNIT_FILE_SYSTEM)
+ return -EINVAL;
+
+ r = is_dir(*root_dir, true);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOTDIR;
+
+ return 0;
+}
+
+int unit_file_changes_add(
+ UnitFileChange **changes,
+ unsigned *n_changes,
+ UnitFileChangeType type,
+ const char *path,
+ const char *source) {
+
+ UnitFileChange *c;
+ unsigned i;
+
+ assert(path);
+ assert(!changes == !n_changes);
+
+ if (!changes)
+ return 0;
+
+ c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
+ if (!c)
+ return -ENOMEM;
+
+ *changes = c;
+ i = *n_changes;
+
+ c[i].type = type;
+ c[i].path = strdup(path);
+ if (!c[i].path)
+ return -ENOMEM;
+
+ path_kill_slashes(c[i].path);
+
+ if (source) {
+ c[i].source = strdup(source);
+ if (!c[i].source) {
+ free(c[i].path);
+ return -ENOMEM;
+ }
+
+ path_kill_slashes(c[i].path);
+ } else
+ c[i].source = NULL;
+
+ *n_changes = i+1;
+ return 0;
+}
+
+void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
+ unsigned i;
+
+ assert(changes || n_changes == 0);
+
+ if (!changes)
+ return;
+
+ for (i = 0; i < n_changes; i++) {
+ free(changes[i].path);
+ free(changes[i].source);
+ }
+
+ free(changes);
+}
+
+static int create_symlink(
+ const char *old_path,
+ const char *new_path,
+ bool force,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ _cleanup_free_ char *dest = NULL;
+ int r;
+
+ assert(old_path);
+ assert(new_path);
+
+ /* Actually create a symlink, and remember that we did. Is
+ * smart enough to check if there's already a valid symlink in
+ * place. */
+
+ mkdir_parents_label(new_path, 0755);
+
+ if (symlink(old_path, new_path) >= 0) {
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
+ return 0;
+ }
+
+ if (errno != EEXIST)
+ return -errno;
+
+ r = readlink_malloc(new_path, &dest);
+ if (r < 0)
+ return r;
+
+ if (path_equal(dest, old_path))
+ return 0;
+
+ if (!force)
+ return -EEXIST;
+
+ r = symlink_atomic(old_path, new_path);
+ if (r < 0)
+ return r;
+
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
+
+ return 0;
+}
+
static int mark_symlink_for_removal(
Set **remove_symlinks_to,
const char *p) {
@@ -138,10 +334,12 @@ static int mark_symlink_for_removal(
path_kill_slashes(n);
r = set_consume(*remove_symlinks_to, n);
+ if (r == -EEXIST)
+ return 0;
if (r < 0)
- return r == -EEXIST ? 0 : r;
+ return r;
- return 0;
+ return 1;
}
static int remove_marked_symlinks_fd(
@@ -149,19 +347,19 @@ static int remove_marked_symlinks_fd(
int fd,
const char *path,
const char *config_path,
- bool *deleted,
+ bool *restart,
UnitFileChange **changes,
- unsigned *n_changes,
- char** instance_whitelist) {
+ unsigned *n_changes) {
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
int r = 0;
assert(remove_symlinks_to);
assert(fd >= 0);
assert(path);
assert(config_path);
- assert(deleted);
+ assert(restart);
d = fdopendir(fd);
if (!d) {
@@ -171,27 +369,13 @@ static int remove_marked_symlinks_fd(
rewinddir(d);
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno != 0) {
- r = -errno;
- break;
- }
-
- if (!de)
- break;
-
- if (hidden_file(de->d_name))
- continue;
+ FOREACH_DIRENT(de, d, return -errno) {
dirent_ensure_type(d, de);
if (de->d_type == DT_DIR) {
- int nfd, q;
_cleanup_free_ char *p = NULL;
+ int nfd, q;
nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (nfd < 0) {
@@ -210,42 +394,23 @@ static int remove_marked_symlinks_fd(
}
/* This will close nfd, regardless whether it succeeds or not */
- q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
+ q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, restart, changes, n_changes);
if (q < 0 && r == 0)
r = q;
} else if (de->d_type == DT_LNK) {
_cleanup_free_ char *p = NULL, *dest = NULL;
- int q;
bool found;
+ int q;
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue;
- if (unit_name_is_valid(de->d_name, UNIT_NAME_INSTANCE) &&
- instance_whitelist &&
- !strv_contains(instance_whitelist, de->d_name)) {
-
- _cleanup_free_ char *w = NULL;
-
- /* OK, the file is not listed directly
- * in the whitelist, so let's check if
- * the template of it might be
- * listed. */
-
- r = unit_name_template(de->d_name, &w);
- if (r < 0)
- return r;
-
- if (!strv_contains(instance_whitelist, w))
- continue;
- }
-
p = path_make_absolute(de->d_name, path);
if (!p)
return -ENOMEM;
- q = readlink_and_canonicalize(p, &dest);
+ q = readlink_malloc(p, &dest);
if (q < 0) {
if (q == -ENOENT)
continue;
@@ -255,9 +420,15 @@ static int remove_marked_symlinks_fd(
continue;
}
+ /* We remove all links pointing to a file or
+ * path that is marked, as well as all files
+ * sharing the same name as a file that is
+ * marked. */
+
found =
- set_get(remove_symlinks_to, dest) ||
- set_get(remove_symlinks_to, basename(dest));
+ set_contains(remove_symlinks_to, dest) ||
+ set_contains(remove_symlinks_to, basename(dest)) ||
+ set_contains(remove_symlinks_to, de->d_name);
if (!found)
continue;
@@ -269,18 +440,15 @@ static int remove_marked_symlinks_fd(
}
path_kill_slashes(p);
- rmdir_parents(p, config_path);
- unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
+ (void) rmdir_parents(p, config_path);
- if (!set_get(remove_symlinks_to, p)) {
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
- q = mark_symlink_for_removal(&remove_symlinks_to, p);
- if (q < 0) {
- if (r == 0)
- r = q;
- } else
- *deleted = true;
- }
+ q = mark_symlink_for_removal(&remove_symlinks_to, p);
+ if (q < 0)
+ return q;
+ if (q > 0)
+ *restart = true;
}
}
@@ -291,12 +459,11 @@ static int remove_marked_symlinks(
Set *remove_symlinks_to,
const char *config_path,
UnitFileChange **changes,
- unsigned *n_changes,
- char** instance_whitelist) {
+ unsigned *n_changes) {
_cleanup_close_ int fd = -1;
+ bool restart;
int r = 0;
- bool deleted;
assert(config_path);
@@ -309,32 +476,32 @@ static int remove_marked_symlinks(
do {
int q, cfd;
- deleted = false;
+ restart = false;
cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
- if (cfd < 0) {
- r = -errno;
- break;
- }
+ if (cfd < 0)
+ return -errno;
/* This takes possession of cfd and closes it */
- q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
+ q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &restart, changes, n_changes);
if (r == 0)
r = q;
- } while (deleted);
+ } while (restart);
return r;
}
static int find_symlinks_fd(
+ const char *root_dir,
const char *name,
int fd,
const char *path,
const char *config_path,
bool *same_name_link) {
- int r = 0;
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
+ int r = 0;
assert(name);
assert(fd >= 0);
@@ -348,25 +515,13 @@ static int find_symlinks_fd(
return -errno;
}
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno != 0)
- return -errno;
-
- if (!de)
- return r;
-
- if (hidden_file(de->d_name))
- continue;
+ FOREACH_DIRENT(de, d, return -errno) {
dirent_ensure_type(d, de);
if (de->d_type == DT_DIR) {
- int nfd, q;
_cleanup_free_ char *p = NULL;
+ int nfd, q;
nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (nfd < 0) {
@@ -385,7 +540,7 @@ static int find_symlinks_fd(
}
/* This will close nfd, regardless whether it succeeds or not */
- q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
+ q = find_symlinks_fd(root_dir, name, nfd, p, config_path, same_name_link);
if (q > 0)
return 1;
if (r == 0)
@@ -402,16 +557,27 @@ static int find_symlinks_fd(
return -ENOMEM;
/* Acquire symlink destination */
- q = readlink_and_canonicalize(p, &dest);
+ q = readlink_malloc(p, &dest);
+ if (q == -ENOENT)
+ continue;
if (q < 0) {
- if (q == -ENOENT)
- continue;
-
if (r == 0)
r = q;
continue;
}
+ /* Make absolute */
+ if (!path_is_absolute(dest)) {
+ char *x;
+
+ x = prefix_root(root_dir, dest);
+ if (!x)
+ return -ENOMEM;
+
+ free(dest);
+ dest = x;
+ }
+
/* Check if the symlink itself matches what we
* are looking for */
if (path_is_absolute(name))
@@ -444,9 +610,12 @@ static int find_symlinks_fd(
return 1;
}
}
+
+ return r;
}
static int find_symlinks(
+ const char *root_dir,
const char *name,
const char *config_path,
bool *same_name_link) {
@@ -465,7 +634,7 @@ static int find_symlinks(
}
/* This takes possession of fd and closes it */
- return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
+ return find_symlinks_fd(root_dir, name, fd, config_path, config_path, same_name_link);
}
static int find_symlinks_in_scope(
@@ -474,350 +643,59 @@ static int find_symlinks_in_scope(
const char *name,
UnitFileState *state) {
- int r;
_cleanup_free_ char *normal_path = NULL, *runtime_path = NULL;
bool same_name_link_runtime = false, same_name_link = false;
+ int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
- /* First look in runtime config path */
- r = get_config_path(scope, true, root_dir, &normal_path);
+ /* First look in the normal config path */
+ r = get_config_path(scope, false, root_dir, &normal_path);
if (r < 0)
return r;
- r = find_symlinks(name, normal_path, &same_name_link_runtime);
+ r = find_symlinks(root_dir, name, normal_path, &same_name_link);
if (r < 0)
return r;
- else if (r > 0) {
- *state = UNIT_FILE_ENABLED_RUNTIME;
+ if (r > 0) {
+ *state = UNIT_FILE_ENABLED;
return r;
}
- /* Then look in the normal config path */
- r = get_config_path(scope, false, root_dir, &runtime_path);
+ /* Then look in runtime config path */
+ r = get_config_path(scope, true, root_dir, &runtime_path);
if (r < 0)
return r;
- r = find_symlinks(name, runtime_path, &same_name_link);
+ r = find_symlinks(root_dir, name, runtime_path, &same_name_link_runtime);
if (r < 0)
return r;
- else if (r > 0) {
- *state = UNIT_FILE_ENABLED;
+ if (r > 0) {
+ *state = UNIT_FILE_ENABLED_RUNTIME;
return r;
}
/* Hmm, we didn't find it, but maybe we found the same name
* link? */
- if (same_name_link_runtime) {
- *state = UNIT_FILE_LINKED_RUNTIME;
- return 1;
- } else if (same_name_link) {
+ if (same_name_link) {
*state = UNIT_FILE_LINKED;
return 1;
}
-
- return 0;
-}
-
-int unit_file_mask(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char **files,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **i;
- _cleanup_free_ char *prefix = NULL;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- r = get_config_path(scope, runtime, root_dir, &prefix);
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, files) {
- _cleanup_free_ char *path = NULL;
-
- if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- path = path_make_absolute(*i, prefix);
- if (!path) {
- r = -ENOMEM;
- break;
- }
-
- if (symlink("/dev/null", path) >= 0) {
- unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
- continue;
- }
-
- if (errno == EEXIST) {
-
- if (null_or_empty_path(path) > 0)
- continue;
-
- if (force) {
- if (symlink_atomic("/dev/null", path) >= 0) {
- unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
- unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
- continue;
- }
- }
-
- if (r == 0)
- r = -EEXIST;
- } else {
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-int unit_file_unmask(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char **files,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **i, *config_path = NULL;
- int r, q;
- Set *remove_symlinks_to = NULL;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
- _cleanup_free_ char *path = NULL;
-
- if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- path = path_make_absolute(*i, config_path);
- if (!path) {
- r = -ENOMEM;
- break;
- }
-
- q = null_or_empty_path(path);
- if (q > 0) {
- if (unlink(path) < 0)
- q = -errno;
- else {
- q = mark_symlink_for_removal(&remove_symlinks_to, path);
- unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
- }
- }
-
- if (q != -ENOENT && r == 0)
- r = q;
- }
-
-
-finish:
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r == 0)
- r = q;
-
- set_free_free(remove_symlinks_to);
- free(config_path);
-
- return r;
-}
-
-int unit_file_link(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char **files,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
- char **i;
- _cleanup_free_ char *config_path = NULL;
- int r, q;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- r = lookup_paths_init_from_scope(&paths, scope, root_dir);
- if (r < 0)
- return r;
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, files) {
- _cleanup_free_ char *path = NULL;
- char *fn;
- struct stat st;
-
- fn = basename(*i);
-
- if (!path_is_absolute(*i) ||
- !unit_name_is_valid(fn, UNIT_NAME_ANY)) {
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- if (lstat(*i, &st) < 0) {
- if (r == 0)
- r = -errno;
- continue;
- }
-
- if (!S_ISREG(st.st_mode)) {
- r = -ENOENT;
- continue;
- }
-
- q = in_search_path(*i, paths.unit_path);
- if (q < 0)
- return q;
-
- if (q > 0)
- continue;
-
- path = path_make_absolute(fn, config_path);
- if (!path)
- return -ENOMEM;
-
- if (symlink(*i, path) >= 0) {
- unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
- continue;
- }
-
- if (errno == EEXIST) {
- _cleanup_free_ char *dest = NULL;
-
- q = readlink_and_make_absolute(path, &dest);
- if (q < 0 && errno != ENOENT) {
- if (r == 0)
- r = q;
- continue;
- }
-
- if (q >= 0 && path_equal(dest, *i))
- continue;
-
- if (force) {
- if (symlink_atomic(*i, path) >= 0) {
- unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
- unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
- continue;
- }
- }
-
- if (r == 0)
- r = -EEXIST;
- } else {
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-void unit_file_list_free(Hashmap *h) {
- UnitFileList *i;
-
- while ((i = hashmap_steal_first(h))) {
- free(i->path);
- free(i);
+ if (same_name_link_runtime) {
+ *state = UNIT_FILE_LINKED_RUNTIME;
+ return 1;
}
- hashmap_free(h);
-}
-
-int unit_file_changes_add(
- UnitFileChange **changes,
- unsigned *n_changes,
- UnitFileChangeType type,
- const char *path,
- const char *source) {
-
- UnitFileChange *c;
- unsigned i;
-
- assert(path);
- assert(!changes == !n_changes);
-
- if (!changes)
- return 0;
-
- c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
- if (!c)
- return -ENOMEM;
-
- *changes = c;
- i = *n_changes;
-
- c[i].type = type;
- c[i].path = strdup(path);
- if (!c[i].path)
- return -ENOMEM;
-
- path_kill_slashes(c[i].path);
-
- if (source) {
- c[i].source = strdup(source);
- if (!c[i].source) {
- free(c[i].path);
- return -ENOMEM;
- }
-
- path_kill_slashes(c[i].path);
- } else
- c[i].source = NULL;
-
- *n_changes = i+1;
return 0;
}
-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
- unsigned i;
-
- assert(changes || n_changes == 0);
+static void install_info_free(UnitFileInstallInfo *i) {
- if (!changes)
+ if (!i)
return;
- for (i = 0; i < n_changes; i++) {
- free(changes[i].path);
- free(changes[i].source);
- }
-
- free(changes);
-}
-
-static void install_info_free(UnitFileInstallInfo *i) {
- assert(i);
-
free(i->name);
free(i->path);
strv_free(i->aliases);
@@ -825,34 +703,45 @@ static void install_info_free(UnitFileInstallInfo *i) {
strv_free(i->required_by);
strv_free(i->also);
free(i->default_instance);
+ free(i->symlink_target);
free(i);
}
-static void install_info_hashmap_free(OrderedHashmap *m) {
+static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) {
UnitFileInstallInfo *i;
if (!m)
- return;
+ return NULL;
while ((i = ordered_hashmap_steal_first(m)))
install_info_free(i);
- ordered_hashmap_free(m);
+ return ordered_hashmap_free(m);
}
static void install_context_done(InstallContext *c) {
assert(c);
- install_info_hashmap_free(c->will_install);
- install_info_hashmap_free(c->have_installed);
+ c->will_process = install_info_hashmap_free(c->will_process);
+ c->have_processed = install_info_hashmap_free(c->have_processed);
+}
+
+static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) {
+ UnitFileInstallInfo *i;
+
+ i = ordered_hashmap_get(c->have_processed, name);
+ if (i)
+ return i;
- c->will_install = c->have_installed = NULL;
+ return ordered_hashmap_get(c->will_process, name);
}
static int install_info_add(
InstallContext *c,
const char *name,
- const char *path) {
+ const char *path,
+ UnitFileInstallInfo **ret) {
+
UnitFileInstallInfo *i = NULL;
int r;
@@ -865,17 +754,21 @@ static int install_info_add(
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
return -EINVAL;
- if (ordered_hashmap_get(c->have_installed, name) ||
- ordered_hashmap_get(c->will_install, name))
+ i = install_info_find(c, name);
+ if (i) {
+ if (ret)
+ *ret = i;
return 0;
+ }
- r = ordered_hashmap_ensure_allocated(&c->will_install, &string_hash_ops);
+ r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
if (r < 0)
return r;
i = new0(UnitFileInstallInfo, 1);
if (!i)
return -ENOMEM;
+ i->type = _UNIT_FILE_TYPE_INVALID;
i->name = strdup(name);
if (!i->name) {
@@ -891,30 +784,32 @@ static int install_info_add(
}
}
- r = ordered_hashmap_put(c->will_install, i->name, i);
+ r = ordered_hashmap_put(c->will_process, i->name, i);
if (r < 0)
goto fail;
+ if (ret)
+ *ret = i;
+
return 0;
fail:
- if (i)
- install_info_free(i);
-
+ install_info_free(i);
return r;
}
static int install_info_add_auto(
InstallContext *c,
- const char *name_or_path) {
+ const char *name_or_path,
+ UnitFileInstallInfo **ret) {
assert(c);
assert(name_or_path);
if (path_is_absolute(name_or_path))
- return install_info_add(c, NULL, name_or_path);
+ return install_info_add(c, NULL, name_or_path, ret);
else
- return install_info_add(c, name_or_path, NULL);
+ return install_info_add(c, name_or_path, NULL, ret);
}
static int config_parse_also(
@@ -929,64 +824,33 @@ static int config_parse_also(
void *data,
void *userdata) {
- InstallContext *c = data;
UnitFileInstallInfo *i = userdata;
+ InstallContext *c = data;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- for(;;) {
- _cleanup_free_ char *n = NULL;
- int r;
-
- r = extract_first_word(&rvalue, &n, NULL, 0);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse config %s, ignoring.", rvalue);
- return 0;
- }
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ r = extract_first_word(&rvalue, &word, NULL, 0);
+ if (r < 0)
+ return r;
if (r == 0)
break;
- r = install_info_add(c, n, NULL);
+ r = install_info_add(c, word, NULL, NULL);
if (r < 0)
return r;
- r = strv_extend(&i->also, n);
+ r = strv_push(&i->also, word);
if (r < 0)
return r;
- }
-
- return 0;
-}
-static int config_parse_user(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- UnitFileInstallInfo *i = data;
- char *printed;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = install_full_printf(i, rvalue, &printed);
- if (r < 0)
- return r;
-
- free(i->user);
- i->user = printed;
+ word = NULL;
+ }
return 0;
}
@@ -1031,9 +895,7 @@ static int unit_file_load(
UnitFileInstallInfo *info,
const char *path,
const char *root_dir,
- bool allow_symlink,
- bool load,
- bool *also) {
+ SearchFlags flags) {
const ConfigTableItem items[] = {
{ "Install", "Alias", config_parse_strv, 0, &info->aliases },
@@ -1041,34 +903,57 @@ static int unit_file_load(
{ "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
{ "Install", "DefaultInstance", config_parse_default_instance, 0, info },
{ "Install", "Also", config_parse_also, 0, c },
- { "Exec", "User", config_parse_user, 0, info },
{}
};
_cleanup_fclose_ FILE *f = NULL;
- int fd, r;
+ _cleanup_close_ int fd = -1;
+ struct stat st;
+ int r;
assert(c);
assert(info);
assert(path);
- if (!isempty(root_dir))
- path = strjoina(root_dir, "/", path);
+ path = prefix_roota(root_dir, path);
- if (!load) {
- r = access(path, F_OK) ? -errno : 0;
- return r;
+ if (!(flags & SEARCH_LOAD)) {
+ r = lstat(path, &st);
+ if (r < 0)
+ return -errno;
+
+ if (null_or_empty(&st))
+ info->type = UNIT_FILE_TYPE_MASKED;
+ else if (S_ISREG(st.st_mode))
+ info->type = UNIT_FILE_TYPE_REGULAR;
+ else if (S_ISLNK(st.st_mode))
+ return -ELOOP;
+ else if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ else
+ return -ENOTTY;
+
+ return 0;
}
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
+ fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
if (fd < 0)
return -errno;
+ if (fstat(fd, &st) < 0)
+ return -errno;
+ if (null_or_empty(&st)) {
+ info->type = UNIT_FILE_TYPE_MASKED;
+ return 0;
+ }
+ if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ if (!S_ISREG(st.st_mode))
+ return -ENOTTY;
f = fdopen(fd, "re");
- if (!f) {
- safe_close(fd);
- return -ENOMEM;
- }
+ if (!f)
+ return -errno;
+ fd = -1;
r = config_parse(NULL, path, f,
NULL,
@@ -1077,8 +962,7 @@ static int unit_file_load(
if (r < 0)
return r;
- if (also)
- *also = !strv_isempty(info->also);
+ info->type = UNIT_FILE_TYPE_REGULAR;
return
(int) strv_length(info->aliases) +
@@ -1086,14 +970,73 @@ static int unit_file_load(
(int) strv_length(info->required_by);
}
+static int unit_file_load_or_readlink(
+ InstallContext *c,
+ UnitFileInstallInfo *info,
+ const char *path,
+ const char *root_dir,
+ SearchFlags flags) {
+
+ _cleanup_free_ char *np = NULL;
+ int r;
+
+ r = unit_file_load(c, info, path, root_dir, flags);
+ if (r != -ELOOP)
+ return r;
+
+ /* This is a symlink, let's read it. */
+
+ r = readlink_and_make_absolute_root(root_dir, path, &np);
+ if (r < 0)
+ return r;
+
+ if (path_equal(np, "/dev/null"))
+ info->type = UNIT_FILE_TYPE_MASKED;
+ else {
+ const char *bn;
+ UnitType a, b;
+
+ bn = basename(np);
+
+ if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
+
+ if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
+ return -EINVAL;
+
+ } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
+
+ if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
+ return -EINVAL;
+
+ } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
+
+ if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ /* Enforce that the symlink destination does not
+ * change the unit file type. */
+
+ a = unit_name_to_type(info->name);
+ b = unit_name_to_type(bn);
+ if (a < 0 || b < 0 || a != b)
+ return -EINVAL;
+
+ info->type = UNIT_FILE_TYPE_SYMLINK;
+ info->symlink_target = np;
+ np = NULL;
+ }
+
+ return 0;
+}
+
static int unit_file_search(
InstallContext *c,
UnitFileInstallInfo *info,
const LookupPaths *paths,
const char *root_dir,
- bool allow_symlink,
- bool load,
- bool *also) {
+ SearchFlags flags) {
char **p;
int r;
@@ -1102,8 +1045,12 @@ static int unit_file_search(
assert(info);
assert(paths);
+ /* Was this unit already loaded? */
+ if (info->type != _UNIT_FILE_TYPE_INVALID)
+ return 0;
+
if (info->path)
- return unit_file_load(c, info, info->path, root_dir, allow_symlink, load, also);
+ return unit_file_load_or_readlink(c, info, info->path, root_dir, flags);
assert(info->name);
@@ -1114,14 +1061,15 @@ static int unit_file_search(
if (!path)
return -ENOMEM;
- r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also);
- if (r >= 0) {
+ r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return r;
+ } else {
info->path = path;
path = NULL;
return r;
}
- if (r != -ENOENT && r != -ELOOP)
- return r;
}
if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
@@ -1143,92 +1091,149 @@ static int unit_file_search(
if (!path)
return -ENOMEM;
- r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also);
- if (r >= 0) {
+ r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return r;
+ } else {
info->path = path;
path = NULL;
return r;
}
- if (r != -ENOENT && r != -ELOOP)
- return r;
}
}
return -ENOENT;
}
-static int unit_file_can_install(
- const LookupPaths *paths,
+static int install_info_follow(
+ InstallContext *c,
+ UnitFileInstallInfo *i,
const char *root_dir,
- const char *name,
- bool allow_symlink,
- bool *also) {
+ SearchFlags flags) {
+
+ assert(c);
+ assert(i);
+
+ if (i->type != UNIT_FILE_TYPE_SYMLINK)
+ return -EINVAL;
+ if (!i->symlink_target)
+ return -EINVAL;
+
+ /* If the basename doesn't match, the caller should add a
+ * complete new entry for this. */
+
+ if (!streq(basename(i->symlink_target), i->name))
+ return -EXDEV;
+
+ free(i->path);
+ i->path = i->symlink_target;
+ i->symlink_target = NULL;
+ i->type = _UNIT_FILE_TYPE_INVALID;
+
+ return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
+}
+
+static int install_info_traverse(
+ UnitFileScope scope,
+ InstallContext *c,
+ const char *root_dir,
+ const LookupPaths *paths,
+ UnitFileInstallInfo *start,
+ SearchFlags flags,
+ UnitFileInstallInfo **ret) {
- _cleanup_(install_context_done) InstallContext c = {};
UnitFileInstallInfo *i;
+ unsigned k = 0;
int r;
assert(paths);
- assert(name);
+ assert(start);
+ assert(c);
- r = install_info_add_auto(&c, name);
+ r = unit_file_search(c, start, paths, root_dir, flags);
if (r < 0)
return r;
- assert_se(i = ordered_hashmap_first(c.will_install));
+ i = start;
+ while (i->type == UNIT_FILE_TYPE_SYMLINK) {
+ /* Follow the symlink */
- r = unit_file_search(&c, i, paths, root_dir, allow_symlink, true, also);
+ if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
+ return -ELOOP;
- if (r >= 0)
- r =
- (int) strv_length(i->aliases) +
- (int) strv_length(i->wanted_by) +
- (int) strv_length(i->required_by);
+ if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS) && is_config_path(scope, i->path))
+ return -ELOOP;
- return r;
-}
+ r = install_info_follow(c, i, root_dir, flags);
+ if (r < 0) {
+ _cleanup_free_ char *buffer = NULL;
+ const char *bn;
-static int create_symlink(
- const char *old_path,
- const char *new_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
+ if (r != -EXDEV)
+ return r;
- _cleanup_free_ char *dest = NULL;
- int r;
+ /* Target has a different name, create a new
+ * install info object for that, and continue
+ * with that. */
- assert(old_path);
- assert(new_path);
+ bn = basename(i->symlink_target);
- mkdir_parents_label(new_path, 0755);
+ if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
+ unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
- if (symlink(old_path, new_path) >= 0) {
- unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
- return 0;
+ _cleanup_free_ char *instance = NULL;
+
+ r = unit_name_to_instance(i->name, &instance);
+ if (r < 0)
+ return r;
+
+ r = unit_name_replace_instance(bn, instance, &buffer);
+ if (r < 0)
+ return r;
+
+ bn = buffer;
+ }
+
+ r = install_info_add(c, bn, NULL, &i);
+ if (r < 0)
+ return r;
+
+ r = unit_file_search(c, i, paths, root_dir, flags);
+ if (r < 0)
+ return r;
+ }
+
+ /* Try again, with the new target we found. */
}
- if (errno != EEXIST)
- return -errno;
+ if (ret)
+ *ret = i;
- r = readlink_and_make_absolute(new_path, &dest);
- if (r < 0)
- return r;
+ return 0;
+}
- if (path_equal(dest, old_path))
- return 0;
+static int install_info_discover(
+ UnitFileScope scope,
+ InstallContext *c,
+ const char *root_dir,
+ const LookupPaths *paths,
+ const char *name,
+ SearchFlags flags,
+ UnitFileInstallInfo **ret) {
- if (!force)
- return -EEXIST;
+ UnitFileInstallInfo *i;
+ int r;
- r = symlink_atomic(old_path, new_path);
+ assert(c);
+ assert(paths);
+ assert(name);
+
+ r = install_info_add_auto(c, name, &i);
if (r < 0)
return r;
- unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
- unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
-
- return 0;
+ return install_info_traverse(scope, c, root_dir, paths, i, flags, ret);
}
static int install_info_symlink_alias(
@@ -1363,6 +1368,9 @@ static int install_info_apply(
assert(paths);
assert(config_path);
+ if (i->type != UNIT_FILE_TYPE_REGULAR)
+ return 0;
+
r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
@@ -1381,53 +1389,59 @@ static int install_info_apply(
}
static int install_context_apply(
+ UnitFileScope scope,
InstallContext *c,
const LookupPaths *paths,
const char *config_path,
const char *root_dir,
bool force,
+ SearchFlags flags,
UnitFileChange **changes,
unsigned *n_changes) {
UnitFileInstallInfo *i;
- int r, q;
+ int r;
assert(c);
assert(paths);
assert(config_path);
- if (!ordered_hashmap_isempty(c->will_install)) {
- r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
- if (r < 0)
- return r;
+ if (ordered_hashmap_isempty(c->will_process))
+ return 0;
- r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
- if (r < 0)
- return r;
- }
+ r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
+ if (r < 0)
+ return r;
r = 0;
- while ((i = ordered_hashmap_first(c->will_install))) {
- assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
+ while ((i = ordered_hashmap_first(c->will_process))) {
+ int q;
- q = unit_file_search(c, i, paths, root_dir, false, true, NULL);
- if (q < 0) {
- if (r >= 0)
- r = q;
+ q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
+ if (q < 0)
+ return q;
+ r = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL);
+ if (r < 0)
return r;
- } else if (r >= 0)
- r += q;
+
+ if (i->type != UNIT_FILE_TYPE_REGULAR)
+ continue;
q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
- if (r >= 0 && q < 0)
- r = q;
+ if (r >= 0) {
+ if (q < 0)
+ r = q;
+ else
+ r+= q;
+ }
}
return r;
}
static int install_context_mark_for_removal(
+ UnitFileScope scope,
InstallContext *c,
const LookupPaths *paths,
Set **remove_symlinks_to,
@@ -1435,7 +1449,7 @@ static int install_context_mark_for_removal(
const char *root_dir) {
UnitFileInstallInfo *i;
- int r, q;
+ int r;
assert(c);
assert(paths);
@@ -1443,87 +1457,182 @@ static int install_context_mark_for_removal(
/* Marks all items for removal */
- if (!ordered_hashmap_isempty(c->will_install)) {
- r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
+ if (ordered_hashmap_isempty(c->will_process))
+ return 0;
+
+ r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
+ if (r < 0)
+ return r;
+
+ while ((i = ordered_hashmap_first(c->will_process))) {
+
+ r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
if (r < 0)
return r;
- r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
+ r = install_info_traverse(scope, c, root_dir, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
if (r < 0)
return r;
- }
- r = 0;
- while ((i = ordered_hashmap_first(c->will_install))) {
- assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
-
- q = unit_file_search(c, i, paths, root_dir, false, true, NULL);
- if (q == -ENOENT) {
- /* do nothing */
- } else if (q < 0) {
- if (r >= 0)
- r = q;
+ if (i->type != UNIT_FILE_TYPE_REGULAR)
+ continue;
+ r = mark_symlink_for_removal(remove_symlinks_to, i->name);
+ if (r < 0)
return r;
- } else if (r >= 0)
- r += q;
-
- if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) {
- char *unit_file;
-
- if (i->path) {
- unit_file = basename(i->path);
-
- if (unit_name_is_valid(unit_file, UNIT_NAME_INSTANCE))
- /* unit file named as instance exists, thus all symlinks
- * pointing to it will be removed */
- q = mark_symlink_for_removal(remove_symlinks_to, i->name);
- else
- /* does not exist, thus we will mark for removal symlinks
- * to template unit file */
- q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
- } else {
- /* If i->path is not set, it means that we didn't actually find
- * the unit file. But we can still remove symlinks to the
- * nonexistent template. */
- r = unit_name_template(i->name, &unit_file);
- if (r < 0)
- return r;
+ }
- q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
- free(unit_file);
- }
- } else
- q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+ return 0;
+}
+
+int unit_file_mask(
+ UnitFileScope scope,
+ bool runtime,
+ const char *root_dir,
+ char **files,
+ bool force,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ _cleanup_free_ char *prefix = NULL;
+ char **i;
+ int r;
+
+ assert(scope >= 0);
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
- if (r >= 0 && q < 0)
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
+ r = get_config_path(scope, runtime, root_dir, &prefix);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(i, files) {
+ _cleanup_free_ char *path = NULL;
+ int q;
+
+ if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
+ if (r == 0)
+ r = -EINVAL;
+ continue;
+ }
+
+ path = path_make_absolute(*i, prefix);
+ if (!path)
+ return -ENOMEM;
+
+ q = create_symlink("/dev/null", path, force, changes, n_changes);
+ if (q < 0 && r >= 0)
r = q;
}
return r;
}
-int unit_file_add_dependency(
+int unit_file_unmask(
+ UnitFileScope scope,
+ bool runtime,
+ const char *root_dir,
+ char **files,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+ _cleanup_free_ char *config_path = NULL;
+ _cleanup_free_ char **todo = NULL;
+ size_t n_todo = 0, n_allocated = 0;
+ char **i;
+ int r, q;
+
+ assert(scope >= 0);
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
+
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
+ r = get_config_path(scope, runtime, root_dir, &config_path);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(i, files) {
+ _cleanup_free_ char *path = NULL;
+
+ if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
+ return -EINVAL;
+
+ path = path_make_absolute(*i, config_path);
+ if (!path)
+ return -ENOMEM;
+
+ r = null_or_empty_path(path);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
+
+ if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
+ return -ENOMEM;
+
+ todo[n_todo++] = *i;
+ }
+
+ strv_uniq(todo);
+
+ r = 0;
+ STRV_FOREACH(i, todo) {
+ _cleanup_free_ char *path = NULL;
+
+ path = path_make_absolute(*i, config_path);
+ if (!path)
+ return -ENOMEM;
+
+ if (unlink(path) < 0) {
+ if (errno != -ENOENT && r >= 0)
+ r = -errno;
+ } else {
+ q = mark_symlink_for_removal(&remove_symlinks_to, path);
+ if (q < 0)
+ return q;
+
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
+ }
+ }
+
+ q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+ if (r >= 0)
+ r = q;
+
+ return r;
+}
+
+int unit_file_link(
UnitFileScope scope,
bool runtime,
const char *root_dir,
char **files,
- char *target,
- UnitDependency dep,
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
- _cleanup_(install_context_done) InstallContext c = {};
_cleanup_free_ char *config_path = NULL;
+ _cleanup_free_ char **todo = NULL;
+ size_t n_todo = 0, n_allocated = 0;
char **i;
- int r;
- UnitFileInstallInfo *info;
+ int r, q;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
@@ -1533,55 +1642,135 @@ int unit_file_add_dependency(
return r;
STRV_FOREACH(i, files) {
- UnitFileState state;
+ _cleanup_free_ char *full = NULL;
+ struct stat st;
+ char *fn;
- state = unit_file_get_state(scope, root_dir, *i);
- if (state < 0)
- return log_error_errno(state, "Failed to get unit file state for %s: %m", *i);
+ if (!path_is_absolute(*i))
+ return -EINVAL;
- if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
- log_error("Failed to enable unit: Unit %s is masked", *i);
- return -EOPNOTSUPP;
- }
+ fn = basename(*i);
+ if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
+ return -EINVAL;
- r = install_info_add_auto(&c, *i);
- if (r < 0)
- return r;
+ full = prefix_root(root_dir, *i);
+ if (!full)
+ return -ENOMEM;
+
+ if (lstat(full, &st) < 0)
+ return -errno;
+ if (S_ISLNK(st.st_mode))
+ return -ELOOP;
+ if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ if (!S_ISREG(st.st_mode))
+ return -ENOTTY;
+
+ q = in_search_path(*i, paths.unit_path);
+ if (q < 0)
+ return q;
+ if (q > 0)
+ continue;
+
+ if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
+ return -ENOMEM;
+
+ todo[n_todo++] = *i;
}
- if (!ordered_hashmap_isempty(c.will_install)) {
- r = ordered_hashmap_ensure_allocated(&c.have_installed, &string_hash_ops);
- if (r < 0)
- return r;
+ strv_uniq(todo);
- r = ordered_hashmap_reserve(c.have_installed, ordered_hashmap_size(c.will_install));
- if (r < 0)
- return r;
+ r = 0;
+ STRV_FOREACH(i, todo) {
+ _cleanup_free_ char *path = NULL;
+
+ path = path_make_absolute(basename(*i), config_path);
+ if (!path)
+ return -ENOMEM;
+
+ q = create_symlink(*i, path, force, changes, n_changes);
+ if (q < 0 && r >= 0)
+ r = q;
}
- while ((info = ordered_hashmap_first(c.will_install))) {
- assert_se(ordered_hashmap_move_one(c.have_installed, c.will_install, info->name) == 0);
+ return r;
+}
+
+int unit_file_add_dependency(
+ UnitFileScope scope,
+ bool runtime,
+ const char *root_dir,
+ char **files,
+ const char *target,
+ UnitDependency dep,
+ bool force,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(install_context_done) InstallContext c = {};
+ _cleanup_free_ char *config_path = NULL;
+ UnitFileInstallInfo *i, *target_info;
+ char **f;
+ int r;
+
+ assert(scope >= 0);
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
+ assert(target);
+
+ if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
+ return -EINVAL;
- r = unit_file_search(&c, info, &paths, root_dir, false, false, NULL);
+ if (!unit_name_is_valid(target, UNIT_NAME_ANY))
+ return -EINVAL;
+
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+ if (r < 0)
+ return r;
+
+ r = get_config_path(scope, runtime, root_dir, &config_path);
+ if (r < 0)
+ return r;
+
+ r = install_info_discover(scope, &c, root_dir, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
+ if (r < 0)
+ return r;
+ if (target_info->type == UNIT_FILE_TYPE_MASKED)
+ return -ESHUTDOWN;
+
+ assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
+
+ STRV_FOREACH(f, files) {
+ char ***l;
+
+ r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
if (r < 0)
return r;
+ if (i->type == UNIT_FILE_TYPE_MASKED)
+ return -ESHUTDOWN;
+
+ assert(i->type == UNIT_FILE_TYPE_REGULAR);
+
+ /* We didn't actually load anything from the unit
+ * file, but instead just add in our new symlink to
+ * create. */
if (dep == UNIT_WANTS)
- r = strv_extend(&info->wanted_by, target);
- else if (dep == UNIT_REQUIRES)
- r = strv_extend(&info->required_by, target);
+ l = &i->wanted_by;
else
- r = -EINVAL;
+ l = &i->required_by;
- if (r < 0)
- return r;
-
- r = install_info_apply(info, &paths, config_path, root_dir, force, changes, n_changes);
- if (r < 0)
- return r;
+ strv_free(*l);
+ *l = strv_new(target_info->name, NULL);
+ if (!*l)
+ return -ENOMEM;
}
- return 0;
+ return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
}
int unit_file_enable(
@@ -1595,13 +1784,18 @@ int unit_file_enable(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
- char **i;
_cleanup_free_ char *config_path = NULL;
+ UnitFileInstallInfo *i;
+ char **f;
int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
@@ -1610,29 +1804,22 @@ int unit_file_enable(
if (r < 0)
return r;
- STRV_FOREACH(i, files) {
- UnitFileState state;
-
- /* We only want to know if this unit is masked, so we ignore
- * errors from unit_file_get_state, deferring other checks.
- * This allows templated units to be enabled on the fly. */
- state = unit_file_get_state(scope, root_dir, *i);
- if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
- log_error("Failed to enable unit: Unit %s is masked", *i);
- return -EOPNOTSUPP;
- }
-
- r = install_info_add_auto(&c, *i);
+ STRV_FOREACH(f, files) {
+ r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_LOAD, &i);
if (r < 0)
return r;
+ if (i->type == UNIT_FILE_TYPE_MASKED)
+ return -ESHUTDOWN;
+
+ assert(i->type == UNIT_FILE_TYPE_REGULAR);
}
/* This will return the number of symlink rules that were
- supposed to be created, not the ones actually created. This is
- useful to determine whether the passed files had any
- installation data at all. */
+ supposed to be created, not the ones actually created. This
+ is useful to determine whether the passed files had any
+ installation data at all. */
- return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
+ return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
}
int unit_file_disable(
@@ -1645,14 +1832,18 @@ int unit_file_disable(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
- char **i;
_cleanup_free_ char *config_path = NULL;
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- int r, q;
+ char **i;
+ int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
@@ -1662,18 +1853,19 @@ int unit_file_disable(
return r;
STRV_FOREACH(i, files) {
- r = install_info_add_auto(&c, *i);
+ if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
+ return -EINVAL;
+
+ r = install_info_add(&c, *i, NULL, NULL);
if (r < 0)
return r;
}
- r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
-
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r >= 0)
- r = q;
+ r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, root_dir);
+ if (r < 0)
+ return r;
- return r;
+ return remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
}
int unit_file_reenable(
@@ -1684,21 +1876,30 @@ int unit_file_reenable(
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
+
+ char **n;
int r;
+ size_t l, i;
+
+ /* First, we invoke the disable command with only the basename... */
+ l = strv_length(files);
+ n = newa(char*, l+1);
+ for (i = 0; i < l; i++)
+ n[i] = basename(files[i]);
+ n[i] = NULL;
- r = unit_file_disable(scope, runtime, root_dir, files,
- changes, n_changes);
+ r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes);
if (r < 0)
return r;
- return unit_file_enable(scope, runtime, root_dir, files, force,
- changes, n_changes);
+ /* But the enable command with the full name */
+ return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes);
}
int unit_file_set_default(
UnitFileScope scope,
const char *root_dir,
- const char *file,
+ const char *name,
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
@@ -1706,42 +1907,40 @@ int unit_file_set_default(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
_cleanup_free_ char *config_path = NULL;
- char *path;
+ UnitFileInstallInfo *i;
+ const char *path;
int r;
- UnitFileInstallInfo *i = NULL;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- assert(file);
+ assert(name);
- if (unit_name_to_type(file) != UNIT_TARGET)
+ if (unit_name_to_type(name) != UNIT_TARGET)
+ return -EINVAL;
+ if (streq(name, SPECIAL_DEFAULT_TARGET))
return -EINVAL;
- r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+ r = verify_root_dir(scope, &root_dir);
if (r < 0)
return r;
- r = get_config_path(scope, false, root_dir, &config_path);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
- r = install_info_add_auto(&c, file);
+ r = get_config_path(scope, false, root_dir, &config_path);
if (r < 0)
return r;
- assert_se(i = ordered_hashmap_first(c.will_install));
-
- r = unit_file_search(&c, i, &paths, root_dir, false, true, NULL);
+ r = install_info_discover(scope, &c, root_dir, &paths, name, 0, &i);
if (r < 0)
return r;
+ if (i->type == UNIT_FILE_TYPE_MASKED)
+ return -ESHUTDOWN;
path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET);
- r = create_symlink(i->path, path, force, changes, n_changes);
- if (r < 0)
- return r;
-
- return 0;
+ return create_symlink(i->path, path, force, changes, n_changes);
}
int unit_file_get_default(
@@ -1750,126 +1949,101 @@ int unit_file_get_default(
char **name) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
- char **p;
+ _cleanup_(install_context_done) InstallContext c = {};
+ UnitFileInstallInfo *i;
+ char *n;
int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
- r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+ r = verify_root_dir(scope, &root_dir);
if (r < 0)
return r;
- STRV_FOREACH(p, paths.unit_path) {
- _cleanup_free_ char *path = NULL, *tmp = NULL;
- char *n;
-
- path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
- if (!path)
- return -ENOMEM;
-
- r = readlink_malloc(path, &tmp);
- if (r == -ENOENT)
- continue;
- else if (r == -EINVAL)
- /* not a symlink */
- n = strdup(SPECIAL_DEFAULT_TARGET);
- else if (r < 0)
- return r;
- else
- n = strdup(basename(tmp));
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+ if (r < 0)
+ return r;
- if (!n)
- return -ENOMEM;
+ r = install_info_discover(scope, &c, root_dir, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
+ if (r < 0)
+ return r;
+ if (i->type == UNIT_FILE_TYPE_MASKED)
+ return -ESHUTDOWN;
- *name = n;
- return 0;
- }
+ n = strdup(i->name);
+ if (!n)
+ return -ENOMEM;
- return -ENOENT;
+ *name = n;
+ return 0;
}
-UnitFileState unit_file_lookup_state(
+int unit_file_lookup_state(
UnitFileScope scope,
const char *root_dir,
const LookupPaths *paths,
- const char *name) {
+ const char *name,
+ UnitFileState *ret) {
- UnitFileState state = _UNIT_FILE_STATE_INVALID;
- char **i;
- _cleanup_free_ char *path = NULL;
- int r = 0;
+ _cleanup_(install_context_done) InstallContext c = {};
+ UnitFileInstallInfo *i;
+ UnitFileState state;
+ int r;
assert(paths);
+ assert(name);
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
return -EINVAL;
- STRV_FOREACH(i, paths->unit_path) {
- struct stat st;
- char *partial;
- bool also = false;
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
- free(path);
- path = path_join(root_dir, *i, name);
- if (!path)
- return -ENOMEM;
+ r = install_info_discover(scope, &c, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
+ if (r < 0)
+ return r;
- if (root_dir)
- partial = path + strlen(root_dir);
- else
- partial = path;
-
- /*
- * Search for a unit file in our default paths, to
- * be sure, that there are no broken symlinks.
- */
- if (lstat(path, &st) < 0) {
- r = -errno;
- if (errno != ENOENT)
- return r;
+ /* Shortcut things, if the caller just wants to know if this unit exists. */
+ if (!ret)
+ return 0;
- if (!unit_name_is_valid(name, UNIT_NAME_INSTANCE))
- continue;
- } else {
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
- return -ENOENT;
+ switch (i->type) {
- r = null_or_empty_path(path);
- if (r < 0 && r != -ENOENT)
- return r;
- else if (r > 0) {
- state = path_startswith(*i, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
- return state;
- }
- }
+ case UNIT_FILE_TYPE_MASKED:
+ state = path_startswith(i->path, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
+ break;
- r = find_symlinks_in_scope(scope, root_dir, name, &state);
+ case UNIT_FILE_TYPE_REGULAR:
+ r = find_symlinks_in_scope(scope, root_dir, i->name, &state);
if (r < 0)
return r;
- else if (r > 0)
- return state;
-
- r = unit_file_can_install(paths, root_dir, partial, true, &also);
- if (r < 0 && errno != ENOENT)
- return r;
- else if (r > 0)
- return UNIT_FILE_DISABLED;
- else if (r == 0) {
- if (also)
- return UNIT_FILE_INDIRECT;
- return UNIT_FILE_STATIC;
+ if (r == 0) {
+ if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i))
+ state = UNIT_FILE_DISABLED;
+ else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i))
+ state = UNIT_FILE_INDIRECT;
+ else
+ state = UNIT_FILE_STATIC;
}
+
+ break;
+
+ default:
+ assert_not_reached("Unexpect unit file type.");
}
- return r < 0 ? r : state;
+ *ret = state;
+ return 0;
}
-UnitFileState unit_file_get_state(
+int unit_file_get_state(
UnitFileScope scope,
const char *root_dir,
- const char *name) {
+ const char *name,
+ UnitFileState *ret) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
int r;
@@ -1878,14 +2052,15 @@ UnitFileState unit_file_get_state(
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
- if (root_dir && scope != UNIT_FILE_SYSTEM)
- return -EINVAL;
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
- return unit_file_lookup_state(scope, root_dir, &paths, name);
+ return unit_file_lookup_state(scope, root_dir, &paths, name, ret);
}
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
@@ -1897,6 +2072,13 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
+ if (!unit_name_is_valid(name, UNIT_NAME_ANY))
+ return -EINVAL;
+
if (scope == UNIT_FILE_SYSTEM)
r = conf_files_list(&files, ".preset", root_dir,
"/etc/systemd/system-preset",
@@ -1913,13 +2095,14 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
"/usr/lib/systemd/user-preset",
NULL);
else
- return 1;
+ return 1; /* Default is "enable" */
if (r < 0)
return r;
STRV_FOREACH(p, files) {
_cleanup_fclose_ FILE *f;
+ char line[LINE_MAX];
f = fopen(*p, "re");
if (!f) {
@@ -1929,39 +2112,38 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
return -errno;
}
- for (;;) {
- char line[LINE_MAX], *l;
-
- if (!fgets(line, sizeof(line), f))
- break;
+ FOREACH_LINE(line, f, return -errno) {
+ const char *parameter;
+ char *l;
l = strstrip(line);
- if (!*l)
- continue;
- if (strchr(COMMENTS "\n", *l))
+ if (isempty(l))
+ continue;
+ if (strchr(COMMENTS, *l))
continue;
- if (first_word(l, "enable")) {
- l += 6;
- l += strspn(l, WHITESPACE);
-
- if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
+ parameter = first_word(l, "enable");
+ if (parameter) {
+ if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
log_debug("Preset file says enable %s.", name);
return 1;
}
- } else if (first_word(l, "disable")) {
- l += 7;
- l += strspn(l, WHITESPACE);
+ continue;
+ }
- if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
+ parameter = first_word(l, "disable");
+ if (parameter) {
+ if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
log_debug("Preset file says disable %s.", name);
return 0;
}
- } else
- log_debug("Couldn't parse line '%s'", l);
+ continue;
+ }
+
+ log_debug("Couldn't parse line '%s'", l);
}
}
@@ -1970,6 +2152,86 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
return 1;
}
+static int execute_preset(
+ UnitFileScope scope,
+ InstallContext *plus,
+ InstallContext *minus,
+ const LookupPaths *paths,
+ const char *config_path,
+ const char *root_dir,
+ char **files,
+ UnitFilePresetMode mode,
+ bool force,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ int r;
+
+ assert(plus);
+ assert(minus);
+ assert(paths);
+ assert(config_path);
+
+ if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
+ _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+
+ r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, root_dir);
+ if (r < 0)
+ return r;
+
+ r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+ } else
+ r = 0;
+
+ if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
+ int q;
+
+ /* Returns number of symlinks that where supposed to be installed. */
+ q = install_context_apply(scope, plus, paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
+ if (r >= 0) {
+ if (q < 0)
+ r = q;
+ else
+ r+= q;
+ }
+ }
+
+ return r;
+}
+
+static int preset_prepare_one(
+ UnitFileScope scope,
+ InstallContext *plus,
+ InstallContext *minus,
+ LookupPaths *paths,
+ const char *root_dir,
+ UnitFilePresetMode mode,
+ const char *name) {
+
+ UnitFileInstallInfo *i;
+ int r;
+
+ if (install_info_find(plus, name) ||
+ install_info_find(minus, name))
+ return 0;
+
+ r = unit_file_query_preset(scope, root_dir, name);
+ if (r < 0)
+ return r;
+
+ if (r > 0) {
+ r = install_info_discover(scope, plus, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
+ if (r < 0)
+ return r;
+
+ if (i->type == UNIT_FILE_TYPE_MASKED)
+ return -ESHUTDOWN;
+ } else
+ r = install_info_discover(scope, minus, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
+
+ return r;
+}
+
int unit_file_preset(
UnitFileScope scope,
bool runtime,
@@ -1984,12 +2246,16 @@ int unit_file_preset(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_free_ char *config_path = NULL;
char **i;
- int r, q;
+ int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(mode < _UNIT_FILE_PRESET_MAX);
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
@@ -1999,44 +2265,15 @@ int unit_file_preset(
return r;
STRV_FOREACH(i, files) {
-
if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
return -EINVAL;
- r = unit_file_query_preset(scope, root_dir, *i);
+ r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, *i);
if (r < 0)
return r;
-
- if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
- r = install_info_add_auto(&plus, *i);
- else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
- r = install_info_add_auto(&minus, *i);
- else
- r = 0;
- if (r < 0)
- return r;
- }
-
- r = 0;
-
- if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
- _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
-
- r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
-
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r == 0)
- r = q;
}
- if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
- /* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
- if (r == 0)
- r = q;
- }
-
- return r;
+ return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, files, mode, force, changes, n_changes);
}
int unit_file_preset_all(
@@ -2052,12 +2289,16 @@ int unit_file_preset_all(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_free_ char *config_path = NULL;
char **i;
- int r, q;
+ int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(mode < _UNIT_FILE_PRESET_MAX);
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
+
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
@@ -2069,6 +2310,7 @@ int unit_file_preset_all(
STRV_FOREACH(i, paths.unit_path) {
_cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *units_dir;
+ struct dirent *de;
units_dir = path_join(root_dir, *i, NULL);
if (!units_dir)
@@ -2082,62 +2324,23 @@ int unit_file_preset_all(
return -errno;
}
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno != 0)
- return -errno;
-
- if (!de)
- break;
-
- if (hidden_file(de->d_name))
- continue;
+ FOREACH_DIRENT(de, d, return -errno) {
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue;
dirent_ensure_type(d, de);
- if (de->d_type != DT_REG)
+ if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue;
- r = unit_file_query_preset(scope, root_dir, de->d_name);
- if (r < 0)
- return r;
-
- if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
- r = install_info_add_auto(&plus, de->d_name);
- else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
- r = install_info_add_auto(&minus, de->d_name);
- else
- r = 0;
+ r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, de->d_name);
if (r < 0)
return r;
}
}
- r = 0;
-
- if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
- _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
-
- r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
-
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
- if (r == 0)
- r = q;
- }
-
- if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
- q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
- if (r == 0)
- r = q;
- }
-
- return r;
+ return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, NULL, mode, force, changes, n_changes);
}
static void unit_file_list_free_one(UnitFileList *f) {
@@ -2148,6 +2351,15 @@ static void unit_file_list_free_one(UnitFileList *f) {
free(f);
}
+Hashmap* unit_file_list_free(Hashmap *h) {
+ UnitFileList *i;
+
+ while ((i = hashmap_steal_first(h)))
+ unit_file_list_free_one(i);
+
+ return hashmap_free(h);
+}
+
DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
int unit_file_get_list(
@@ -2163,14 +2375,9 @@ int unit_file_get_list(
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(h);
- if (root_dir && scope != UNIT_FILE_SYSTEM)
- return -EINVAL;
-
- if (root_dir) {
- r = access(root_dir, F_OK);
- if (r < 0)
- return -errno;
- }
+ r = verify_root_dir(scope, &root_dir);
+ if (r < 0)
+ return r;
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
@@ -2179,6 +2386,7 @@ int unit_file_get_list(
STRV_FOREACH(i, paths.unit_path) {
_cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *units_dir;
+ struct dirent *de;
units_dir = path_join(root_dir, *i, NULL);
if (!units_dir)
@@ -2192,22 +2400,8 @@ int unit_file_get_list(
return -errno;
}
- for (;;) {
+ FOREACH_DIRENT(de, d, return -errno) {
_cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
- struct dirent *de;
- _cleanup_free_ char *path = NULL;
- bool also = false;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno != 0)
- return -errno;
-
- if (!de)
- break;
-
- if (hidden_file(de->d_name))
- continue;
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue;
@@ -2228,44 +2422,14 @@ int unit_file_get_list(
if (!f->path)
return -ENOMEM;
- r = null_or_empty_path(f->path);
- if (r < 0 && r != -ENOENT)
- return r;
- else if (r > 0) {
- f->state =
- path_startswith(*i, "/run") ?
- UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
- goto found;
- }
-
- r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
+ r = unit_file_lookup_state(scope, root_dir, &paths, basename(f->path), &f->state);
if (r < 0)
- return r;
- else if (r > 0) {
- f->state = UNIT_FILE_ENABLED;
- goto found;
- }
-
- path = path_make_absolute(de->d_name, *i);
- if (!path)
- return -ENOMEM;
+ f->state = UNIT_FILE_BAD;
- r = unit_file_can_install(&paths, root_dir, path, true, &also);
- if (r == -EINVAL || /* Invalid setting? */
- r == -EBADMSG || /* Invalid format? */
- r == -ENOENT /* Included file not found? */)
- f->state = UNIT_FILE_INVALID;
- else if (r < 0)
- return r;
- else if (r > 0)
- f->state = UNIT_FILE_DISABLED;
- else
- f->state = also ? UNIT_FILE_INDIRECT : UNIT_FILE_STATIC;
-
- found:
r = hashmap_put(h, basename(f->path), f);
if (r < 0)
return r;
+
f = NULL; /* prevent cleanup */
}
}
@@ -2283,7 +2447,7 @@ static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
[UNIT_FILE_STATIC] = "static",
[UNIT_FILE_DISABLED] = "disabled",
[UNIT_FILE_INDIRECT] = "indirect",
- [UNIT_FILE_INVALID] = "invalid",
+ [UNIT_FILE_BAD] = "bad",
};
DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
diff --git a/src/shared/install.h b/src/shared/install.h
index a9d77dd91b..45a417df92 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -25,13 +25,15 @@ typedef enum UnitFileScope UnitFileScope;
typedef enum UnitFileState UnitFileState;
typedef enum UnitFilePresetMode UnitFilePresetMode;
typedef enum UnitFileChangeType UnitFileChangeType;
+typedef enum UnitFileType UnitFileType;
typedef struct UnitFileChange UnitFileChange;
typedef struct UnitFileList UnitFileList;
typedef struct UnitFileInstallInfo UnitFileInstallInfo;
#include "hashmap.h"
-#include "unit-name.h"
#include "path-lookup.h"
+#include "strv.h"
+#include "unit-name.h"
enum UnitFileScope {
UNIT_FILE_SYSTEM,
@@ -51,7 +53,7 @@ enum UnitFileState {
UNIT_FILE_STATIC,
UNIT_FILE_DISABLED,
UNIT_FILE_INDIRECT,
- UNIT_FILE_INVALID,
+ UNIT_FILE_BAD,
_UNIT_FILE_STATE_MAX,
_UNIT_FILE_STATE_INVALID = -1
};
@@ -82,10 +84,17 @@ struct UnitFileList {
UnitFileState state;
};
+enum UnitFileType {
+ UNIT_FILE_TYPE_REGULAR,
+ UNIT_FILE_TYPE_SYMLINK,
+ UNIT_FILE_TYPE_MASKED,
+ _UNIT_FILE_TYPE_MAX,
+ _UNIT_FILE_TYPE_INVALID = -1,
+};
+
struct UnitFileInstallInfo {
char *name;
char *path;
- char *user;
char **aliases;
char **wanted_by;
@@ -93,8 +102,26 @@ struct UnitFileInstallInfo {
char **also;
char *default_instance;
+
+ UnitFileType type;
+
+ char *symlink_target;
};
+static inline bool UNIT_FILE_INSTALL_INFO_HAS_RULES(UnitFileInstallInfo *i) {
+ assert(i);
+
+ return !strv_isempty(i->aliases) ||
+ !strv_isempty(i->wanted_by) ||
+ !strv_isempty(i->required_by);
+}
+
+static inline bool UNIT_FILE_INSTALL_INFO_HAS_ALSO(UnitFileInstallInfo *i) {
+ assert(i);
+
+ return !strv_isempty(i->also);
+}
+
int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes);
int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes);
@@ -105,21 +132,14 @@ int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes);
int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
-int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes);
-
-UnitFileState unit_file_lookup_state(
- UnitFileScope scope,
- const char *root_dir,
- const LookupPaths *paths,
- const char *name);
-UnitFileState unit_file_get_state(
- UnitFileScope scope,
- const char *root_dir,
- const char *filename);
+int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes);
+
+int unit_file_lookup_state(UnitFileScope scope, const char *root_dir,const LookupPaths *paths, const char *name, UnitFileState *ret);
+int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret);
int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h);
+Hashmap* unit_file_list_free(Hashmap *h);
-void unit_file_list_free(Hashmap *h);
int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source);
void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index d71f379e76..4a82bd18cd 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -19,18 +19,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
+#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include "alloc-util.h"
-#include "util.h"
-#include "strv.h"
-#include "path-util.h"
#include "install.h"
-#include "string-util.h"
#include "path-lookup.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
int user_config_home(char **config_home) {
const char *e;
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 63e81f4894..2666b8f7e2 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <limits.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
-#include <limits.h>
#include <termios.h>
#include "alloc-util.h"
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index c518cf83ec..09baf51661 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -21,9 +21,9 @@
#include <seccomp.h>
+#include "seccomp-util.h"
#include "string-util.h"
#include "util.h"
-#include "seccomp-util.h"
const char* seccomp_arch_to_string(uint32_t c) {
diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c
index 29db855c67..3fcea61873 100644
--- a/src/shared/spawn-ask-password-agent.c
+++ b/src/shared/spawn-ask-password-agent.c
@@ -25,8 +25,8 @@
#include "log.h"
#include "process-util.h"
-#include "util.h"
#include "spawn-ask-password-agent.h"
+#include "util.h"
static pid_t agent_pid = 0;
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index ec6e5a8312..8ea6cb830b 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -19,11 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
#include <errno.h>
#include <poll.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
#include "fd-util.h"
#include "io-util.h"
diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c
index 21cb82ea1c..70caa542e7 100644
--- a/src/shared/sysctl-util.c
+++ b/src/shared/sysctl-util.c
@@ -30,8 +30,8 @@
#include "fileio.h"
#include "log.h"
#include "string-util.h"
-#include "util.h"
#include "sysctl-util.h"
+#include "util.h"
char *sysctl_normalize(char *s) {
char *n;
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
index d58f9873d5..7131e94cdb 100644
--- a/src/shared/watchdog.c
+++ b/src/shared/watchdog.c
@@ -19,15 +19,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/watchdog.h>
-#include "watchdog.h"
-#include "log.h"
#include "fd-util.h"
+#include "log.h"
+#include "watchdog.h"
static int watchdog_fd = -1;
static usec_t watchdog_timeout = USEC_INFINITY;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 70871cf3e6..51b82d57db 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1335,7 +1335,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
UNIT_FILE_MASKED,
UNIT_FILE_MASKED_RUNTIME,
UNIT_FILE_DISABLED,
- UNIT_FILE_INVALID)) {
+ UNIT_FILE_BAD)) {
on = ansi_highlight_red();
off = ansi_normal();
} else if (u->state == UNIT_FILE_ENABLED) {
@@ -1503,16 +1503,12 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha
static const char *dependencies[_DEPENDENCY_MAX] = {
[DEPENDENCY_FORWARD] = "Requires\0"
- "RequiresOverridable\0"
"Requisite\0"
- "RequisiteOverridable\0"
"Wants\0"
"ConsistsOf\0"
"BindsTo\0",
[DEPENDENCY_REVERSE] = "RequiredBy\0"
- "RequiredByOverridable\0"
"RequisiteOf\0"
- "RequisiteOfOverridable\0"
"WantedBy\0"
"PartOf\0"
"BoundBy\0",
@@ -2186,7 +2182,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
return bus_log_parse_error(r);
output_jobs_list(jobs, c, skipped);
- return r;
+ return 0;
}
static int cancel_job(int argc, char *argv[], void *userdata) {
@@ -4905,102 +4901,6 @@ static int set_property(int argc, char *argv[], void *userdata) {
return 0;
}
-static int snapshot(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_free_ char *n = NULL, *id = NULL;
- const char *path;
- sd_bus *bus;
- int r;
-
- polkit_agent_open_if_enabled();
-
- if (argc > 1) {
- r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".snapshot", &n);
- if (r < 0)
- return log_error_errno(r, "Failed to generate unit name: %m");
- } else {
- n = strdup("");
- if (!n)
- return log_oom();
- }
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "CreateSnapshot",
- &error,
- &reply,
- "sb", n, false);
- if (r < 0)
- return log_error_errno(r, "Failed to create snapshot: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "o", &path);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "Id",
- &error,
- &id);
- if (r < 0)
- return log_error_errno(r, "Failed to get ID of snapshot: %s", bus_error_message(&error, r));
-
- if (!arg_quiet)
- puts(id);
-
- return 0;
-}
-
-static int delete_snapshot(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- sd_bus *bus;
- char **name;
- int r;
-
- polkit_agent_open_if_enabled();
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = expand_names(bus, strv_skip(argv, 1), ".snapshot", &names);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- STRV_FOREACH(name, names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- int q;
-
- q = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "RemoveSnapshot",
- &error,
- NULL,
- "s", *name);
- if (q < 0) {
- log_error_errno(q, "Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
- }
-
- return r;
-}
-
static int daemon_reload(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
const char *method;
@@ -5533,10 +5433,10 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
else
assert_not_reached("Unknown verb");
- if (r < 0) {
- log_error_errno(r, "Operation failed: %m");
- goto finish;
- }
+ if (r == -ESHUTDOWN)
+ return log_error_errno(r, "Unit file is masked.");
+ if (r < 0)
+ return log_error_errno(r, "Operation failed: %m");
if (!arg_quiet)
dump_unit_file_changes(changes, n_changes);
@@ -5653,7 +5553,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
- return r;
+ goto finish;
new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
for (i = 0; i < n_changes; i++)
@@ -5699,7 +5599,8 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
unsigned n_changes = 0;
r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
-
+ if (r == -ESHUTDOWN)
+ return log_error_errno(r, "Unit file is masked.");
if (r < 0)
return log_error_errno(r, "Can't add dependency: %m");
@@ -5836,8 +5737,8 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
STRV_FOREACH(name, names) {
UnitFileState state;
- state = unit_file_get_state(arg_scope, arg_root, *name);
- if (state < 0)
+ r = unit_file_get_state(arg_scope, arg_root, *name, &state);
+ if (r < 0)
return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
if (IN_SET(state,
@@ -6381,9 +6282,6 @@ static void systemctl_help(void) {
"Job Commands:\n"
" list-jobs [PATTERN...] List jobs\n"
" cancel [JOB...] Cancel all, one, or more jobs\n\n"
- "Snapshot Commands:\n"
- " snapshot [NAME] Create a snapshot\n"
- " delete NAME... Remove one or more snapshots\n\n"
"Environment Commands:\n"
" show-environment Dump environment\n"
" set-environment NAME=VALUE... Set one or more environment variables\n"
@@ -6526,11 +6424,6 @@ static void help_states(void) {
puts(slice_state_to_string(i));
if (!arg_no_legend)
- puts("\nAvailable snapshot unit substates:");
- for (i = 0; i < _SNAPSHOT_STATE_MAX; i++)
- puts(snapshot_state_to_string(i));
-
- if (!arg_no_legend)
puts("\nAvailable socket unit substates:");
for (i = 0; i < _SOCKET_STATE_MAX; i++)
puts(socket_state_to_string(i));
@@ -7439,7 +7332,7 @@ static int systemctl_main(int argc, char *argv[]) {
{ "list-jobs", VERB_ANY, VERB_ANY, 0, list_jobs },
{ "list-machines", VERB_ANY, VERB_ANY, 0, list_machines },
{ "clear-jobs", VERB_ANY, 1, 0, daemon_reload },
- { "cancel", 2, VERB_ANY, 0, cancel_job },
+ { "cancel", VERB_ANY, VERB_ANY, 0, cancel_job },
{ "start", 2, VERB_ANY, 0, start_unit },
{ "stop", 2, VERB_ANY, 0, start_unit },
{ "condstop", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */
@@ -7460,8 +7353,6 @@ static int systemctl_main(int argc, char *argv[]) {
{ "cat", 2, VERB_ANY, 0, cat },
{ "status", VERB_ANY, VERB_ANY, 0, show },
{ "help", VERB_ANY, VERB_ANY, 0, show },
- { "snapshot", VERB_ANY, 2, 0, snapshot },
- { "delete", 2, VERB_ANY, 0, delete_snapshot },
{ "daemon-reload", VERB_ANY, 1, 0, daemon_reload },
{ "daemon-reexec", VERB_ANY, 1, 0, daemon_reload },
{ "show-environment", VERB_ANY, 1, 0, show_environment },
@@ -7815,5 +7706,7 @@ finish:
release_busses();
+ /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
+
return r < 0 ? EXIT_FAILURE : r;
}
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index 13182a481d..9f0e92806e 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -62,6 +62,7 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret);
int sd_dhcp6_client_stop(sd_dhcp6_client *client);
int sd_dhcp6_client_start(sd_dhcp6_client *client);
+int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
int priority);
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h
index 570e1741d6..80e24325f7 100644
--- a/src/systemd/sd-ndisc.h
+++ b/src/systemd/sd-ndisc.h
@@ -31,19 +31,25 @@
_SD_BEGIN_DECLARATIONS;
enum {
- SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE = 0,
- SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT = 1,
- SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER = 2,
- SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED = 3,
+ SD_NDISC_EVENT_STOP = 0,
+ SD_NDISC_EVENT_TIMEOUT = 1,
};
typedef struct sd_ndisc sd_ndisc;
-typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event,
- void *userdata);
-
-int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb,
- void *userdata);
+typedef void(*sd_ndisc_router_callback_t)(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata);
+typedef void(*sd_ndisc_prefix_onlink_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
+ unsigned lifetime, void *userdata);
+typedef void(*sd_ndisc_prefix_autonomous_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
+ unsigned lifetime_prefered, unsigned lifetime_valid, void *userdata);
+typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event, void *userdata);
+
+int sd_ndisc_set_callback(sd_ndisc *nd,
+ sd_ndisc_router_callback_t rcb,
+ sd_ndisc_prefix_onlink_callback_t plcb,
+ sd_ndisc_prefix_autonomous_callback_t pacb,
+ sd_ndisc_callback_t cb,
+ void *userdata);
int sd_ndisc_set_index(sd_ndisc *nd, int interface_index);
int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index 8e1b06ee9a..2960deda0a 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -136,6 +136,8 @@ int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type);
int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
+int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags);
+int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags);
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family);
int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol);
int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope);
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 042be97840..5075548507 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -742,6 +742,7 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
char **path;
+ int r;
assert(lp);
assert(all_services);
@@ -761,7 +762,6 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
_cleanup_free_ char *fpath = NULL, *name = NULL;
_cleanup_(free_sysvstubp) SysvStub *service = NULL;
struct stat st;
- int r;
if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name);
@@ -781,8 +781,12 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
if (hashmap_contains(all_services, name))
continue;
- if (unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name) >= 0) {
- log_debug("Native unit for %s already exists, skipping", name);
+ r = unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name, NULL);
+ if (r < 0 && r != -ENOENT) {
+ log_debug_errno(r, "Failed to detect whether %s exists, skipping: %m", name);
+ continue;
+ } else if (r >= 0) {
+ log_debug("Native unit for %s already exists, skipping.", name);
continue;
}
diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c
index a5b66a7d2f..35479d67c1 100644
--- a/src/test/test-architecture.c
+++ b/src/test/test-architecture.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "virt.h"
#include "architecture.h"
-#include "util.h"
#include "log.h"
+#include "util.h"
+#include "virt.h"
int main(int argc, char *argv[]) {
int a, v;
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index 06d93af533..fab33d20c7 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -20,11 +20,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "log.h"
+#include "acpi-fpdt.h"
#include "boot-timestamps.h"
#include "efivars.h"
-#include "acpi-fpdt.h"
+#include "log.h"
+#include "util.h"
static int test_acpi_fpdt(void) {
usec_t loader_start;
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index de6c421b82..2746013522 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -21,10 +21,10 @@
#include <stdio.h>
-#include "manager.h"
-#include "unit.h"
#include "macro.h"
+#include "manager.h"
#include "test-helper.h"
+#include "unit.h"
static int test_cgroup_mask(void) {
Manager *m = NULL;
@@ -40,6 +40,16 @@ static int test_cgroup_mask(void) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
}
+
+ /* Turn off all kinds of default accouning, so that we can
+ * verify the masks resulting of our configuration and nothing
+ * else. */
+ m->default_cpu_accounting =
+ m->default_memory_accounting =
+ m->default_blockio_accounting =
+ m->default_tasks_accounting = false;
+ m->default_tasks_max = (uint64_t) -1;
+
assert_se(r >= 0);
assert_se(manager_startup(m, serial, fdset) >= 0);
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index a69698d4ea..86ac513d4f 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -26,6 +26,7 @@
#include "conf-files.h"
#include "fs-util.h"
#include "macro.h"
+#include "parse-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
@@ -40,7 +41,7 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
va_start(ap, files);
while (files != NULL) {
_cleanup_free_ char *path = strappend(tmp_dir, files);
- assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0) == 0);
+ assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID) == 0);
files = va_arg(ap, const char *);
}
va_end(ap);
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index 6596069ade..4f14c58788 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <errno.h>
+#include <stdio.h>
#include <string.h>
-#include "manager.h"
#include "bus-util.h"
+#include "manager.h"
int main(int argc, char *argv[]) {
_cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
@@ -52,7 +52,7 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test1: (Trivial)\n");
- r = manager_add_job(m, JOB_START, c, JOB_REPLACE, false, &err, &j);
+ r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j);
if (sd_bus_error_is_set(&err))
log_error("error: %s: %s", err.name, err.message);
assert_se(r == 0);
@@ -65,15 +65,15 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test2: (Cyclic Order, Unfixable)\n");
- assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, false, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK);
manager_dump_jobs(m, stdout, "\t");
printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Test4: (Identical transaction)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Load3:\n");
@@ -81,21 +81,21 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test5: (Colliding transaction, fail)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, false, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK);
printf("Test6: (Colliding transaction, replace)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Test7: (Unmergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, false, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK);
printf("Test8: (Mergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Test9: (Unmergeable job type, replace)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Load4:\n");
@@ -103,7 +103,7 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
- assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
manager_free(m);
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index e2ec53ee51..03ec0fcfc7 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -168,6 +168,30 @@ static void test_exec_environmentfile(Manager *m) {
unlink("/tmp/test-exec_environmentfile.conf");
}
+static void test_exec_passenvironment(Manager *m) {
+ /* test-execute runs under MANAGER_USER which, by default, forwards all
+ * variables present in the environment, but only those that are
+ * present _at the time it is created_!
+ *
+ * So these PassEnvironment checks are still expected to work, since we
+ * are ensuring the variables are not present at manager creation (they
+ * are unset explicitly in main) and are only set here.
+ *
+ * This is still a good approximation of how a test for MANAGER_SYSTEM
+ * would work.
+ */
+ assert_se(setenv("VAR1", "word1 word2", 1) == 0);
+ assert_se(setenv("VAR2", "word3", 1) == 0);
+ assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
+ test(m, "exec-passenvironment.service", 0, CLD_EXITED);
+ test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
+ test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
+ assert_se(unsetenv("VAR1") == 0);
+ assert_se(unsetenv("VAR2") == 0);
+ assert_se(unsetenv("VAR3") == 0);
+ test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
+}
+
static void test_exec_umask(Manager *m) {
test(m, "exec-umask-default.service", 0, CLD_EXITED);
test(m, "exec-umask-0177.service", 0, CLD_EXITED);
@@ -237,6 +261,7 @@ int main(int argc, char *argv[]) {
test_exec_group,
test_exec_environment,
test_exec_environmentfile,
+ test_exec_passenvironment,
test_exec_umask,
test_exec_runtimedirectory,
test_exec_capabilityboundingset,
@@ -260,6 +285,16 @@ int main(int argc, char *argv[]) {
assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0);
assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0);
+ /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
+ * cases, otherwise (and if they are present in the environment),
+ * `manager_default_environment` will copy them into the default
+ * environment which is passed to each created job, which will make the
+ * tests that expect those not to be present to fail.
+ */
+ assert_se(unsetenv("VAR1") == 0);
+ assert_se(unsetenv("VAR2") == 0);
+ assert_se(unsetenv("VAR3") == 0);
+
r = manager_new(MANAGER_USER, true, &m);
if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
printf("Skipping test: manager_new: %s", strerror(-r));
diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c
index 09698c07c7..65d3a0a96e 100644
--- a/src/test/test-extract-word.c
+++ b/src/test/test-extract-word.c
@@ -325,6 +325,18 @@ static void test_extract_first_word(void) {
assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
assert_se(!t);
assert_se(!p);
+
+ p = "foo\\xbar";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "fooxbar"));
+ free(t);
+ assert_se(p == NULL);
+
+ p = "foo\\xbar";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) > 0);
+ assert_se(streq(t, "foo\\xbar"));
+ free(t);
+ assert_se(p == NULL);
}
static void test_extract_first_word_and_warn(void) {
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index e588681b86..871c71e171 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <fcntl.h>
+#include <stdio.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -363,6 +363,26 @@ static void test_write_string_file_no_create(void) {
unlink(fn);
}
+static void test_write_string_file_verify(void) {
+ _cleanup_free_ char *buf = NULL, *buf2 = NULL;
+ int r;
+
+ assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
+ assert_se((buf2 = strjoin(buf, "\n", NULL)));
+
+ r = write_string_file("/proc/cmdline", buf, 0);
+ assert_se(r == -EACCES || r == -EIO);
+ r = write_string_file("/proc/cmdline", buf2, 0);
+ assert_se(r == -EACCES || r == -EIO);
+
+ assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
+ assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
+
+ r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE);
+ assert_se(r == -EACCES || r == -EIO);
+ assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
+}
+
static void test_load_env_file_pairs(void) {
char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
int fd;
@@ -419,6 +439,7 @@ int main(int argc, char *argv[]) {
test_write_string_stream();
test_write_string_file();
test_write_string_file_no_create();
+ test_write_string_file_verify();
test_load_env_file_pairs();
return 0;
diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c
index d636e427c4..ff66bde094 100644
--- a/src/test/test-firewall-util.c
+++ b/src/test/test-firewall-util.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "log.h"
#include "firewall-util.h"
+#include "log.h"
#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index d0e65001f5..83cea360e6 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -17,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
#include "hashmap.h"
+#include "util.h"
void test_hashmap_funcs(void);
void test_ordered_hashmap_funcs(void);
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
new file mode 100644
index 0000000000..08fde94f7f
--- /dev/null
+++ b/src/test/test-install-root.c
@@ -0,0 +1,665 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 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 "fileio.h"
+#include "install.h"
+#include "mkdir.h"
+#include "rm-rf.h"
+#include "string-util.h"
+
+static void test_basic_mask_and_enable(const char *root) {
+ const char *p;
+ UnitFileState state;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/a.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system/b.service");
+ assert_se(symlink("a.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system/c.service");
+ assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system/d.service");
+ assert_se(symlink("c.service", p) >= 0);
+
+ /* This one is interesting, as d follows a relative, then an absolute symlink */
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/dev/null"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
+ assert_se(streq(changes[0].path, p));
+
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+
+ /* Enabling a masked unit should fail! */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ESHUTDOWN);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* Enabling it again should succeed but be a NOP */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ /* Disabling a disabled unit must suceed but be a NOP */
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ /* Let's enable this indirectly via a symlink */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* Let's try to reenable */
+
+ assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ assert_se(changes[1].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
+ assert_se(streq(changes[1].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+}
+
+static void test_linked_units(const char *root) {
+ const char *p, *q;
+ UnitFileState state;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0, i;
+
+ /*
+ * We'll test three cases here:
+ *
+ * a) a unit file in /opt, that we use "systemctl link" and
+ * "systemctl enable" on to make it available to the system
+ *
+ * b) a unit file in /opt, that is statically linked into
+ * /usr/lib/systemd/system, that "enable" should work on
+ * correctly.
+ *
+ * c) a unit file in /opt, that is linked into
+ * /etc/systemd/system, and where "enable" should result in
+ * -ELOOP, since using information from /etc to generate
+ * information in /etc should not be allowed.
+ */
+
+ p = strjoina(root, "/opt/linked.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/opt/linked2.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/opt/linked3.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
+ assert_se(symlink("/opt/linked2.service", p) >= 0);
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
+ assert_se(symlink("/opt/linked3.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
+
+ /* First, let's link the unit into the search path */
+ assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/opt/linked.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
+
+ /* Let's unlink it from the search path again */
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
+
+ /* Now, let's not just link it, but also enable it */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
+ q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ for (i = 0 ; i < n_changes; i++) {
+ assert_se(changes[i].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[i].source, "/opt/linked.service"));
+
+ if (p && streq(changes[i].path, p))
+ p = NULL;
+ else if (q && streq(changes[i].path, q))
+ q = NULL;
+ else
+ assert_not_reached("wut?");
+ }
+ assert(!p && !q);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* And let's unlink it again */
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
+ q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ for (i = 0; i < n_changes; i++) {
+ assert_se(changes[i].type == UNIT_FILE_UNLINK);
+
+ if (p && streq(changes[i].path, p))
+ p = NULL;
+ else if (q && streq(changes[i].path, q))
+ q = NULL;
+ else
+ assert_not_reached("wut?");
+ }
+ assert(!p && !q);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
+ q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
+ for (i = 0 ; i < n_changes; i++) {
+ assert_se(changes[i].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[i].source, "/opt/linked2.service"));
+
+ if (p && streq(changes[i].path, p))
+ p = NULL;
+ else if (q && streq(changes[i].path, q))
+ q = NULL;
+ else
+ assert_not_reached("wut?");
+ }
+ assert(!p && !q);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) == -ELOOP);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_default(const char *root) {
+ _cleanup_free_ char *def = NULL;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ const char *p;
+
+ p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
+ assert_se(symlink("test-default-real.target", p) >= 0);
+
+ assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
+
+ assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
+
+ assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
+ assert_se(streq_ptr(def, "test-default-real.target"));
+}
+
+static void test_add_dependency(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ const char *p;
+
+ p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
+ assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
+ assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
+
+ assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_template_enable(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ UnitFileState state;
+ const char *p;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/template@.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "DefaultInstance=def\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
+ assert_se(symlink("template@.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+}
+
+static void test_indirect(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ UnitFileState state;
+ const char *p;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
+ assert_se(symlink("indirecta.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_preset_and_list(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0, i;
+ const char *p, *q;
+ UnitFileState state;
+ bool got_yes = false, got_no = false;
+ Iterator j;
+ UnitFileList *fl;
+ Hashmap *h;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
+ assert_se(write_string_file(p,
+ "enable *-yes.*\n"
+ "disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+
+ assert_se(n_changes > 0);
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
+
+ for (i = 0; i < n_changes; i++) {
+
+ if (changes[i].type == UNIT_FILE_SYMLINK) {
+ assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
+ assert_se(streq(changes[i].path, p));
+ } else
+ assert_se(changes[i].type == UNIT_FILE_UNLINK);
+ }
+
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(h = hashmap_new(&string_hash_ops));
+ assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
+ q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
+
+ HASHMAP_FOREACH(fl, h, j) {
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
+ assert_se(fl->state == state);
+
+ if (streq(fl->path, p)) {
+ got_yes = true;
+ assert_se(fl->state == UNIT_FILE_ENABLED);
+ } else if (streq(fl->path, q)) {
+ got_no = true;
+ assert_se(fl->state == UNIT_FILE_DISABLED);
+ } else
+ assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
+ }
+
+ unit_file_list_free(h);
+
+ assert_se(got_yes && got_no);
+}
+
+int main(int argc, char *argv[]) {
+ char root[] = "/tmp/rootXXXXXX";
+ const char *p;
+
+ assert_se(mkdtemp(root));
+
+ p = strjoina(root, "/usr/lib/systemd/system/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/run/systemd/system/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/opt/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system-preset/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ test_basic_mask_and_enable(root);
+ test_linked_units(root);
+ test_default(root);
+ test_add_dependency(root);
+ test_template_enable(root);
+ test_indirect(root);
+ test_preset_and_list(root);
+
+ assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+
+ return 0;
+}
diff --git a/src/test/test-install.c b/src/test/test-install.c
index 5ee52e64cb..ef6f1efb89 100644
--- a/src/test/test-install.c
+++ b/src/test/test-install.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "install.h"
@@ -46,17 +46,19 @@ int main(int argc, char* argv[]) {
const char *const files2[] = { "/home/lennart/test.service", NULL };
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
+ UnitFileState state = 0;
h = hashmap_new(&string_hash_ops);
r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
assert_se(r == 0);
HASHMAP_FOREACH(p, h, i) {
- UnitFileState s;
+ UnitFileState s = _UNIT_FILE_STATE_INVALID;
- s = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path));
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s);
- assert_se(p->state == s);
+ assert_se((r < 0 && p->state == UNIT_FILE_BAD) ||
+ (p->state == s));
fprintf(stderr, "%s (%s)\n",
p->path,
@@ -78,7 +80,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
log_error("disable");
@@ -91,7 +95,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_DISABLED);
log_error("mask");
changes = NULL;
@@ -106,7 +112,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_MASKED);
log_error("unmask");
changes = NULL;
@@ -121,7 +129,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_DISABLED);
log_error("mask");
changes = NULL;
@@ -133,7 +143,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_MASKED);
log_error("disable");
changes = NULL;
@@ -148,7 +160,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_MASKED);
log_error("umask");
changes = NULL;
@@ -160,7 +174,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_DISABLED);
log_error("enable files2");
changes = NULL;
@@ -172,19 +188,22 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
log_error("disable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r < 0);
log_error("link files2");
changes = NULL;
@@ -196,19 +215,22 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_LINKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_LINKED);
log_error("disable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r < 0);
log_error("link files2");
changes = NULL;
@@ -220,7 +242,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_LINKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_LINKED);
log_error("reenable files2");
changes = NULL;
@@ -232,19 +256,22 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
log_error("disable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r < 0);
log_error("preset files");
changes = NULL;
n_changes = 0;
@@ -255,7 +282,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0])) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
return 0;
}
diff --git a/src/test/test-job-type.c b/src/test/test-job-type.c
index af0d76e894..75ce3a349e 100644
--- a/src/test/test-job-type.c
+++ b/src/test/test-job-type.c
@@ -22,8 +22,8 @@
#include <stdio.h>
#include "job.h"
-#include "unit.h"
#include "service.h"
+#include "unit.h"
int main(int argc, char*argv[]) {
JobType a, b, c, ab, bc, ab_c, bc_a, a_bc;
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 9765075365..427c698d1d 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -19,8 +19,8 @@
#include "locale-util.h"
-#include "strv.h"
#include "macro.h"
+#include "strv.h"
static void test_get_locales(void) {
_cleanup_strv_free_ char **locales = NULL;
diff --git a/src/test/test-log.c b/src/test/test-log.c
index 9dcfa2f274..a01df9b049 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -22,9 +22,9 @@
#include <stddef.h>
#include <unistd.h>
+#include "formats-util.h"
#include "log.h"
#include "util.h"
-#include "formats-util.h"
int main(int argc, char* argv[]) {
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index e3e5a95add..556938a0f8 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -19,11 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
-#include "loopback-setup.h"
#include "log.h"
+#include "loopback-setup.h"
int main(int argc, char* argv[]) {
int r;
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index 3050be9e9d..1175114a3a 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -22,8 +22,8 @@
#include <stdlib.h>
#include <unistd.h>
-#include "namespace.h"
#include "log.h"
+#include "namespace.h"
int main(int argc, char *argv[]) {
const char * const writable[] = {
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
index d3ae0599ab..f0d5d71083 100644
--- a/src/test/test-parse-util.c
+++ b/src/test/test-parse-util.c
@@ -352,6 +352,24 @@ static void test_safe_atolli(void) {
assert_se(r == 0);
assert_se(l == 12345);
+ r = safe_atolli(" 12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atolli("-12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atolli(" -12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atolli("12345678901234567890", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atolli("-12345678901234567890", &l);
+ assert_se(r == -ERANGE);
+
r = safe_atolli("junk", &l);
assert_se(r == -EINVAL);
}
@@ -364,9 +382,19 @@ static void test_safe_atou16(void) {
assert_se(r == 0);
assert_se(l == 12345);
+ r = safe_atou16(" 12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
r = safe_atou16("123456", &l);
assert_se(r == -ERANGE);
+ r = safe_atou16("-1", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atou16(" -1", &l);
+ assert_se(r == -ERANGE);
+
r = safe_atou16("junk", &l);
assert_se(r == -EINVAL);
}
@@ -379,9 +407,24 @@ static void test_safe_atoi16(void) {
assert_se(r == 0);
assert_se(l == -12345);
+ r = safe_atoi16(" -12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atoi16("32767", &l);
+ assert_se(r == 0);
+ assert_se(l == 32767);
+
+ r = safe_atoi16(" 32767", &l);
+ assert_se(r == 0);
+ assert_se(l == 32767);
+
r = safe_atoi16("36536", &l);
assert_se(r == -ERANGE);
+ r = safe_atoi16("-32769", &l);
+ assert_se(r == -ERANGE);
+
r = safe_atoi16("junk", &l);
assert_se(r == -EINVAL);
}
diff --git a/src/test/test-ratelimit.c b/src/test/test-ratelimit.c
index 462b55cdb3..990b834c79 100644
--- a/src/test/test-ratelimit.c
+++ b/src/test/test-ratelimit.c
@@ -19,9 +19,9 @@
#include <unistd.h>
+#include "macro.h"
#include "ratelimit.h"
#include "time-util.h"
-#include "macro.h"
static void test_ratelimit_test(void) {
int i;
diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index ebc9110c4d..8396ae60f3 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -21,8 +21,8 @@
#include <sched.h>
-#include "manager.h"
#include "macro.h"
+#include "manager.h"
int main(int argc, char *argv[]) {
Manager *m = NULL;
diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c
index 2402da6a6f..a571a95a70 100644
--- a/src/test/test-siphash24.c
+++ b/src/test/test-siphash24.c
@@ -19,22 +19,17 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
#include "siphash24.h"
+#include "util.h"
#define ITERATIONS 10000000ULL
-/* see https://131002.net/siphash/siphash.pdf, Appendix A */
-int main(int argc, char *argv[]) {
+static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
struct siphash state = {};
- const uint8_t in[15] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e };
- const uint8_t key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
uint64_t out = 0;
unsigned i, j;
- siphash24((uint8_t *)&out, in, sizeof(in), key);
+ out = siphash24(in, len, key);
assert_se(out == htole64(0xa129ca6149be45e5));
/* verify the internal state as given in the above paper */
@@ -43,12 +38,12 @@ int main(int argc, char *argv[]) {
assert_se(state.v1 == 0x6b617f6d656e6665);
assert_se(state.v2 == 0x6b7f62616d677361);
assert_se(state.v3 == 0x7b6b696e727e6c7b);
- siphash24_compress(in, sizeof(in), &state);
+ siphash24_compress(in, len, &state);
assert_se(state.v0 == 0x4a017198de0a59e0);
assert_se(state.v1 == 0x0d52f6f62a4f59a4);
assert_se(state.v2 == 0x634cb3577b01fd3d);
assert_se(state.v3 == 0xa5224d6f55c7d9c8);
- siphash24_finalize((uint8_t*)&out, &state);
+ out = siphash24_finalize(&state);
assert_se(out == htole64(0xa129ca6149be45e5));
assert_se(state.v0 == 0xf6bcd53893fecff1);
assert_se(state.v1 == 0x54b9964c7ea0d937);
@@ -57,14 +52,34 @@ int main(int argc, char *argv[]) {
/* verify that decomposing the input in three chunks gives the
same result */
- for (i = 0; i < sizeof(in); i++) {
- for (j = i; j < sizeof(in); j++) {
+ for (i = 0; i < len; i++) {
+ for (j = i; j < len; j++) {
siphash24_init(&state, key);
siphash24_compress(in, i, &state);
siphash24_compress(&in[i], j - i, &state);
- siphash24_compress(&in[j], sizeof(in) - j, &state);
- siphash24_finalize((uint8_t*)&out, &state);
+ siphash24_compress(&in[j], len - j, &state);
+ out = siphash24_finalize(&state);
assert_se(out == htole64(0xa129ca6149be45e5));
}
}
+ return 0;
+}
+
+/* see https://131002.net/siphash/siphash.pdf, Appendix A */
+int main(int argc, char *argv[]) {
+ const uint8_t in[15] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e };
+ const uint8_t key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
+ uint8_t in_buf[20];
+
+ /* Test with same input but different alignments. */
+ memcpy(in_buf, in, sizeof(in));
+ do_test(in_buf, sizeof(in), key);
+ memcpy(in_buf + 1, in, sizeof(in));
+ do_test(in_buf + 1, sizeof(in), key);
+ memcpy(in_buf + 2, in, sizeof(in));
+ do_test(in_buf + 2, sizeof(in), key);
+ memcpy(in_buf + 4, in, sizeof(in));
+ do_test(in_buf + 4, sizeof(in), key);
}
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index 4308ddfb64..fb115ce4f3 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -21,10 +21,10 @@
#include <stdio.h>
-#include "util.h"
#include "log.h"
#include "sleep-config.h"
#include "strv.h"
+#include "util.h"
static void test_sleep(void) {
_cleanup_strv_free_ char
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index b9699b2028..33ff3755bc 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -41,28 +41,25 @@ static void test_socket_address_parse(void) {
assert_se(socket_address_parse(&a, "65535") >= 0);
- if (socket_ipv6_is_supported()) {
- assert_se(socket_address_parse(&a, "[::1]") < 0);
- assert_se(socket_address_parse(&a, "[::1]8888") < 0);
- assert_se(socket_address_parse(&a, "::1") < 0);
- assert_se(socket_address_parse(&a, "[::1]:0") < 0);
- assert_se(socket_address_parse(&a, "[::1]:65536") < 0);
- assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0);
-
- assert_se(socket_address_parse(&a, "8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
-
- assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
-
- assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
- } else {
- assert_se(socket_address_parse(&a, "[::1]:8888") < 0);
-
- assert_se(socket_address_parse(&a, "8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET);
- }
+ /* The checks below will pass even if ipv6 is disabled in
+ * kernel. The underlying glibc's inet_pton() is just a string
+ * parser and doesn't make any syscalls. */
+
+ assert_se(socket_address_parse(&a, "[::1]") < 0);
+ assert_se(socket_address_parse(&a, "[::1]8888") < 0);
+ assert_se(socket_address_parse(&a, "::1") < 0);
+ assert_se(socket_address_parse(&a, "[::1]:0") < 0);
+ assert_se(socket_address_parse(&a, "[::1]:65536") < 0);
+ assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0);
+
+ assert_se(socket_address_parse(&a, "8888") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == (socket_ipv6_is_supported() ? AF_INET6 : AF_INET));
+
+ assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+
+ assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_INET6);
assert_se(socket_address_parse(&a, "192.168.1.254:8888") >= 0);
assert_se(a.sockaddr.sa.sa_family == AF_INET);
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index ed4abdbf12..aef992ee3c 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -36,21 +36,19 @@
#include "logs-show.h"
#include "mount.h"
#include "path.h"
+#include "rlimit-util.h"
#include "scope.h"
#include "service.h"
#include "slice.h"
-#include "snapshot.h"
#include "socket-util.h"
#include "socket.h"
#include "swap.h"
#include "target.h"
+#include "test-tables.h"
#include "timer.h"
#include "unit-name.h"
#include "unit.h"
#include "util.h"
-#include "rlimit-util.h"
-
-#include "test-tables.h"
int main(int argc, char **argv) {
test_table(architecture, ARCHITECTURE);
@@ -98,7 +96,6 @@ int main(int argc, char **argv) {
test_table(service_state, SERVICE_STATE);
test_table(service_type, SERVICE_TYPE);
test_table(slice_state, SLICE_STATE);
- test_table(snapshot_state, SNAPSHOT_STATE);
test_table(socket_address_bind_ipv6_only, SOCKET_ADDRESS_BIND_IPV6_ONLY);
test_table(socket_exec_command, SOCKET_EXEC_COMMAND);
test_table(socket_result, SOCKET_RESULT);
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index e940b5a204..84b448a095 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -18,8 +18,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <stdbool.h>
+#include <stdio.h>
#include "fd-util.h"
#include "fileio.h"
diff --git a/src/test/test-time.c b/src/test/test-time.c
index 820e4aaee2..8896b2c92b 100644
--- a/src/test/test-time.c
+++ b/src/test/test-time.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "time-util.h"
#include "strv.h"
+#include "time-util.h"
static void test_parse_sec(void) {
usec_t u;
diff --git a/src/test/test-unaligned.c b/src/test/test-unaligned.c
index 1754d06b2d..b18b3fca0e 100644
--- a/src/test/test-unaligned.c
+++ b/src/test/test-unaligned.c
@@ -17,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unaligned.h"
#include "sparse-endian.h"
+#include "unaligned.h"
#include "util.h"
static uint8_t data[] = {
@@ -26,7 +26,7 @@ static uint8_t data[] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
};
-int main(int argc, const char *argv[]) {
+static void test_be(void) {
uint8_t scratch[16];
assert_se(unaligned_read_be16(&data[0]) == 0x0001);
@@ -91,3 +91,75 @@ int main(int argc, const char *argv[]) {
unaligned_write_be64(&scratch[7], 0x0708090a0b0c0d0e);
assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0);
}
+
+static void test_le(void) {
+ uint8_t scratch[16];
+
+ assert_se(unaligned_read_le16(&data[0]) == 0x0100);
+ assert_se(unaligned_read_le16(&data[1]) == 0x0201);
+
+ assert_se(unaligned_read_le32(&data[0]) == 0x03020100);
+ assert_se(unaligned_read_le32(&data[1]) == 0x04030201);
+ assert_se(unaligned_read_le32(&data[2]) == 0x05040302);
+ assert_se(unaligned_read_le32(&data[3]) == 0x06050403);
+
+ assert_se(unaligned_read_le64(&data[0]) == 0x0706050403020100);
+ assert_se(unaligned_read_le64(&data[1]) == 0x0807060504030201);
+ assert_se(unaligned_read_le64(&data[2]) == 0x0908070605040302);
+ assert_se(unaligned_read_le64(&data[3]) == 0x0a09080706050403);
+ assert_se(unaligned_read_le64(&data[4]) == 0x0b0a090807060504);
+ assert_se(unaligned_read_le64(&data[5]) == 0x0c0b0a0908070605);
+ assert_se(unaligned_read_le64(&data[6]) == 0x0d0c0b0a09080706);
+ assert_se(unaligned_read_le64(&data[7]) == 0x0e0d0c0b0a090807);
+
+ zero(scratch);
+ unaligned_write_le16(&scratch[0], 0x0100);
+ assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0);
+ zero(scratch);
+ unaligned_write_le16(&scratch[1], 0x0201);
+ assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0);
+
+ zero(scratch);
+ unaligned_write_le32(&scratch[0], 0x03020100);
+
+ assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0);
+ zero(scratch);
+ unaligned_write_le32(&scratch[1], 0x04030201);
+ assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0);
+ zero(scratch);
+ unaligned_write_le32(&scratch[2], 0x05040302);
+ assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0);
+ zero(scratch);
+ unaligned_write_le32(&scratch[3], 0x06050403);
+ assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0);
+
+ zero(scratch);
+ unaligned_write_le64(&scratch[0], 0x0706050403020100);
+ assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[1], 0x0807060504030201);
+ assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[2], 0x0908070605040302);
+ assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[3], 0x0a09080706050403);
+ assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[4], 0x0B0A090807060504);
+ assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[5], 0x0c0b0a0908070605);
+ assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[6], 0x0d0c0b0a09080706);
+ assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[7], 0x0e0d0c0b0a090807);
+ assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0);
+}
+
+int main(int argc, const char *argv[]) {
+ test_be();
+ test_le();
+}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 3648ec9c58..c3973a316e 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -40,6 +40,7 @@
#include "string-util.h"
#include "strv.h"
#include "test-helper.h"
+#include "user-util.h"
#include "util.h"
static int test_unit_file_get_set(void) {
@@ -558,76 +559,66 @@ static void test_load_env_file_5(void) {
static void test_install_printf(void) {
char name[] = "name.service",
- path[] = "/run/systemd/system/name.service",
- user[] = "xxxx-no-such-user";
- UnitFileInstallInfo i = {name, path, user};
- UnitFileInstallInfo i2 = {name, path, NULL};
+ path[] = "/run/systemd/system/name.service";
+ UnitFileInstallInfo i = { .name = name, .path = path, };
+ UnitFileInstallInfo i2 = { .name= name, .path = path, };
char name3[] = "name@inst.service",
path3[] = "/run/systemd/system/name.service";
- UnitFileInstallInfo i3 = {name3, path3, user};
- UnitFileInstallInfo i4 = {name3, path3, NULL};
+ UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
+ UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
- _cleanup_free_ char *mid, *bid, *host;
+ _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
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(asprintf(&uid, UID_FMT, getuid()) >= 0);
#define expect(src, pattern, result) \
do { \
_cleanup_free_ char *t = NULL; \
_cleanup_free_ char \
*d1 = strdup(i.name), \
- *d2 = strdup(i.path), \
- *d3 = strdup(i.user); \
+ *d2 = strdup(i.path); \
assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
memzero(i.name, strlen(i.name)); \
memzero(i.path, strlen(i.path)); \
- memzero(i.user, strlen(i.user)); \
- assert_se(d1 && d2 && d3); \
+ assert_se(d1 && d2); \
if (result) { \
printf("%s\n", t); \
- assert_se(streq(t, result)); \
- } else assert_se(t == NULL); \
+ assert_se(streq(t, result)); \
+ } else assert_se(t == NULL); \
strcpy(i.name, d1); \
strcpy(i.path, d2); \
- strcpy(i.user, d3); \
} while(false)
- assert_se(setenv("USER", "root", 1) == 0);
-
expect(i, "%n", "name.service");
expect(i, "%N", "name");
expect(i, "%p", "name");
expect(i, "%i", "");
- expect(i, "%u", "xxxx-no-such-user");
-
- DISABLE_WARNING_NONNULL;
- expect(i, "%U", NULL);
- REENABLE_WARNING;
+ expect(i, "%u", user);
+ expect(i, "%U", uid);
expect(i, "%m", mid);
expect(i, "%b", bid);
expect(i, "%H", host);
- expect(i2, "%u", "root");
- expect(i2, "%U", "0");
+ expect(i2, "%u", user);
+ expect(i2, "%U", uid);
expect(i3, "%n", "name@inst.service");
expect(i3, "%N", "name@inst");
expect(i3, "%p", "name");
- expect(i3, "%u", "xxxx-no-such-user");
-
- DISABLE_WARNING_NONNULL;
- expect(i3, "%U", NULL);
- REENABLE_WARNING;
+ expect(i3, "%u", user);
+ expect(i3, "%U", uid);
expect(i3, "%m", mid);
expect(i3, "%b", bid);
expect(i3, "%H", host);
- expect(i4, "%u", "root");
- expect(i4, "%U", "0");
+ expect(i4, "%u", user);
+ expect(i4, "%U", uid);
}
static uint64_t make_cap(int cap) {
@@ -741,6 +732,44 @@ static void test_config_parse_rlimit(void) {
rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
}
+static void test_config_parse_pass_environ(void) {
+ /* int config_parse_pass_environ(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
+ int r;
+ _cleanup_strv_free_ char **passenv = NULL;
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "A B",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_length(passenv) == 2);
+ assert_se(streq(passenv[0], "A"));
+ assert_se(streq(passenv[1], "B"));
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_isempty(passenv));
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_length(passenv) == 1);
+ assert_se(streq(passenv[0], "normal_name"));
+
+}
+
int main(int argc, char *argv[]) {
int r;
@@ -751,6 +780,7 @@ int main(int argc, char *argv[]) {
test_config_parse_exec();
test_config_parse_bounding_set();
test_config_parse_rlimit();
+ test_config_parse_pass_environ();
test_load_env_file_1();
test_load_env_file_2();
test_load_env_file_3();
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 9db7853dd4..842ca40102 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -37,6 +37,7 @@
#include "unit-name.h"
#include "unit-printf.h"
#include "unit.h"
+#include "user-util.h"
#include "util.h"
static void test_unit_name_is_valid(void) {
@@ -193,15 +194,15 @@ static int test_unit_printf(void) {
Unit *u, *u2;
int r;
- _cleanup_free_ char *mid, *bid, *host, *root_uid;
- struct passwd *root;
+ _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
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((root = getpwnam("root")));
- assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
+ assert_se(host = gethostname_malloc());
+ assert_se(user = getusername_malloc());
+ assert_se(asprintf(&uid, UID_FMT, getuid()));
+ assert_se(get_home_dir(&home) >= 0);
+ assert_se(get_shell(&shell) >= 0);
r = manager_new(MANAGER_USER, true, &m);
if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
@@ -222,8 +223,6 @@ static int test_unit_printf(void) {
assert_se(streq(t, expected)); \
}
- assert_se(setenv("USER", "root", 1) == 0);
- assert_se(setenv("HOME", "/root", 1) == 0);
assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
assert_se(u = unit_new(m, sizeof(Service)));
@@ -242,9 +241,9 @@ static int test_unit_printf(void) {
expect(u, "%p", "blah");
expect(u, "%P", "blah");
expect(u, "%i", "");
- expect(u, "%u", root->pw_name);
- expect(u, "%U", root_uid);
- expect(u, "%h", root->pw_dir);
+ expect(u, "%u", user);
+ expect(u, "%U", uid);
+ expect(u, "%h", home);
expect(u, "%m", mid);
expect(u, "%b", bid);
expect(u, "%H", host);
@@ -262,9 +261,9 @@ static int test_unit_printf(void) {
expect(u2, "%P", "blah");
expect(u2, "%i", "foo-foo");
expect(u2, "%I", "foo/foo");
- expect(u2, "%u", root->pw_name);
- expect(u2, "%U", root_uid);
- expect(u2, "%h", root->pw_dir);
+ expect(u2, "%u", user);
+ expect(u2, "%U", uid);
+ expect(u2, "%h", home);
expect(u2, "%m", mid);
expect(u2, "%b", bid);
expect(u2, "%H", host);
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index 0af8349732..e98be5763c 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -20,9 +20,9 @@
***/
#include "alloc-util.h"
+#include "string-util.h"
#include "utf8.h"
#include "util.h"
-#include "string-util.h"
static void test_utf8_is_printable(void) {
assert_se(utf8_is_printable("ascii is valid\tunicode", 22));
diff --git a/src/test/test-watchdog.c b/src/test/test-watchdog.c
index 2e5d0c3aae..d10d9f49af 100644
--- a/src/test/test-watchdog.c
+++ b/src/test/test-watchdog.c
@@ -21,8 +21,8 @@
#include <unistd.h>
-#include "watchdog.h"
#include "log.h"
+#include "watchdog.h"
int main(int argc, char *argv[]) {
usec_t t = 10 * USEC_PER_SEC;
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 64f0c9396c..f9a759e223 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1226,8 +1226,28 @@ static int create_item(Item *i) {
mkdir_parents_label(i->path, 0755);
if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {
- RUN_WITH_UMASK((~i->mode) & 0777)
- r = btrfs_subvol_make(i->path);
+
+ if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)
+
+ /* Don't create a subvolume unless the
+ * root directory is one, too. We do
+ * this under the assumption that if
+ * the root directory is just a plain
+ * directory (i.e. very light-weight),
+ * we shouldn't try to split it up
+ * into subvolumes (i.e. more
+ * heavy-weight). Thus, chroot()
+ * environments and suchlike will get
+ * a full brtfs subvolume set up below
+ * their tree only if they
+ * specifically set up a btrfs
+ * subvolume for the root dir too. */
+
+ r = -ENOTTY;
+ else {
+ RUN_WITH_UMASK((~i->mode) & 0777)
+ r = btrfs_subvol_make(i->path);
+ }
} else
r = 0;
@@ -1267,6 +1287,10 @@ static int create_item(Item *i) {
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of read-only file system: %m", i->path);
return 0;
}
+ if (r == -ENOPROTOOPT) {
+ log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because quota support is disabled: %m", i->path);
+ return 0;
+ }
if (r < 0)
return log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
if (r > 0)
diff --git a/src/udev/mtd_probe/mtd_probe.c b/src/udev/mtd_probe/mtd_probe.c
index 67b750c4b3..462fab7623 100644
--- a/src/udev/mtd_probe/mtd_probe.c
+++ b/src/udev/mtd_probe/mtd_probe.c
@@ -17,14 +17,14 @@
* Boston, MA 02110-1301 USA
*/
+#include <fcntl.h>
+#include <mtd/mtd-user.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/ioctl.h>
-#include <mtd/mtd-user.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <sys/types.h>
#include <unistd.h>
-#include <stdlib.h>
#include "mtd_probe.h"
diff --git a/src/udev/mtd_probe/probe_smartmedia.c b/src/udev/mtd_probe/probe_smartmedia.c
index a007ccee2f..6a6c5522a7 100644
--- a/src/udev/mtd_probe/probe_smartmedia.c
+++ b/src/udev/mtd_probe/probe_smartmedia.c
@@ -17,15 +17,16 @@
* Boston, MA 02110-1301 USA
*/
+#include <fcntl.h>
+#include <mtd/mtd-user.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <mtd/mtd-user.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <sys/types.h>
#include <unistd.h>
-#include <stdint.h>
+
#include "mtd_probe.h"
static const uint8_t cis_signature[] = {
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 776674e994..77d9bf995a 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -354,14 +354,14 @@ static int get_mac(struct udev_device *device, bool want_random,
if (want_random)
random_bytes(mac->ether_addr_octet, ETH_ALEN);
else {
- uint8_t result[8];
+ uint64_t result;
- r = net_get_unique_predictable_data(device, result);
+ r = net_get_unique_predictable_data(device, &result);
if (r < 0)
return r;
assert_cc(ETH_ALEN <= sizeof(result));
- memcpy(mac->ether_addr_octet, result, ETH_ALEN);
+ memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
}
/* see eth_random_addr in the kernel */
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 1e190140b2..aa18c7e420 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -593,31 +593,23 @@ static struct udev_device *handle_bcma(struct udev_device *parent, char **path)
return parent;
}
-static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) {
- struct udev_device *scsi_dev;
+/* Handle devices of AP bus in System z platform. */
+static struct udev_device *handle_ap(struct udev_device *parent, char **path) {
+ const char *type, *func;
assert(parent);
- assert(dev);
assert(path);
- scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device");
- if (scsi_dev != NULL) {
- const char *wwpn;
- const char *lun;
- const char *hba_id;
-
- hba_id = udev_device_get_sysattr_value(scsi_dev, "hba_id");
- wwpn = udev_device_get_sysattr_value(scsi_dev, "wwpn");
- lun = udev_device_get_sysattr_value(scsi_dev, "fcp_lun");
- if (hba_id != NULL && lun != NULL && wwpn != NULL) {
- path_prepend(path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun);
- goto out;
- }
- }
+ type = udev_device_get_sysattr_value(parent, "type");
+ func = udev_device_get_sysattr_value(parent, "ap_functions");
- path_prepend(path, "ccw-%s", udev_device_get_sysname(parent));
+ if (type != NULL && func != NULL) {
+ path_prepend(path, "ap-%s-%s", type, func);
+ goto out;
+ }
+ path_prepend(path, "ap-%s", udev_device_get_sysname(parent));
out:
- parent = skip_subsystem(parent, "ccw");
+ parent = skip_subsystem(parent, "ap");
return parent;
}
@@ -629,13 +621,6 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
assert(dev);
- /* S390 ccw bus */
- parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL);
- if (parent != NULL) {
- handle_ccw(parent, dev, &path);
- goto out;
- }
-
/* walk up the chain of devices and compose path */
parent = dev;
while (parent != NULL) {
@@ -683,6 +668,25 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
parent = skip_subsystem(parent, "scm");
supported_transport = true;
supported_parent = true;
+ } else if (streq(subsys, "ccw")) {
+ path_prepend(&path, "ccw-%s", udev_device_get_sysname(parent));
+ parent = skip_subsystem(parent, "ccw");
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "ccwgroup")) {
+ path_prepend(&path, "ccwgroup-%s", udev_device_get_sysname(parent));
+ parent = skip_subsystem(parent, "ccwgroup");
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "ap")) {
+ parent = handle_ap(parent, &path);
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "iucv")) {
+ path_prepend(&path, "iucv-%s", udev_device_get_sysname(parent));
+ parent = skip_subsystem(parent, "iucv");
+ supported_transport = true;
+ supported_parent = true;
}
if (parent)
@@ -705,7 +709,6 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport)
path = mfree(path);
-out:
if (path != NULL) {
char tag[UTIL_NAME_SIZE];
size_t i;
diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c
index bbda9de08c..3ebe36f043 100644
--- a/src/udev/udev-builtin-uaccess.c
+++ b/src/udev/udev-builtin-uaccess.c
@@ -18,9 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#include "sd-login.h"
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index 1e05be51a5..962de22f43 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -10,13 +10,13 @@
*/
#include <errno.h>
-#include <stdlib.h>
+#include <poll.h>
#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <poll.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "fd-util.h"
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
index 9aa5ab185d..f1fdccaed8 100644
--- a/src/udev/udev-watch.c
+++ b/src/udev/udev-watch.c
@@ -17,12 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <errno.h>
-#include <stdio.h>
#include <dirent.h>
+#include <errno.h>
#include <stddef.h>
-#include <unistd.h>
+#include <stdio.h>
#include <sys/inotify.h>
+#include <unistd.h>
#include "udev.h"
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
index 78170463b6..989decbe95 100644
--- a/src/udev/udevadm-control.c
+++ b/src/udev/udevadm-control.c
@@ -13,15 +13,15 @@
*/
#include <errno.h>
+#include <getopt.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stddef.h>
#include <string.h>
#include <unistd.h>
-#include <getopt.h>
-#include "udev.h"
#include "udev-util.h"
+#include "udev.h"
static void print_help(void) {
printf("%s control COMMAND\n\n"
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index 30aa53feb2..f9cb5e63a2 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -15,15 +15,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
#include <errno.h>
-#include <signal.h>
#include <getopt.h>
-#include <time.h>
-#include <sys/time.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/epoll.h>
+#include <sys/time.h>
+#include <time.h>
#include "fd-util.h"
#include "formats-util.h"
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index c25071b0fe..6a5dc6e9e4 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -17,14 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "parse-util.h"
#include "udev.h"
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 5364b92a57..6d9d765153 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -191,7 +191,7 @@ static void worker_free(struct worker *worker) {
assert(worker->manager);
- hashmap_remove(worker->manager->workers, UINT_TO_PTR(worker->pid));
+ hashmap_remove(worker->manager->workers, PID_TO_PTR(worker->pid));
udev_monitor_unref(worker->monitor);
event_free(worker->event);
@@ -234,7 +234,7 @@ static int worker_new(struct worker **ret, Manager *manager, struct udev_monitor
if (r < 0)
return r;
- r = hashmap_put(manager->workers, UINT_TO_PTR(pid), worker);
+ r = hashmap_put(manager->workers, PID_TO_PTR(pid), worker);
if (r < 0)
return r;
@@ -891,7 +891,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
}
/* lookup worker who sent the signal */
- worker = hashmap_get(manager->workers, UINT_TO_PTR(ucred->pid));
+ worker = hashmap_get(manager->workers, PID_TO_PTR(ucred->pid));
if (!worker) {
log_debug("worker ["PID_FMT"] returned, but is no longer tracked", ucred->pid);
continue;
@@ -1195,7 +1195,7 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi
if (pid <= 0)
break;
- worker = hashmap_get(manager->workers, UINT_TO_PTR(pid));
+ worker = hashmap_get(manager->workers, PID_TO_PTR(pid));
if (!worker) {
log_warning("worker ["PID_FMT"] is unknown, ignoring", pid);
continue;
diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c
index 607d78a019..aec6676a33 100644
--- a/src/udev/v4l_id/v4l_id.c
+++ b/src/udev/v4l_id/v4l_id.c
@@ -13,17 +13,17 @@
* General Public License for more details:
*/
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
-#include <sys/types.h>
-#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <linux/videodev2.h>
#include "fd-util.h"