summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore17
-rw-r--r--Makefile-man.am9
-rw-r--r--Makefile.am218
-rw-r--r--NEWS50
-rw-r--r--README2
-rw-r--r--TODO2
-rw-r--r--configure.ac21
-rw-r--r--hwdb/20-bluetooth-vendor-product.hwdb239
-rw-r--r--hwdb/60-evdev.hwdb6
-rw-r--r--hwdb/60-keyboard.hwdb16
-rw-r--r--man/loginctl.xml10
-rw-r--r--man/machinectl.xml7
-rw-r--r--man/networkd.conf.xml159
-rw-r--r--man/nss-myhostname.xml7
-rw-r--r--man/systemctl.xml10
-rw-r--r--man/systemd-ask-password.xml9
-rw-r--r--man/systemd-nspawn.xml5
-rw-r--r--man/systemd-resolved.service.xml7
-rw-r--r--man/systemd-run.xml6
-rw-r--r--man/systemd-sysv-generator.xml2
-rw-r--r--man/systemd.exec.xml16
-rw-r--r--man/systemd.network.xml88
-rw-r--r--man/systemd.nspawn.xml12
-rw-r--r--man/systemd.offline-updates.xml169
-rw-r--r--man/systemd.resource-control.xml24
-rw-r--r--man/udev_device_get_syspath.xml4
-rw-r--r--po/zh_CN.po141
-rw-r--r--shell-completion/bash/systemd-nspawn4
-rw-r--r--src/activate/activate.c24
-rw-r--r--src/ask-password/ask-password.c11
-rw-r--r--src/basic/c-rbtree.c5
-rw-r--r--src/basic/cgroup-util.c47
-rw-r--r--src/basic/cgroup-util.h2
-rw-r--r--src/basic/copy.c63
-rw-r--r--src/basic/hostname-util.c10
-rw-r--r--src/basic/locale-util.c2
-rw-r--r--src/basic/log.h1
-rw-r--r--src/basic/macro.h7
-rw-r--r--src/basic/missing.h220
-rw-r--r--src/basic/missing_syscall.h310
-rw-r--r--src/basic/mount-util.c4
-rw-r--r--src/basic/selinux-util.c12
-rw-r--r--src/basic/socket-label.c34
-rw-r--r--src/basic/utf8.h1
-rw-r--r--src/basic/util.h1
-rw-r--r--src/basic/xattr-util.c2
-rw-r--r--src/core/cgroup.c6
-rw-r--r--src/core/device.c2
-rw-r--r--src/core/execute.c16
-rw-r--r--src/core/failure-action.c6
-rw-r--r--src/core/job.c28
-rw-r--r--src/core/load-fragment.c14
-rw-r--r--src/core/main.c17
-rw-r--r--src/core/manager.c14
-rw-r--r--src/core/mount-setup.c2
-rw-r--r--src/core/mount.c26
-rw-r--r--src/core/selinux-setup.c2
-rw-r--r--src/core/socket.c8
-rw-r--r--src/core/transaction.c9
-rw-r--r--src/core/umount.c1
-rw-r--r--src/cryptsetup/cryptsetup.c8
-rw-r--r--src/firstboot/firstboot.c12
-rw-r--r--src/fstab-generator/fstab-generator.c4
-rw-r--r--src/import/import-common.c4
-rw-r--r--src/journal/test-compress-benchmark.c2
-rw-r--r--src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/libsystemd-network/dhcp-identifier.h43
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h7
-rw-r--r--src/libsystemd-network/lldp-neighbor.c54
-rw-r--r--src/libsystemd-network/lldp.h102
-rw-r--r--src/libsystemd-network/network-internal.c29
-rw-r--r--src/libsystemd-network/network-internal.h4
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c48
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c48
-rw-r--r--src/libsystemd-network/sd-lldp.c17
-rw-r--r--src/libsystemd-network/test-lldp.c23
-rw-r--r--src/libsystemd/sd-bus/bus-message.c15
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c5
-rw-r--r--src/libsystemd/sd-device/sd-device.c37
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c5
-rw-r--r--src/libsystemd/sd-path/sd-path.c9
-rw-r--r--src/libudev/libudev.h1
-rw-r--r--src/locale/localectl.c6
-rw-r--r--src/login/70-uaccess.rules6
-rw-r--r--src/login/loginctl.c29
-rw-r--r--src/login/logind-utmp.c2
-rw-r--r--src/machine/machinectl.c80
-rw-r--r--src/network/networkctl.c7
-rw-r--r--src/network/networkd-conf.c155
-rw-r--r--src/network/networkd-conf.h36
-rw-r--r--src/network/networkd-dhcp4.c16
-rw-r--r--src/network/networkd-dhcp6.c17
-rw-r--r--src/network/networkd-gperf.gperf18
-rw-r--r--src/network/networkd-link.c38
-rw-r--r--src/network/networkd-lldp-tx.c31
-rw-r--r--src/network/networkd-manager.c2
-rw-r--r--src/network/networkd-network-gperf.gperf4
-rw-r--r--src/network/networkd-network.c7
-rw-r--r--src/network/networkd-network.h8
-rw-r--r--src/network/networkd.c5
-rw-r--r--src/network/networkd.h8
-rw-r--r--src/nspawn/nspawn-cgroup.c9
-rw-r--r--src/nspawn/nspawn-mount.c25
-rw-r--r--src/nspawn/nspawn.c14
-rw-r--r--src/resolve/resolve-tool.c23
-rw-r--r--src/run/run.c14
-rw-r--r--src/shared/acpi-fpdt.c6
-rw-r--r--src/shared/bus-util.c48
-rw-r--r--src/shared/bus-util.h4
-rw-r--r--src/shared/conf-parser.c13
-rw-r--r--src/shared/gcrypt-util.c4
-rw-r--r--src/shared/gcrypt-util.h14
-rw-r--r--src/shared/machine-pool.c8
-rw-r--r--src/shared/ptyfwd.c5
-rw-r--r--src/shared/spawn-polkit-agent.c4
-rw-r--r--src/systemctl/systemctl.c197
-rw-r--r--src/systemd/_sd-common.h2
-rw-r--r--src/systemd/sd-bus-protocol.h2
-rw-r--r--src/systemd/sd-bus-vtable.h2
-rw-r--r--src/systemd/sd-bus.h4
-rw-r--r--src/systemd/sd-device.h1
-rw-r--r--src/systemd/sd-dhcp-client.h2
-rw-r--r--src/systemd/sd-dhcp6-client.h5
-rw-r--r--src/systemd/sd-event.h6
-rw-r--r--src/systemd/sd-id128.h4
-rw-r--r--src/systemd/sd-journal.h2
-rw-r--r--src/systemd/sd-lldp.h81
-rw-r--r--src/test/test-alloc-util.c55
-rw-r--r--src/test/test-boot-timestamps.c51
-rw-r--r--src/test/test-conf-parser.c9
-rw-r--r--src/test/test-copy.c61
-rw-r--r--src/test/test-cpu-set-util.c143
-rw-r--r--src/test/test-daemon.c10
-rw-r--r--src/test/test-env-util.c (renamed from src/test/test-env-replace.c)30
-rw-r--r--src/test/test-escape.c114
-rw-r--r--src/test/test-execute.c84
-rw-r--r--src/test/test-fd-util.c103
-rw-r--r--src/test/test-fileio.c133
-rw-r--r--src/test/test-fs-util.c91
-rw-r--r--src/test/test-fstab-util.c37
-rw-r--r--src/test/test-glob-util.c50
-rw-r--r--src/test/test-hexdecoct.c387
-rw-r--r--src/test/test-io-util.c69
-rw-r--r--src/test/test-ipcrm.c11
-rw-r--r--src/test/test-libudev.c267
-rw-r--r--src/test/test-loopback.c4
-rw-r--r--src/test/test-path-util.c46
-rw-r--r--src/test/test-proc-cmdline.c52
-rw-r--r--src/test/test-selinux.c19
-rw-r--r--src/test/test-signal-util.c18
-rw-r--r--src/test/test-stat-util.c68
-rw-r--r--src/test/test-string-util.c265
-rw-r--r--src/test/test-strv.c21
-rw-r--r--src/test/test-udev.c10
-rw-r--r--src/test/test-user-util.c27
-rw-r--r--src/test/test-util.c1441
-rw-r--r--src/test/test-web-util.c39
-rw-r--r--src/test/test-xattr-util.c69
-rw-r--r--src/tmpfiles/tmpfiles.c9
-rw-r--r--src/udev/udev.h1
-rw-r--r--test/TEST-08-ISSUE-2730/Makefile10
-rwxr-xr-xtest/TEST-08-ISSUE-2730/test.sh94
-rw-r--r--test/test-execute/exec-capabilityambientset-merge-nfsnobody.service9
-rw-r--r--test/test-execute/exec-capabilityambientset-nfsnobody.service8
-rw-r--r--test/test-execute/exec-group-nfsnobody.service7
-rw-r--r--test/test-execute/exec-runtimedirectory-owner-nfsnobody.service9
-rw-r--r--test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service11
-rw-r--r--test/test-execute/exec-systemcallfilter-system-user.service11
-rw-r--r--test/test-execute/exec-user-nfsnobody.service7
-rw-r--r--test/test-functions31
-rwxr-xr-xtest/udev-test.pl9
-rw-r--r--units/ldconfig.service3
172 files changed, 4981 insertions, 2642 deletions
diff --git a/.gitignore b/.gitignore
index 0e467b0c6c..403c16c339 100644
--- a/.gitignore
+++ b/.gitignore
@@ -126,6 +126,7 @@
/test-acd
/test-acl-util
/test-af-list
+/test-alloc-util
/test-architecture
/test-arphrd-list
/test-ask-password-api
@@ -133,7 +134,7 @@
/test-audit-type
/test-barrier
/test-bitmap
-/test-boot-timestamp
+/test-boot-timestamps
/test-btrfs
/test-bus-benchmark
/test-bus-chat
@@ -166,6 +167,7 @@
/test-conf-parser
/test-copy
/test-coredump-vacuum
+/test-cpu-set-util
/test-daemon
/test-date
/test-device-nodes
@@ -180,21 +182,27 @@
/test-efi-disk.img
/test-ellipsize
/test-engine
-/test-env-replace
+/test-env-util
+/test-escape
/test-event
/test-execute
/test-extract-word
+/test-fd-util
/test-fdset
/test-fileio
/test-firewall-util
+/test-fs-util
/test-fstab-util
+/test-glob-util
/test-hashmap
+/test-hexdecoct
/test-hostname
/test-hostname-util
/test-id128
/test-inhibit
/test-install
/test-install-root
+/test-io-util
/test-ipcrm
/test-ipv4ll
/test-ipv4ll-manual
@@ -236,6 +244,7 @@
/test-path-lookup
/test-path-util
/test-prioq
+/test-proc-cmdline
/test-process-util
/test-pty
/test-qcow2
@@ -255,6 +264,7 @@
/test-siphash24
/test-sleep
/test-socket-util
+/test-stat-util
/test-strbuf
/test-string-util
/test-strip-tab-ansi
@@ -274,6 +284,8 @@
/test-util
/test-verbs
/test-watchdog
+/test-web-util
+/test-xattr-util
/test-xml
/timedatectl
/udevadm
@@ -281,6 +293,7 @@
/v4l_id
Makefile.in
__pycache__/
+*.py[co]
aclocal.m4
config.h
config.h.in
diff --git a/Makefile-man.am b/Makefile-man.am
index 3f03afc2ef..a4835a533f 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -144,6 +144,7 @@ MANPAGES += \
man/systemd.link.5 \
man/systemd.mount.5 \
man/systemd.nspawn.5 \
+ man/systemd.offline-updates.7 \
man/systemd.path.5 \
man/systemd.preset.5 \
man/systemd.resource-control.5 \
@@ -1960,15 +1961,21 @@ endif
if ENABLE_NETWORKD
MANPAGES += \
man/networkctl.1 \
+ man/networkd.conf.5 \
man/systemd-networkd-wait-online.service.8 \
man/systemd-networkd.service.8 \
man/systemd.netdev.5 \
man/systemd.network.5
MANPAGES_ALIAS += \
+ man/networkd.conf.d.5 \
man/systemd-networkd-wait-online.8 \
man/systemd-networkd.8
+man/networkd.conf.d.5: man/networkd.conf.5
man/systemd-networkd-wait-online.8: man/systemd-networkd-wait-online.service.8
man/systemd-networkd.8: man/systemd-networkd.service.8
+man/networkd.conf.d.html: man/networkd.conf.html
+ $(html-alias)
+
man/systemd-networkd-wait-online.html: man/systemd-networkd-wait-online.service.html
$(html-alias)
@@ -2479,6 +2486,7 @@ EXTRA_DIST += \
man/machinectl.xml \
man/modules-load.d.xml \
man/networkctl.xml \
+ man/networkd.conf.xml \
man/nss-myhostname.xml \
man/nss-mymachines.xml \
man/nss-resolve.xml \
@@ -2644,6 +2652,7 @@ EXTRA_DIST += \
man/systemd.netdev.xml \
man/systemd.network.xml \
man/systemd.nspawn.xml \
+ man/systemd.offline-updates.xml \
man/systemd.path.xml \
man/systemd.preset.xml \
man/systemd.resource-control.xml \
diff --git a/Makefile.am b/Makefile.am
index dc9f9afa9c..4ff9276fdd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -131,8 +131,12 @@ TEST_EXTENSIONS = .py
PY_LOG_COMPILER = $(PYTHON)
DISABLE_HARD_ERRORS = yes
if ENABLE_TESTS
-noinst_PROGRAMS = $(manual_tests) $(tests)
+noinst_PROGRAMS = $(manual_tests) $(tests) $(unsafe_tests)
TESTS = $(tests)
+if ENABLE_UNSAFE_TESTS
+TESTS += \
+ $(unsafe_tests)
+endif
else
noinst_PROGRAMS =
TESTS =
@@ -740,6 +744,7 @@ noinst_LTLIBRARIES += \
libbasic_la_SOURCES = \
src/basic/missing.h \
+ src/basic/missing_syscall.h \
src/basic/capability-util.c \
src/basic/capability-util.h \
src/basic/c-rbtree.c \
@@ -1387,19 +1392,17 @@ EXTRA_DIST += \
manual_tests += \
test-ns \
- test-loopback \
- test-hostname \
- test-daemon \
test-cgroup \
test-install \
- test-watchdog \
- test-log \
- test-ipcrm \
test-btrfs \
test-acd \
test-ipv4ll-manual \
test-ask-password-api
+unsafe_tests = \
+ test-hostname \
+ test-ipcrm
+
if HAVE_LIBIPTC
manual_tests += \
test-firewall-util
@@ -1411,10 +1414,14 @@ manual_tests += \
endif
tests += \
+ test-daemon \
+ test-log \
+ test-loopback \
test-engine \
+ test-watchdog \
test-cgroup-mask \
test-job-type \
- test-env-replace \
+ test-env-util \
test-strbuf \
test-strv \
test-path \
@@ -1426,6 +1433,18 @@ tests += \
test-utf8 \
test-ellipsize \
test-util \
+ test-cpu-set-util \
+ test-hexdecoct \
+ test-escape \
+ test-alloc-util \
+ test-proc-cmdline \
+ test-io-util \
+ test-glob-util \
+ test-xattr-util \
+ test-fs-util \
+ test-web-util \
+ test-stat-util \
+ test-fd-util \
test-string-util \
test-extract-word \
test-parse-util \
@@ -1544,6 +1563,7 @@ EXTRA_DIST += \
test/test-execute/exec-passenvironment-repeated.service \
test/test-execute/exec-passenvironment.service \
test/test-execute/exec-group.service \
+ test/test-execute/exec-group-nfsnobody.service \
test/test-execute/exec-ignoresigpipe-no.service \
test/test-execute/exec-ignoresigpipe-yes.service \
test/test-execute/exec-personality-x86-64.service \
@@ -1559,7 +1579,10 @@ EXTRA_DIST += \
test/test-execute/exec-systemcallfilter-failing.service \
test/test-execute/exec-systemcallfilter-not-failing2.service \
test/test-execute/exec-systemcallfilter-not-failing.service \
+ test/test-execute/exec-systemcallfilter-system-user.service \
+ test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service \
test/test-execute/exec-user.service \
+ test/test-execute/exec-user-nfsnobody.service \
test/test-execute/exec-workingdirectory.service \
test/test-execute/exec-umask-0177.service \
test/test-execute/exec-umask-default.service \
@@ -1576,10 +1599,13 @@ EXTRA_DIST += \
test/test-execute/exec-capabilityboundingset-reset.service \
test/test-execute/exec-capabilityboundingset-simple.service \
test/test-execute/exec-capabilityambientset.service \
+ test/test-execute/exec-capabilityambientset-nfsnobody.service \
test/test-execute/exec-capabilityambientset-merge.service \
+ test/test-execute/exec-capabilityambientset-merge-nfsnobody.service \
test/test-execute/exec-runtimedirectory.service \
test/test-execute/exec-runtimedirectory-mode.service \
test/test-execute/exec-runtimedirectory-owner.service \
+ test/test-execute/exec-runtimedirectory-owner-nfsnobody.service \
test/bus-policy/hello.conf \
test/bus-policy/methods.conf \
test/bus-policy/ownerships.conf \
@@ -1651,13 +1677,13 @@ test_dns_domain_LDADD = \
if ENABLE_EFI
-manual_tests += \
- test-boot-timestamp
+tests += \
+ test-boot-timestamps
-test_boot_timestamp_SOURCES = \
+test_boot_timestamps_SOURCES = \
src/test/test-boot-timestamps.c
-test_boot_timestamp_LDADD = \
+test_boot_timestamps_LDADD = \
libshared.la
endif
@@ -1755,6 +1781,78 @@ test_util_SOURCES = \
test_util_LDADD = \
libshared.la
+test_hexdecoct_SOURCES = \
+ src/test/test-hexdecoct.c
+
+test_hexdecoct_LDADD = \
+ libbasic.la
+
+test_alloc_util_SOURCES = \
+ src/test/test-alloc-util.c
+
+test_alloc_util_LDADD = \
+ libbasic.la
+
+test_xattr_util_SOURCES = \
+ src/test/test-xattr-util.c
+
+test_xattr_util_LDADD = \
+ libbasic.la
+
+test_io_util_SOURCES = \
+ src/test/test-io-util.c
+
+test_io_util_LDADD = \
+ libbasic.la
+
+test_glob_util_SOURCES = \
+ src/test/test-glob-util.c
+
+test_glob_util_LDADD = \
+ libbasic.la
+
+test_fs_util_SOURCES = \
+ src/test/test-fs-util.c
+
+test_fs_util_LDADD = \
+ libbasic.la
+
+test_proc_cmdline_SOURCES = \
+ src/test/test-proc-cmdline.c
+
+test_proc_cmdline_LDADD = \
+ libbasic.la
+
+test_fd_util_SOURCES = \
+ src/test/test-fd-util.c
+
+test_fd_util_LDADD = \
+ libbasic.la
+
+test_web_util_SOURCES = \
+ src/test/test-web-util.c
+
+test_web_util_LDADD = \
+ libbasic.la
+
+test_cpu_set_util_SOURCES = \
+ src/test/test-cpu-set-util.c
+
+test_cpu_set_util_LDADD = \
+ libbasic.la
+
+test_stat_util_SOURCES = \
+ src/test/test-stat-util.c
+
+test_stat_util_LDADD = \
+ libbasic.la
+
+test_escape_SOURCES = \
+ src/test/test-escape.c
+
+test_escape_LDADD = \
+ libbasic.la
+
test_string_util_SOURCES = \
src/test/test-string-util.c
@@ -2099,10 +2197,10 @@ test_cgroup_util_SOURCES = \
test_cgroup_util_LDADD = \
libshared.la
-test_env_replace_SOURCES = \
- src/test/test-env-replace.c
+test_env_util_SOURCES = \
+ src/test/test-env-util.c
-test_env_replace_LDADD = \
+test_env_util_LDADD = \
libshared.la
test_strbuf_SOURCES = \
@@ -3325,7 +3423,6 @@ libsystemd_network_la_SOURCES = \
src/libsystemd-network/sd-dhcp6-lease.c \
src/libsystemd-network/dhcp-identifier.h \
src/libsystemd-network/dhcp-identifier.c \
- src/libsystemd-network/lldp.h \
src/libsystemd-network/lldp-internal.h \
src/libsystemd-network/lldp-network.h \
src/libsystemd-network/lldp-network.c \
@@ -3703,8 +3800,10 @@ endif
endif
endif
+tests += \
+ test-libudev
+
manual_tests += \
- test-libudev \
test-udev
test_libudev_SOURCES = \
@@ -3852,6 +3951,34 @@ systemd_cat_SOURCES = \
systemd_cat_LDADD = \
libjournal-core.la
+if HAVE_LIBCURL
+rootlibexec_PROGRAMS += \
+ systemd-journal-upload
+
+systemd_journal_upload_SOURCES = \
+ src/journal-remote/journal-upload.h \
+ src/journal-remote/journal-upload.c \
+ src/journal-remote/journal-upload-journal.c
+
+systemd_journal_upload_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(LIBCURL_CFLAGS)
+
+systemd_journal_upload_LDADD = \
+ libshared.la \
+ $(LIBCURL_LIBS)
+
+nodist_systemunit_DATA += \
+ units/systemd-journal-upload.service
+
+nodist_pkgsysconf_DATA += \
+ src/journal-remote/journal-upload.conf
+endif
+
+EXTRA_DIST += \
+ units/systemd-journal-upload.service.in \
+ src/journal-remote/journal-upload.conf.in
+
if HAVE_MICROHTTPD
rootlibexec_PROGRAMS += \
systemd-journal-remote
@@ -3911,34 +4038,6 @@ EXTRA_DIST += \
src/journal-remote/log-generator.py
endif
-if HAVE_LIBCURL
-rootlibexec_PROGRAMS += \
- systemd-journal-upload
-
-systemd_journal_upload_SOURCES = \
- src/journal-remote/journal-upload.h \
- src/journal-remote/journal-upload.c \
- src/journal-remote/journal-upload-journal.c
-
-systemd_journal_upload_CFLAGS = \
- $(AM_CFLAGS) \
- $(LIBCURL_CFLAGS)
-
-systemd_journal_upload_LDADD = \
- libshared.la \
- $(LIBCURL_LIBS)
-
-nodist_systemunit_DATA += \
- units/systemd-journal-upload.service
-
-nodist_pkgsysconf_DATA += \
- src/journal-remote/journal-upload.conf
-endif
-
-EXTRA_DIST += \
- units/systemd-journal-upload.service.in \
- src/journal-remote/journal-upload.conf.in
-
# using _CFLAGS = in the conditional below would suppress AM_CFLAGS
journalctl_CFLAGS = \
$(AM_CFLAGS)
@@ -4115,11 +4214,9 @@ catalog-remove-hook:
UNINSTALL_DATA_HOOKS += \
catalog-remove-hook
-manual_tests += \
- test-journal-enum
-
tests += \
test-journal \
+ test-journal-enum \
test-journal-send \
test-journal-syslog \
test-journal-match \
@@ -4164,7 +4261,9 @@ libsystemd_journal_internal_la_SOURCES = \
src/journal/mmap-cache.h \
src/journal/compress.c \
src/journal/audit-type.h \
- src/journal/audit-type.c
+ src/journal/audit-type.c \
+ src/shared/gcrypt-util.h \
+ src/shared/gcrypt-util.c
nodist_libsystemd_journal_internal_la_SOURCES = \
src/journal/audit_type-to-name.h
@@ -4196,9 +4295,7 @@ libsystemd_journal_internal_la_SOURCES += \
src/journal/journal-authenticate.c \
src/journal/journal-authenticate.h \
src/journal/fsprg.c \
- src/journal/fsprg.h \
- src/shared/gcrypt-util.c \
- src/shared/gcrypt-util.h
+ src/journal/fsprg.h
libsystemd_journal_internal_la_LIBADD += \
$(GCRYPT_LIBS)
@@ -5311,6 +5408,8 @@ libnetworkd_core_la_CFLAGS = \
libnetworkd_core_la_SOURCES = \
src/libsystemd-network/network-internal.h \
src/network/networkd.h \
+ src/network/networkd-conf.h \
+ src/network/networkd-conf.c \
src/network/networkd-link.h \
src/network/networkd-link.c \
src/network/networkd-netdev.h \
@@ -5359,6 +5458,7 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-lldp-tx.c
nodist_libnetworkd_core_la_SOURCES = \
+ src/network/networkd-gperf.c \
src/network/networkd-network-gperf.c \
src/network/networkd-netdev-gperf.c
@@ -5455,6 +5555,7 @@ BUSNAMES_TARGET_WANTS += \
endif
gperf_gperf_sources += \
+ src/network/networkd-gperf.gperf \
src/network/networkd-network-gperf.gperf \
src/network/networkd-netdev-gperf.gperf
@@ -6078,7 +6179,6 @@ DISTCHECK_CONFIGURE_FLAGS += \
endif
.PHONY: dist-check-help
-
dist-check-help: $(rootbin_PROGRAMS) $(bin_PROGRAMS)
for i in $(abspath $^); do \
if $$i --help | grep -v 'default:' | grep -E -q '.{80}.' ; then \
@@ -6087,6 +6187,18 @@ dist-check-help: $(rootbin_PROGRAMS) $(bin_PROGRAMS)
exit 1; \
fi; done
+include_compilers = "$(CC)" "$(CC) -ansi" "$(CC) -std=iso9899:1990"
+public_headers = $(filter-out src/systemd/_sd-common.h, $(pkginclude_HEADERS) $(include_HEADERS))
+.PHONY: dist-check-includes
+dist-check-includes: $(public_headers)
+ @res=0; \
+ for i in $(abspath $^); do \
+ for cc in $(include_compilers); do \
+ echo "$$cc -o/dev/null -c -x c -include "$$i" - </dev/null"; \
+ $$cc -o/dev/null -c -x c -include "$$i" - </dev/null || res=1; \
+ done; \
+ done; exit $$res
+
.PHONY: hwdb-update
hwdb-update:
( cd $(top_srcdir)/hwdb && \
diff --git a/NEWS b/NEWS
index 8b30bee6b7..b75638ed36 100644
--- a/NEWS
+++ b/NEWS
@@ -19,10 +19,58 @@ CHANGES WITH 230 in spe:
again don't consider turning this on in your stable, LTS or
production release just yet.
+ * systemd-resolve conveniently resolves DANE records with the --tlsa
+ option and OPENPGPKEY records with the --openpgp option.
+
* Testing tool /usr/lib/systemd/systemd-activate is renamed to
systemd-socket-activate and installed into /usr/bin. It is now fully
supported.
+ * The unified cgroup hierarchy added in Linux 4.5 is now supported.
+ Use systemd.unified_cgroup_hierarchy=1 on the kernel command line
+ to enable.
+ WARNING: it is not possible to use previous systemd versions with
+ systemd.unified_cgroup_hierarchy=1 and the new kernel. Therefore it
+ is necessary to also update systemd in the initramfs if using the
+ unified hierarchy. Updated selinux policy is also required.
+
+ * LLDP support has been extended, and both passive (receive-only)
+ and active (sender) modes are supported. Passive mode
+ ("routers-only") is enabled by default in systemd-networkd.
+ Active LLDP mode is enabled by default for containers on the
+ internal network.
+ "networkctl lldp" can be used to list information gathered.
+
+ * Headers for LLDP support (sd-lldp.h) are now public.
+
+ * The Unique Identifier sent in DHCP requests can be configured.
+
+ * systemd-journald now uses separate threads to flush changes to
+ disk when closing journal files.
+
+ * systemd-ask-password skips printing of the password to stdout
+ with --no-output which can be useful in scripts.
+
+ * Framebuffer devices (/dev/fb*) and 3D printers and scanners
+ (devices tagged with ID_MAKER_TOOL) are now tagged with
+ "uaccess" and are available to logged in users.
+
+ * systemd-bootchart has been split out to a separate repository:
+ https://github.com/systemd/systemd-bootchart
+
+ * Compatibility libraries libsystemd-daemon.so, libsystemd-journal.so,
+ libsystemd-id128.so, and libsystemd-login.so which have been
+ deprecated since systemd-209 have been removed along along with the
+ corresponding pkg-config files. All symbols provided by the those
+ libraries are provided by libsystemd.so.
+
+ * Capabilities= setting has been removed (it is ignored for backwards
+ compatibility). AmbientCapabilities= and CapabilityBoundingSet=
+ should be used instead.
+
+ * systemd-bus-proxyd has been removed, as kdbus will not be merged
+ in current form.
+
CHANGES WITH 229:
* The systemd-resolved DNS resolver service has gained a substantial
@@ -1345,7 +1393,7 @@ CHANGES WITH 219:
* machinectl is now able to clone container images
efficiently, if the underlying file system (btrfs) supports
- it, with the new "machinectl list-images" command. It also
+ it, with the new "machinectl clone" command. It also
gained commands for renaming and removing images, as well as
marking them read-only or read-write (supported also on
legacy file systems).
diff --git a/README b/README
index 3bdf4107cf..0118c102f6 100644
--- a/README
+++ b/README
@@ -35,7 +35,7 @@ LICENSE:
- except src/udev/* which is (currently still) GPLv2, GPLv2+
REQUIREMENTS:
- Linux kernel >= 3.11
+ Linux kernel >= 3.12
Linux kernel >= 4.2 for unified cgroup hierarchy support
Kernel Config Options:
diff --git a/TODO b/TODO
index 08b74083d3..b2840ba4ab 100644
--- a/TODO
+++ b/TODO
@@ -49,8 +49,6 @@ Features:
* cache sd_event_now() result from before the first iteration...
-* support for the new copy_file_range() syscall
-
* add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction
* Maybe add a way how users can "pin" units into memory, so that they are not subject to automatic GC?
diff --git a/configure.ac b/configure.ac
index a02185d252..464f318dfc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -296,8 +296,19 @@ LIBS="$save_LIBS"
AC_SUBST(CAP_LIBS)
AC_CHECK_FUNCS([__secure_getenv secure_getenv])
-AC_CHECK_DECLS([memfd_create, gettid, pivot_root, name_to_handle_at, setns, getrandom, renameat2, kcmp, keyctl, LO_FLAGS_PARTSCAN],
- [], [], [[
+AC_CHECK_DECLS([
+ memfd_create,
+ gettid,
+ pivot_root,
+ name_to_handle_at,
+ setns,
+ getrandom,
+ renameat2,
+ kcmp,
+ keyctl,
+ LO_FLAGS_PARTSCAN,
+ copy_file_range],
+ [], [], [[
#include <sys/types.h>
#include <unistd.h>
#include <sys/mount.h>
@@ -1489,9 +1500,10 @@ AS_IF([test x"$cross_compiling" = "xyes"], [], [
])
AC_ARG_ENABLE(tests,
- [AC_HELP_STRING([--disable-tests], [disable tests])],
+ [AC_HELP_STRING([--disable-tests], [disable tests, or enable extra tests with =unsafe])],
enable_tests=$enableval, enable_tests=yes)
-AM_CONDITIONAL(ENABLE_TESTS, [test x$enable_tests = xyes])
+AM_CONDITIONAL(ENABLE_TESTS, [test x$enable_tests = xyes -o x$enable_tests = xunsafe])
+AM_CONDITIONAL(ENABLE_UNSAFE_TESTS, [test x$enable_tests = xunsafe])
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug@<:@=LIST@:>@], [enable extra debugging (hashmap,mmap-cache)])],
@@ -1613,6 +1625,7 @@ AC_MSG_RESULT([
ldconfig support: ${enable_ldconfig}
hibernate support: ${enable_hibernate}
extra debugging: ${enable_debug}
+ tests: ${enable_tests}
prefix: ${prefix}
rootprefix: ${with_rootprefix}
diff --git a/hwdb/20-bluetooth-vendor-product.hwdb b/hwdb/20-bluetooth-vendor-product.hwdb
index 516abad246..821d3e96bd 100644
--- a/hwdb/20-bluetooth-vendor-product.hwdb
+++ b/hwdb/20-bluetooth-vendor-product.hwdb
@@ -1111,7 +1111,7 @@ bluetooth:v016F*
ID_VENDOR_FROM_DATABASE=Podo Labs, Inc
bluetooth:v0170*
- ID_VENDOR_FROM_DATABASE=Roche Diabetes Care AG
+ ID_VENDOR_FROM_DATABASE=F. Hoffmann-La Roche AG
bluetooth:v0171*
ID_VENDOR_FROM_DATABASE=Amazon Fulfillment Service
@@ -2231,3 +2231,240 @@ bluetooth:v02E4*
bluetooth:v02E5*
ID_VENDOR_FROM_DATABASE=Espressif Incorporated ( 乐鑫信息科技(上海)有限公司 )
+
+bluetooth:v02E6*
+ ID_VENDOR_FROM_DATABASE=Unwire
+
+bluetooth:v02E7*
+ ID_VENDOR_FROM_DATABASE=Connected Yard, Inc.
+
+bluetooth:v02E8*
+ ID_VENDOR_FROM_DATABASE=American Music Environments
+
+bluetooth:v02E9*
+ ID_VENDOR_FROM_DATABASE=Sensogram Technologies, Inc.
+
+bluetooth:v02EA*
+ ID_VENDOR_FROM_DATABASE=Fujitsu Limited
+
+bluetooth:v02EB*
+ ID_VENDOR_FROM_DATABASE=Ardic Technology
+
+bluetooth:v02EC*
+ ID_VENDOR_FROM_DATABASE=Delta Systems, Inc
+
+bluetooth:v02ED*
+ ID_VENDOR_FROM_DATABASE=HTC Corporation
+
+bluetooth:v02EE*
+ ID_VENDOR_FROM_DATABASE=Citizen Holdings Co., Ltd.
+
+bluetooth:v02EF*
+ ID_VENDOR_FROM_DATABASE=SMART-INNOVATION.inc
+
+bluetooth:v02F0*
+ ID_VENDOR_FROM_DATABASE=Blackrat Software
+
+bluetooth:v02F1*
+ ID_VENDOR_FROM_DATABASE=The Idea Cave, LLC
+
+bluetooth:v02F2*
+ ID_VENDOR_FROM_DATABASE=GoPro, Inc.
+
+bluetooth:v02F3*
+ ID_VENDOR_FROM_DATABASE=AuthAir, Inc
+
+bluetooth:v02F4*
+ ID_VENDOR_FROM_DATABASE=Vensi, Inc.
+
+bluetooth:v02F5*
+ ID_VENDOR_FROM_DATABASE=Indagem Tech LLC
+
+bluetooth:v02F6*
+ ID_VENDOR_FROM_DATABASE=Intemo Technologies
+
+bluetooth:v02F7*
+ ID_VENDOR_FROM_DATABASE=DreamVisions co., Ltd.
+
+bluetooth:v02F8*
+ ID_VENDOR_FROM_DATABASE=Runteq Oy Ltd
+
+bluetooth:v02F9*
+ ID_VENDOR_FROM_DATABASE=IMAGINATION TECHNOLOGIES LTD
+
+bluetooth:v02FA*
+ ID_VENDOR_FROM_DATABASE=CoSTAR Technologies
+
+bluetooth:v02FB*
+ ID_VENDOR_FROM_DATABASE=Clarius Mobile Health Corp.
+
+bluetooth:v02FC*
+ ID_VENDOR_FROM_DATABASE=Shanghai Frequen Microelectronics Co., Ltd.
+
+bluetooth:v02FD*
+ ID_VENDOR_FROM_DATABASE=Uwanna, Inc.
+
+bluetooth:v02FE*
+ ID_VENDOR_FROM_DATABASE=Lierda Science & Technology Group Co., Ltd.
+
+bluetooth:v02FF*
+ ID_VENDOR_FROM_DATABASE=Silicon Laboratories
+
+bluetooth:v0300*
+ ID_VENDOR_FROM_DATABASE=World Moto Inc.
+
+bluetooth:v0301*
+ ID_VENDOR_FROM_DATABASE=Giatec Scientific Inc.
+
+bluetooth:v0302*
+ ID_VENDOR_FROM_DATABASE=Loop Devices, Inc
+
+bluetooth:v0303*
+ ID_VENDOR_FROM_DATABASE=IACA electronique
+
+bluetooth:v0304*
+ ID_VENDOR_FROM_DATABASE=Martians Inc
+
+bluetooth:v0305*
+ ID_VENDOR_FROM_DATABASE=Swipp ApS
+
+bluetooth:v0306*
+ ID_VENDOR_FROM_DATABASE=Life Laboratory Inc.
+
+bluetooth:v0307*
+ ID_VENDOR_FROM_DATABASE=FUJI INDUSTRIAL CO.,LTD.
+
+bluetooth:v0308*
+ ID_VENDOR_FROM_DATABASE=Surefire, LLC
+
+bluetooth:v0309*
+ ID_VENDOR_FROM_DATABASE=Dolby Labs
+
+bluetooth:v030A*
+ ID_VENDOR_FROM_DATABASE=Ellisys
+
+bluetooth:v030B*
+ ID_VENDOR_FROM_DATABASE=Magnitude Lighting Converters
+
+bluetooth:v030C*
+ ID_VENDOR_FROM_DATABASE=Hilti AG
+
+bluetooth:v030D*
+ ID_VENDOR_FROM_DATABASE=Devdata S.r.l.
+
+bluetooth:v030E*
+ ID_VENDOR_FROM_DATABASE=Deviceworx
+
+bluetooth:v030F*
+ ID_VENDOR_FROM_DATABASE=Shortcut Labs
+
+bluetooth:v0310*
+ ID_VENDOR_FROM_DATABASE=SGL Italia S.r.l.
+
+bluetooth:v0311*
+ ID_VENDOR_FROM_DATABASE=PEEQ DATA
+
+bluetooth:v0312*
+ ID_VENDOR_FROM_DATABASE=Ducere Technologies Pvt Ltd
+
+bluetooth:v0313*
+ ID_VENDOR_FROM_DATABASE=DiveNav, Inc.
+
+bluetooth:v0314*
+ ID_VENDOR_FROM_DATABASE=RIIG AI Sp. z o.o.
+
+bluetooth:v0315*
+ ID_VENDOR_FROM_DATABASE=Thermo Fisher Scientific
+
+bluetooth:v0316*
+ ID_VENDOR_FROM_DATABASE=AG Measurematics Pvt. Ltd.
+
+bluetooth:v0317*
+ ID_VENDOR_FROM_DATABASE=CHUO Electronics CO., LTD.
+
+bluetooth:v0318*
+ ID_VENDOR_FROM_DATABASE=Aspenta International
+
+bluetooth:v0319*
+ ID_VENDOR_FROM_DATABASE=Eugster Frismag AG
+
+bluetooth:v031A*
+ ID_VENDOR_FROM_DATABASE=Amber wireless GmbH
+
+bluetooth:v031B*
+ ID_VENDOR_FROM_DATABASE=HQ Inc
+
+bluetooth:v031C*
+ ID_VENDOR_FROM_DATABASE=Lab Sensor Solutions
+
+bluetooth:v031D*
+ ID_VENDOR_FROM_DATABASE=Enterlab ApS
+
+bluetooth:v031E*
+ ID_VENDOR_FROM_DATABASE=Eyefi, Inc.
+
+bluetooth:v031F*
+ ID_VENDOR_FROM_DATABASE=MetaSystem S.p.A
+
+bluetooth:v0320*
+ ID_VENDOR_FROM_DATABASE=SONO ELECTRONICS. CO., LTD
+
+bluetooth:v0321*
+ ID_VENDOR_FROM_DATABASE=Jewelbots
+
+bluetooth:v0322*
+ ID_VENDOR_FROM_DATABASE=Compumedics Limited
+
+bluetooth:v0323*
+ ID_VENDOR_FROM_DATABASE=Rotor Bike Components
+
+bluetooth:v0324*
+ ID_VENDOR_FROM_DATABASE=Astro, Inc.
+
+bluetooth:v0325*
+ ID_VENDOR_FROM_DATABASE=Amotus Solutions
+
+bluetooth:v0326*
+ ID_VENDOR_FROM_DATABASE=Healthwear Technologies (Changzhou)Ltd
+
+bluetooth:v0327*
+ ID_VENDOR_FROM_DATABASE=Essex Electronics
+
+bluetooth:v0328*
+ ID_VENDOR_FROM_DATABASE=Grundfos A/S
+
+bluetooth:v0329*
+ ID_VENDOR_FROM_DATABASE=Eargo, Inc.
+
+bluetooth:v032A*
+ ID_VENDOR_FROM_DATABASE=Electronic Design Lab
+
+bluetooth:v032B*
+ ID_VENDOR_FROM_DATABASE=ESYLUX
+
+bluetooth:v032C*
+ ID_VENDOR_FROM_DATABASE=NIPPON SMT.CO.,Ltd
+
+bluetooth:v032D*
+ ID_VENDOR_FROM_DATABASE=BM innovations GmbH
+
+bluetooth:v032E*
+ ID_VENDOR_FROM_DATABASE=indoormap
+
+bluetooth:v032F*
+ ID_VENDOR_FROM_DATABASE=OttoQ Inc
+
+bluetooth:v0330*
+ ID_VENDOR_FROM_DATABASE=North Pole Engineering
+
+bluetooth:v0331*
+ ID_VENDOR_FROM_DATABASE=3flares Technologies Inc.
+
+bluetooth:v0332*
+ ID_VENDOR_FROM_DATABASE=Electrocompaniet A.S.
+
+bluetooth:v0333*
+ ID_VENDOR_FROM_DATABASE=Mul-T-Lock
+
+bluetooth:v0334*
+ ID_VENDOR_FROM_DATABASE=Corentium AS
diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
index 598172256b..4f04539e12 100644
--- a/hwdb/60-evdev.hwdb
+++ b/hwdb/60-evdev.hwdb
@@ -98,6 +98,12 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:bvn*:bvr*:bd*:svnASUSTeKComputerInc.:pnK
EVDEV_ABS_35=::18
EVDEV_ABS_36=::16
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnX550CC:*
+ EVDEV_ABS_00=::31
+ EVDEV_ABS_01=::30
+ EVDEV_ABS_35=::31
+ EVDEV_ABS_36=::30
+
#########################################
# Dell
#########################################
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 01213b6069..46013d3449 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -378,6 +378,7 @@ evdev:input:b0003v0458p0708*
###########################################################
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*:pvr*
KEYBOARD_KEY_81=fn_esc
KEYBOARD_KEY_89=battery # Fn+F8
KEYBOARD_KEY_8a=screenlock # Fn+F6
@@ -488,10 +489,11 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:pvr*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPLicrice:pvr*
# HP ProBook 440 G2
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP440G2:pvr*
-# HP ProBook 445 G1
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook445G1NotebookPC:pvr*
-# HP ProBook 450 G0
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook450G0:pvr*
+# several HP ProBooks 4xx
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook4*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHP*ProBook*4*:pvr*
+# HP ZBook
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook*:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
# HP ProBook 6555b
@@ -500,10 +502,8 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard:pnHPProBook6555b:*
# HP ProBook 440 G3
evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*440*G3*
- KEYBOARD_KEY_92=brightnessdown
- KEYBOARD_KEY_97=brightnessup
- KEYBOARD_KEY_ee=switchvideomode
- KEYBOARD_KEY_81=f20 # micmute
+ KEYBOARD_KEY_85=unknown # lid close; also reported via special evdev
+ KEYBOARD_KEY_f8=unknown # rf kill; also reported via special evdev
###########################################################
# IBM
diff --git a/man/loginctl.xml b/man/loginctl.xml
index f41acc6a1b..7f7252a5d9 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -94,6 +94,16 @@
</varlistentry>
<varlistentry>
+ <term><option>--value</option></term>
+
+ <listitem>
+ <para>When printing properties with <command>show</command>,
+ only print the value, and skip the property name and
+ <literal>=</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-a</option></term>
<term><option>--all</option></term>
diff --git a/man/machinectl.xml b/man/machinectl.xml
index 967ca01470..cee4bb72ce 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -136,6 +136,13 @@
(<literal>.</literal>).</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--value</option></term>
+
+ <listitem><para>When printing properties with <command>show</command>, only print the value,
+ and skip the property name and <literal>=</literal>.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>-l</option></term>
<term><option>--full</option></term>
diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml
new file mode 100644
index 0000000000..30674e12bc
--- /dev/null
+++ b/man/networkd.conf.xml
@@ -0,0 +1,159 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2014 Vinay Kulkarni
+
+ 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/>.
+-->
+
+<refentry id="networkd.conf" conditional='ENABLE_NETWORKD'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>networkd.conf</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Vinay</firstname>
+ <surname>Kulkarni</surname>
+ <email>kulkarniv@vmware.com</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>networkd.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>networkd.conf</refname>
+ <refname>networkd.conf.d</refname>
+ <refpurpose>Global Network configuration files</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/etc/systemd/networkd.conf</filename></para>
+ <para><filename>/etc/systemd/networkd.conf.d/*.conf</filename></para>
+ <para><filename>/usr/lib/systemd/networkd.conf.d/*.conf</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>These configuration files control global network parameters.
+ For e.g. DHCP Unique Identifier (DUID).</para>
+
+ </refsect1>
+
+ <xi:include href="standard-conf.xml" xpointer="main-conf" />
+
+ <refsect1>
+ <title>[DUID] Section Options</title>
+
+ <para>This section configures the DHCP Unique Idendifier (DUID) value used by DHCP
+ protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface
+ Identity Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6
+ address. DHCPv4 client protocol sends IAID and DUID to the DHCP server when acquiring
+ a dynamic IPv4 address if <option>ClientIdentifier=duid</option>. IAID and DUID allows
+ a DHCP server to uniquely identify the machine and the interface requesting a DHCP IP.
+ To configure IAID and ClientIdentifier, see <citerefentry><refentrytitle>systemd.network
+ </refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+ <para>The DUID value specified here overrides the DUID that systemd-networkd
+ generates using the machine-id from the <filename>/etc/machine-id</filename> file.
+ To configure DUID per-network, see <citerefentry><refentrytitle>systemd.network
+ </refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+ <para>The configured DHCP DUID should conform to the specification in
+ <ulink url="http://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>,
+ <ulink url="http://tools.ietf.org/html/rfc6355">RFC 6355</ulink>. To configure IAID, see
+ <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>.</para>
+
+ <para>The following options are available in <literal>[DUID]</literal> section:</para>
+
+ <variablelist class='network-directives'>
+
+ <varlistentry>
+ <term><varname>Type=</varname></term>
+ <listitem><para>The type of DUID specified in this section. The following values are
+ supported:</para>
+ <para>raw : If <literal>Type=raw</literal>, then <literal>RawData=</literal> specifies
+ the entire DUID. For e.g: <literal>RawData=00:02:00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</literal>
+ specifies a 14 byte long DUID-EN ("00:02"), with enterprise number 43793 ("00:00:ab:11"),
+ and identifier value "f9:2a:c2:77:29:f9:5c:00".</para><para>If Type is not specified and
+ RawData is specified, Type defaults to 'raw'.</para>
+ <para>Type will support the following values in the future:</para>
+ <para>link-layer-and-time : If <literal>Type=link-layer-and-time</literal>, then
+ <literal>MACAddress=</literal> and <literal>TimeStamp=</literal> specify the hardware
+ address and time-stamp for DUID-LLT.</para>
+ <para>vendor : If <literal>Type=vendor</literal>, then <literal>EnterpriseNumber=</literal>
+ and <literal>RawData=</literal> specify the enterprise number and identifier for DUID-EN.</para>
+ <para>link-layer : If <literal>Type=link-layer</literal>, then <literal>MACAddress=</literal>
+ specifies the hardware address for DUID-LL.</para>
+ <para>uuid : If <literal>Type=uuid</literal>, then <literal>UUID=</literal> specifies DUID-UUID.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>RawData=</varname></term>
+ <listitem><para>Specifies the DUID bytes as a single newline-terminated, hexadecimal
+ string, with each byte separated by a ':'.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <para>The following options will be supported in the future:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><varname>MACAddress=</varname></term>
+ <listitem><para>Specifies the link-layer address for DUID Type <option>link-layer
+ </option> or <option>link-layer-and-time</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>TimeStamp=</varname></term>
+ <listitem><para>Specifies the DUID generation time for DUID Type <option>
+ link-layer-and-time</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>EnterpriseNumber=</varname></term>
+ <listitem><para>Specifies the enterprise number for DUID Type
+ <option>vendor</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>UUID=</varname></term>
+ <listitem><para>Specifies the UUID for DUID Type <option>uuid</option>.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml
index f8837745ae..a920ec334f 100644
--- a/man/nss-myhostname.xml
+++ b/man/nss-myhostname.xml
@@ -70,9 +70,10 @@
is on the local loopback) and the IPv6 address ::1 (which is the
local host).</para></listitem>
- <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in
- <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is
- resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
+ <listitem><para>The hostnames <literal>localhost</literal> and
+ <literal>localhost.localdomain</literal> (as well as any hostname
+ ending in <literal>.localhost</literal> or <literal>.localhost.localdomain</literal>)
+ are resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
<listitem><para>The hostname <literal>gateway</literal> is
resolved to all current default routing gateway addresses,
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 1480bf8380..089fb0f5c3 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -233,6 +233,16 @@
</varlistentry>
<varlistentry>
+ <term><option>--value</option></term>
+
+ <listitem>
+ <para>When printing properties with <command>show</command>,
+ only print the value, and skip the property name and
+ <literal>=</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--show-types</option></term>
<listitem>
diff --git a/man/systemd-ask-password.xml b/man/systemd-ask-password.xml
index 2a4d24349b..e84a15c554 100644
--- a/man/systemd-ask-password.xml
+++ b/man/systemd-ask-password.xml
@@ -192,6 +192,15 @@
This will output one password per line.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--no-output</option></term>
+
+ <listitem><para>Do not print passwords to standard output.
+ This is useful if you want to store a password in kernel
+ keyring with <option>--keyname</option> but do not want it
+ to show up on screen or in logs.</para></listitem>
+ </varlistentry>
+
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 86cdb4e124..7e87865ba8 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -595,9 +595,8 @@
order to trigger an orderly shutdown of the
container. Defaults to SIGRTMIN+3 if <option>--boot</option>
is used (on systemd-compatible init systems SIGRTMIN+3
- triggers an orderly shutdown). Takes a signal name like
- <literal>SIGHUP</literal>, <literal>SIGTERM</literal> or
- similar as argument.</para></listitem>
+ triggers an orderly shutdown). For a list of valid signals, see
+ <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml
index 7a9e23a2c6..829729ca09 100644
--- a/man/systemd-resolved.service.xml
+++ b/man/systemd-resolved.service.xml
@@ -87,9 +87,10 @@
is on the local loopback) and the IPv6 address ::1 (which is the
local host).</para></listitem>
- <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in
- <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is
- resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
+ <listitem><para>The hostnames <literal>localhost</literal> and
+ <literal>localhost.localdomain</literal> (as well as any hostname
+ ending in <literal>.localhost</literal> or <literal>.localhost.localdomain</literal>)
+ are resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
<listitem><para>The hostname <literal>gateway</literal> is
resolved to all current default routing gateway addresses,
diff --git a/man/systemd-run.xml b/man/systemd-run.xml
index 414e1c8335..473f83eac6 100644
--- a/man/systemd-run.xml
+++ b/man/systemd-run.xml
@@ -345,7 +345,7 @@
provided by systemd to services:</para>
<programlisting># systemd-run env
-Running as unit run-19945.service.
+Running as unit: run-19945.service
# journalctl -u run-19945.service
Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env...
Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env.
@@ -366,8 +366,8 @@ Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20.
<programlisting># date; systemd-run --on-active=30 --timer-property=AccuracySec=100ms /bin/touch /tmp/foo
Mon Dec 8 20:44:24 KST 2014
-Running as unit run-71.timer.
-Will run as unit run-71.service.
+Running as unit: run-71.timer
+Will run service as unit: run-71.service
# journalctl -b -u run-71.timer
-- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. --
Dec 08 20:44:38 container systemd[1]: Starting /bin/touch /tmp/foo.
diff --git a/man/systemd-sysv-generator.xml b/man/systemd-sysv-generator.xml
index bb5cc55e9f..2353eb3efe 100644
--- a/man/systemd-sysv-generator.xml
+++ b/man/systemd-sysv-generator.xml
@@ -77,7 +77,7 @@
which correspond to runlevels for which the script is
enabled.</para>
- <para><command>systemd</command> does not supports SysV scripts as
+ <para><command>systemd</command> does not support SysV scripts as
part of early boot, so all wrapper units are ordered after
<filename>basic.target</filename>.</para>
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index c1f47e84e6..3e1a2cb224 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -1155,7 +1155,9 @@
first character of the list is <literal>~</literal>, the
effect is inverted: only the listed system calls will result
in immediate process termination (blacklisting). If running in
- user mode and this option is used,
+ user mode, or in system mode, but without the
+ <constant>CAP_SYS_ADMIN</constant> capabiblity (e.g. setting
+ <varname>User=nobody</varname>),
<varname>NoNewPrivileges=yes</varname> is implied. This
feature makes use of the Secure Computing Mode 2 interfaces of
the kernel ('seccomp filtering') and is useful for enforcing a
@@ -1214,8 +1216,10 @@
systems. The special <constant>native</constant> identifier
implicitly maps to the native architecture of the system (or
more strictly: to the architecture the system manager is
- compiled for). If running in user mode and this option is
- used, <varname>NoNewPrivileges=yes</varname> is implied. Note
+ compiled for). If running in user mode, or in system mode,
+ but without the <constant>CAP_SYS_ADMIN</constant>
+ capabiblity (e.g. setting <varname>User=nobody</varname>),
+ <varname>NoNewPrivileges=yes</varname> is implied. Note
that setting this option to a non-empty list implies that
<constant>native</constant> is included too. By default, this
option is set to the empty list, i.e. no architecture system
@@ -1244,8 +1248,10 @@
<function>socketpair()</function> (which creates connected
AF_UNIX sockets only) are unaffected. Note that this option
has no effect on 32-bit x86 and is ignored (but works
- correctly on x86-64). If running in user mode and this option
- is used, <varname>NoNewPrivileges=yes</varname> is implied. By
+ correctly on x86-64). If running in user mode, or in system
+ mode, but without the <constant>CAP_SYS_ADMIN</constant>
+ capabiblity (e.g. setting <varname>User=nobody</varname>),
+ <varname>NoNewPrivileges=yes</varname> is implied. By
default, no restriction applies, all address families are
accessible to processes. If assigned the empty string, any
previous list changes are undone.</para>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 752a15a4e0..b2e1d40287 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -204,6 +204,12 @@
understood to the base of 1024.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>IAID=</varname></term>
+ <listitem>
+ <para>Identity Association Identifier for the interface, a 32-bit unsigned integer.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -272,7 +278,7 @@
<para>An IPv6 address with the top 64 bits unset. When set, indicates the
64-bit interface part of SLAAC IPv6 addresses for this link. Note that
the token is only ever used for SLAAC, and not for DHCPv6 addresses, even
- in the case DHCP is requested by router advertisment. By default, the
+ in the case DHCP is requested by router advertisement. By default, the
token is autogenerated.</para>
</listitem>
</varlistentry>
@@ -824,6 +830,86 @@
</refsect1>
<refsect1>
+ <title>[DUID] Section Options</title>
+
+ <para>This section configures the DHCP Unique Idendifier (DUID) value used by DHCP
+ protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface
+ Identity Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6
+ address. DHCPv4 client protocol sends IAID and DUID to the DHCP server when acquiring
+ a dynamic IPv4 address if <option>ClientIdentifier=duid</option>. IAID and DUID allows a
+ DHCP server to uniquely identify the machine and the interface requesting a DHCP IP.</para>
+
+ <para>The DUID value specified here overrides the DUID that systemd-networkd generates
+ using the machine-id from the <filename>/etc/machine-id</filename> file, as well as the
+ global DUID that may be specified in <citerefentry><refentrytitle>networkd.conf
+ </refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+ <para>The configured DHCP DUID should conform to the specification in
+ <ulink url="http://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>,
+ <ulink url="http://tools.ietf.org/html/rfc6355">RFC 6355</ulink>.</para>
+
+ <para>The following options are available in <literal>[DUID]</literal> section:</para>
+
+ <variablelist class='network-directives'>
+
+ <varlistentry>
+ <term><varname>Type=</varname></term>
+ <listitem><para>The type of DUID specified in this section. The following values are
+ supported:</para>
+ <para>raw : If <literal>Type=raw</literal>, then <literal>RawData=</literal> specifies
+ the entire DUID. For e.g: <literal>RawData=00:02:00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</literal>
+ specifies a 14 byte long DUID-EN ("00:02"), with enterprise number 43793 ("00:00:ab:11"),
+ and identifier value "f9:2a:c2:77:29:f9:5c:00".</para><para>If Type is not specified and
+ RawData is specified, Type defaults to 'raw'.</para>
+ <para>Type will support the following values in the future:</para>
+ <para>link-layer-and-time : If <literal>Type=link-layer-and-time</literal>, then
+ <literal>MACAddress=</literal> and <literal>TimeStamp=</literal> specify the hardware
+ address and time-stamp for DUID-LLT.</para>
+ <para>vendor : If <literal>Type=vendor</literal>, then <literal>EnterpriseNumber=</literal>
+ and <literal>RawData=</literal> specify the enterprise number and identifier for DUID-EN.</para>
+ <para>link-layer : If <literal>Type=link-layer</literal>, then <literal>MACAddress=</literal>
+ specifies the hardware address for DUID-LL.</para>
+ <para>uuid : If <literal>Type=uuid</literal>, then <literal>UUID=</literal> specifies DUID-UUID.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>RawData=</varname></term>
+ <listitem><para>Specifies the DUID bytes as a single newline-terminated, hexadecimal
+ string, with each byte separated by a ':'.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <para>The following options will be supported in the future:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><varname>MACAddress=</varname></term>
+ <listitem><para>Specifies the link-layer address for DUID Type <option>link-layer
+ </option> or <option>link-layer-and-time</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>TimeStamp=</varname></term>
+ <listitem><para>Specifies the DUID generation time for DUID Type <option>
+ link-layer-and-time</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>EnterpriseNumber=</varname></term>
+ <listitem><para>Specifies the enterprise number for DUID Type <option>
+ vendor</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>UUID=</varname></term>
+ <listitem><para>Specifies the UUID for DUID Type <option>uuid</option>.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>[DHCPServer] Section Options</title>
<para>The <literal>[DHCPServer]</literal> section contains
settings for the DHCP server, if enabled via the
diff --git a/man/systemd.nspawn.xml b/man/systemd.nspawn.xml
index c07a4b0243..5ec878512a 100644
--- a/man/systemd.nspawn.xml
+++ b/man/systemd.nspawn.xml
@@ -224,6 +224,18 @@
</varlistentry>
<varlistentry>
+ <term><option>KillSignal=</option></term>
+
+ <listitem><para>Specify the process signal to send to the
+ container's PID 1 when nspawn itself receives SIGTERM, in
+ order to trigger an orderly shutdown of the container.
+ Defaults to SIGRTMIN+3 if <option>Boot=</option> is used
+ (on systemd-compatible init systems SIGRTMIN+3 triggers an
+ orderly shutdown). For a list of valid signals, see
+ <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>Personality=</varname></term>
<listitem><para>Configures the kernel personality for the
diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml
new file mode 100644
index 0000000000..946234ad90
--- /dev/null
+++ b/man/systemd.offline-updates.xml
@@ -0,0 +1,169 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2013 Lennart Poettering
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ 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/>.
+-->
+
+<refentry id="systemd.offline-updates">
+ <refentryinfo>
+ <title>systemd.offline-updates</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd.offline-updates</refentrytitle>
+ <manvolnum>7</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd.offline-updates</refname>
+ <refpurpose>Implementation of offline updates in systemd</refpurpose>
+ </refnamediv>
+
+ <refsect1>
+ <title>Implementing Offline System Updates</title>
+
+ <para>This man page describes how to implement "offline" system updates with systemd. By "offline"
+ OS updates we mean package installations and updates that are run with the system booted into a
+ special system update mode, in order to avoid problems related to conflicts of libraries and
+ services that are currently running with those on disk. This document is inspired by this
+ <ulink url="https://wiki.gnome.org/Design/OS/SoftwareUpdates">GNOME design whiteboard</ulink>.
+ </para>
+
+ <para>The logic:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>The package manager prepares system updates by downloading all (RPM or DEB or
+ whatever) packages to update off-line in a special directory
+ <filename noindex="true">/var/lib/system-update</filename> (or
+ another directory of the package/upgrade manager's choice).</para>
+ </listitem>
+
+ <listitem>
+ <para>When the user OK'ed the update, the symlink <filename>/system-update</filename> is
+ created that points to <filename noindex="true">/var/lib/system-update</filename> (or
+ wherever the directory with the upgrade files is located) and the system is rebooted. This
+ symlink is in the root directory, since we need to check for it very early at boot, at a
+ time where <filename>/var</filename> is not available yet.</para>
+ </listitem>
+
+ <listitem>
+ <para>Very early in the new boot
+ <citerefentry><refentrytitle>systemd-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ checks whether <filename>/system-update</filename> exists. If so, it (temporarily and for
+ this boot only) redirects (i.e. symlinks) <filename>default.target</filename> to
+ <filename>system-update.target</filename>, a special target that is pulls in the base system
+ (i.e. <filename>sysinit.target</filename>, so that all file systems are mounted but little
+ else) and the system update units.</para>
+ </listitem>
+
+ <listitem>
+ <para>The system now continues to boot into <filename>default.target</filename>, and thus
+ into <filename>system-update.target</filename>. This target pulls in the system update unit,
+ which starts the system update script after all file systems have been mounted.</para>
+ </listitem>
+
+ <listitem>
+ <para>As the first step, the update script should check if the
+ <filename>/system-update</filename> symlink points to the the location used by that update
+ script. In case it does not exists or points to a different location, the script must exit
+ without error. It is possible for multiple update services to be installed, and for multiple
+ update scripts to be launched in parallel, and only the one that corresponds to the tool
+ that <emphasis>created</emphasis> the symlink before reboot should perform any actions. It
+ is unsafe to run multiple updates in parallel.</para>
+ </listitem>
+
+ <listitem>
+ <para>The update script should now do its job. If applicable and possible, it should
+ create a file system snapshot, then install all packages.
+ After completion (regardless whether the update succeeded or failed) the machine
+ must be rebooted, for example by calling <command>systemctl reboot</command>.
+ In addition, on failure the script should revert to the old file system snapshot
+ (without the symlink).</para>
+ </listitem>
+
+ <listitem>
+ <para>The system is rebooted. Since the <filename>/system-update</filename> symlink is gone,
+ the generator won't redirect <filename>default.target</filename> after reboot and the
+ system now boots into the default target again.</para>
+ </listitem>
+ </orderedlist>
+ </refsect1>
+
+ <refsect1>
+ <title>Recommendations</title>
+
+ <orderedlist>
+ <listitem>
+ <para>To make things a bit more robust we recommend hooking the update script into
+ <filename>system-update.target</filename> via a <filename noindex='true'>.wants/</filename>
+ symlink in the distribution package, rather than depending on <command>systemctl
+ enable</command> in the postinst scriptlets of your package. More specifically, for your
+ update script create a .service file, without [Install] section, and then add a symlink like
+ <filename noindex='true'>/usr/lib/systemd/system-update.target.wants/foobar.service</filename>
+ → <filename noindex='true'>../foobar.service</filename> to your package.</para>
+ </listitem>
+
+ <listitem>
+ <para>Make sure to remove the <filename>/system-update</filename> symlink as early as
+ possible in the update script to avoid reboot loops in case the update fails.</para>
+ </listitem>
+
+ <listitem>
+ <para>Use <varname>FailureAction=reboot</varname> in the service file for your update script
+ to ensure that a reboot is automatically triggered if the update fails.
+ <varname>FailureAction=</varname> makes sure that the specified unit is activated if your
+ script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds
+ you should trigger the reboot in your own code, for example by invoking logind's
+ <command>Reboot()</command> call or calling <command>systemct reboot</command>. See
+ <ulink url="http://www.freedesktop.org/wiki/Software/systemd/logind">logind dbus API</ulink>
+ for details.</para>
+ </listitem>
+
+ <listitem>
+ <para>The update service should declare <varname>DefaultDependencies=false</varname>,
+ and pull in any services it requires explicitly.</para>
+ </listitem>
+ </orderedlist>
+ </refsect1>
+
+ <refsect1>
+ <title>See also</title>
+
+ <para>
+ <ulink url="http://www.freedesktop.org/wiki/Software/systemd/SystemUpdates/">Implementing Offline System Updates</ulink>,
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>dnf.plugin.system-upgrade</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+</refentry>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 08cdf06e23..fd6f7a1b69 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -202,7 +202,7 @@
controls the <literal>memory.limit_in_bytes</literal>
control group attribute. For details about this control
group attribute, see <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>.</para>
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt">memory.txt</ulink>.</para>
<para>Implies <literal>MemoryAccounting=true</literal>.</para>
</listitem>
@@ -239,7 +239,7 @@
controls the <literal>pids.max</literal> control group
attribute. For details about this control group attribute,
see <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/pids.txt">pids.txt</ulink>.</para>
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/pids.txt">pids.txt</ulink>.</para>
<para>Implies <literal>TasksAccounting=true</literal>. The
system default for this setting may be controlled with
@@ -273,7 +273,7 @@
the <literal>blkio.weight</literal> control group attribute,
which defaults to 500. For details about this control group
attribute, see <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>.
The available I/O bandwidth is split up among all units within
one slice relative to their block I/O weight.</para>
@@ -305,7 +305,7 @@
attribute, which defaults to 1000. Use this option multiple
times to set weights for multiple devices. For details about
this control group attribute, see <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.</para>
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>.</para>
<para>Implies
<literal>BlockIOAccounting=true</literal>.</para>
@@ -328,12 +328,12 @@
Gigabytes, or Terabytes, respectively, to the base of
1000. (Example:
"/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This
- controls the <literal>blkio.read_bps_device</literal> and
- <literal>blkio.write_bps_device</literal> control group
+ controls the <literal>blkio.throttle.read_bps_device</literal> and
+ <literal>blkio.throttle.write_bps_device</literal> control group
attributes. Use this option multiple times to set bandwidth
limits for multiple devices. For details about these control
group attributes, see <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>.
</para>
<para>Implies
@@ -357,7 +357,7 @@
<literal>devices.deny</literal> control group
attributes. For details about these control group
attributes, see <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/devices.txt">devices.txt</ulink>.</para>
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/devices.txt">devices.txt</ulink>.</para>
<para>The device node specifier is either a path to a device
node in the file system, starting with
@@ -482,10 +482,10 @@
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
The documentation for control groups and specific controllers in the Linux kernel:
- <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>,
- <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cpuacct.txt">cpuacct.txt</ulink>,
- <ulink url="https://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>,
- <ulink url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt">cgroups.txt</ulink>,
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt">cpuacct.txt</ulink>,
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt">memory.txt</ulink>,
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>.
</para>
</refsect1>
</refentry>
diff --git a/man/udev_device_get_syspath.xml b/man/udev_device_get_syspath.xml
index ca9763fedf..b54749ed56 100644
--- a/man/udev_device_get_syspath.xml
+++ b/man/udev_device_get_syspath.xml
@@ -127,6 +127,8 @@
<funcprototype>
<funcdef>struct udev_device *<function>udev_device_get_parent_with_subsystem_devtype</function></funcdef>
<paramdef>struct udev_device *<parameter>udev_device</parameter></paramdef>
+ <paramdef>const char *<parameter>subsystem</parameter></paramdef>
+ <paramdef>const char *<parameter>devtype</parameter></paramdef>
</funcprototype>
<funcprototype>
@@ -137,8 +139,6 @@
<funcprototype>
<funcdef>const char *<function>udev_device_get_action</function></funcdef>
<paramdef>struct udev_device *<parameter>udev_device</parameter></paramdef>
- <paramdef>const char *<parameter>subsystem</parameter></paramdef>
- <paramdef>const char *<parameter>devtype</parameter></paramdef>
</funcprototype>
</funcsynopsis>
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 67639620fb..10c53d4538 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -4,19 +4,20 @@
#
# Frank Hill <hxf.prc@gmail.com>, 2014.
# Boyuan Yang <073plan@gmail.com>, 2015.
+# Jeff Bai <jeffbai@aosc.xyz>, 2016.
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
"POT-Creation-Date: 2015-10-27 02:24+0000\n"
-"PO-Revision-Date: 2015-10-28 15:00+0800\n"
-"Last-Translator: Boyuan Yang <073plan@gmail.com>\n"
+"PO-Revision-Date: 2016-03-01 20:38-0700\n"
+"Last-Translator: Jeff Bai <jeffbai@aosc.xyz>\n"
"Language-Team: Chinese <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Lokalize 2.0\n"
+"X-Generator: Poedit 1.8.7.1\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
@@ -26,7 +27,7 @@ msgstr "将密码发回系统"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
msgid ""
"Authentication is required to send the entered passphrase back to the system."
-msgstr "将输入的密码发回系统需要验证。"
+msgstr "将输入的密码发回系统需要认证。"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
msgid "Manage system services or other units"
@@ -34,7 +35,7 @@ msgstr "管理系统服务或其它单元"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
msgid "Authentication is required to manage system services or other units."
-msgstr "管理系统服务或其它单元需要验证。"
+msgstr "管理系统服务或其它单元需要认证。"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
msgid "Manage system service or unit files"
@@ -42,7 +43,7 @@ msgstr "管理系统服务或单元文件"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
msgid "Authentication is required to manage system service or unit files."
-msgstr "管理系统服务或单元文件需要验证。"
+msgstr "管理系统服务或单元文件需要认证。"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
msgid "Set or unset system and service manager environment variables"
@@ -52,7 +53,7 @@ msgstr "设置或清除系统及服务管理器的环境变量"
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
-msgstr "设置或清除系统及服务管理器的环境变量需要验证。"
+msgstr "设置或清除系统及服务管理器的环境变量需要认证。"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
msgid "Reload the systemd state"
@@ -60,7 +61,7 @@ msgstr "重新载入 systemd 状态"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
msgid "Authentication is required to reload the systemd state."
-msgstr "重新载入 systemd 状态需要验证。"
+msgstr "重新载入 systemd 状态需要认证。"
#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
msgid "Set host name"
@@ -68,7 +69,7 @@ msgstr "设置主机名"
#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
msgid "Authentication is required to set the local host name."
-msgstr "设置本地主机名需要验证。"
+msgstr "设置本地主机名需要认证。"
#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
msgid "Set static host name"
@@ -82,7 +83,7 @@ msgstr "设置静态主机名"
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
-msgstr "设置静态本地主机名或漂亮的主机名需要验证。"
+msgstr "设置静态本地主机名或美观主机名需要认证。"
#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
msgid "Set machine information"
@@ -90,7 +91,7 @@ msgstr "设置机器信息"
#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
msgid "Authentication is required to set local machine information."
-msgstr "设置本地机器信息需要验证。"
+msgstr "设置本地机器信息需要认证。"
#: ../src/import/org.freedesktop.import1.policy.in.h:1
msgid "Import a VM or container image"
@@ -98,7 +99,7 @@ msgstr "导入虚拟机或容器镜像"
#: ../src/import/org.freedesktop.import1.policy.in.h:2
msgid "Authentication is required to import a VM or container image"
-msgstr "导入虚拟机或容器镜像需要验证"
+msgstr "导入虚拟机或容器镜像需要认证"
#: ../src/import/org.freedesktop.import1.policy.in.h:3
msgid "Export a VM or container image"
@@ -106,7 +107,7 @@ msgstr "导出虚拟机或容器镜像"
#: ../src/import/org.freedesktop.import1.policy.in.h:4
msgid "Authentication is required to export a VM or container image"
-msgstr "导出虚拟机或容器镜像需要验证"
+msgstr "导出虚拟机或容器镜像需要认证"
#: ../src/import/org.freedesktop.import1.policy.in.h:5
msgid "Download a VM or container image"
@@ -114,7 +115,7 @@ msgstr "下载虚拟机或容器镜像"
#: ../src/import/org.freedesktop.import1.policy.in.h:6
msgid "Authentication is required to download a VM or container image"
-msgstr "下载虚拟机或容器镜像需要验证。"
+msgstr "下载虚拟机或容器镜像需要认证。"
#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
msgid "Set system locale"
@@ -122,7 +123,7 @@ msgstr "设置系统区域和语言"
#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
msgid "Authentication is required to set the system locale."
-msgstr "设置系统区域和语言需要验证。"
+msgstr "设置系统区域和语言需要认证。"
#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
msgid "Set system keyboard settings"
@@ -130,7 +131,7 @@ msgstr "设置系统键盘"
#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
msgid "Authentication is required to set the system keyboard settings."
-msgstr "设置系统键盘需要验证。"
+msgstr "设置系统键盘需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -139,7 +140,7 @@ msgstr "允许应用程序阻止系统关机"
#: ../src/login/org.freedesktop.login1.policy.in.h:2
msgid ""
"Authentication is required for an application to inhibit system shutdown."
-msgstr "要允许应用程序阻止系统关机需要验证。"
+msgstr "允许应用程序阻止系统关机需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:3
msgid "Allow applications to delay system shutdown"
@@ -147,7 +148,7 @@ msgstr "允许应用程序延迟系统关机"
#: ../src/login/org.freedesktop.login1.policy.in.h:4
msgid "Authentication is required for an application to delay system shutdown."
-msgstr "要允许应用程序延迟系统关机需要验证。"
+msgstr "允许应用程序延迟系统关机需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:5
msgid "Allow applications to inhibit system sleep"
@@ -155,7 +156,7 @@ msgstr "允许应用程序阻止系统睡眠"
#: ../src/login/org.freedesktop.login1.policy.in.h:6
msgid "Authentication is required for an application to inhibit system sleep."
-msgstr "要允许应用程序阻止系统睡眠需要验证。"
+msgstr "允许应用程序阻止系统睡眠需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:7
msgid "Allow applications to delay system sleep"
@@ -163,7 +164,7 @@ msgstr "允许应用程序延迟系统睡眠"
#: ../src/login/org.freedesktop.login1.policy.in.h:8
msgid "Authentication is required for an application to delay system sleep."
-msgstr "要允许应用程序延迟系统睡眠需要验证。"
+msgstr "允许应用程序延迟系统睡眠需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:9
msgid "Allow applications to inhibit automatic system suspend"
@@ -173,7 +174,7 @@ msgstr "允许应用程序阻止系统自动挂起"
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
-msgstr "要允许应用程序阻止系统自动挂起需要验证。"
+msgstr "允许应用程序阻止系统自动挂起需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:11
msgid "Allow applications to inhibit system handling of the power key"
@@ -183,7 +184,7 @@ msgstr "允许应用程序阻止系统响应电源键"
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
-msgstr "要允许应用程序阻止系统响应电源键需要验证。"
+msgstr "允许应用程序阻止系统响应电源键需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:13
msgid "Allow applications to inhibit system handling of the suspend key"
@@ -193,7 +194,7 @@ msgstr "允许应用程序阻止系统响应挂起键"
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
-msgstr "要允许应用程序阻止系统响应挂起键需要验证。"
+msgstr "允许应用程序阻止系统响应挂起键需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:15
msgid "Allow applications to inhibit system handling of the hibernate key"
@@ -203,19 +204,17 @@ msgstr "允许应用程序阻止系统响应挂起键"
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
-msgstr "要允许应用程序阻止系统响应挂起键需要验证。"
+msgstr "允许应用程序阻止系统响应挂起键需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:17
-#, fuzzy
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr "允许应用程序阻止系统响应笔记本上盖开关事件"
#: ../src/login/org.freedesktop.login1.policy.in.h:18
-#, fuzzy
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
-msgstr "要允许应用程序阻止系统响应笔记本上盖开关事件需要验证。"
+msgstr "允许应用程序阻止系统响应笔记本上盖开关事件需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:19
msgid "Allow non-logged-in users to run programs"
@@ -223,7 +222,7 @@ msgstr "允许未登录用户运行程序"
#: ../src/login/org.freedesktop.login1.policy.in.h:20
msgid "Authentication is required to run programs as a non-logged-in user."
-msgstr "要允许未登录用户运行程序需要验证。"
+msgstr "允许未登录用户运行程序需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:21
msgid "Allow attaching devices to seats"
@@ -234,7 +233,7 @@ msgstr "允许将设备附加至会话座位"
# To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind.
#: ../src/login/org.freedesktop.login1.policy.in.h:22
msgid "Authentication is required for attaching a device to a seat."
-msgstr "要允许将设备附加至某个会话座位需要验证。"
+msgstr "允许将设备附加至某个会话座位需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:23
msgid "Flush device to seat attachments"
@@ -243,7 +242,7 @@ msgstr "刷新设备至会话座位间的连接"
#: ../src/login/org.freedesktop.login1.policy.in.h:24
msgid ""
"Authentication is required for resetting how devices are attached to seats."
-msgstr "重新设定设备的会话座位接入方式时需要验证。"
+msgstr "重新设定设备的会话座位接入方式时需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:25
msgid "Power off the system"
@@ -251,7 +250,7 @@ msgstr "关闭系统"
#: ../src/login/org.freedesktop.login1.policy.in.h:26
msgid "Authentication is required for powering off the system."
-msgstr "关闭系统需要验证。"
+msgstr "关闭系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:27
msgid "Power off the system while other users are logged in"
@@ -261,7 +260,7 @@ msgstr "存在其他已登录用户时仍然关机"
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
-msgstr "存在其他已登录用户时关闭系统需要验证。"
+msgstr "存在其他已登录用户时关闭系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:29
msgid "Power off the system while an application asked to inhibit it"
@@ -271,7 +270,7 @@ msgstr "有其它应用程序阻止时仍然关机"
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
-msgstr "要在其它应用程序阻止关机时关闭系统需要验证。"
+msgstr "在其它应用程序阻止关机时关闭系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:31
msgid "Reboot the system"
@@ -279,7 +278,7 @@ msgstr "重启系统"
#: ../src/login/org.freedesktop.login1.policy.in.h:32
msgid "Authentication is required for rebooting the system."
-msgstr "重启系统需要验证。"
+msgstr "重启系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:33
msgid "Reboot the system while other users are logged in"
@@ -289,7 +288,7 @@ msgstr "存在其他已登录用户时仍然重启"
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
-msgstr "存在其他已登录用户时重启系统需要验证。"
+msgstr "存在其他已登录用户时重启系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:35
msgid "Reboot the system while an application asked to inhibit it"
@@ -299,7 +298,7 @@ msgstr "有其它应用程序阻止时仍然重启"
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
-msgstr "要在其它应用程序阻止重启时重启系统需要验证。"
+msgstr "在其它应用程序阻止重启时重启系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:37
msgid "Suspend the system"
@@ -307,7 +306,7 @@ msgstr "挂起系统"
#: ../src/login/org.freedesktop.login1.policy.in.h:38
msgid "Authentication is required for suspending the system."
-msgstr "挂起系统需要验证。"
+msgstr "挂起系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:39
msgid "Suspend the system while other users are logged in"
@@ -317,7 +316,7 @@ msgstr "存在其他已登录用户时仍然挂起系统"
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
-msgstr "存在其他已登录用户时挂起系统需要验证。"
+msgstr "存在其他已登录用户时挂起系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:41
msgid "Suspend the system while an application asked to inhibit it"
@@ -327,15 +326,15 @@ msgstr "有其它应用程序阻止时仍然挂起系统"
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
-msgstr "要在其它应用程序阻止挂起时挂起系统需要验证。"
+msgstr "在其它应用程序阻止挂起时挂起系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:43
msgid "Hibernate the system"
-msgstr "休眠"
+msgstr "休眠系统"
#: ../src/login/org.freedesktop.login1.policy.in.h:44
msgid "Authentication is required for hibernating the system."
-msgstr "休眠需要验证。"
+msgstr "休眠系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:45
msgid "Hibernate the system while other users are logged in"
@@ -345,7 +344,7 @@ msgstr "存在其他已登录用户时仍然休眠"
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
-msgstr "存在其他已登录用户时进行休眠需要验证。"
+msgstr "存在其他已登录用户时进行休眠系统需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Hibernate the system while an application asked to inhibit it"
@@ -355,7 +354,7 @@ msgstr "有其它应用程序阻止时仍然休眠"
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
-msgstr "要在其它应用程序阻止休眠时进行休眠需要验证。"
+msgstr "在其它应用程序阻止休眠时进行休眠需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Manage active sessions, users and seats"
@@ -364,42 +363,41 @@ msgstr "管理活动会话、用户与会话座位"
#: ../src/login/org.freedesktop.login1.policy.in.h:50
msgid ""
"Authentication is required for managing active sessions, users and seats."
-msgstr "要管理活动会话、用户与会话座位需要验证。"
+msgstr "管理活动会话、用户与会话座位需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Lock or unlock active sessions"
-msgstr "活动会话锁定与解锁"
+msgstr "锁定或解锁活动会话"
#: ../src/login/org.freedesktop.login1.policy.in.h:52
msgid "Authentication is required to lock or unlock active sessions."
-msgstr "要对活动会话进行锁定或解锁需要验证。"
+msgstr "对活动会话进行锁定或解锁需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Allow indication to the firmware to boot to setup interface"
-msgstr "允许向固件发出指示以启动至固件设置界面"
+msgstr "允许向固件发出指示以启动至设置界面"
#: ../src/login/org.freedesktop.login1.policy.in.h:54
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
-msgstr "要允许向固件发出启动时进入设置界面的指令需要验证。"
+msgstr "向固件发出启动时进入设置界面的指令需要认证。"
#: ../src/login/org.freedesktop.login1.policy.in.h:55
msgid "Set a wall message"
-msgstr ""
+msgstr "设置 wall 消息"
#: ../src/login/org.freedesktop.login1.policy.in.h:56
-#, fuzzy
msgid "Authentication is required to set a wall message"
-msgstr ""
+msgstr "设置 wall 消息需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
msgid "Log into a local container"
-msgstr "登入一个本地容器"
+msgstr "登入本地容器"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
msgid "Authentication is required to log into a local container."
-msgstr "要登入一个本地容器需要验证。"
+msgstr "登录一个本地容器需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
msgid "Log into the local host"
@@ -407,7 +405,7 @@ msgstr "登入本地主机"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
msgid "Authentication is required to log into the local host."
-msgstr "要登入本地主机需要验证。"
+msgstr "登入本地主机需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
msgid "Acquire a shell in a local container"
@@ -415,7 +413,7 @@ msgstr "在本地容器中获取一个 shell"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
msgid "Authentication is required to acquire a shell in a local container."
-msgstr "要在本地容器中获取 shell 需要验证。"
+msgstr "在本地容器中获取 shell 需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
msgid "Acquire a shell on the local host"
@@ -423,7 +421,7 @@ msgstr "在本地主机中获取一个 shell"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
msgid "Authentication is required to acquire a shell on the local host."
-msgstr "要在本地主机中获取 shell 需要验证。"
+msgstr "在本地主机中获取 shell 需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
msgid "Acquire a pseudo TTY in a local container"
@@ -432,7 +430,7 @@ msgstr "在本地容器中获取一个假 TTY"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
-msgstr "要在本地容器中获取假 TTY 需要验证。"
+msgstr "在本地容器中获取假 TTY 需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
msgid "Acquire a pseudo TTY on the local host"
@@ -440,7 +438,7 @@ msgstr "在本地主机中获取一个假 TTY"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "要在本地主机中获取假 TTY 需要验证。"
+msgstr "在本地主机中获取假 TTY 需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
msgid "Manage local virtual machines and containers"
@@ -449,7 +447,7 @@ msgstr "管理本地虚拟机和容器"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
msgid ""
"Authentication is required to manage local virtual machines and containers."
-msgstr "要管理本地虚拟机和容器需要验证。"
+msgstr "管理本地虚拟机和容器需要认证。"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
msgid "Manage local virtual machine and container images"
@@ -459,7 +457,7 @@ msgstr "管理本地虚拟机和容器的镜像"
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
-msgstr "要管理本地的虚拟机和容器镜像需要验证。"
+msgstr "管理本地的虚拟机和容器镜像需要认证。"
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
msgid "Set system time"
@@ -467,7 +465,7 @@ msgstr "设置系统时间"
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
msgid "Authentication is required to set the system time."
-msgstr "设置系统时间需要验证。"
+msgstr "设置系统时间需要认证。"
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
msgid "Set system timezone"
@@ -475,7 +473,7 @@ msgstr "设置系统时区"
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
msgid "Authentication is required to set the system timezone."
-msgstr "设置系统时区需要验证。"
+msgstr "设置系统时区需要认证。"
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
msgid "Set RTC to local timezone or UTC"
@@ -485,7 +483,7 @@ msgstr "设置硬件时钟使用本地时间或 UTC"
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
-msgstr "设置硬件时钟使用本地时间或 UTC 需要验证。"
+msgstr "设置硬件时钟使用本地时间或 UTC 需要认证。"
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
msgid "Turn network time synchronization on or off"
@@ -495,33 +493,32 @@ msgstr "打开或关闭网络时间同步"
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
-msgstr "设置是否启用网络时间同步需要验证。"
+msgstr "打开或关闭网络时间同步需要认证。"
#: ../src/core/dbus-unit.c:430
msgid "Authentication is required to start '$(unit)'."
-msgstr "启动“$(unit)”需要验证。"
+msgstr "启动“$(unit)”需要认证。"
#: ../src/core/dbus-unit.c:431
msgid "Authentication is required to stop '$(unit)'."
-msgstr "停止“$(unit)”需要验证。"
+msgstr "停止“$(unit)”需要认证。"
#: ../src/core/dbus-unit.c:432
msgid "Authentication is required to reload '$(unit)'."
-msgstr "重新载入“$(unit)”需要验证。"
+msgstr "重新载入“$(unit)”需要认证。"
#: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434
msgid "Authentication is required to restart '$(unit)'."
-msgstr "重新启动“$(unit)”需要验证。"
+msgstr "重新启动“$(unit)”需要认证。"
#: ../src/core/dbus-unit.c:537
msgid "Authentication is required to kill '$(unit)'."
-msgstr "杀死“$(unit)”需要验证。"
+msgstr "杀死“$(unit)”需要认证。"
#: ../src/core/dbus-unit.c:567
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "重置“$(unit)”的失败(\"failed\")状态需要验证。"
+msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。"
#: ../src/core/dbus-unit.c:599
msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "设置“$(unit)”的属性需要验证。"
-
+msgstr "设置“$(unit)”的属性需要认证。"
diff --git a/shell-completion/bash/systemd-nspawn b/shell-completion/bash/systemd-nspawn
index 8318f6e590..0cf249d8ce 100644
--- a/shell-completion/bash/systemd-nspawn
+++ b/shell-completion/bash/systemd-nspawn
@@ -60,14 +60,14 @@ _systemd_nspawn() {
[ARG]='-D --directory -u --user --uuid --capability --drop-capability --link-journal --bind --bind-ro -M --machine
-S --slice --setenv -Z --selinux-context -L --selinux-apifs-context --register --network-interface --network-bridge
--personality -i --image --tmpfs --volatile
- --network-macvlan --kill-signal'
+ --network-macvlan --kill-signal --template'
)
_init_completion || return
if __contains_word "$prev" ${OPTS[ARG]}; then
case $prev in
- --directory|-D)
+ --directory|-D|--template)
compopt -o nospace
comps=$(compgen -S/ -A directory -- "$cur" )
;;
diff --git a/src/activate/activate.c b/src/activate/activate.c
index 8ac8dd8e72..a0cfc22000 100644
--- a/src/activate/activate.c
+++ b/src/activate/activate.c
@@ -316,19 +316,31 @@ static int do_accept(const char* name, char **argv, char **envp, int fd) {
}
/* SIGCHLD handler. */
-static void sigchld_hdl(int sig, siginfo_t *t, void *data) {
+static void sigchld_hdl(int sig) {
PROTECT_ERRNO;
- log_info("Child %d died with code %d", t->si_pid, t->si_status);
+ for (;;) {
+ siginfo_t si;
+ int r;
- /* Wait for a dead child. */
- (void) waitpid(t->si_pid, NULL, 0);
+ si.si_pid = 0;
+ r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG);
+ if (r < 0) {
+ if (errno != ECHILD)
+ log_error_errno(errno, "Failed to reap children: %m");
+ return;
+ }
+ if (si.si_pid == 0)
+ return;
+
+ log_info("Child %d died with code %d", si.si_pid, si.si_status);
+ }
}
static int install_chld_handler(void) {
static const struct sigaction act = {
- .sa_flags = SA_SIGINFO,
- .sa_sigaction = sigchld_hdl,
+ .sa_flags = SA_NOCLDSTOP,
+ .sa_handler = sigchld_hdl,
};
int r;
diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c
index adc9286612..6d53dd982c 100644
--- a/src/ask-password/ask-password.c
+++ b/src/ask-password/ask-password.c
@@ -34,6 +34,7 @@ static const char *arg_keyname = NULL;
static char *arg_message = NULL;
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static bool arg_multiple = false;
+static bool arg_no_output = false;
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
static void help(void) {
@@ -48,6 +49,7 @@ static void help(void) {
" --no-tty Ask question via agent even on TTY\n"
" --accept-cached Accept cached passwords\n"
" --multiple List multiple passwords if available\n"
+ " --no-output Do not print password to standard output\n"
, program_invocation_short_name);
}
@@ -62,6 +64,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_MULTIPLE,
ARG_ID,
ARG_KEYNAME,
+ ARG_NO_OUTPUT,
};
static const struct option options[] = {
@@ -74,6 +77,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "multiple", no_argument, NULL, ARG_MULTIPLE },
{ "id", required_argument, NULL, ARG_ID },
{ "keyname", required_argument, NULL, ARG_KEYNAME },
+ { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
{}
};
@@ -125,6 +129,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_keyname = optarg;
break;
+ case ARG_NO_OUTPUT:
+ arg_no_output = true;
+ break;
+
case '?':
return -EINVAL;
@@ -166,7 +174,8 @@ int main(int argc, char *argv[]) {
}
STRV_FOREACH(p, l) {
- puts(*p);
+ if (!arg_no_output)
+ puts(*p);
if (!arg_multiple)
break;
diff --git a/src/basic/c-rbtree.c b/src/basic/c-rbtree.c
index 914d7e5229..cf5a7242df 100644
--- a/src/basic/c-rbtree.c
+++ b/src/basic/c-rbtree.c
@@ -195,11 +195,6 @@ static inline void c_rbnode_set_parent_and_color(CRBNode *n, CRBNode *p, unsigne
n->__parent_and_color = (CRBNode*)((unsigned long)p | c);
}
-/* same as c_rbnode_set_parent_and_color(), but keeps the current parent */
-static inline void c_rbnode_set_color(CRBNode *n, unsigned long c) {
- c_rbnode_set_parent_and_color(n, c_rbnode_parent(n), c);
-}
-
/* same as c_rbnode_set_parent_and_color(), but keeps the current color */
static inline void c_rbnode_set_parent(CRBNode *n, CRBNode *p) {
c_rbnode_set_parent_and_color(n, p, c_rbnode_color(n));
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 56c1fcaab9..5043180747 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -101,6 +101,39 @@ int cg_read_pid(FILE *f, pid_t *_pid) {
return 1;
}
+int cg_read_event(const char *controller, const char *path, const char *event,
+ char **val)
+{
+ _cleanup_free_ char *events = NULL, *content = NULL;
+ char *p, *line;
+ int r;
+
+ r = cg_get_path(controller, path, "cgroup.events", &events);
+ if (r < 0)
+ return r;
+
+ r = read_full_file(events, &content, NULL);
+ if (r < 0)
+ return r;
+
+ p = content;
+ while ((line = strsep(&p, "\n"))) {
+ char *key;
+
+ key = strsep(&line, " ");
+ if (!key || !line)
+ return -EINVAL;
+
+ if (strcmp(key, event))
+ continue;
+
+ *val = strdup(line);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
_cleanup_free_ char *fs = NULL;
int r;
@@ -1007,18 +1040,12 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
return unified;
if (unified > 0) {
- _cleanup_free_ char *populated = NULL, *t = NULL;
+ _cleanup_free_ char *t = NULL;
/* On the unified hierarchy we can check empty state
- * via the "cgroup.populated" attribute. */
+ * via the "populated" attribute of "cgroup.events". */
- r = cg_get_path(controller, path, "cgroup.populated", &populated);
- if (r < 0)
- return r;
-
- r = read_one_line_file(populated, &t);
- if (r == -ENOENT)
- return 1;
+ r = cg_read_event(controller, path, "populated", &t);
if (r < 0)
return r;
@@ -2129,7 +2156,7 @@ int cg_unified(void) {
if (statfs("/sys/fs/cgroup/", &fs) < 0)
return -errno;
- if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
+ if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
unified_cache = true;
else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
unified_cache = false;
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index ad1edd9cdb..4254e51e5d 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -96,6 +96,8 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
int cg_read_pid(FILE *f, pid_t *_pid);
+int cg_read_event(const char *controller, const char *path, const char *event,
+ char **val);
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
int cg_read_subgroup(DIR *d, char **fn);
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 519b412941..41dc8ca79a 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -40,17 +40,38 @@
#include "fs-util.h"
#include "io-util.h"
#include "macro.h"
+#include "missing.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "umask-util.h"
#include "xattr-util.h"
-#define COPY_BUFFER_SIZE (16*1024)
+#define COPY_BUFFER_SIZE (16*1024u)
+
+static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+ static int have = -1;
+ ssize_t r;
+
+ if (have == false)
+ return -ENOSYS;
+
+ r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+ if (_unlikely_(have < 0))
+ have = r >= 0 || errno != ENOSYS;
+ if (r >= 0)
+ return r;
+ else
+ return -errno;
+}
int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
- bool try_sendfile = true, try_splice = true;
+ bool try_cfr = true, try_sendfile = true, try_splice = true;
int r;
+ size_t m = SSIZE_MAX; /* that the maximum that sendfile and c_f_r accept */
assert(fdf >= 0);
assert(fdt >= 0);
@@ -67,11 +88,9 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
}
for (;;) {
- size_t m = COPY_BUFFER_SIZE;
ssize_t n;
if (max_bytes != (uint64_t) -1) {
-
if (max_bytes <= 0)
return 1; /* return > 0 if we hit the max_bytes limit */
@@ -79,44 +98,59 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
m = (size_t) max_bytes;
}
+ /* First try copy_file_range(), unless we already tried */
+ if (try_cfr) {
+ n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
+ if (n < 0) {
+ if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV))
+ return n;
+
+ try_cfr = false;
+ /* use fallback below */
+ } else if (n == 0) /* EOF */
+ break;
+ else
+ /* Success! */
+ goto next;
+ }
+
/* First try sendfile(), unless we already tried */
if (try_sendfile) {
-
n = sendfile(fdt, fdf, NULL, m);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_sendfile = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
- /* The try splice, unless we already tried */
+ /* Then try splice, unless we already tried */
if (try_splice) {
n = splice(fdf, NULL, fdt, NULL, m, 0);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_splice = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
/* As a fallback just copy bits by hand */
{
- uint8_t buf[m];
+ uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
- n = read(fdf, buf, m);
+ n = read(fdf, buf, sizeof buf);
if (n < 0)
return -errno;
if (n == 0) /* EOF */
@@ -132,6 +166,11 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
assert(max_bytes >= (uint64_t) n);
max_bytes -= n;
}
+ /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
+ * so reduce our maximum by the amount we already copied,
+ * but don't go below our copy buffer size, unless we are
+ * close the the limit of bytes we are allowed to copy. */
+ m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
}
return 0; /* return 0 if we hit EOF earlier than the size limit */
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 5a7ee87a20..13c3bb6446 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -178,16 +178,16 @@ bool is_localhost(const char *hostname) {
assert(hostname);
/* This tries to identify local host and domain names
- * described in RFC6761 plus the redhatism of .localdomain */
+ * described in RFC6761 plus the redhatism of localdomain */
return strcaseeq(hostname, "localhost") ||
strcaseeq(hostname, "localhost.") ||
- strcaseeq(hostname, "localdomain.") ||
- strcaseeq(hostname, "localdomain") ||
+ strcaseeq(hostname, "localhost.localdomain") ||
+ strcaseeq(hostname, "localhost.localdomain.") ||
endswith_no_case(hostname, ".localhost") ||
endswith_no_case(hostname, ".localhost.") ||
- endswith_no_case(hostname, ".localdomain") ||
- endswith_no_case(hostname, ".localdomain.");
+ endswith_no_case(hostname, ".localhost.localdomain") ||
+ endswith_no_case(hostname, ".localhost.localdomain.");
}
bool is_gateway_hostname(const char *hostname) {
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index cda6b2895d..eaad25e65b 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -153,6 +153,8 @@ static int add_locales_from_libdir (Set *locales) {
FOREACH_DIRENT(entry, dir, return -errno) {
char *z;
+ dirent_ensure_type(dir, entry);
+
if (entry->d_type != DT_DIR)
continue;
diff --git a/src/basic/log.h b/src/basic/log.h
index f9fb1742a1..b6356228d9 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -246,5 +246,4 @@ int log_syntax_internal(
log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \
"String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
} \
- -EINVAL; \
})
diff --git a/src/basic/macro.h b/src/basic/macro.h
index c34441d75d..e41aa4260f 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -23,10 +23,15 @@
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
-#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#ifdef __clang__
+# define _alloc_(...)
+#else
+# define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#endif
#define _sentinel_ __attribute__ ((sentinel))
#define _unused_ __attribute__ ((unused))
#define _destructor_ __attribute__ ((destructor))
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 417604aa64..66cd5921ad 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -135,84 +135,6 @@
#define SOL_SCTP 132
#endif
-#if !HAVE_DECL_PIVOT_ROOT
-static inline int pivot_root(const char *new_root, const char *put_old) {
- return syscall(SYS_pivot_root, new_root, put_old);
-}
-#endif
-
-#ifndef __NR_memfd_create
-# if defined __x86_64__
-# define __NR_memfd_create 319
-# elif defined __arm__
-# define __NR_memfd_create 385
-# elif defined __aarch64__
-# define __NR_memfd_create 279
-# elif defined __s390__
-# define __NR_memfd_create 350
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_memfd_create 4354
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_memfd_create 6318
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_memfd_create 5314
-# endif
-# elif defined __i386__
-# define __NR_memfd_create 356
-# else
-# warning "__NR_memfd_create unknown for your architecture"
-# define __NR_memfd_create 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_MEMFD_CREATE
-static inline int memfd_create(const char *name, unsigned int flags) {
- return syscall(__NR_memfd_create, name, flags);
-}
-#endif
-
-#ifndef __NR_getrandom
-# if defined __x86_64__
-# define __NR_getrandom 318
-# elif defined(__i386__)
-# define __NR_getrandom 355
-# elif defined(__arm__)
-# define __NR_getrandom 384
-# elif defined(__aarch64__)
-# define __NR_getrandom 278
-# elif defined(__ia64__)
-# define __NR_getrandom 1339
-# elif defined(__m68k__)
-# define __NR_getrandom 352
-# elif defined(__s390x__)
-# define __NR_getrandom 349
-# elif defined(__powerpc__)
-# define __NR_getrandom 359
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_getrandom 4353
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_getrandom 6317
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_getrandom 5313
-# endif
-# else
-# warning "__NR_getrandom unknown for your architecture"
-# define __NR_getrandom 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_GETRANDOM
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
- return syscall(__NR_getrandom, buffer, count, flags);
-}
-#endif
-
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
@@ -515,6 +437,10 @@ struct btrfs_ioctl_quota_ctl_args {
#define CGROUP_SUPER_MAGIC 0x27e0eb
#endif
+#ifndef CGROUP2_SUPER_MAGIC
+#define CGROUP2_SUPER_MAGIC 0x63677270
+#endif
+
#ifndef TMPFS_MAGIC
#define TMPFS_MAGIC 0x01021994
#endif
@@ -527,12 +453,6 @@ struct btrfs_ioctl_quota_ctl_args {
#define MS_PRIVATE (1 << 18)
#endif
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
#ifndef SCM_SECURITY
#define SCM_SECURITY 0x03
#endif
@@ -561,32 +481,6 @@ static inline pid_t gettid(void) {
#define MAX_HANDLE_SZ 128
#endif
-#ifndef __NR_name_to_handle_at
-# if defined(__x86_64__)
-# define __NR_name_to_handle_at 303
-# elif defined(__i386__)
-# define __NR_name_to_handle_at 341
-# elif defined(__arm__)
-# define __NR_name_to_handle_at 370
-# elif defined(__powerpc__)
-# define __NR_name_to_handle_at 345
-# else
-# error "__NR_name_to_handle_at is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
- unsigned int handle_bytes;
- int handle_type;
- unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
- return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
#ifndef HAVE_SECURE_GETENV
# ifdef HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
@@ -635,22 +529,6 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
#endif
-#ifndef __NR_setns
-# if defined(__x86_64__)
-# define __NR_setns 308
-# elif defined(__i386__)
-# define __NR_setns 346
-# else
-# error "__NR_setns is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_SETNS
-static inline int setns(int fd, int nstype) {
- return syscall(__NR_setns, fd, nstype);
-}
-#endif
-
#if !HAVE_DECL_LO_FLAGS_PARTSCAN
#define LO_FLAGS_PARTSCAN 8
#endif
@@ -1018,69 +896,10 @@ static inline int setns(int fd, int nstype) {
#define CAP_AUDIT_READ 37
#endif
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
- /* On s390 and cris the order of the first and second arguments
- * of the raw clone() system call is reversed. */
- return (int) syscall(__NR_clone, child_stack, flags);
-#else
- return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
- return (pid_t) syscall(__NR_getxpid);
-#else
- return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
-#if !HAVE_DECL_RENAMEAT2
-
-#ifndef __NR_renameat2
-# if defined __x86_64__
-# define __NR_renameat2 316
-# elif defined __arm__
-# define __NR_renameat2 382
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_renameat2 4351
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_renameat2 6315
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_renameat2 5311
-# endif
-# elif defined __i386__
-# define __NR_renameat2 353
-# else
-# warning "__NR_renameat2 unknown for your architecture"
-# define __NR_renameat2 0xffffffff
-# endif
-#endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
- return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-}
-#endif
-
#ifndef RENAME_NOREPLACE
#define RENAME_NOREPLACE (1 << 0)
#endif
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-#if defined(__NR_kcmp)
- return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KCMP_FILE
#define KCMP_FILE 0
#endif
@@ -1097,35 +916,6 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
typedef int32_t key_serial_t;
#endif
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-#if defined(__NR_keyctl)
- return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-#if defined (__NR_add_key)
- return syscall(__NR_add_key, type, description, payload, plen, ringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-#if defined (__NR_request_key)
- return syscall(__NR_request_key, type, description, callout_info, destringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KEYCTL_READ
#define KEYCTL_READ 11
#endif
@@ -1177,3 +967,5 @@ static inline key_serial_t request_key(const char *type, const char *description
#endif
#endif
+
+#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
new file mode 100644
index 0000000000..d502d3b9ca
--- /dev/null
+++ b/src/basic/missing_syscall.h
@@ -0,0 +1,310 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ 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/>.
+***/
+
+/* Missing glibc definitions to access certain kernel APIs */
+
+#if !HAVE_DECL_PIVOT_ROOT
+static inline int pivot_root(const char *new_root, const char *put_old) {
+ return syscall(SYS_pivot_root, new_root, put_old);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_MEMFD_CREATE
+# ifndef __NR_memfd_create
+# if defined __x86_64__
+# define __NR_memfd_create 319
+# elif defined __arm__
+# define __NR_memfd_create 385
+# elif defined __aarch64__
+# define __NR_memfd_create 279
+# elif defined __s390__
+# define __NR_memfd_create 350
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_memfd_create 4354
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_memfd_create 6318
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_memfd_create 5314
+# endif
+# elif defined __i386__
+# define __NR_memfd_create 356
+# else
+# warning "__NR_memfd_create unknown for your architecture"
+# endif
+# endif
+
+static inline int memfd_create(const char *name, unsigned int flags) {
+# ifdef __NR_memfd_create
+ return syscall(__NR_memfd_create, name, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETRANDOM
+# ifndef __NR_getrandom
+# if defined __x86_64__
+# define __NR_getrandom 318
+# elif defined(__i386__)
+# define __NR_getrandom 355
+# elif defined(__arm__)
+# define __NR_getrandom 384
+# elif defined(__aarch64__)
+# define __NR_getrandom 278
+# elif defined(__ia64__)
+# define __NR_getrandom 1339
+# elif defined(__m68k__)
+# define __NR_getrandom 352
+# elif defined(__s390x__)
+# define __NR_getrandom 349
+# elif defined(__powerpc__)
+# define __NR_getrandom 359
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_getrandom 4353
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_getrandom 6317
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_getrandom 5313
+# endif
+# else
+# warning "__NR_getrandom unknown for your architecture"
+# endif
+# endif
+
+static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+# ifdef __NR_getrandom
+ return syscall(__NR_getrandom, buffer, count, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETTID
+static inline pid_t gettid(void) {
+ return (pid_t) syscall(SYS_gettid);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_NAME_TO_HANDLE_AT
+# ifndef __NR_name_to_handle_at
+# if defined(__x86_64__)
+# define __NR_name_to_handle_at 303
+# elif defined(__i386__)
+# define __NR_name_to_handle_at 341
+# elif defined(__arm__)
+# define __NR_name_to_handle_at 370
+# elif defined(__powerpc__)
+# define __NR_name_to_handle_at 345
+# else
+# error "__NR_name_to_handle_at is not defined"
+# endif
+# endif
+
+struct file_handle {
+ unsigned int handle_bytes;
+ int handle_type;
+ unsigned char f_handle[0];
+};
+
+static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
+# ifdef __NR_name_to_handle_at
+ return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_SETNS
+# ifndef __NR_setns
+# if defined(__x86_64__)
+# define __NR_setns 308
+# elif defined(__i386__)
+# define __NR_setns 346
+# else
+# error "__NR_setns is not defined"
+# endif
+# endif
+
+static inline int setns(int fd, int nstype) {
+# ifdef __NR_setns
+ return syscall(__NR_setns, fd, nstype);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+static inline int raw_clone(unsigned long flags, void *child_stack) {
+#if defined(__s390__) || defined(__CRIS__)
+ /* On s390 and cris the order of the first and second arguments
+ * of the raw clone() system call is reversed. */
+ return (int) syscall(__NR_clone, child_stack, flags);
+#else
+ return (int) syscall(__NR_clone, flags, child_stack);
+#endif
+}
+
+/* ======================================================================= */
+
+static inline pid_t raw_getpid(void) {
+#if defined(__alpha__)
+ return (pid_t) syscall(__NR_getxpid);
+#else
+ return (pid_t) syscall(__NR_getpid);
+#endif
+}
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_RENAMEAT2
+# ifndef __NR_renameat2
+# if defined __x86_64__
+# define __NR_renameat2 316
+# elif defined __arm__
+# define __NR_renameat2 382
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_renameat2 4351
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_renameat2 6315
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_renameat2 5311
+# endif
+# elif defined __i386__
+# define __NR_renameat2 353
+# else
+# warning "__NR_renameat2 unknown for your architecture"
+# endif
+# endif
+
+static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
+# ifdef __NR_renameat2
+ return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KCMP
+static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
+# ifdef __NR_kcmp
+ return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KEYCTL
+static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+# ifdef __NR_keyctl
+ return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
+# ifdef __NR_add_key
+ return syscall(__NR_add_key, type, description, payload, plen, ringid);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
+# ifdef __NR_request_key
+ return syscall(__NR_request_key, type, description, callout_info, destringid);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_COPY_FILE_RANGE
+# ifndef __NR_copy_file_range
+# if defined(__x86_64__)
+# define __NR_copy_file_range 326
+# elif defined(__i386__)
+# define __NR_copy_file_range 377
+# elif defined __s390__
+# define __NR_copy_file_range 375
+# elif defined __arm__
+# define __NR_copy_file_range 391
+# elif defined __aarch64__
+# define __NR_copy_file_range 285
+# else
+# warning "__NR_copy_file_range not defined for your architecture"
+# endif
+# endif
+
+static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+# ifdef __NR_copy_file_range
+ return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 33f2ee96d8..5faa2eba05 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -47,7 +47,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
if ((flags & AT_EMPTY_PATH) && isempty(filename))
xsprintf(path, "/proc/self/fdinfo/%i", fd);
else {
- subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+ subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
if (subfd < 0)
return -errno;
@@ -230,7 +230,7 @@ int path_is_mount_point(const char *t, int flags) {
if (!parent)
return -ENOMEM;
- fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+ fd = openat(AT_FDCWD, parent, O_DIRECTORY|O_CLOEXEC|O_PATH);
if (fd < 0)
return -errno;
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 5e6181f662..10c2f39369 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -152,7 +152,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
return 0;
if (r >= 0) {
- r = lsetfilecon(path, fcon);
+ r = lsetfilecon_raw(path, fcon);
/* If the FS doesn't support labels, then exit without warning */
if (r < 0 && errno == EOPNOTSUPP)
@@ -262,7 +262,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
if (r < 0)
return -errno;
- r = getpeercon(socket_fd, &peercon);
+ r = getpeercon_raw(socket_fd, &peercon);
if (r < 0)
return -errno;
@@ -371,7 +371,7 @@ void mac_selinux_create_file_clear(void) {
if (!mac_selinux_use())
return;
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
#endif
}
@@ -402,7 +402,7 @@ void mac_selinux_create_socket_clear(void) {
if (!mac_selinux_use())
return;
- setsockcreatecon(NULL);
+ setsockcreatecon_raw(NULL);
#endif
}
@@ -461,7 +461,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
return -errno;
} else {
- if (setfscreatecon(fcon) < 0) {
+ if (setfscreatecon_raw(fcon) < 0) {
log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
@@ -472,7 +472,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
return r;
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index 35e9573aa4..6d1dc83874 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -23,7 +23,6 @@
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
-#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
@@ -35,6 +34,7 @@
#include "mkdir.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "umask-util.h"
int socket_address_listen(
const SocketAddress *a,
@@ -112,28 +112,24 @@ int socket_address_listen(
return -errno;
if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
- mode_t old_mask;
-
/* Create parents */
- mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
+ (void) mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
/* Enforce the right access mode for the socket */
- old_mask = umask(~ socket_mode);
-
- r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0 && errno == EADDRINUSE) {
- /* Unlink and try again */
- unlink(a->sockaddr.un.sun_path);
- r = bind(fd, &a->sockaddr.sa, a->size);
+ RUN_WITH_UMASK(~socket_mode) {
+ r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
+ if (r == -EADDRINUSE) {
+ /* Unlink and try again */
+ unlink(a->sockaddr.un.sun_path);
+ if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ return -errno;
+ } else if (r < 0)
+ return r;
}
-
- umask(old_mask);
- } else
- r = bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0)
- return -errno;
+ } else {
+ if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ return -errno;
+ }
if (socket_address_can_accept(a))
if (listen(fd, backlog) < 0)
diff --git a/src/basic/utf8.h b/src/basic/utf8.h
index 12c272d66e..f9b9c9468b 100644
--- a/src/basic/utf8.h
+++ b/src/basic/utf8.h
@@ -28,6 +28,7 @@
#include "missing.h"
#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
+#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
bool unichar_is_valid(char32_t c);
diff --git a/src/basic/util.h b/src/basic/util.h
index e095254b57..286db05159 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -36,6 +36,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statfs.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
index 8d7f14f382..8256899eda 100644
--- a/src/basic/xattr-util.c
+++ b/src/basic/xattr-util.c
@@ -110,7 +110,7 @@ ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute,
/* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
- fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+ fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
if (fd < 0)
return -errno;
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 39235a95f6..9c34928052 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -765,7 +765,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
}
int unit_watch_cgroup(Unit *u) {
- _cleanup_free_ char *populated = NULL;
+ _cleanup_free_ char *events = NULL;
int r;
assert(u);
@@ -791,11 +791,11 @@ int unit_watch_cgroup(Unit *u) {
if (r < 0)
return log_oom();
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated);
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events);
if (r < 0)
return log_oom();
- u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, populated, IN_MODIFY);
+ u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY);
if (u->cgroup_inotify_wd < 0) {
if (errno == ENOENT) /* If the directory is already
diff --git a/src/core/device.c b/src/core/device.c
index d201dc5e4b..28e4039da2 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -318,7 +318,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
* the GC to have garbaged it. That's desired since the device
* unit may have a dependency on the mount unit which was
* added during the loading of the later. */
- if (u && DEVICE(u)->state == DEVICE_PLUGGED) {
+ if (dev && u && DEVICE(u)->state == DEVICE_PLUGGED) {
/* This unit is in plugged state: we're sure it's
* attached to a device. */
if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
diff --git a/src/core/execute.c b/src/core/execute.c
index 517c2fb45b..ac2ac39892 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -24,6 +24,7 @@
#include <poll.h>
#include <signal.h>
#include <string.h>
+#include <sys/capability.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/socket.h>
@@ -1824,6 +1825,11 @@ static int exec_child(
if (params->apply_permissions) {
+ bool use_address_families = context->address_families_whitelist ||
+ !set_isempty(context->address_families);
+ bool use_syscall_filter = context->syscall_whitelist ||
+ !set_isempty(context->syscall_filter) ||
+ !set_isempty(context->syscall_archs);
int secure_bits = context->secure_bits;
for (i = 0; i < _RLIMIT_MAX; i++) {
@@ -1890,15 +1896,15 @@ static int exec_child(
return -errno;
}
- if (context->no_new_privileges)
+ if (context->no_new_privileges ||
+ (!have_effective_cap(CAP_SYS_ADMIN) && (use_address_families || use_syscall_filter)))
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
*exit_status = EXIT_NO_NEW_PRIVILEGES;
return -errno;
}
#ifdef HAVE_SECCOMP
- if (context->address_families_whitelist ||
- !set_isempty(context->address_families)) {
+ if (use_address_families) {
r = apply_address_families(context);
if (r < 0) {
*exit_status = EXIT_ADDRESS_FAMILIES;
@@ -1906,9 +1912,7 @@ static int exec_child(
}
}
- if (context->syscall_whitelist ||
- !set_isempty(context->syscall_filter) ||
- !set_isempty(context->syscall_archs)) {
+ if (use_syscall_filter) {
r = apply_seccomp(context);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index 39f5519ca1..bb2bc3f399 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -62,7 +62,8 @@ int failure_action(
log_and_status(m, "Rebooting as result of failure.");
update_reboot_param_file(reboot_arg);
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, NULL);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET,
+ JOB_REPLACE_IRREVERSIBLY, NULL);
break;
@@ -89,7 +90,8 @@ int failure_action(
case FAILURE_ACTION_POWEROFF:
log_and_status(m, "Powering off as result of failure.");
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, NULL);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET,
+ JOB_REPLACE_IRREVERSIBLY, NULL);
break;
case FAILURE_ACTION_POWEROFF_FORCE:
diff --git a/src/core/job.c b/src/core/job.c
index 012cf72d1f..5557a6a942 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -645,7 +645,7 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
[JOB_DONE] = "Stopped %s.",
[JOB_FAILED] = "Stopped (with error) %s.",
- [JOB_TIMEOUT] = "Timed out stoppping %s.",
+ [JOB_TIMEOUT] = "Timed out stopping %s.",
};
static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = {
[JOB_DONE] = "Reloaded %s.",
@@ -690,17 +690,20 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
}
static void job_print_status_message(Unit *u, JobType t, JobResult result) {
- static const char* const job_result_status_table[_JOB_RESULT_MAX] = {
- [JOB_DONE] = ANSI_GREEN " OK " ANSI_NORMAL,
- [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED " TIME " ANSI_NORMAL,
- [JOB_FAILED] = ANSI_HIGHLIGHT_RED "FAILED" ANSI_NORMAL,
- [JOB_DEPENDENCY] = ANSI_HIGHLIGHT_YELLOW "DEPEND" ANSI_NORMAL,
- [JOB_SKIPPED] = ANSI_HIGHLIGHT " INFO " ANSI_NORMAL,
- [JOB_ASSERT] = ANSI_HIGHLIGHT_YELLOW "ASSERT" ANSI_NORMAL,
- [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW "UNSUPP" ANSI_NORMAL,
+ static struct {
+ const char *color, *word;
+ } const statuses[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = {ANSI_GREEN, " OK "},
+ [JOB_TIMEOUT] = {ANSI_HIGHLIGHT_RED, " TIME "},
+ [JOB_FAILED] = {ANSI_HIGHLIGHT_RED, "FAILED"},
+ [JOB_DEPENDENCY] = {ANSI_HIGHLIGHT_YELLOW, "DEPEND"},
+ [JOB_SKIPPED] = {ANSI_HIGHLIGHT, " INFO "},
+ [JOB_ASSERT] = {ANSI_HIGHLIGHT_YELLOW, "ASSERT"},
+ [JOB_UNSUPPORTED] = {ANSI_HIGHLIGHT_YELLOW, "UNSUPP"},
};
const char *format;
+ const char *status;
assert(u);
assert(t >= 0);
@@ -714,11 +717,16 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
if (!format)
return;
+ if (log_get_show_color())
+ status = strjoina(statuses[result].color, statuses[result].word, ANSI_NORMAL);
+ else
+ status = statuses[result].word;
+
if (result != JOB_DONE)
manager_flip_auto_status(u->manager, true);
DISABLE_WARNING_FORMAT_NONLITERAL;
- unit_status_printf(u, job_result_status_table[result], format);
+ unit_status_printf(u, status, format);
REENABLE_WARNING;
if (t == JOB_START && result == JOB_FAILED) {
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e1bfdccbca..d078924c5b 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3507,7 +3507,19 @@ static int merge_by_names(Unit **u, Set *names, const char *id) {
* ours? Then let's try it the other way
* round */
- other = manager_get_unit((*u)->manager, k);
+ /* If the symlink name we are looking at is unit template, then
+ we must search for instance of this template */
+ if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE)) {
+ _cleanup_free_ char *instance = NULL;
+
+ r = unit_name_replace_instance(k, (*u)->instance, &instance);
+ if (r < 0)
+ return r;
+
+ other = manager_get_unit((*u)->manager, instance);
+ } else
+ other = manager_get_unit((*u)->manager, k);
+
free(k);
if (other) {
diff --git a/src/core/main.c b/src/core/main.c
index 1783b9c7af..56df32426a 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1218,10 +1218,15 @@ static int status_welcome(void) {
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read os-release file: %m");
- return status_printf(NULL, false, false,
- "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
- isempty(ansi_color) ? "1" : ansi_color,
- isempty(pretty_name) ? "Linux" : pretty_name);
+ if (log_get_show_color())
+ return status_printf(NULL, false, false,
+ "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+ isempty(ansi_color) ? "1" : ansi_color,
+ isempty(pretty_name) ? "Linux" : pretty_name);
+ else
+ return status_printf(NULL, false, false,
+ "\nWelcome to %s!\n",
+ isempty(pretty_name) ? "Linux" : pretty_name);
}
static int write_container_id(void) {
@@ -1659,7 +1664,7 @@ int main(int argc, char *argv[]) {
test_usr();
}
- if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
+ if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
watchdog_set_timeout(&arg_runtime_watchdog);
if (arg_timer_slack_nsec != NSEC_INFINITY)
@@ -2090,7 +2095,7 @@ finish:
assert(pos < ELEMENTSOF(command_line));
- if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
+ if (arm_reboot_watchdog && arg_shutdown_watchdog > 0 && arg_shutdown_watchdog != USEC_INFINITY) {
char *e;
/* If we reboot let's set the shutdown
diff --git a/src/core/manager.c b/src/core/manager.c
index f13e933578..e739795e70 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1333,8 +1333,12 @@ int manager_load_unit_prepare(
t = unit_name_to_type(name);
- if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+ if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+ if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE))
+ return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is missing the instance name.", name);
+
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
+ }
ret = manager_get_unit(m, name);
if (ret) {
@@ -1631,7 +1635,9 @@ static void invoke_sigchld_event(Manager *m, Unit *u, const siginfo_t *si) {
log_unit_debug(u, "Child "PID_FMT" belongs to %s", si->si_pid, u->id);
unit_unwatch_pid(u, si->si_pid);
- UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
+
+ if (UNIT_VTABLE(u)->sigchld_event)
+ UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
}
static int manager_dispatch_sigchld(Manager *m) {
@@ -2016,7 +2022,7 @@ int manager_loop(Manager *m) {
while (m->exit_code == MANAGER_OK) {
usec_t wait_usec;
- if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM)
+ if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && m->running_as == MANAGER_SYSTEM)
watchdog_ping();
if (!ratelimit_test(&rl)) {
@@ -2041,7 +2047,7 @@ int manager_loop(Manager *m) {
continue;
/* Sleep for half the watchdog time */
- if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) {
+ if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && m->running_as == MANAGER_SYSTEM) {
wait_usec = m->runtime_watchdog / 2;
if (wait_usec <= 0)
wait_usec = 1;
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index de1a361cc4..32fe51c67e 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -94,7 +94,7 @@ static const MountPoint mount_table[] = {
#endif
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "cgroup", "/sys/fs/cgroup", "cgroup", "__DEVEL__sane_behavior", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ { "cgroup", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
cg_is_unified_wanted, MNT_FATAL|MNT_IN_CONTAINER },
{ "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
diff --git a/src/core/mount.c b/src/core/mount.c
index 93d2bd595c..0fd880df5d 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -104,6 +104,14 @@ static bool mount_is_auto(const MountParameters *p) {
return !fstab_test_option(p->options, "noauto\0");
}
+static bool mount_is_automount(const MountParameters *p) {
+ assert(p);
+
+ return fstab_test_option(p->options,
+ "comment=systemd.automount\0"
+ "x-systemd.automount\0");
+}
+
static bool needs_quota(const MountParameters *p) {
assert(p);
@@ -328,7 +336,8 @@ static int mount_add_device_links(Mount *m) {
if (path_equal(m->where, "/"))
return 0;
- if (mount_is_auto(p) && UNIT(m)->manager->running_as == MANAGER_SYSTEM)
+ if (mount_is_auto(p) && !mount_is_automount(p) &&
+ UNIT(m)->manager->running_as == MANAGER_SYSTEM)
device_wants_mount = true;
r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
@@ -369,7 +378,8 @@ static bool should_umount(Mount *m) {
MountParameters *p;
if (path_equal(m->where, "/") ||
- path_equal(m->where, "/usr"))
+ path_equal(m->where, "/usr") ||
+ path_startswith(m->where, "/run/initramfs"))
return false;
p = get_mount_parameters(m);
@@ -393,13 +403,15 @@ static int mount_add_default_dependencies(Mount *m) {
if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
return 0;
- /* We do not add any default dependencies to / and /usr, since
- * they are guaranteed to stay mounted the whole time, since
- * our system is on it. Also, don't bother with anything
- * mounted below virtual file systems, it's also going to be
- * virtual, and hence not worth the effort. */
+ /* We do not add any default dependencies to /, /usr or
+ * /run/initramfs/, since they are guaranteed to stay
+ * mounted the whole time, since our system is on it.
+ * Also, don't bother with anything mounted below virtual
+ * file systems, it's also going to be virtual, and hence
+ * not worth the effort. */
if (path_equal(m->where, "/") ||
path_equal(m->where, "/usr") ||
+ path_startswith(m->where, "/run/initramfs") ||
path_startswith(m->where, "/proc") ||
path_startswith(m->where, "/sys") ||
path_startswith(m->where, "/dev"))
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index 9a115a4387..4072df58e6 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -88,7 +88,7 @@ int mac_selinux_setup(bool *loaded_policy) {
log_open();
log_error("Failed to compute init label, ignoring.");
} else {
- r = setcon(label);
+ r = setcon_raw(label);
log_open();
if (r < 0)
diff --git a/src/core/socket.c b/src/core/socket.c
index 87586c1c2e..dd515a17a5 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1341,8 +1341,12 @@ static int socket_open_fds(Socket *s) {
break;
case SOCKET_USB_FUNCTION:
+ {
+ _cleanup_free_ char *ep = NULL;
- p->fd = usbffs_address_create(p->path);
+ ep = path_make_absolute("ep0", p->path);
+
+ p->fd = usbffs_address_create(ep);
if (p->fd < 0) {
r = p->fd;
goto rollback;
@@ -1357,7 +1361,7 @@ static int socket_open_fds(Socket *s) {
goto rollback;
break;
-
+ }
default:
assert_not_reached("Unknown port type");
}
diff --git a/src/core/transaction.c b/src/core/transaction.c
index b28fc76785..c894001cf9 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -391,6 +391,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
if (delete) {
+ const char *status;
/* logging for j not k here here to provide consistent narrative */
log_unit_warning(j->unit,
"Breaking ordering cycle by deleting job %s/%s",
@@ -399,7 +400,13 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
"Job %s/%s deleted to break ordering cycle starting with %s/%s",
delete->unit->id, job_type_to_string(delete->type),
j->unit->id, job_type_to_string(j->type));
- unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL,
+
+ if (log_get_show_color())
+ status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL;
+ else
+ status = " SKIP ";
+
+ unit_status_printf(delete->unit, status,
"Ordering cycle found, skipping %s");
transaction_delete_unit(tr, delete->unit);
return -EAGAIN;
diff --git a/src/core/umount.c b/src/core/umount.c
index b953fcc152..c21a2be54e 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -412,6 +412,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
#ifndef HAVE_SPLIT_USR
|| path_equal(m->path, "/usr")
#endif
+ || path_startswith(m->path, "/run/initramfs")
)
continue;
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index 2ef966257a..9927621ea0 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -719,8 +719,12 @@ int main(int argc, char *argv[]) {
int k;
k = crypt_init_by_name(&cd, argv[2]);
- if (k) {
- log_error_errno(k, "crypt_init() failed: %m");
+ if (k == -ENODEV) {
+ log_info("Volume %s already inactive.", argv[2]);
+ r = EXIT_SUCCESS;
+ goto finish;
+ } else if (k) {
+ log_error_errno(k, "crypt_init_by_name() failed: %m");
goto finish;
}
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 7790ab865d..435e3805c4 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -245,7 +245,7 @@ static int process_locale(void) {
int r;
etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
- if (faccessat(AT_FDCWD, etc_localeconf, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_localeconf, F_OK) >= 0)
return 0;
if (arg_copy_locale && arg_root) {
@@ -319,7 +319,7 @@ static int process_timezone(void) {
int r;
etc_localtime = prefix_roota(arg_root, "/etc/localtime");
- if (faccessat(AT_FDCWD, etc_localtime, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_localtime, F_OK) >= 0)
return 0;
if (arg_copy_timezone && arg_root) {
@@ -399,7 +399,7 @@ static int process_hostname(void) {
int r;
etc_hostname = prefix_roota(arg_root, "/etc/hostname");
- if (faccessat(AT_FDCWD, etc_hostname, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_hostname, F_OK) >= 0)
return 0;
r = prompt_hostname();
@@ -424,7 +424,7 @@ static int process_machine_id(void) {
int r;
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
- if (faccessat(AT_FDCWD, etc_machine_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_machine_id, F_OK) >= 0)
return 0;
if (sd_id128_equal(arg_machine_id, SD_ID128_NULL))
@@ -450,7 +450,7 @@ static int prompt_root_password(void) {
return 0;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_shadow, F_OK) >= 0)
return 0;
print_welcome();
@@ -533,7 +533,7 @@ static int process_root_password(void) {
int r;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_shadow, F_OK) >= 0)
return 0;
mkdir_parents(etc_shadow, 0755);
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 97a48764ae..6f576b5ecf 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -336,8 +336,8 @@ static int add_mount(
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", unit);
- if (!noauto) {
- lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
+ if (!noauto && !automount) {
+ lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", name, NULL);
if (!lnk)
return log_oom();
diff --git a/src/import/import-common.c b/src/import/import-common.c
index 18a30be36d..287a3382a1 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -136,7 +136,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", NULL);
+ execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
@@ -210,7 +210,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "-C", path, "-c", ".", NULL);
+ execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", ".", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c
index 5b2d130cd6..0ef6d36a50 100644
--- a/src/journal/test-compress-benchmark.c
+++ b/src/journal/test-compress-benchmark.c
@@ -105,6 +105,8 @@ static void test_compress_decompress(const char* label, const char* type,
int r;
size = permute(i);
+ if (size == 0)
+ continue;
log_debug("%s %zu %zu", type, i, size);
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 1d9ec7be82..4f7d4d8bf2 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -43,7 +43,7 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
if (r < 0)
return r;
- unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
+ unaligned_write_be16(&duid->type, DUID_TYPE_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
*len = sizeof(duid->type) + sizeof(duid->en);
diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h
index 93f06f5938..e6486b78f8 100644
--- a/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libsystemd-network/dhcp-identifier.h
@@ -25,13 +25,23 @@
#include "sparse-endian.h"
#include "unaligned.h"
+typedef enum DUIDType {
+ DUID_TYPE_RAW = 0,
+ DUID_TYPE_LLT = 1,
+ DUID_TYPE_EN = 2,
+ DUID_TYPE_LL = 3,
+ DUID_TYPE_UUID = 4,
+ _DUID_TYPE_MAX,
+ _DUID_TYPE_INVALID = -1,
+} DUIDType;
+
/* RFC 3315 section 9.1:
* A DUID can be no more than 128 octets long (not including the type code).
*/
#define MAX_DUID_LEN 128
struct duid {
- uint16_t type;
+ be16_t type;
union {
struct {
/* DHCP6_DUID_LLT */
@@ -61,3 +71,34 @@ struct duid {
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
+
+static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
+ struct duid d;
+
+ assert(duid_len > 0);
+
+ switch (duid_type) {
+ case DUID_TYPE_LLT:
+ if (duid_len <= sizeof(d.llt))
+ return -EINVAL;
+ break;
+ case DUID_TYPE_EN:
+ if (duid_len != sizeof(d.en))
+ return -EINVAL;
+ break;
+ case DUID_TYPE_LL:
+ if (duid_len <= sizeof(d.ll))
+ return -EINVAL;
+ break;
+ case DUID_TYPE_UUID:
+ if (duid_len != sizeof(d.uuid))
+ return -EINVAL;
+ break;
+ default:
+ if (duid_len > sizeof(d.raw))
+ return -EINVAL;
+ /* accept unknown type in order to be forward compatible */
+ break;
+ }
+ return 0;
+}
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
index ee4bdfb07f..2487c470ab 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -62,13 +62,6 @@ enum {
#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC
#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC
-enum {
- DHCP6_DUID_LLT = 1,
- DHCP6_DUID_EN = 2,
- DHCP6_DUID_LL = 3,
- DHCP6_DUID_UUID = 4,
-};
-
enum DHCP6State {
DHCP6_STATE_STOPPED = 0,
DHCP6_STATE_INFORMATION_REQUEST = 1,
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c
index c61941cd70..6a716430e3 100644
--- a/src/libsystemd-network/lldp-neighbor.c
+++ b/src/libsystemd-network/lldp-neighbor.c
@@ -24,7 +24,6 @@
#include "in-addr-util.h"
#include "lldp-internal.h"
#include "lldp-neighbor.h"
-#include "lldp.h"
#include "unaligned.h"
static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) {
@@ -245,7 +244,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
switch (type) {
- case LLDP_TYPE_END:
+ case SD_LLDP_TYPE_END:
if (length != 0) {
log_lldp("End marker TLV not zero-sized, ignoring datagram.");
return -EBADMSG;
@@ -257,7 +256,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
goto end_marker;
- case LLDP_TYPE_CHASSIS_ID:
+ case SD_LLDP_TYPE_CHASSIS_ID:
if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */
log_lldp("Chassis ID field size out of range, ignoring datagram.");
return -EBADMSG;
@@ -274,7 +273,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
n->id.chassis_id_size = length;
break;
- case LLDP_TYPE_PORT_ID:
+ case SD_LLDP_TYPE_PORT_ID:
if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */
log_lldp("Port ID field size out of range, ignoring datagram.");
return -EBADMSG;
@@ -291,7 +290,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
n->id.port_id_size = length;
break;
- case LLDP_TYPE_TTL:
+ case SD_LLDP_TYPE_TTL:
if (length != 2) {
log_lldp("TTL field has wrong size, ignoring datagram.");
return -EBADMSG;
@@ -306,25 +305,25 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
n->has_ttl = true;
break;
- case LLDP_TYPE_PORT_DESCRIPTION:
+ case SD_LLDP_TYPE_PORT_DESCRIPTION:
r = parse_string(&n->port_description, p, length);
if (r < 0)
return r;
break;
- case LLDP_TYPE_SYSTEM_NAME:
+ case SD_LLDP_TYPE_SYSTEM_NAME:
r = parse_string(&n->system_name, p, length);
if (r < 0)
return r;
break;
- case LLDP_TYPE_SYSTEM_DESCRIPTION:
+ case SD_LLDP_TYPE_SYSTEM_DESCRIPTION:
r = parse_string(&n->system_description, p, length);
if (r < 0)
return r;
break;
- case LLDP_TYPE_SYSTEM_CAPABILITIES:
+ case SD_LLDP_TYPE_SYSTEM_CAPABILITIES:
if (length != 4)
log_lldp("System capabilities field has wrong size, ignoring.");
else {
@@ -335,7 +334,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
break;
- case LLDP_TYPE_PRIVATE:
+ case SD_LLDP_TYPE_PRIVATE:
if (length < 4)
log_lldp("Found private TLV that is too short, ignoring.");
@@ -446,7 +445,7 @@ static int format_mac_address(const void *data, size_t sz, char **ret) {
static int format_network_address(const void *data, size_t sz, char **ret) {
union in_addr_union a;
- int family;
+ int family, r;
if (sz == 6 && ((uint8_t*) data)[1] == 1) {
memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in));
@@ -457,7 +456,10 @@ static int format_network_address(const void *data, size_t sz, char **ret) {
} else
return 0;
- return in_addr_to_string(family, &a, ret);
+ r = in_addr_to_string(family, &a, ret);
+ if (r < 0)
+ return r;
+ return 1;
}
_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) {
@@ -476,18 +478,18 @@ _public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, cons
switch (*(uint8_t*) n->id.chassis_id) {
- case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
- case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
- case LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
- case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
- case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
+ case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
+ case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
+ case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
+ case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
+ case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1);
if (!k)
return -ENOMEM;
goto done;
- case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
+ case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k);
if (r < 0)
return r;
@@ -496,7 +498,7 @@ _public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, cons
break;
- case LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
+ case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k);
if (r < 0)
return r;
@@ -547,17 +549,17 @@ _public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const c
switch (*(uint8_t*) n->id.port_id) {
- case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
- case LLDP_PORT_SUBTYPE_PORT_COMPONENT:
- case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
- case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
+ case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
+ case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT:
+ case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME:
+ case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1);
if (!k)
return -ENOMEM;
goto done;
- case LLDP_PORT_SUBTYPE_MAC_ADDRESS:
+ case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS:
r = format_mac_address(n->id.port_id, n->id.port_id_size, &k);
if (r < 0)
return r;
@@ -566,7 +568,7 @@ _public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const c
break;
- case LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
+ case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
r = format_network_address(n->id.port_id, n->id.port_id_size, &k);
if (r < 0)
return r;
@@ -735,7 +737,7 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], u
assert_return(oui, -EINVAL);
assert_return(subtype, -EINVAL);
- r = sd_lldp_neighbor_tlv_is_type(n, LLDP_TYPE_PRIVATE);
+ r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE);
if (r < 0)
return r;
if (r == 0)
diff --git a/src/libsystemd-network/lldp.h b/src/libsystemd-network/lldp.h
deleted file mode 100644
index d61ecabcfc..0000000000
--- a/src/libsystemd-network/lldp.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
- 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/>.
-***/
-
-#define LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
-
-/* IEEE 802.3AB Clause 9: TLV Types */
-enum {
- LLDP_TYPE_END = 0,
- LLDP_TYPE_CHASSIS_ID = 1,
- LLDP_TYPE_PORT_ID = 2,
- LLDP_TYPE_TTL = 3,
- LLDP_TYPE_PORT_DESCRIPTION = 4,
- LLDP_TYPE_SYSTEM_NAME = 5,
- LLDP_TYPE_SYSTEM_DESCRIPTION = 6,
- LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
- LLDP_TYPE_MGMT_ADDRESS = 8,
- LLDP_TYPE_PRIVATE = 127,
-};
-
-/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
-enum {
- LLDP_CHASSIS_SUBTYPE_RESERVED = 0,
- LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1,
- LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2,
- LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3,
- LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4,
- LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5,
- LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6,
- LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7,
-};
-
-/* IEEE 802.3AB Clause 9.5.3: Port subtype */
-enum {
- LLDP_PORT_SUBTYPE_RESERVED = 0,
- LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1,
- LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2,
- LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3,
- LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4,
- LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5,
- LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
- LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
-};
-
-enum {
- LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0,
- LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
- LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2,
- LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3,
- LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4,
- LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5,
- LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6,
- LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7,
- LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8,
- LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9,
- LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10,
-};
-
-#define _LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1)
-
-#define _LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS \
- ((uint16_t) \
- (LLDP_SYSTEM_CAPABILITIES_REPEATER| \
- LLDP_SYSTEM_CAPABILITIES_BRIDGE| \
- LLDP_SYSTEM_CAPABILITIES_WLAN_AP| \
- LLDP_SYSTEM_CAPABILITIES_ROUTER| \
- LLDP_SYSTEM_CAPABILITIES_DOCSIS| \
- LLDP_SYSTEM_CAPABILITIES_CVLAN| \
- LLDP_SYSTEM_CAPABILITIES_SVLAN| \
- LLDP_SYSTEM_CAPABILITIES_TPMR))
-
-
-#define LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
-#define LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
-
-enum {
- LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1,
- LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
- LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3,
- LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4,
- LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5,
- LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6,
- LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7,
-};
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index cb7252bbeb..0e2d757b2b 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -335,6 +335,35 @@ int config_parse_hwaddr(const char *unit,
return 0;
}
+int config_parse_iaid(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) {
+ uint32_t iaid;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou32(rvalue, &iaid);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue);
+ return r;
+ }
+
+ *((uint32_t *)data) = iaid;
+
+ return 0;
+}
+
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
unsigned i;
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index c8a531ab0f..72432774d7 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -62,6 +62,10 @@ 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 config_parse_iaid(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, uint64_t *result);
const char *net_get_name(struct udev_device *device);
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 1188b31500..287b6e26fa 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -82,7 +82,7 @@ struct sd_dhcp_client {
} _packed_ ll;
struct {
/* 255: Node-specific (RFC 4361) */
- uint32_t iaid;
+ be32_t iaid;
struct duid duid;
} _packed_ ns;
struct {
@@ -298,6 +298,52 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
return 0;
}
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
+ uint16_t duid_type, uint8_t *duid, size_t duid_len) {
+ DHCP_CLIENT_DONT_DESTROY(client);
+ int r;
+ assert_return(client, -EINVAL);
+ zero(client->client_id);
+
+ client->client_id.type = 255;
+
+ /* If IAID is not configured, generate it. */
+ if (iaid == 0) {
+ r = dhcp_identifier_set_iaid(client->index, client->mac_addr,
+ client->mac_addr_len,
+ &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+ } else
+ client->client_id.ns.iaid = htobe32(iaid);
+
+ /* If DUID is not configured, generate DUID-EN. */
+ if (duid_len == 0) {
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
+ &duid_len);
+ if (r < 0)
+ return r;
+ } else {
+ r = dhcp_validate_duid_len(client->client_id.type, duid_len);
+ if (r < 0)
+ return r;
+ client->client_id.ns.duid.type = htobe16(duid_type);
+ memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
+ duid_len += sizeof(client->client_id.ns.duid.type);
+ }
+
+ client->client_id_len = sizeof(client->client_id.type) + duid_len +
+ sizeof(client->client_id.ns.iaid);
+
+ if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
+ log_dhcp_client(client, "Configured IAID+DUID, restarting.");
+ client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
+ sd_dhcp_client_start(client);
+ }
+
+ return 0;
+}
+
int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
const char *hostname) {
char *new_hostname = NULL;
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index af4709d788..ee4fb4fc1e 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -180,41 +180,29 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
}
-int sd_dhcp6_client_set_duid(
- sd_dhcp6_client *client,
- uint16_t type,
- uint8_t *duid, size_t duid_len) {
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
+ uint8_t *duid, size_t duid_len) {
+ int r;
assert_return(client, -EINVAL);
- assert_return(duid, -EINVAL);
- assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
-
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
- switch (type) {
- case DHCP6_DUID_LLT:
- if (duid_len <= sizeof(client->duid.llt))
- return -EINVAL;
- break;
- case DHCP6_DUID_EN:
- if (duid_len != sizeof(client->duid.en))
- return -EINVAL;
- break;
- case DHCP6_DUID_LL:
- if (duid_len <= sizeof(client->duid.ll))
- return -EINVAL;
- break;
- case DHCP6_DUID_UUID:
- if (duid_len != sizeof(client->duid.uuid))
- return -EINVAL;
- break;
- default:
- /* accept unknown type in order to be forward compatible */
- break;
+ if (duid_len > 0) {
+ r = dhcp_validate_duid_len(duid_type, duid_len);
+ if (r < 0)
+ return r;
+ client->duid.type = htobe16(duid_type);
+ memcpy(&client->duid.raw.data, duid, duid_len);
+ client->duid_len = duid_len + sizeof(client->duid.type);
}
- client->duid.type = htobe16(type);
- memcpy(&client->duid.raw.data, duid, duid_len);
- client->duid_len = duid_len + sizeof(client->duid.type);
+ return 0;
+}
+
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
+ assert_return(client, -EINVAL);
+ assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+
+ client->ia_na.id = htobe32(iaid);
return 0;
}
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index d0743cf3e2..9d4587c80e 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -112,6 +112,8 @@ static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
return true;
}
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor);
+
static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
_cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL;
bool keep;
@@ -136,7 +138,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
if (lldp_neighbor_equal(n, old)) {
/* Is this equal, then restart the TTL counter, but don't do anyting else. */
- lldp_neighbor_start_ttl(old);
+ lldp_start_timer(lldp, old);
lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
return 0;
}
@@ -162,7 +164,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
n->lldp = lldp;
- lldp_neighbor_start_ttl(n);
+ lldp_start_timer(lldp, n);
lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n);
return 1;
@@ -368,8 +370,6 @@ static int neighbor_compare_func(const void *a, const void *b) {
return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id);
}
-static int lldp_start_timer(sd_lldp *lldp);
-
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
sd_lldp *lldp = userdata;
int r, q;
@@ -378,19 +378,22 @@ static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
if (r < 0)
return log_lldp_errno(r, "Failed to make space: %m");
- q = lldp_start_timer(lldp);
+ q = lldp_start_timer(lldp, NULL);
if (q < 0)
return log_lldp_errno(q, "Failed to restart timer: %m");
return 0;
}
-static int lldp_start_timer(sd_lldp *lldp) {
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
sd_lldp_neighbor *n;
int r;
assert(lldp);
+ if (neighbor)
+ lldp_neighbor_start_ttl(neighbor);
+
n = prioq_peek(lldp->neighbor_by_expiry);
if (!n) {
@@ -440,7 +443,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
if (!l)
return -ENOMEM;
- r = lldp_start_timer(lldp);
+ r = lldp_start_timer(lldp, NULL);
if (r < 0) {
free(l);
return r;
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index da4ce293bc..1aae2253c0 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -30,7 +30,6 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "lldp-network.h"
-#include "lldp.h"
#include "macro.h"
#include "string-util.h"
@@ -127,12 +126,12 @@ static void test_receive_basic_packet(sd_event *e) {
assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[0], &type, &data, &length) == 0);
- assert_se(type == LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
+ assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
assert_se(length == ETH_ALEN);
assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN));
assert_se(sd_lldp_neighbor_get_port_id(neighbors[0], &type, &data, &length) == 0);
- assert_se(type == LLDP_PORT_SUBTYPE_INTERFACE_NAME);
+ assert_se(type == SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME);
assert_se(length == 3);
assert_se(strneq((char *) data, "1/3", 3));
@@ -218,23 +217,23 @@ static void test_receive_oui_packet(sd_event *e) {
assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
assert_se(sd_lldp_neighbor_tlv_rewind(neighbors[0]) >= 0);
- assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], LLDP_TYPE_CHASSIS_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_CHASSIS_ID) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], LLDP_TYPE_PORT_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_PORT_ID) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], LLDP_TYPE_TTL) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_TTL) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], LLDP_OUI_802_1, LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], LLDP_OUI_802_1, LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], LLDP_OUI_802_1, LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], LLDP_OUI_802_1, LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], LLDP_OUI_802_1, LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
- assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], LLDP_TYPE_END) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0);
sd_lldp_neighbor_unref(neighbors[0]);
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 542c37e41b..b8958ec7bb 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -1131,10 +1131,7 @@ _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
assert_return(!m->sealed, -EPERM);
assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
- else
- m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
return 0;
}
@@ -1143,10 +1140,7 @@ _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
- else
- m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
return 0;
}
@@ -1155,10 +1149,7 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
- else
- m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
return 0;
}
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index cc15afeb1c..862f26aad7 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -313,10 +313,7 @@ _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (b)
- bus->creds_mask |= mask;
- else
- bus->creds_mask &= ~mask;
+ SET_FLAG(bus->creds_mask, mask, b);
/* The well knowns we need unconditionally, so that matches can work */
bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 8657e61cd9..e9f8970d2c 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -1457,15 +1457,20 @@ static int device_properties_prepare(sd_device *device) {
return r;
if (device->property_devlinks_outdated) {
- char *devlinks = NULL;
+ _cleanup_free_ char *devlinks = NULL;
+ size_t devlinks_allocated = 0, devlinks_len = 0;
const char *devlink;
- devlink = sd_device_get_devlink_first(device);
- if (devlink)
- devlinks = strdupa(devlink);
+ for (devlink = sd_device_get_devlink_first(device); devlink; devlink = sd_device_get_devlink_next(device)) {
+ char *e;
- while ((devlink = sd_device_get_devlink_next(device)))
- devlinks = strjoina(devlinks, " ", devlink);
+ if (!GREEDY_REALLOC(devlinks, devlinks_allocated, devlinks_len + strlen(devlink) + 2))
+ return -ENOMEM;
+ if (devlinks_len > 0)
+ stpcpy(devlinks + devlinks_len++, " ");
+ e = stpcpy(devlinks + devlinks_len, devlink);
+ devlinks_len = e - devlinks;
+ }
r = device_add_property_internal(device, "DEVLINKS", devlinks);
if (r < 0)
@@ -1475,17 +1480,23 @@ static int device_properties_prepare(sd_device *device) {
}
if (device->property_tags_outdated) {
- char *tags = NULL;
+ _cleanup_free_ char *tags = NULL;
+ size_t tags_allocated = 0, tags_len = 0;
const char *tag;
- tag = sd_device_get_tag_first(device);
- if (tag)
- tags = strjoina(":", tag);
+ if (!GREEDY_REALLOC(tags, tags_allocated, 2))
+ return -ENOMEM;
+ stpcpy(tags, ":");
+ tags_len++;
- while ((tag = sd_device_get_tag_next(device)))
- tags = strjoina(tags, ":", tag);
+ for (tag = sd_device_get_tag_first(device); tag; tag = sd_device_get_tag_next(device)) {
+ char *e;
- tags = strjoina(tags, ":");
+ if (!GREEDY_REALLOC(tags, tags_allocated, tags_len + strlen(tag) + 1))
+ return -ENOMEM;
+ e = stpcpy(stpcpy(tags + tags_len, tag), ":");
+ tags_len = e - tags;
+ }
r = device_add_property_internal(device, "TAGS", tags);
if (r < 0)
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 3924300817..f56798674c 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -107,10 +107,7 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
m->hdr->nlmsg_type == RTM_GETNEIGH,
-EINVAL);
- if (dump)
- m->hdr->nlmsg_flags |= NLM_F_DUMP;
- else
- m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
+ SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
return 0;
}
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
index 480f1ad065..b7aec1f20a 100644
--- a/src/libsystemd/sd-path/sd-path.c
+++ b/src/libsystemd/sd-path/sd-path.c
@@ -89,7 +89,8 @@ static int from_home_dir(const char *envname, const char *suffix, char **buffer,
static int from_user_dir(const char *field, char **buffer, const char **ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *b = NULL;
- const char *fn = NULL;
+ _cleanup_free_ const char *fn = NULL;
+ const char *c = NULL;
char line[LINE_MAX];
size_t n;
int r;
@@ -98,10 +99,14 @@ static int from_user_dir(const char *field, char **buffer, const char **ret) {
assert(buffer);
assert(ret);
- r = from_home_dir(NULL, ".config/user-dirs.dirs", &b, &fn);
+ r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c);
if (r < 0)
return r;
+ fn = strappend(c, "/user-dirs.dirs");
+ if (!fn)
+ return -ENOMEM;
+
f = fopen(fn, "re");
if (!f) {
if (errno == ENOENT)
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index eb58740d26..3f6d0ed16c 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -21,6 +21,7 @@
#define _LIBUDEV_H_
#include <stdarg.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#ifdef __cplusplus
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index cde33bdf41..4865335349 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -116,11 +116,11 @@ static void print_overridden_variables(void) {
if (variables[j]) {
if (print_warning) {
log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
- " Command Line: %s=%s", locale_variable_to_string(j), variables[j]);
+ " Command Line: %s=%s", locale_variable_to_string(j), variables[j]);
print_warning = false;
} else
- log_warning(" %s=%s", locale_variable_to_string(j), variables[j]);
+ log_warning(" %s=%s", locale_variable_to_string(j), variables[j]);
}
finish:
for (j = 0; j < _VARIABLE_LC_MAX; j++)
@@ -131,7 +131,7 @@ static void print_status_info(StatusInfo *i) {
assert(i);
if (strv_isempty(i->locale))
- puts(" System Locale: n/a\n");
+ puts(" System Locale: n/a");
else {
char **j;
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules
index 694df2cfc8..886c5bfcdf 100644
--- a/src/login/70-uaccess.rules
+++ b/src/login/70-uaccess.rules
@@ -42,8 +42,9 @@ SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
-# DRI video devices
+# DRI and frame buffer video devices
SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess"
+SUBSYSTEM=="graphics", KERNEL=="fb*", TAG+="uaccess"
# KVM
SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
@@ -75,4 +76,7 @@ SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
# software-defined radio communication devices
ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
+# 3D printers, CNC machines, laser cutters, 3D scanners, etc.
+ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess"
+
LABEL="uaccess_end"
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index c9a5cd796b..01f6fa5db0 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -48,6 +48,7 @@
static char **arg_property = NULL;
static bool arg_all = false;
+static bool arg_value = false;
static bool arg_full = false;
static bool arg_no_pager = false;
static bool arg_legend = true;
@@ -679,6 +680,14 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
return 0;
}
+#define property(name, fmt, ...) \
+ do { \
+ if (arg_value) \
+ printf(fmt "\n", __VA_ARGS__); \
+ else \
+ printf("%s=" fmt "\n", name, __VA_ARGS__); \
+ } while(0)
+
static int print_property(const char *name, sd_bus_message *m, const char *contents) {
int r;
@@ -702,7 +711,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
if (arg_all || !isempty(s))
- printf("%s=%s\n", name, s);
+ property(name, "%s", s);
return 0;
@@ -718,8 +727,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return -EINVAL;
}
- printf("%s=" UID_FMT "\n", name, uid);
-
+ property(name, UID_FMT, uid);
return 0;
}
@@ -735,14 +743,16 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- printf("%s=", name);
+ if (!arg_value)
+ printf("%s=", name);
while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
printf("%s%s", space ? " " : "", s);
space = true;
}
- printf("\n");
+ if (space || !arg_value)
+ printf("\n");
if (r < 0)
return bus_log_parse_error(r);
@@ -757,7 +767,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
break;
}
- r = bus_print_property(name, m, arg_all);
+ r = bus_print_property(name, m, arg_value, arg_all);
if (r < 0)
return bus_log_parse_error(r);
@@ -1330,6 +1340,7 @@ static int help(int argc, char *argv[], void *userdata) {
" -M --machine=CONTAINER Operate on local container\n"
" -p --property=NAME Show only properties by this name\n"
" -a --all Show all properties, including empty ones\n"
+ " --value When showing properties, only print the value\n"
" -l --full Do not ellipsize output\n"
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
@@ -1371,6 +1382,7 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
+ ARG_VALUE,
ARG_NO_PAGER,
ARG_NO_LEGEND,
ARG_KILL_WHO,
@@ -1382,6 +1394,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "property", required_argument, NULL, 'p' },
{ "all", no_argument, NULL, 'a' },
+ { "value", no_argument, NULL, ARG_VALUE },
{ "full", no_argument, NULL, 'l' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
@@ -1427,6 +1440,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_all = true;
break;
+ case ARG_VALUE:
+ arg_value = true;
+ break;
+
case 'l':
arg_full = true;
break;
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
index 11a91c3947..29ab00eb1f 100644
--- a/src/login/logind-utmp.c
+++ b/src/login/logind-utmp.c
@@ -65,7 +65,7 @@ bool logind_wall_tty_filter(const char *tty, void *userdata) {
assert(m);
- if (!startswith(tty, "/dev/"))
+ if (!startswith(tty, "/dev/") || !m->scheduled_shutdown_tty)
return true;
return !streq(tty + 5, m->scheduled_shutdown_tty);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index e49c90fd1b..1d3264a1de 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -61,6 +61,7 @@
static char **arg_property = NULL;
static bool arg_all = false;
+static bool arg_value = false;
static bool arg_full = false;
static bool arg_no_pager = false;
static bool arg_legend = true;
@@ -129,15 +130,14 @@ static int list_machines(int argc, char *argv[], void *userdata) {
pager_open(arg_no_pager, false);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.machine1",
- "/org/freedesktop/machine1",
- "org.freedesktop.machine1.Manager",
- "ListMachines",
- &error,
- &reply,
- NULL);
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "ListMachines",
+ &error,
+ &reply,
+ NULL);
if (r < 0) {
log_error("Could not get machines: %s", bus_error_message(&error, -r));
return r;
@@ -232,15 +232,14 @@ static int list_images(int argc, char *argv[], void *userdata) {
pager_open(arg_no_pager, false);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.machine1",
- "/org/freedesktop/machine1",
- "org.freedesktop.machine1.Manager",
- "ListImages",
- &error,
- &reply,
- "");
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "ListImages",
+ &error,
+ &reply,
+ "");
if (r < 0) {
log_error("Could not get images: %s", bus_error_message(&error, -r));
return r;
@@ -680,7 +679,7 @@ static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line
*new_line = true;
- r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
+ r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
@@ -713,15 +712,14 @@ static int show_machine(int argc, char *argv[], void *userdata) {
for (i = 1; i < argc; i++) {
const char *path = NULL;
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.machine1",
- "/org/freedesktop/machine1",
- "org.freedesktop.machine1.Manager",
- "GetMachine",
- &error,
- &reply,
- "s", argv[i]);
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "GetMachine",
+ &error,
+ &reply,
+ "s", argv[i]);
if (r < 0) {
log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
return r;
@@ -929,7 +927,7 @@ static int show_image_properties(sd_bus *bus, const char *path, bool *new_line)
*new_line = true;
- r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
+ r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
@@ -2183,15 +2181,14 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
pager_open(arg_no_pager, false);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.import1",
- "/org/freedesktop/import1",
- "org.freedesktop.import1.Manager",
- "ListTransfers",
- &error,
- &reply,
- NULL);
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.import1",
+ "/org/freedesktop/import1",
+ "org.freedesktop.import1.Manager",
+ "ListTransfers",
+ &error,
+ &reply,
+ NULL);
if (r < 0) {
log_error("Could not get transfers: %s", bus_error_message(&error, -r));
return r;
@@ -2356,6 +2353,7 @@ static int help(int argc, char *argv[], void *userdata) {
" -p --property=NAME Show only properties by this name\n"
" -q --quiet Suppress output\n"
" -a --all Show all properties, including empty ones\n"
+ " --value When showing properties, only print the value\n"
" -l --full Do not ellipsize output\n"
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
@@ -2418,6 +2416,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_NO_LEGEND,
+ ARG_VALUE,
ARG_KILL_WHO,
ARG_READ_ONLY,
ARG_MKDIR,
@@ -2434,6 +2433,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "property", required_argument, NULL, 'p' },
{ "all", no_argument, NULL, 'a' },
+ { "value", no_argument, NULL, ARG_VALUE },
{ "full", no_argument, NULL, 'l' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
@@ -2485,6 +2485,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_all = true;
break;
+ case ARG_VALUE:
+ arg_value = true;
+ break;
+
case 'l':
arg_full = true;
break;
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 0679114f74..b22a0f648a 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -33,7 +33,6 @@
#include "ether-addr-util.h"
#include "fd-util.h"
#include "hwdb-util.h"
-#include "lldp.h"
#include "local-addresses.h"
#include "locale-util.h"
#include "netlink-util.h"
@@ -45,6 +44,7 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "strxcpyx.h"
#include "terminal-util.h"
#include "util.h"
#include "verbs.h"
@@ -147,7 +147,6 @@ static int link_info_compare(const void *a, const void *b) {
}
static int decode_link(sd_netlink_message *m, LinkInfo *info) {
- static const struct ether_addr null_address = {};
const char *name;
uint16_t type;
int r;
@@ -174,11 +173,11 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
if (r < 0)
return r;
- strncpy(info->name, name, sizeof(info->name));
+ strscpy(info->name, sizeof info->name, name);
info->has_mac_address =
sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 &&
- memcmp(&info->mac_address, &null_address, sizeof(struct ether_addr)) != 0;
+ memcmp(&info->mac_address, &ETHER_ADDR_NULL, sizeof(struct ether_addr)) != 0;
info->has_mtu =
sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) &&
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
new file mode 100644
index 0000000000..8b149124b3
--- /dev/null
+++ b/src/network/networkd-conf.c
@@ -0,0 +1,155 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
+
+ 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 <ctype.h>
+
+#include "conf-parser.h"
+#include "def.h"
+#include "dhcp-identifier.h"
+#include "networkd-conf.h"
+#include "string-table.h"
+
+int manager_parse_config_file(Manager *m) {
+ assert(m);
+
+ return config_parse_many(PKGSYSCONFDIR "/networkd.conf",
+ CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
+ "DUID\0",
+ config_item_perf_lookup, networkd_gperf_lookup,
+ false, m);
+}
+
+static const char* const duid_type_table[_DUID_TYPE_MAX] = {
+ [DUID_TYPE_RAW] = "raw",
+ [DUID_TYPE_LLT] = "link-layer-time",
+ [DUID_TYPE_EN] = "vendor",
+ [DUID_TYPE_LL] = "link-layer",
+ [DUID_TYPE_UUID] = "uuid"
+};
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type");
+
+int config_parse_duid_rawdata(
+ 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;
+ long byte;
+ char *cbyte, *pnext;
+ const char *pduid = rvalue;
+ size_t count = 0, duid_index = 0;
+ Manager *m;
+ Network *n;
+ DUIDType *duid_type;
+ uint16_t *dhcp_duid_type;
+ size_t *dhcp_duid_len;
+ uint8_t *dhcp_duid;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(userdata);
+
+ if (ltype == DUID_CONFIG_SOURCE_GLOBAL) {
+ m = userdata;
+ duid_type = &m->duid_type;
+ dhcp_duid_type = &m->dhcp_duid_type;
+ dhcp_duid_len = &m->dhcp_duid_len;
+ dhcp_duid = m->dhcp_duid;
+ } else {
+ /* DUID_CONFIG_SOURCE_NETWORK */
+ n = userdata;
+ duid_type = &n->duid_type;
+ dhcp_duid_type = &n->dhcp_duid_type;
+ dhcp_duid_len = &n->dhcp_duid_len;
+ dhcp_duid = n->dhcp_duid;
+ }
+
+ if (*duid_type == _DUID_TYPE_INVALID)
+ *duid_type = DUID_TYPE_RAW;
+
+ switch (*duid_type) {
+ case DUID_TYPE_LLT:
+ /* RawData contains DUID-LLT link-layer address (offset 6) */
+ duid_index = 6;
+ break;
+ case DUID_TYPE_EN:
+ /* RawData contains DUID-EN identifier (offset 4) */
+ duid_index = 4;
+ break;
+ case DUID_TYPE_LL:
+ /* RawData contains DUID-LL link-layer address (offset 2) */
+ duid_index = 2;
+ break;
+ case DUID_TYPE_UUID:
+ /* RawData specifies UUID (offset 0) - fall thru */
+ case DUID_TYPE_RAW:
+ /* First two bytes of RawData is DUID Type - fall thru */
+ default:
+ break;
+ }
+
+ if (*duid_type != DUID_TYPE_RAW)
+ *dhcp_duid_type = (uint16_t)(*duid_type);
+
+ /* RawData contains DUID in format " NN:NN:NN... " */
+ while (true) {
+ r = extract_first_word(&pduid, &cbyte, ":", 0);
+ if (r < 0) {
+ log_error("Failed to read DUID.");
+ return -EINVAL;
+ }
+ if (r == 0)
+ break;
+ if (duid_index >= MAX_DUID_LEN) {
+ log_error("DUID length exceeds maximum length.");
+ return -EINVAL;
+ }
+
+ errno = 0;
+ byte = strtol(cbyte, &pnext, 16);
+ if ((errno == ERANGE && (byte == LONG_MAX || byte == LONG_MIN))
+ || (errno != 0 && byte == 0) || (cbyte == pnext)) {
+ log_error("Invalid DUID byte: %s.", cbyte);
+ return -EINVAL;
+ }
+
+ /* If DUID_TYPE_RAW, first two bytes hold DHCP DUID type code */
+ if ((*duid_type == DUID_TYPE_RAW) && (count < 2)) {
+ *dhcp_duid_type |= (byte << (8 * (1 - count)));
+ count++;
+ continue;
+ }
+
+ dhcp_duid[duid_index++] = byte;
+ }
+
+ *dhcp_duid_len = duid_index;
+
+ return 0;
+}
diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h
new file mode 100644
index 0000000000..efc370f839
--- /dev/null
+++ b/src/network/networkd-conf.h
@@ -0,0 +1,36 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
+
+ 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 "networkd.h"
+
+typedef enum DuidConfigSource {
+ DUID_CONFIG_SOURCE_GLOBAL = 0,
+ DUID_CONFIG_SOURCE_NETWORK,
+} DuidConfigSource;
+
+int manager_parse_config_file(Manager *m);
+
+const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length);
+
+int config_parse_duid_type(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_duid_rawdata(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/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 68998eabf2..0589ebf227 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -625,7 +625,21 @@ int dhcp4_configure(Link *link) {
switch (link->network->dhcp_client_identifier) {
case DHCP_CLIENT_ID_DUID:
- /* Library defaults to this. */
+ /* If configured, apply user specified DUID and/or IAID */
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ return r;
break;
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 5f7a005c36..d4b2fbfc57 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -230,6 +230,23 @@ int dhcp6_configure(Link *link) {
if (r < 0)
goto error;
+ r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
+ if (r < 0)
+ goto error;
+
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp6_client_set_duid(client,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp6_client_set_duid(client,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ goto error;
+
r = sd_dhcp6_client_set_index(client, link->ifindex);
if (r < 0)
goto error;
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
new file mode 100644
index 0000000000..0625fb335b
--- /dev/null
+++ b/src/network/networkd-gperf.gperf
@@ -0,0 +1,18 @@
+%{
+#include <stddef.h>
+#include "conf-parser.h"
+#include "networkd-conf.h"
+%}
+struct ConfigPerfItem;
+%null_strings
+%language=ANSI-C
+%define slot-name section_and_lvalue
+%define hash-function-name networkd_gperf_hash
+%define lookup-function-name networkd_gperf_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+DUID.Type, config_parse_duid_type, 0, offsetof(Manager, duid_type)
+DUID.RawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_GLOBAL, offsetof(Manager, dhcp_duid)
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index ff4bd76554..88b3cbe90a 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -26,7 +26,6 @@
#include "dhcp-lease-internal.h"
#include "fd-util.h"
#include "fileio.h"
-#include "lldp.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-link.h"
@@ -2234,8 +2233,8 @@ static int link_configure(Link *link) {
r = sd_lldp_match_capabilities(link->lldp,
link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
- _LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
- _LLDP_SYSTEM_CAPABILITIES_ALL);
+ SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
+ SD_LLDP_SYSTEM_CAPABILITIES_ALL);
if (r < 0)
return r;
@@ -2781,6 +2780,21 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
+
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
}
if (link->dhcp6_client) {
@@ -2790,6 +2804,24 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
+
+ r = sd_dhcp6_client_set_iaid(link->dhcp6_client,
+ link->network->iaid);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
+
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp6_client_set_duid(link->dhcp6_client,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp6_client_set_duid(link->dhcp6_client,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
}
}
}
diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c
index ae8367a60e..5af2a31ea7 100644
--- a/src/network/networkd-lldp-tx.c
+++ b/src/network/networkd-lldp-tx.c
@@ -24,7 +24,6 @@
#include "fd-util.h"
#include "fileio.h"
#include "hostname-util.h"
-#include "lldp.h"
#include "networkd-lldp-tx.h"
#include "random-util.h"
#include "socket-util.h"
@@ -128,51 +127,51 @@ static int lldp_make_packet(
h = (struct ether_header*) packet;
h->ether_type = htobe16(ETHERTYPE_LLDP);
- memcpy(h->ether_dhost, &(struct ether_addr) { LLDP_MULTICAST_ADDR }, ETH_ALEN);
+ memcpy(h->ether_dhost, &(struct ether_addr) { SD_LLDP_MULTICAST_ADDR }, ETH_ALEN);
memcpy(h->ether_shost, hwaddr, ETH_ALEN);
p = (uint8_t*) packet + sizeof(struct ether_header);
- r = lldp_write_tlv_header(&p, LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length);
if (r < 0)
return r;
- *(p++) = LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED;
+ *(p++) = SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED;
p = mempcpy(p, machine_id, machine_id_length);
- r = lldp_write_tlv_header(&p, LLDP_TYPE_PORT_ID, 1 + ifname_length);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_ID, 1 + ifname_length);
if (r < 0)
return r;
- *(p++) = LLDP_PORT_SUBTYPE_INTERFACE_NAME;
+ *(p++) = SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME;
p = mempcpy(p, ifname, ifname_length);
- r = lldp_write_tlv_header(&p, LLDP_TYPE_TTL, 2);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_TTL, 2);
if (r < 0)
return r;
unaligned_write_be16(p, ttl);
p += 2;
if (port_description) {
- r = lldp_write_tlv_header(&p, LLDP_TYPE_PORT_DESCRIPTION, port_description_length);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_DESCRIPTION, port_description_length);
if (r < 0)
return r;
p = mempcpy(p, port_description, port_description_length);
}
if (hostname) {
- r = lldp_write_tlv_header(&p, LLDP_TYPE_SYSTEM_NAME, hostname_length);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_NAME, hostname_length);
if (r < 0)
return r;
p = mempcpy(p, hostname, hostname_length);
}
if (pretty_hostname) {
- r = lldp_write_tlv_header(&p, LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length);
if (r < 0)
return r;
p = mempcpy(p, pretty_hostname, pretty_hostname_length);
}
- r = lldp_write_tlv_header(&p, LLDP_TYPE_SYSTEM_CAPABILITIES, 4);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4);
if (r < 0)
return r;
unaligned_write_be16(p, system_capabilities);
@@ -180,7 +179,7 @@ static int lldp_make_packet(
unaligned_write_be16(p, enabled_capabilities);
p += 2;
- r = lldp_write_tlv_header(&p, LLDP_TYPE_END, 0);
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_END, 0);
if (r < 0)
return r;
@@ -200,7 +199,7 @@ static int lldp_send_packet(int ifindex, const void *packet, size_t packet_size)
.ll.sll_protocol = htobe16(ETHERTYPE_LLDP),
.ll.sll_ifindex = ifindex,
.ll.sll_halen = ETH_ALEN,
- .ll.sll_addr = LLDP_MULTICAST_ADDR,
+ .ll.sll_addr = SD_LLDP_MULTICAST_ADDR,
};
_cleanup_close_ int fd = -1;
@@ -245,8 +244,8 @@ static int link_send_lldp(Link *link) {
ttl = (usec_t) UINT16_MAX;
caps = (link->network && link->network->ip_forward != ADDRESS_FAMILY_NO) ?
- LLDP_SYSTEM_CAPABILITIES_ROUTER :
- LLDP_SYSTEM_CAPABILITIES_STATION;
+ SD_LLDP_SYSTEM_CAPABILITIES_ROUTER :
+ SD_LLDP_SYSTEM_CAPABILITIES_STATION;
r = lldp_make_packet(&link->mac,
sd_id128_to_string(machine_id, machine_id_string),
@@ -255,7 +254,7 @@ static int link_send_lldp(Link *link) {
link->network ? link->network->description : NULL,
hostname,
pretty_hostname,
- LLDP_SYSTEM_CAPABILITIES_STATION|LLDP_SYSTEM_CAPABILITIES_BRIDGE|LLDP_SYSTEM_CAPABILITIES_ROUTER,
+ SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
caps,
&packet, &packet_size);
if (r < 0)
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index b8cb7f875d..d355aaa19c 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1037,6 +1037,8 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
+ m->duid_type = _DUID_TYPE_INVALID;
+
*ret = m;
m = NULL;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index a5d1714293..9793938080 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -2,6 +2,7 @@
#include <stddef.h>
#include "conf-parser.h"
#include "networkd.h"
+#include "networkd-conf.h"
#include "network-internal.h"
%}
struct ConfigPerfItem;
@@ -26,6 +27,9 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
+Link.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
+DUID.Type, config_parse_duid_type, 0, offsetof(Network, duid_type)
+DUID.RawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_NETWORK, offsetof(Network, dhcp_duid)
Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index f175788977..5946ba18dc 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -131,10 +131,12 @@ static int network_load_one(Manager *manager, const char *filename) {
network->ipv6_accept_ra = -1;
network->ipv6_dad_transmits = -1;
network->ipv6_hop_limit = -1;
+ network->duid_type = _DUID_TYPE_INVALID;
r = config_parse(NULL, filename, file,
"Match\0"
"Link\0"
+ "DUID\0"
"Network\0"
"Address\0"
"Route\0"
@@ -629,10 +631,7 @@ int config_parse_ipv4ll(
* config_parse_address_family_boolean(), except that it
* applies only to IPv4 */
- if (parse_boolean(rvalue))
- *link_local |= ADDRESS_FAMILY_IPV4;
- else
- *link_local &= ~ADDRESS_FAMILY_IPV4;
+ SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
return 0;
}
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 4a13e2b574..5400a8bc9d 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -24,6 +24,7 @@
typedef struct Network Network;
+#include "dhcp-identifier.h"
#include "networkd-address.h"
#include "networkd-fdb.h"
#include "networkd-netdev.h"
@@ -144,6 +145,13 @@ struct Network {
struct ether_addr *mac;
unsigned mtu;
+ uint32_t iaid;
+ /* Value of Type in [DUID] section */
+ DUIDType duid_type;
+ /* DUID type code - RFC 3315 */
+ uint16_t dhcp_duid_type;
+ size_t dhcp_duid_len;
+ uint8_t dhcp_duid[MAX_DUID_LEN];
LLDPMode lldp_mode; /* LLDP reception */
bool lldp_emit; /* LLDP transmission */
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 3a2615e6fd..c8f81a2ca6 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -21,6 +21,7 @@
#include "capability-util.h"
#include "networkd.h"
+#include "networkd-conf.h"
#include "signal-util.h"
#include "user-util.h"
@@ -89,6 +90,10 @@ int main(int argc, char *argv[]) {
goto out;
}
+ r = manager_parse_config_file(m);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse configuration file: %m");
+
r = manager_load_config(m);
if (r < 0) {
log_error_errno(r, "Could not load configuration files: %m");
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 6bdd8302a0..72a2438ac8 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -31,6 +31,7 @@
typedef struct Manager Manager;
+#include "dhcp-identifier.h"
#include "networkd-address-pool.h"
#include "networkd-link.h"
#include "networkd-network.h"
@@ -61,6 +62,13 @@ struct Manager {
LIST_HEAD(AddressPool, address_pools);
usec_t network_dirs_ts_usec;
+
+ /* Value of Type in [DUID] section */
+ DUIDType duid_type;
+ /* DUID type code - RFC 3315 */
+ uint16_t dhcp_duid_type;
+ size_t dhcp_duid_len;
+ uint8_t dhcp_duid[MAX_DUID_LEN];
};
extern const char* const network_dirs[];
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index 1db5ba7116..f50f1ad6c2 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -55,8 +55,7 @@ int chown_cgroup(pid_t pid, uid_t uid_shift) {
"cgroup.events",
"cgroup.clone_children",
"cgroup.controllers",
- "cgroup.subtree_control",
- "cgroup.populated")
+ "cgroup.subtree_control")
if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0)
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
"Failed to chown() cgroup file %s, ignoring: %m", fn);
@@ -73,7 +72,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) {
unified = cg_unified();
if (unified < 0)
- return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m");
+ return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
if ((unified > 0) == unified_requested)
return 0;
@@ -94,7 +93,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) {
if (unified)
r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr");
else
- r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "__DEVEL__sane_behavior");
+ r = mount("cgroup", tree, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
if (r < 0) {
r = log_error_errno(errno, "Failed to mount unified hierarchy: %m");
goto finish;
@@ -135,7 +134,7 @@ int create_subcgroup(pid_t pid, bool unified_requested) {
unified = cg_unified();
if (unified < 0)
- return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m");
+ return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
if (unified == 0)
return 0;
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 70cca15278..8e2d2d543c 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -438,21 +438,22 @@ static int mount_bind(const char *dest, CustomMount *m) {
r = mkdir_parents_label(where, 0755);
if (r < 0)
return log_error_errno(r, "Failed to make parents of %s: %m", where);
+
+ /* Create the mount point. Any non-directory file can be
+ * mounted on any non-directory file (regular, fifo, socket,
+ * char, block).
+ */
+ if (S_ISDIR(source_st.st_mode))
+ r = mkdir_label(where, 0755);
+ else
+ r = touch(where);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create mount point %s: %m", where);
+
} else {
return log_error_errno(errno, "Failed to stat %s: %m", where);
}
- /* Create the mount point. Any non-directory file can be
- * mounted on any non-directory file (regular, fifo, socket,
- * char, block).
- */
- if (S_ISDIR(source_st.st_mode))
- r = mkdir_label(where, 0755);
- else
- r = touch(where);
- if (r < 0 && r != -EEXIST)
- return log_error_errno(r, "Failed to create mount point %s: %m", where);
-
if (mount(m->source, where, NULL, mount_flags, mount_opts) < 0)
return log_error_errno(errno, "mount(%s) failed: %m", where);
@@ -750,7 +751,7 @@ static int mount_unified_cgroups(const char *dest) {
return -EINVAL;
}
- if (mount("cgroup", p, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "__DEVEL__sane_behavior") < 0)
+ if (mount("cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0)
return log_error_errno(errno, "Failed to mount unified cgroup hierarchy to %s: %m", p);
return 0;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 4851c439c9..eb89916b7e 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -87,6 +87,7 @@
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stat-util.h"
@@ -976,6 +977,13 @@ static int verify_arguments(void) {
return -EINVAL;
}
+#ifndef HAVE_LIBIPTC
+ if (arg_expose_ports) {
+ log_error("--port= is not supported, compiled without libiptc support.");
+ return -EOPNOTSUPP;
+ }
+#endif
+
if (arg_start_mode == START_BOOT && arg_kill_signal <= 0)
arg_kill_signal = SIGRTMIN+3;
@@ -3284,6 +3292,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ if (arg_selinux_apifs_context) {
+ r = mac_selinux_apply(console, arg_selinux_apifs_context);
+ if (r < 0)
+ goto finish;
+ }
+
if (unlockpt(master) < 0) {
r = log_error_errno(errno, "Failed to unlock tty: %m");
goto finish;
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index 484fbb4d92..14ee01c49d 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <gcrypt.h>
#include <getopt.h>
#include <net/if.h>
@@ -863,7 +862,7 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
}
domain++;
- r = string_hashsum(address, domain - 1 - address, GCRY_MD_SHA224, &hashed);
+ r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
if (r < 0)
return log_error_errno(r, "Hashing failed: %m");
@@ -1280,40 +1279,28 @@ static int parse_argv(int argc, char *argv[]) {
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --cname= argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_CNAME;
- else
- arg_flags &= ~SD_RESOLVED_NO_CNAME;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
break;
case ARG_SERVICE_ADDRESS:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --service-address= argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_ADDRESS;
- else
- arg_flags &= ~SD_RESOLVED_NO_ADDRESS;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
break;
case ARG_SERVICE_TXT:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --service-txt= argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_TXT;
- else
- arg_flags &= ~SD_RESOLVED_NO_TXT;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
break;
case ARG_SEARCH:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --search argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_SEARCH;
- else
- arg_flags &= ~SD_RESOLVED_NO_SEARCH;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
break;
case ARG_STATISTICS:
diff --git a/src/run/run.c b/src/run/run.c
index e7f4c21f73..f92a7f4e2e 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -83,8 +83,8 @@ static void polkit_agent_open_if_enabled(void) {
static void help(void) {
printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
"Run the specified command in a transient scope or service or timer\n"
- "unit. If timer option is specified and unit is exist which is\n"
- "specified with --unit option then command can be omitted.\n\n"
+ "unit. If a timer option is specified and the unit specified with\n"
+ "the --unit option exists, the command can be omitted.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-ask-password Do not prompt for password\n"
@@ -878,7 +878,7 @@ static int start_transient_service(
(void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
if (!arg_quiet)
- log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
+ log_info("Running as unit: %s\nPress ^] three times within 1s to disconnect TTY.", service);
r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward);
if (r < 0)
@@ -896,7 +896,7 @@ static int start_transient_service(
fputc('\n', stdout);
} else if (!arg_quiet)
- log_info("Running as unit %s.", service);
+ log_info("Running as unit: %s", service);
return 0;
}
@@ -1038,7 +1038,7 @@ static int start_transient_scope(
return r;
if (!arg_quiet)
- log_info("Running scope as unit %s.", scope);
+ log_info("Running scope as unit: %s", scope);
execvpe(argv[0], argv, env);
@@ -1189,9 +1189,9 @@ static int start_transient_timer(
if (r < 0)
return r;
- log_info("Running timer as unit %s.", timer);
+ log_info("Running timer as unit: %s", timer);
if (argv[0])
- log_info("Will run service as unit %s.", service);
+ log_info("Will run service as unit: %s", service);
return 0;
}
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index 3cb9e781fd..6779691c28 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -119,7 +119,7 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
}
if (ptr == 0)
- return -EINVAL;
+ return -ENODATA;
/* read Firmware Basic Boot Performance Data Record */
fd = open("/dev/mem", O_CLOEXEC|O_RDONLY);
@@ -146,6 +146,10 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
if (brec.type != ACPI_FPDT_BOOT_REC)
return -EINVAL;
+ if (brec.exit_services_exit == 0)
+ /* Non-UEFI compatible boot. */
+ return -ENODATA;
+
if (brec.startup_start == 0 || brec.exit_services_exit < brec.startup_start)
return -EINVAL;
if (brec.exit_services_exit > NSEC_PER_HOUR)
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index b102a79da8..0caaca03c7 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -712,7 +712,15 @@ int bus_connect_user_systemd(sd_bus **_bus) {
return 0;
}
-int bus_print_property(const char *name, sd_bus_message *property, bool all) {
+#define print_property(name, fmt, ...) \
+ do { \
+ if (value) \
+ printf(fmt "\n", __VA_ARGS__); \
+ else \
+ printf("%s=" fmt "\n", name, __VA_ARGS__); \
+ } while(0)
+
+int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) {
char type;
const char *contents;
int r;
@@ -740,7 +748,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (!escaped)
return -ENOMEM;
- printf("%s=%s\n", name, escaped);
+ print_property(name, "%s", escaped);
}
return 1;
@@ -753,7 +761,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (r < 0)
return r;
- printf("%s=%s\n", name, yes_no(b));
+ print_property(name, "%s", yes_no(b));
return 1;
}
@@ -773,14 +781,14 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
t = format_timestamp(timestamp, sizeof(timestamp), u);
if (t || all)
- printf("%s=%s\n", name, strempty(t));
+ print_property(name, "%s", strempty(t));
} else if (strstr(name, "USec")) {
char timespan[FORMAT_TIMESPAN_MAX];
- printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
+ print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
} else
- printf("%s=%llu\n", name, (unsigned long long) u);
+ print_property(name, "%"PRIu64, u);
return 1;
}
@@ -792,7 +800,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (r < 0)
return r;
- printf("%s=%lld\n", name, (long long) i);
+ print_property(name, "%"PRIi64, i);
return 1;
}
@@ -805,9 +813,9 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
return r;
if (strstr(name, "UMask") || strstr(name, "Mode"))
- printf("%s=%04o\n", name, u);
+ print_property(name, "%04o", u);
else
- printf("%s=%u\n", name, (unsigned) u);
+ print_property(name, "%"PRIu32, u);
return 1;
}
@@ -819,7 +827,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (r < 0)
return r;
- printf("%s=%i\n", name, (int) i);
+ print_property(name, "%"PRIi32, i);
return 1;
}
@@ -830,7 +838,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (r < 0)
return r;
- printf("%s=%g\n", name, d);
+ print_property(name, "%g", d);
return 1;
}
@@ -846,7 +854,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
_cleanup_free_ char *escaped = NULL;
- if (first)
+ if (first && !value)
printf("%s=", name);
escaped = xescape(str, "\n ");
@@ -860,7 +868,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (r < 0)
return r;
- if (first && all)
+ if (first && all && !value)
printf("%s=", name);
if (!first || all)
puts("");
@@ -882,7 +890,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (all || n > 0) {
unsigned int i;
- printf("%s=", name);
+ if (!value)
+ printf("%s=", name);
for (i = 0; i < n; i++)
printf("%02x", u[i]);
@@ -903,7 +912,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (all || n > 0) {
unsigned int i;
- printf("%s=", name);
+ if (!value)
+ printf("%s=", name);
for (i = 0; i < n; i++)
printf("%08x", u[i]);
@@ -920,7 +930,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
return 0;
}
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
@@ -960,7 +970,7 @@ int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, ch
if (r < 0)
return r;
- r = bus_print_property(name, reply, all);
+ r = bus_print_property(name, reply, value, all);
if (r < 0)
return r;
if (r == 0) {
@@ -1068,7 +1078,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
}
case SD_BUS_TYPE_UINT32: {
- uint64_t u;
+ uint32_t u;
uint32_t *p = userdata;
r = sd_bus_message_read_basic(m, type, &u);
@@ -2030,7 +2040,7 @@ static const struct {
static void log_job_error_with_service_result(const char* service, const char *result, const char* const* extra_args) {
_cleanup_free_ char *service_shell_quoted = NULL;
- const char *systemctl = "systemctl", *journalctl = "journalct";
+ const char *systemctl = "systemctl", *journalctl = "journalctl";
assert(service);
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index fcda1b2c6c..1a0841ce81 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -78,8 +78,8 @@ int bus_connect_user_systemd(sd_bus **_bus);
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
-int bus_print_property(const char *name, sd_bus_message *property, bool all);
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all);
+int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all);
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index e7fe9ac21e..bd0a1f483b 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -294,7 +294,7 @@ int config_parse(const char *unit,
_cleanup_free_ char *section = NULL, *continuation = NULL;
_cleanup_fclose_ FILE *ours = NULL;
unsigned line = 0, section_line = 0;
- bool section_ignored = false;
+ bool section_ignored = false, allow_bom = true;
int r;
assert(filename);
@@ -314,11 +314,11 @@ int config_parse(const char *unit,
fd_warn_permissions(filename, fileno(f));
- while (!feof(f)) {
- char l[LINE_MAX], *p, *c = NULL, *e;
+ for (;;) {
+ char buf[LINE_MAX], *l, *p, *c = NULL, *e;
bool escaped = false;
- if (!fgets(l, sizeof(l), f)) {
+ if (!fgets(buf, sizeof buf, f)) {
if (feof(f))
break;
@@ -326,6 +326,11 @@ int config_parse(const char *unit,
return -errno;
}
+ l = buf;
+ if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
+ l += strlen(UTF8_BYTE_ORDER_MARK);
+ allow_bom = false;
+
truncate_nl(l);
if (continuation) {
diff --git a/src/shared/gcrypt-util.c b/src/shared/gcrypt-util.c
index 4ff94520c3..39b544b6f0 100644
--- a/src/shared/gcrypt-util.c
+++ b/src/shared/gcrypt-util.c
@@ -19,10 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#ifdef HAVE_GCRYPT
#include <gcrypt.h>
-#include "hexdecoct.h"
#include "gcrypt-util.h"
+#include "hexdecoct.h"
void initialize_libgcrypt(bool secmem) {
const char *p;
@@ -67,3 +68,4 @@ int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) {
*out = enc;
return 0;
}
+#endif
diff --git a/src/shared/gcrypt-util.h b/src/shared/gcrypt-util.h
index c7652c22d1..cf33b3c59c 100644
--- a/src/shared/gcrypt-util.h
+++ b/src/shared/gcrypt-util.h
@@ -19,7 +19,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
void initialize_libgcrypt(bool secmem);
int string_hashsum(const char *s, size_t len, int md_algorithm, char **out);
+#endif
+
+static inline int string_hashsum_sha224(const char *s, size_t len, char **out) {
+#ifdef HAVE_GCRYPT
+ return string_hashsum(s, len, GCRY_MD_SHA224, out);
+#else
+ return -EOPNOTSUPP;
+#endif
+}
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index f080b849a4..23890c63a0 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -139,7 +139,7 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
execlp("mkfs.btrfs", "-Lvar-lib-machines", tmp, NULL);
if (errno == ENOENT)
- return 99;
+ _exit(99);
_exit(EXIT_FAILURE);
}
@@ -239,10 +239,8 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) {
}
r = mkfs_exists("btrfs");
- if (r == -ENOENT) {
- log_debug("mkfs.btrfs is missing, cannot create loopback file for /var/lib/machines.");
- return 0;
- }
+ if (r == 0)
+ return sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing");
if (r < 0)
return r;
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 061d31f4de..02c03b98d8 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -461,10 +461,7 @@ int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) {
if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b)
return 0;
- if (b)
- f->flags |= PTY_FORWARD_IGNORE_VHANGUP;
- else
- f->flags &= ~PTY_FORWARD_IGNORE_VHANGUP;
+ SET_FLAG(f->flags, PTY_FORWARD_IGNORE_VHANGUP, b);
if (!ignore_vhangup(f)) {
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index cf3c8ad5a3..7dae4d14fe 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -44,6 +44,10 @@ int polkit_agent_open(void) {
if (agent_pid > 0)
return 0;
+ /* Clients that run as root don't need to activate/query polkit */
+ if (geteuid() == 0)
+ return 0;
+
/* We check STDIN here, not STDOUT, since this is about input,
* not output */
if (!isatty(STDIN_FILENO))
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 11e26ce737..62cff3a677 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -103,6 +103,7 @@ static bool arg_no_pager = false;
static bool arg_no_wtmp = false;
static bool arg_no_wall = false;
static bool arg_no_reload = false;
+static bool arg_value = false;
static bool arg_show_types = false;
static bool arg_ignore_inhibitors = false;
static bool arg_dry = false;
@@ -152,7 +153,7 @@ static bool arg_now = false;
static int daemon_reload(int argc, char *argv[], void* userdata);
static int halt_now(enum action a);
-static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
+static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
static bool original_stdout_is_tty;
@@ -340,6 +341,11 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) {
if (arg_all)
return true;
+ if (!strv_isempty(arg_states))
+ return true;
+
+ /* By default show all units except the ones in inactive
+ * state and with no pending job */
if (u->job_id > 0)
return true;
@@ -1630,11 +1636,27 @@ static int list_dependencies_one(
if (arg_plain)
printf(" ");
else {
- int state;
+ UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
const char *on;
- state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
- on = state > 0 ? ansi_highlight_green() : ansi_highlight_red();
+ (void) get_state_one_unit(bus, *c, &active_state);
+ switch (active_state) {
+ case UNIT_ACTIVE:
+ case UNIT_RELOADING:
+ case UNIT_ACTIVATING:
+ on = ansi_highlight_green();
+ break;
+
+ case UNIT_INACTIVE:
+ case UNIT_DEACTIVATING:
+ on = ansi_normal();
+ break;
+
+ default:
+ on = ansi_highlight_red();
+ break;
+ }
+
printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_normal());
}
@@ -1875,13 +1897,13 @@ static void output_machines_list(struct machine_info *machine_infos, unsigned n)
printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
if (m->is_host)
- printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
+ printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
(int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
on_state, statelen, strna(m->state), off_state,
on_failed, failedlen, m->n_failed_units, off_failed,
jobslen, m->n_jobs);
else
- printf("%-*s %s%-*s%s %s%*u%s %*u\n",
+ printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
namelen, strna(m->name),
on_state, statelen, strna(m->state), off_state,
on_failed, failedlen, m->n_failed_units, off_failed,
@@ -2399,18 +2421,19 @@ static int unit_find_paths(
return r;
}
-static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
+static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *buf = NULL;
- const char *path, *state;
+ UnitActiveState state;
+ const char *path;
int r;
assert(name);
+ assert(active_state);
/* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
* isn't loaded. */
-
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
@@ -2426,7 +2449,7 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
/* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
* considered inactive. */
- state = "inactive";
+ state = UNIT_INACTIVE;
} else {
r = sd_bus_message_read(reply, "o", &path);
@@ -2444,13 +2467,15 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
if (r < 0)
return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
- state = buf;
+ state = unit_active_state_from_string(buf);
+ if (state == _UNIT_ACTIVE_STATE_INVALID) {
+ log_error("Invalid unit state '%s' for: %s", buf, name);
+ return -EINVAL;
+ }
}
- if (!quiet)
- puts(state);
-
- return nulstr_contains(good_states, state);
+ *active_state = state;
+ return 0;
}
static int check_triggering_units(
@@ -2458,9 +2483,10 @@ static int check_triggering_units(
const char *name) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
+ _cleanup_free_ char *path = NULL, *n = NULL, *load_state = NULL;
_cleanup_strv_free_ char **triggered_by = NULL;
bool print_warning_label = true;
+ UnitActiveState active_state;
char **i;
int r;
@@ -2479,11 +2505,11 @@ static int check_triggering_units(
"org.freedesktop.systemd1.Unit",
"LoadState",
&error,
- &state);
+ &load_state);
if (r < 0)
return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r));
- if (streq(state, "masked"))
+ if (streq(load_state, "masked"))
return 0;
r = sd_bus_get_property_strv(
@@ -2498,11 +2524,11 @@ static int check_triggering_units(
return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
STRV_FOREACH(i, triggered_by) {
- r = check_one_unit(bus, *i, "active\0reloading\0", true);
+ r = get_state_one_unit(bus, *i, &active_state);
if (r < 0)
- return log_error_errno(r, "Failed to check unit: %m");
+ return r;
- if (r == 0)
+ if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
continue;
if (print_warning_label) {
@@ -2596,7 +2622,10 @@ static int start_unit_one(
if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
!sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
- log_error("See system logs and 'systemctl status %s' for details.", name);
+ log_error("See %s logs and 'systemctl%s status %s' for details.",
+ arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ name);
return r;
}
@@ -3163,11 +3192,12 @@ static int start_special(int argc, char *argv[], void *userdata) {
return start_unit(argc, argv, userdata);
}
-static int check_unit_generic(int code, const char *good_states, char **args) {
+static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
_cleanup_strv_free_ char **names = NULL;
+ UnitActiveState active_state;
sd_bus *bus;
char **name;
- int r;
+ int r, i;
bool found = false;
r = acquire_bus(BUS_MANAGER, &bus);
@@ -3179,13 +3209,16 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
- int state;
+ r = get_state_one_unit(bus, *name, &active_state);
+ if (r < 0)
+ return r;
+
+ if (!arg_quiet)
+ puts(unit_active_state_to_string(active_state));
- state = check_one_unit(bus, *name, good_states, arg_quiet);
- if (state < 0)
- return state;
- if (state > 0)
- found = true;
+ for (i = 0; i < nb_states; ++i)
+ if (good_states[i] == active_state)
+ found = true;
}
/* use the given return code for the case that we won't find
@@ -3194,12 +3227,14 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
}
static int check_unit_active(int argc, char *argv[], void *userdata) {
+ const UnitActiveState states[] = { UNIT_ACTIVE, UNIT_RELOADING };
/* According to LSB: 3, "program is not running" */
- return check_unit_generic(3, "active\0reloading\0", strv_skip(argv, 1));
+ return check_unit_generic(3, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int check_unit_failed(int argc, char *argv[], void *userdata) {
- return check_unit_generic(1, "failed\0", strv_skip(argv, 1));
+ const UnitActiveState states[] = { UNIT_FAILED };
+ return check_unit_generic(1, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int kill_unit(int argc, char *argv[], void *userdata) {
@@ -4082,6 +4117,14 @@ skip:
return 0;
}
+#define print_prop(name, fmt, ...) \
+ do { \
+ if (arg_value) \
+ printf(fmt "\n", __VA_ARGS__); \
+ else \
+ printf("%s=" fmt "\n", name, __VA_ARGS__); \
+ } while(0)
+
static int print_property(const char *name, sd_bus_message *m, const char *contents) {
int r;
@@ -4109,9 +4152,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
if (u > 0)
- printf("%s=%"PRIu32"\n", name, u);
+ print_prop(name, "%"PRIu32, u);
else if (arg_all)
- printf("%s=\n", name);
+ print_prop(name, "%s", "");
return 0;
@@ -4123,7 +4166,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
if (arg_all || !isempty(s))
- printf("%s=%s\n", name, s);
+ print_prop(name, "%s", s);
return 0;
@@ -4135,7 +4178,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
if (arg_all || !isempty(a) || !isempty(b))
- printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
+ print_prop(name, "%s \"%s\"", strempty(a), strempty(b));
return 0;
} else if (streq_ptr(name, "SystemCallFilter")) {
@@ -4162,8 +4205,10 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
bool first = true;
char **i;
- fputs(name, stdout);
- fputc('=', stdout);
+ if (!arg_value) {
+ fputs(name, stdout);
+ fputc('=', stdout);
+ }
if (!whitelist)
fputc('~', stdout);
@@ -4195,7 +4240,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
- printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
+ print_prop("EnvironmentFile", "%s (ignore_errors=%s)\n", path, yes_no(ignore));
if (r < 0)
return bus_log_parse_error(r);
@@ -4214,7 +4259,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
- printf("%s=%s\n", type, path);
+ print_prop(type, "%s", path);
if (r < 0)
return bus_log_parse_error(r);
@@ -4232,7 +4277,10 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
- printf("Listen%s=%s\n", type, path);
+ if (arg_value)
+ puts(path);
+ else
+ printf("Listen%s=%s\n", type, path);
if (r < 0)
return bus_log_parse_error(r);
@@ -4253,10 +4301,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
- printf("%s={ value=%s ; next_elapse=%s }\n",
- base,
- format_timespan(timespan1, sizeof(timespan1), value, 0),
- format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
+ print_prop(base, "{ value=%s ; next_elapse=%s }",
+ format_timespan(timespan1, sizeof(timespan1), value, 0),
+ format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
}
if (r < 0)
return bus_log_parse_error(r);
@@ -4280,18 +4327,18 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
tt = strv_join(info.argv, " ");
- printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n",
- name,
- strna(info.path),
- strna(tt),
- yes_no(info.ignore),
- strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
- strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
- info.pid,
- sigchld_code_to_string(info.code),
- info.status,
- info.code == CLD_EXITED ? "" : "/",
- strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
+ print_prop(name,
+ "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
+ strna(info.path),
+ strna(tt),
+ yes_no(info.ignore),
+ strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
+ strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
+ info.pid,
+ sigchld_code_to_string(info.code),
+ info.status,
+ info.code == CLD_EXITED ? "" : "/",
+ strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
free(info.path);
strv_free(info.argv);
@@ -4312,7 +4359,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
- printf("%s=%s %s\n", name, strna(path), strna(rwm));
+ print_prop(name, "%s %s", strna(path), strna(rwm));
if (r < 0)
return bus_log_parse_error(r);
@@ -4331,7 +4378,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
- printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
+ print_prop(name, "%s %"PRIu64, strna(path), weight);
if (r < 0)
return bus_log_parse_error(r);
@@ -4350,7 +4397,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
- printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
+ print_prop(name, "%s %"PRIu64, strna(path), bandwidth);
if (r < 0)
return bus_log_parse_error(r);
@@ -4364,7 +4411,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
break;
}
- r = bus_print_property(name, m, arg_all);
+ r = bus_print_property(name, m, arg_value, arg_all);
if (r < 0)
return bus_log_parse_error(r);
@@ -4603,8 +4650,8 @@ static int show_system_status(sd_bus *bus) {
printf(" State: %s%s%s\n",
on, strna(mi.state), off);
- printf(" Jobs: %u queued\n", mi.n_jobs);
- printf(" Failed: %u units\n", mi.n_failed_units);
+ printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
+ printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
printf(" Since: %s; %s\n",
format_timestamp(since2, sizeof(since2), mi.timestamp),
@@ -6162,9 +6209,24 @@ static int edit(int argc, char *argv[], void *userdata) {
r = daemon_reload(argc, argv, userdata);
end:
- STRV_FOREACH_PAIR(original, tmp, paths)
+ STRV_FOREACH_PAIR(original, tmp, paths) {
(void) unlink(*tmp);
+ /* Removing empty dropin dirs */
+ if (!arg_full) {
+ _cleanup_free_ char *dir;
+
+ dir = dirname_malloc(*original);
+ if (!dir)
+ return log_oom();
+
+ /* no need to check if the dir is empty, rmdir
+ * does nothing if it is not the case.
+ */
+ (void) rmdir(dir);
+ }
+ }
+
return r;
}
@@ -6194,6 +6256,7 @@ static void systemctl_help(void) {
" --job-mode=MODE Specify how to deal with already queued jobs, when\n"
" queueing a new job\n"
" --show-types When showing sockets, explicitly show their type\n"
+ " --value When showing properties, only print the value\n"
" -i --ignore-inhibitors\n"
" When shutting down or sleeping, ignore inhibitors\n"
" --kill-who=WHO Who to send signal to\n"
@@ -6445,6 +6508,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_SHOW_TYPES,
ARG_IRREVERSIBLE,
ARG_IGNORE_DEPENDENCIES,
+ ARG_VALUE,
ARG_VERSION,
ARG_USER,
ARG_SYSTEM,
@@ -6486,6 +6550,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
{ "ignore-inhibitors", no_argument, NULL, 'i' },
+ { "value", no_argument, NULL, ARG_VALUE },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "global", no_argument, NULL, ARG_GLOBAL },
@@ -6637,6 +6702,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_show_types = true;
break;
+ case ARG_VALUE:
+ arg_value = true;
+ break;
+
case ARG_JOB_MODE:
arg_job_mode = optarg;
break;
diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index 2d4e1f26e1..3bb886be75 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -74,7 +74,7 @@
#endif
#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \
- static inline void func##p(type **p) { \
+ static __inline__ void func##p(type **p) { \
if (*p) \
func(*p); \
} \
diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h
index 47b256d5b9..623cee0c50 100644
--- a/src/systemd/sd-bus-protocol.h
+++ b/src/systemd/sd-bus-protocol.h
@@ -59,7 +59,7 @@ enum {
SD_BUS_TYPE_STRUCT_END = ')',
SD_BUS_TYPE_DICT_ENTRY = 'e', /* not actually used in signatures */
SD_BUS_TYPE_DICT_ENTRY_BEGIN = '{',
- SD_BUS_TYPE_DICT_ENTRY_END = '}',
+ SD_BUS_TYPE_DICT_ENTRY_END = '}'
};
/* Well-known errors. Note that this is only a sanitized subset of the
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 6ad6d51979..e8f84eb545 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -34,7 +34,7 @@ enum {
_SD_BUS_VTABLE_METHOD = 'M',
_SD_BUS_VTABLE_SIGNAL = 'S',
_SD_BUS_VTABLE_PROPERTY = 'P',
- _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W',
+ _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W'
};
enum {
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 2a2ef0eb98..295989cd69 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -89,13 +89,13 @@ enum {
SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32,
SD_BUS_CREDS_DESCRIPTION = 1ULL << 33,
SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */
- _SD_BUS_CREDS_ALL = (1ULL << 34) -1,
+ _SD_BUS_CREDS_ALL = (1ULL << 34) -1
};
enum {
SD_BUS_NAME_REPLACE_EXISTING = 1ULL << 0,
SD_BUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
- SD_BUS_NAME_QUEUE = 1ULL << 2,
+ SD_BUS_NAME_QUEUE = 1ULL << 2
};
/* Callbacks */
diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h
index 5bfca6ecec..c1d07561d7 100644
--- a/src/systemd/sd-device.h
+++ b/src/systemd/sd-device.h
@@ -22,6 +22,7 @@
***/
#include <inttypes.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include "_sd-common.h"
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index ef45370505..374ff8774e 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -98,6 +98,8 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type);
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
const uint8_t *data, size_t data_len);
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
+ uint16_t duid_type, uint8_t *duid, size_t duid_len);
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
const uint8_t **data, size_t *data_len);
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index 1bedc941aa..4604cb6382 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -85,8 +85,9 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type);
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
- size_t duid_len);
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
+ uint8_t *duid, size_t duid_len);
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid);
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled);
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled);
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index 1ea97e47f8..531ace1c34 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -55,7 +55,7 @@ enum {
SD_EVENT_RUNNING,
SD_EVENT_EXITING,
SD_EVENT_FINISHED,
- SD_EVENT_PREPARING,
+ SD_EVENT_PREPARING
};
enum {
@@ -69,7 +69,11 @@ typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
+#else
+typedef void* sd_event_child_handler_t;
+#endif
int sd_event_default(sd_event **e);
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index a3bf5897b8..4dff0b9b81 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -100,11 +100,11 @@ int sd_id128_get_boot(sd_id128_t *ret);
((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \
0 })
-_sd_pure_ static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
+_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
return memcmp(&a, &b, 16) == 0;
}
-_sd_pure_ static inline int sd_id128_is_null(sd_id128_t a) {
+_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) {
return a.qwords[0] == 0 && a.qwords[1] == 0;
}
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index abb9eca576..d4c6f409cd 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -72,7 +72,7 @@ enum {
SD_JOURNAL_SYSTEM = 4,
SD_JOURNAL_CURRENT_USER = 8,
- SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM, /* deprecated name */
+ SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM /* deprecated name */
};
/* Wakeup event types */
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index f7eff58769..4f2a3b50c0 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -33,6 +33,87 @@ _SD_BEGIN_DECLARATIONS;
typedef struct sd_lldp sd_lldp;
typedef struct sd_lldp_neighbor sd_lldp_neighbor;
+#define SD_LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
+
+/* IEEE 802.3AB Clause 9: TLV Types */
+enum {
+ SD_LLDP_TYPE_END = 0,
+ SD_LLDP_TYPE_CHASSIS_ID = 1,
+ SD_LLDP_TYPE_PORT_ID = 2,
+ SD_LLDP_TYPE_TTL = 3,
+ SD_LLDP_TYPE_PORT_DESCRIPTION = 4,
+ SD_LLDP_TYPE_SYSTEM_NAME = 5,
+ SD_LLDP_TYPE_SYSTEM_DESCRIPTION = 6,
+ SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
+ SD_LLDP_TYPE_MGMT_ADDRESS = 8,
+ SD_LLDP_TYPE_PRIVATE = 127,
+};
+
+/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
+enum {
+ SD_LLDP_CHASSIS_SUBTYPE_RESERVED = 0,
+ SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1,
+ SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2,
+ SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3,
+ SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4,
+ SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5,
+ SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6,
+ SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7,
+};
+
+/* IEEE 802.3AB Clause 9.5.3: Port subtype */
+enum {
+ SD_LLDP_PORT_SUBTYPE_RESERVED = 0,
+ SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1,
+ SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2,
+ SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3,
+ SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4,
+ SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5,
+ SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
+ SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
+};
+
+enum {
+ SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0,
+ SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
+ SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2,
+ SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3,
+ SD_LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4,
+ SD_LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5,
+ SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6,
+ SD_LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7,
+ SD_LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8,
+ SD_LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9,
+ SD_LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10,
+};
+
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1)
+
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS \
+ ((uint16_t) \
+ (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER| \
+ SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE| \
+ SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP| \
+ SD_LLDP_SYSTEM_CAPABILITIES_ROUTER| \
+ SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS| \
+ SD_LLDP_SYSTEM_CAPABILITIES_CVLAN| \
+ SD_LLDP_SYSTEM_CAPABILITIES_SVLAN| \
+ SD_LLDP_SYSTEM_CAPABILITIES_TPMR))
+
+
+#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
+#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
+
+enum {
+ SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1,
+ SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
+ SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3,
+ SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4,
+ SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5,
+ SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6,
+ SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7,
+};
+
typedef enum sd_lldp_event {
SD_LLDP_EVENT_ADDED = 'a',
SD_LLDP_EVENT_REMOVED = 'r',
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
new file mode 100644
index 0000000000..cc4821eaf5
--- /dev/null
+++ b/src/test/test-alloc-util.c
@@ -0,0 +1,55 @@
+/***
+ 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 "alloc-util.h"
+#include "macro.h"
+#include "util.h"
+
+static void test_alloca(void) {
+ static const uint8_t zero[997] = { };
+ char *t;
+
+ t = alloca_align(17, 512);
+ assert_se(!((uintptr_t)t & 0xff));
+ memzero(t, 17);
+
+ t = alloca0_align(997, 1024);
+ assert_se(!((uintptr_t)t & 0x1ff));
+ assert_se(!memcmp(t, zero, 997));
+}
+
+static void test_memdup_multiply(void) {
+ int org[] = {1, 2, 3};
+ int *dup;
+
+ dup = (int*)memdup_multiply(org, sizeof(int), 3);
+
+ assert_se(dup);
+ assert_se(dup[0] == 1);
+ assert_se(dup[1] == 2);
+ assert_se(dup[2] == 3);
+ free(dup);
+}
+
+int main(int argc, char *argv[]) {
+ test_alloca();
+ test_memdup_multiply();
+
+ return 0;
+}
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index d2add5880c..8e68d6510d 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -34,17 +34,18 @@ static int test_acpi_fpdt(void) {
r = acpi_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read ACPI FPDT: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA;
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read ACPI FPDT: %m");
+ return ok ? 0 : r;
}
log_info("ACPI FPDT: loader start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
static int test_efi_loader(void) {
@@ -57,33 +58,34 @@ static int test_efi_loader(void) {
r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read EFI loader data: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read EFI loader data: %m");
+ return ok ? 0 : r;
}
log_info("EFI Loader: start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
-int main(int argc, char* argv[]) {
+static int test_boot_timestamps(void) {
char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
int r;
dual_timestamp fw, l, k;
- test_acpi_fpdt();
- test_efi_loader();
-
dual_timestamp_from_monotonic(&k, 0);
r = boot_timestamps(NULL, &fw, &l);
if (r < 0) {
- log_error_errno(r, "Failed to read variables: %m");
- return 1;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read variables: %m");
+ return ok ? 0 : r;
}
log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0));
@@ -91,6 +93,21 @@ int main(int argc, char* argv[]) {
log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime));
log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime));
log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime));
+ return 1;
+}
+
+int main(int argc, char* argv[]) {
+ int p, q, r;
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ p = test_acpi_fpdt();
+ assert(p >= 0);
+ q = test_efi_loader();
+ assert(q >= 0);
+ r = test_boot_timestamps();
+ assert(r >= 0);
- return 0;
+ return (p > 0 || q > 0 || r >> 0) ? EXIT_SUCCESS : EXIT_TEST_SKIP;
}
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index b3a4c40339..be5d2611f8 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -215,6 +215,14 @@ static void test_config_parse_nsec(void) {
test_config_parse_nsec_one("garbage", 0);
}
+static void test_config_parse_iec_uint64(void) {
+ uint64_t offset = 0;
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
+ assert_se(offset == 4 * 1024 * 1024);
+
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
+}
+
int main(int argc, char **argv) {
log_parse_environment();
log_open();
@@ -230,6 +238,7 @@ int main(int argc, char **argv) {
test_config_parse_mode();
test_config_parse_sec();
test_config_parse_nsec();
+ test_config_parse_iec_uint64();
return 0;
}
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index ad57cb0202..cb437754b4 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -24,6 +24,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "log.h"
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
@@ -39,6 +40,8 @@ static void test_copy_file(void) {
size_t sz = 0;
int fd;
+ log_info("%s", __func__);
+
fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
assert_se(fd >= 0);
close(fd);
@@ -66,6 +69,8 @@ static void test_copy_file_fd(void) {
char text[] = "boohoo\nfoo\n\tbar\n";
char buf[64] = {0};
+ log_info("%s", __func__);
+
in_fd = mkostemp_safe(in_fn, O_RDWR);
assert_se(in_fd >= 0);
out_fd = mkostemp_safe(out_fn, O_RDWR);
@@ -91,6 +96,8 @@ static void test_copy_tree(void) {
"link2", "dir1/file");
char **p, **link;
+ log_info("%s", __func__);
+
(void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -173,11 +180,65 @@ static void test_copy_bytes(void) {
assert_se(r == -EBADF);
}
+static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint64_t max_bytes) {
+ char fn2[] = "/tmp/test-copy-file-XXXXXX";
+ char fn3[] = "/tmp/test-copy-file-XXXXXX";
+ _cleanup_close_ int fd = -1, fd2 = -1, fd3 = -1;
+ int r;
+ struct stat buf, buf2, buf3;
+
+ log_info("%s try_reflink=%s max_bytes=%" PRIu64, __func__, yes_no(try_reflink), max_bytes);
+
+ fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ assert_se(fd >= 0);
+
+ fd2 = mkostemp_safe(fn2, O_RDWR);
+ assert_se(fd2 >= 0);
+
+ fd3 = mkostemp_safe(fn3, O_WRONLY);
+ assert_se(fd3 >= 0);
+
+ r = copy_bytes(fd, fd2, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ assert_se(IN_SET(r, 0, 1));
+
+ assert_se(lseek(fd2, 0, SEEK_SET) == 0);
+
+ r = copy_bytes(fd2, fd3, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ /* We cannot distinguish between the input being exactly max_bytes
+ * or longer than max_bytes (without trying to read one more byte,
+ * or calling stat, or FION_READ, etc, and we don't want to do any
+ * of that). So we expect "truncation" since we know that file we
+ * are copying is exactly max_bytes bytes. */
+ assert_se(r == 1);
+
+ assert_se(fstat(fd, &buf) == 0);
+ assert_se(fstat(fd2, &buf2) == 0);
+ assert_se(fstat(fd3, &buf3) == 0);
+
+ assert_se((uint64_t) buf2.st_size == MIN((uint64_t) buf.st_size, max_bytes));
+ assert_se(buf3.st_size == buf2.st_size);
+
+ unlink(fn2);
+ unlink(fn3);
+}
+
int main(int argc, char *argv[]) {
test_copy_file();
test_copy_file_fd();
test_copy_tree();
test_copy_bytes();
+ test_copy_bytes_regular_file(argv[0], false, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], true, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], false, 1000); /* smaller than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 1000);
+ test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 32000);
return 0;
}
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
new file mode 100644
index 0000000000..8818d1ffb7
--- /dev/null
+++ b/src/test/test-cpu-set-util.c
@@ -0,0 +1,143 @@
+/***
+ 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 "alloc-util.h"
+#include "cpu-set-util.h"
+#include "macro.h"
+
+static void test_parse_cpu_set(void) {
+ cpu_set_t *c = NULL;
+ int ncpus;
+ int cpu;
+
+ /* Simple range (from CPUAffinity example) */
+ ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
+ c = mfree(c);
+
+ /* A more interesting range */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Quoted strings */
+ ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Use commas as separators */
+ ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Commas with spaces (and trailing comma, space) */
+ ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 8; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges */
+ ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges with trailing comma, space */
+ ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Negative range (returns empty cpu_set) */
+ ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
+ c = mfree(c);
+
+ /* Overlapping ranges */
+ ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
+ for (cpu = 0; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Mix ranges and individual CPUs */
+ ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
+ assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 4; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Garbage */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Range with garbage */
+ ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Empty string */
+ c = NULL;
+ ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus == 0); /* empty string returns 0 */
+ assert_se(!c);
+
+ /* Runnaway quoted string */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+}
+
+int main(int argc, char *argv[]) {
+ test_parse_cpu_set();
+
+ return 0;
+}
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index 4ce00f4b1f..a7cb426282 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -38,27 +38,27 @@ int main(int argc, char*argv[]) {
sd_notify(0,
"STATUS=Starting up");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Reloading\n"
"RELOADING=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Quitting\n"
"STOPPING=1");
- sleep(5);
+ sleep(1);
return EXIT_SUCCESS;
}
diff --git a/src/test/test-env-replace.c b/src/test/test-env-util.c
index 264acc6ea6..35bb62906e 100644
--- a/src/test/test-env-replace.c
+++ b/src/test/test-env-util.c
@@ -2,6 +2,7 @@
This file is part of systemd.
Copyright 2010 Lennart Poettering
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
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
@@ -177,10 +178,37 @@ static void test_env_name_is_valid(void) {
assert_se(!env_name_is_valid(NULL));
assert_se(!env_name_is_valid(""));
+ assert_se(!env_name_is_valid("xxx\a"));
+ assert_se(!env_name_is_valid("xxx\007b"));
+ assert_se(!env_name_is_valid("\007\009"));
assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
}
+static void test_env_value_is_valid(void) {
+ assert_se(env_value_is_valid(""));
+ assert_se(env_value_is_valid("głąb kapuściany"));
+ assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+}
+
+static void test_env_assignment_is_valid(void) {
+ assert_se(env_assignment_is_valid("a="));
+ assert_se(env_assignment_is_valid("b=głąb kapuściany"));
+ assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
+ assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+
+ assert_se(!env_assignment_is_valid("="));
+ assert_se(!env_assignment_is_valid("a b="));
+ assert_se(!env_assignment_is_valid("a ="));
+ assert_se(!env_assignment_is_valid(" b="));
+ /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
+ assert_se(!env_assignment_is_valid("a.b="));
+ assert_se(!env_assignment_is_valid("a-b="));
+ assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
+ assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
+ assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
+}
+
int main(int argc, char *argv[]) {
test_strv_env_delete();
test_strv_env_unset();
@@ -189,6 +217,8 @@ int main(int argc, char *argv[]) {
test_replace_env_arg();
test_env_clean();
test_env_name_is_valid();
+ test_env_value_is_valid();
+ test_env_assignment_is_valid();
return 0;
}
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
new file mode 100644
index 0000000000..6cbb8443fe
--- /dev/null
+++ b/src/test/test-escape.c
@@ -0,0 +1,114 @@
+/***
+ 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 "alloc-util.h"
+#include "escape.h"
+#include "macro.h"
+
+static void test_cescape(void) {
+ _cleanup_free_ char *escaped;
+
+ assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
+ assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+}
+
+static void test_cunescape(void) {
+ _cleanup_free_ char *unescaped;
+
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
+ unescaped = mfree(unescaped);
+
+ /* incomplete sequences */
+ assert_se(cunescape("\\x0", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x0"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\x", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\", 0, &unescaped) < 0);
+ assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\11", 0, &unescaped) < 0);
+ assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\11"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\1", 0, &unescaped) < 0);
+ assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\1"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
+ assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "ßßΠA"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\073", 0, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, ";"));
+}
+
+static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_escape(s, bad));
+ assert_se(streq_ptr(r, expected));
+}
+
+static void test_shell_escape(void) {
+ test_shell_escape_one("", "", "");
+ test_shell_escape_one("\\", "", "\\\\");
+ test_shell_escape_one("foobar", "", "foobar");
+ test_shell_escape_one("foobar", "o", "f\\o\\obar");
+ test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
+}
+
+static void test_shell_maybe_quote_one(const char *s, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_maybe_quote(s));
+ assert_se(streq(r, expected));
+}
+
+static void test_shell_maybe_quote(void) {
+
+ test_shell_maybe_quote_one("", "");
+ test_shell_maybe_quote_one("\\", "\"\\\\\"");
+ test_shell_maybe_quote_one("\"", "\"\\\"\"");
+ test_shell_maybe_quote_one("foobar", "foobar");
+ test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
+ test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
+ test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
+}
+
+int main(int argc, char *argv[]) {
+ test_cescape();
+ test_cunescape();
+ test_shell_escape();
+ test_shell_maybe_quote();
+
+ return 0;
+}
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 0d2e4bfc15..901cc44af6 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -130,18 +130,33 @@ static void test_exec_systemcallerrornumber(Manager *m) {
#endif
}
+static void test_exec_systemcall_system_mode_with_user(Manager *m) {
+#ifdef HAVE_SECCOMP
+ if (getpwnam("nobody"))
+ test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
+ else if (getpwnam("nfsnobody"))
+ test(m, "exec-systemcallfilter-system-user-nfsnobody.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_systemcall_system_mode_with_user, could not find nobody/nfsnobody user: %m");
+#endif
+}
+
static void test_exec_user(Manager *m) {
if (getpwnam("nobody"))
test(m, "exec-user.service", 0, CLD_EXITED);
+ else if (getpwnam("nfsnobody"))
+ test(m, "exec-user-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_user, could not find nobody user: %m");
+ log_error_errno(errno, "Skipping test_exec_user, could not find nobody/nfsnobody user: %m");
}
static void test_exec_group(Manager *m) {
if (getgrnam("nobody"))
test(m, "exec-group.service", 0, CLD_EXITED);
+ else if (getgrnam("nfsnobody"))
+ test(m, "exec-group-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_group, could not find nobody group: %m");
+ log_error_errno(errno, "Skipping test_exec_group, could not find nobody/nfsnobody group: %m");
}
static void test_exec_environment(Manager *m) {
@@ -204,8 +219,10 @@ static void test_exec_runtimedirectory(Manager *m) {
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
if (getgrnam("nobody"))
test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ else if (getgrnam("nfsnobody"))
+ test(m, "exec-runtimedirectory-owner-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody group: %m");
+ log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody/nfsnobody group: %m");
}
static void test_exec_capabilityboundingset(Manager *m) {
@@ -234,9 +251,16 @@ static void test_exec_capabilityambientset(Manager *m) {
* in the first place for the tests. */
r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
if (r >= 0 || errno != EINVAL) {
- test(m, "exec-capabilityambientset.service", 0, CLD_EXITED);
- test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED);
- }
+ if (getpwnam("nobody")) {
+ test(m, "exec-capabilityambientset.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED);
+ } else if (getpwnam("nfsnobody")) {
+ test(m, "exec-capabilityambientset-nfsnobody.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityambientset-merge-nfsnobody.service", 0, CLD_EXITED);
+ } else
+ log_error_errno(errno, "Skipping test_exec_capabilityambientset, could not find nobody/nfsnobody user: %m");
+ } else
+ log_error_errno(errno, "Skipping test_exec_capabilityambientset, the kernel does not support ambient capabilities: %m");
}
static void test_exec_privatenetwork(Manager *m) {
@@ -267,8 +291,31 @@ static void test_exec_spec_interpolation(Manager *m) {
test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
}
+static int run_tests(ManagerRunningAs running_as, test_function_t *tests) {
+ test_function_t *test = NULL;
+ Manager *m = NULL;
+ int r;
+
+ assert_se(tests);
+
+ r = manager_new(running_as, true, &m);
+ if (MANAGER_SKIP_TEST(r)) {
+ printf("Skipping test: manager_new: %s\n", strerror(-r));
+ return EXIT_TEST_SKIP;
+ }
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ for (test = tests; test && *test; test++)
+ (*test)(m);
+
+ manager_free(m);
+
+ return 0;
+}
+
int main(int argc, char *argv[]) {
- test_function_t tests[] = {
+ test_function_t user_tests[] = {
test_exec_workingdirectory,
test_exec_personality,
test_exec_ignoresigpipe,
@@ -291,8 +338,10 @@ int main(int argc, char *argv[]) {
test_exec_spec_interpolation,
NULL,
};
- test_function_t *test = NULL;
- Manager *m = NULL;
+ test_function_t system_tests[] = {
+ test_exec_systemcall_system_mode_with_user,
+ NULL,
+ };
int r;
log_parse_environment();
@@ -317,18 +366,9 @@ int main(int argc, char *argv[]) {
assert_se(unsetenv("VAR2") == 0);
assert_se(unsetenv("VAR3") == 0);
- r = manager_new(MANAGER_USER, true, &m);
- if (MANAGER_SKIP_TEST(r)) {
- printf("Skipping test: manager_new: %s\n", strerror(-r));
- return EXIT_TEST_SKIP;
- }
- assert_se(r >= 0);
- assert_se(manager_startup(m, NULL, NULL) >= 0);
-
- for (test = tests; test && *test; test++)
- (*test)(m);
+ r = run_tests(MANAGER_USER, user_tests);
+ if (r != 0)
+ return r;
- manager_free(m);
-
- return 0;
+ return run_tests(MANAGER_SYSTEM, system_tests);
}
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
new file mode 100644
index 0000000000..421d3bdeb3
--- /dev/null
+++ b/src/test/test-fd-util.c
@@ -0,0 +1,103 @@
+/***
+ 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+
+static void test_close_many(void) {
+ int fds[3];
+ char name0[] = "/tmp/test-close-many.XXXXXX";
+ char name1[] = "/tmp/test-close-many.XXXXXX";
+ char name2[] = "/tmp/test-close-many.XXXXXX";
+
+ fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
+ fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
+ fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
+
+ close_many(fds, 2);
+
+ assert_se(fcntl(fds[0], F_GETFD) == -1);
+ assert_se(fcntl(fds[1], F_GETFD) == -1);
+ assert_se(fcntl(fds[2], F_GETFD) >= 0);
+
+ safe_close(fds[2]);
+
+ unlink(name0);
+ unlink(name1);
+ unlink(name2);
+}
+
+static void test_close_nointr(void) {
+ char name[] = "/tmp/test-test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+ assert_se(close_nointr(fd) < 0);
+
+ unlink(name);
+}
+
+static void test_same_fd(void) {
+ _cleanup_close_pair_ int p[2] = { -1, -1 };
+ _cleanup_close_ int a = -1, b = -1, c = -1;
+
+ assert_se(pipe2(p, O_CLOEXEC) >= 0);
+ assert_se((a = dup(p[0])) >= 0);
+ assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
+ assert_se((c = dup(a)) >= 0);
+
+ assert_se(same_fd(p[0], p[0]) > 0);
+ assert_se(same_fd(p[1], p[1]) > 0);
+ assert_se(same_fd(a, a) > 0);
+ assert_se(same_fd(b, b) > 0);
+
+ assert_se(same_fd(a, p[0]) > 0);
+ assert_se(same_fd(p[0], a) > 0);
+ assert_se(same_fd(c, p[0]) > 0);
+ assert_se(same_fd(p[0], c) > 0);
+ assert_se(same_fd(a, c) > 0);
+ assert_se(same_fd(c, a) > 0);
+
+ assert_se(same_fd(p[0], p[1]) == 0);
+ assert_se(same_fd(p[1], p[0]) == 0);
+ assert_se(same_fd(p[0], b) == 0);
+ assert_se(same_fd(b, p[0]) == 0);
+ assert_se(same_fd(p[1], a) == 0);
+ assert_se(same_fd(a, p[1]) == 0);
+ assert_se(same_fd(p[1], b) == 0);
+ assert_se(same_fd(b, p[1]) == 0);
+
+ assert_se(same_fd(a, b) == 0);
+ assert_se(same_fd(b, a) == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_close_many();
+ test_close_nointr();
+ test_same_fd();
+
+ return 0;
+}
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 5586a2d6c1..ec9f173da2 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -27,6 +27,7 @@
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "io-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
@@ -425,6 +426,134 @@ static void test_load_env_file_pairs(void) {
unlink(fn);
}
+static void test_search_and_fopen(void) {
+ const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(basename(name), "r", "/", dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+
+static void test_search_and_fopen_nulstr(void) {
+ const char dirs[] = "/tmp/foo/bar\0/tmp\0";
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+static void test_writing_tmpfile(void) {
+ char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
+ _cleanup_free_ char *contents = NULL;
+ size_t size;
+ int fd, r;
+ struct iovec iov[3];
+
+ IOVEC_SET_STRING(iov[0], "abc\n");
+ IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
+ IOVEC_SET_STRING(iov[2], "");
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ printf("tmpfile: %s", name);
+
+ r = writev(fd, iov, 3);
+ assert_se(r >= 0);
+
+ r = read_full_file(name, &contents, &size);
+ assert_se(r == 0);
+ printf("contents: %s", contents);
+ assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
+
+ unlink(name);
+}
+
+static void test_tempfn(void) {
+ char *ret = NULL, *p;
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -439,6 +568,10 @@ int main(int argc, char *argv[]) {
test_write_string_file_no_create();
test_write_string_file_verify();
test_load_env_file_pairs();
+ test_search_and_fopen();
+ test_search_and_fopen_nulstr();
+ test_writing_tmpfile();
+ test_tempfn();
return 0;
}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
new file mode 100644
index 0000000000..6db2c2b6f1
--- /dev/null
+++ b/src/test/test-fs-util.c
@@ -0,0 +1,91 @@
+/***
+ 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 <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "mkdir.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+
+static void test_unlink_noerrno(void) {
+ char name[] = "/tmp/test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+
+ {
+ PROTECT_ERRNO;
+ errno = -42;
+ assert_se(unlink_noerrno(name) >= 0);
+ assert_se(errno == -42);
+ assert_se(unlink_noerrno(name) < 0);
+ assert_se(errno == -42);
+ }
+}
+
+static void test_readlink_and_make_absolute(void) {
+ char tempdir[] = "/tmp/test-readlink_and_make_absolute";
+ char name[] = "/tmp/test-readlink_and_make_absolute/original";
+ char name2[] = "test-readlink_and_make_absolute/original";
+ char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
+ char *r = NULL;
+
+ assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
+ assert_se(touch(name) >= 0);
+
+ assert_se(symlink(name, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(chdir(tempdir) >= 0);
+ assert_se(symlink(name2, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+}
+
+static void test_get_files_in_directory(void) {
+ _cleanup_strv_free_ char **l = NULL, **t = NULL;
+
+ assert_se(get_files_in_directory("/tmp", &l) >= 0);
+ assert_se(get_files_in_directory(".", &t) >= 0);
+ assert_se(get_files_in_directory(".", NULL) >= 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_unlink_noerrno();
+ test_readlink_and_make_absolute();
+ test_get_files_in_directory();
+
+ return 0;
+}
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
index ea3d1a6909..63a4b8c243 100644
--- a/src/test/test-fstab-util.c
+++ b/src/test/test-fstab-util.c
@@ -131,8 +131,45 @@ static void test_fstab_yes_no_option(void) {
assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false);
}
+static void test_fstab_node_to_udev_node(void) {
+ char *n;
+
+ n = fstab_node_to_udev_node("LABEL=applé/jack");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
+ free(n);
+
+ n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PONIES=awesome");
+ puts(n);
+ assert_se(streq(n, "PONIES=awesome"));
+ free(n);
+
+ n = fstab_node_to_udev_node("/dev/xda1");
+ puts(n);
+ assert_se(streq(n, "/dev/xda1"));
+ free(n);
+}
+
int main(void) {
test_fstab_filter_options();
test_fstab_find_pri();
test_fstab_yes_no_option();
+ test_fstab_node_to_udev_node();
+
+ return 0;
}
diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c
new file mode 100644
index 0000000000..227d4290f0
--- /dev/null
+++ b/src/test/test-glob-util.c
@@ -0,0 +1,50 @@
+/***
+ 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "glob-util.h"
+#include "macro.h"
+
+static void test_glob_exists(void) {
+ char name[] = "/tmp/test-glob_exists.XXXXXX";
+ int fd = -1;
+ int r;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 1);
+
+ r = unlink(name);
+ assert_se(r == 0);
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 0);
+}
+
+int main(void) {
+ test_glob_exists();
+
+ return 0;
+}
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
new file mode 100644
index 0000000000..276f25d091
--- /dev/null
+++ b/src/test/test-hexdecoct.c
@@ -0,0 +1,387 @@
+/***
+ 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 "alloc-util.h"
+#include "hexdecoct.h"
+#include "macro.h"
+#include "string-util.h"
+
+static void test_hexchar(void) {
+ assert_se(hexchar(0xa) == 'a');
+ assert_se(hexchar(0x0) == '0');
+}
+
+static void test_unhexchar(void) {
+ assert_se(unhexchar('a') == 0xA);
+ assert_se(unhexchar('A') == 0xA);
+ assert_se(unhexchar('0') == 0x0);
+}
+
+static void test_base32hexchar(void) {
+ assert_se(base32hexchar(0) == '0');
+ assert_se(base32hexchar(9) == '9');
+ assert_se(base32hexchar(10) == 'A');
+ assert_se(base32hexchar(31) == 'V');
+}
+
+static void test_unbase32hexchar(void) {
+ assert_se(unbase32hexchar('0') == 0);
+ assert_se(unbase32hexchar('9') == 9);
+ assert_se(unbase32hexchar('A') == 10);
+ assert_se(unbase32hexchar('V') == 31);
+ assert_se(unbase32hexchar('=') == -EINVAL);
+}
+
+static void test_base64char(void) {
+ assert_se(base64char(0) == 'A');
+ assert_se(base64char(26) == 'a');
+ assert_se(base64char(63) == '/');
+}
+
+static void test_unbase64char(void) {
+ assert_se(unbase64char('A') == 0);
+ assert_se(unbase64char('Z') == 25);
+ assert_se(unbase64char('a') == 26);
+ assert_se(unbase64char('z') == 51);
+ assert_se(unbase64char('0') == 52);
+ assert_se(unbase64char('9') == 61);
+ assert_se(unbase64char('+') == 62);
+ assert_se(unbase64char('/') == 63);
+ assert_se(unbase64char('=') == -EINVAL);
+}
+
+static void test_octchar(void) {
+ assert_se(octchar(00) == '0');
+ assert_se(octchar(07) == '7');
+}
+
+static void test_unoctchar(void) {
+ assert_se(unoctchar('0') == 00);
+ assert_se(unoctchar('7') == 07);
+}
+
+static void test_decchar(void) {
+ assert_se(decchar(0) == '0');
+ assert_se(decchar(9) == '9');
+}
+
+static void test_undecchar(void) {
+ assert_se(undecchar('0') == 0);
+ assert_se(undecchar('9') == 9);
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa214921";
+ const char *hex_invalid = "efa214921o";
+ _cleanup_free_ char *hex2 = NULL;
+ _cleanup_free_ void *mem = NULL;
+ size_t len;
+
+ assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
+ assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
+
+ assert_se((hex2 = hexmem(mem, len)));
+
+ free(mem);
+
+ assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
+
+ free(hex2);
+
+ assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
+ assert_se((hex2 = hexmem(mem, len)));
+ assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base32hexmem(void) {
+ char *b32;
+
+ b32 = base32hexmem("", strlen(""), true);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CO======"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG===="));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU==="));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG="));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8======"));
+ free(b32);
+
+ b32 = base32hexmem("", strlen(""), false);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CO"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG"));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU"));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG"));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8"));
+ free(b32);
+}
+
+static void test_unbase32hexmem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base64mem(void) {
+ char *b64;
+
+ assert_se(base64mem("", strlen(""), &b64) == 0);
+ assert_se(streq(b64, ""));
+ free(b64);
+
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
+ assert_se(streq(b64, "Zg=="));
+ free(b64);
+
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
+ assert_se(streq(b64, "Zm8="));
+ free(b64);
+
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
+ assert_se(streq(b64, "Zm9v"));
+ free(b64);
+
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYg=="));
+ free(b64);
+
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmE="));
+ free(b64);
+
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmFy"));
+ free(b64);
+}
+
+static void test_unbase64mem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
+}
+
+static void test_hexdump(void) {
+ uint8_t data[146];
+ unsigned i;
+
+ hexdump(stdout, NULL, 0);
+ hexdump(stdout, "", 0);
+ hexdump(stdout, "", 1);
+ hexdump(stdout, "x", 1);
+ hexdump(stdout, "x", 2);
+ hexdump(stdout, "foobar", 7);
+ hexdump(stdout, "f\nobar", 7);
+ hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
+
+ for (i = 0; i < ELEMENTSOF(data); i++)
+ data[i] = i*2;
+
+ hexdump(stdout, data, sizeof(data));
+}
+
+int main(int argc, char *argv[]) {
+ test_hexchar();
+ test_unhexchar();
+ test_base32hexchar();
+ test_unbase32hexchar();
+ test_base64char();
+ test_unbase64char();
+ test_octchar();
+ test_unoctchar();
+ test_decchar();
+ test_undecchar();
+ test_unhexmem();
+ test_base32hexmem();
+ test_unbase32hexmem();
+ test_base64mem();
+ test_unbase64mem();
+ test_hexdump();
+
+ return 0;
+}
diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c
new file mode 100644
index 0000000000..10bd3833bc
--- /dev/null
+++ b/src/test/test-io-util.c
@@ -0,0 +1,69 @@
+/***
+ 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 <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "macro.h"
+
+static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
+ char check[n];
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+ assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
+
+ assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
+ assert_se(ftruncate(fd, n) >= 0);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(read(fd, check, n) == (ssize_t) n);
+
+ assert_se(memcmp(buffer, check, n) == 0);
+}
+
+static void test_sparse_write(void) {
+ const char test_a[] = "test";
+ const char test_b[] = "\0\0\0\0test\0\0\0\0";
+ const char test_c[] = "\0\0test\0\0\0\0";
+ const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
+ const char test_e[] = "test\0\0\0\0test";
+ _cleanup_close_ int fd = -1;
+ char fn[] = "/tmp/sparseXXXXXX";
+
+ fd = mkostemp(fn, O_CLOEXEC);
+ assert_se(fd >= 0);
+ unlink(fn);
+
+ test_sparse_write_one(fd, test_a, sizeof(test_a));
+ test_sparse_write_one(fd, test_b, sizeof(test_b));
+ test_sparse_write_one(fd, test_c, sizeof(test_c));
+ test_sparse_write_one(fd, test_d, sizeof(test_d));
+ test_sparse_write_one(fd, test_e, sizeof(test_e));
+}
+
+int main(void) {
+ test_sparse_write();
+
+ return 0;
+}
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 2464d32458..c5bcaf47bb 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -23,9 +23,14 @@
int main(int argc, char *argv[]) {
uid_t uid;
-
- assert_se(argc == 2);
- assert_se(parse_uid(argv[1], &uid) >= 0);
+ int r;
+ const char* name = argv[1] ?: "nfsnobody";
+
+ r = get_user_creds(&name, &uid, NULL, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to resolve \"%s\": %m", name);
+ return EXIT_FAILURE;
+ }
return clean_ipc(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index a7eb60e8cf..e28de9b37b 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -24,170 +24,140 @@
#include "libudev.h"
+#include "fd-util.h"
+#include "log.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
static void print_device(struct udev_device *device) {
const char *str;
dev_t devnum;
int count;
struct udev_list_entry *list_entry;
- printf("*** device: %p ***\n", device);
+ log_info("*** device: %p ***", device);
str = udev_device_get_action(device);
if (str != NULL)
- printf("action: '%s'\n", str);
+ log_info("action: '%s'", str);
str = udev_device_get_syspath(device);
- printf("syspath: '%s'\n", str);
+ log_info("syspath: '%s'", str);
str = udev_device_get_sysname(device);
- printf("sysname: '%s'\n", str);
+ log_info("sysname: '%s'", str);
str = udev_device_get_sysnum(device);
if (str != NULL)
- printf("sysnum: '%s'\n", str);
+ log_info("sysnum: '%s'", str);
str = udev_device_get_devpath(device);
- printf("devpath: '%s'\n", str);
+ log_info("devpath: '%s'", str);
str = udev_device_get_subsystem(device);
if (str != NULL)
- printf("subsystem: '%s'\n", str);
+ log_info("subsystem: '%s'", str);
str = udev_device_get_devtype(device);
if (str != NULL)
- printf("devtype: '%s'\n", str);
+ log_info("devtype: '%s'", str);
str = udev_device_get_driver(device);
if (str != NULL)
- printf("driver: '%s'\n", str);
+ log_info("driver: '%s'", str);
str = udev_device_get_devnode(device);
if (str != NULL)
- printf("devname: '%s'\n", str);
+ log_info("devname: '%s'", str);
devnum = udev_device_get_devnum(device);
if (major(devnum) > 0)
- printf("devnum: %u:%u\n", major(devnum), minor(devnum));
+ log_info("devnum: %u:%u", major(devnum), minor(devnum));
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
- printf("link: '%s'\n", udev_list_entry_get_name(list_entry));
+ log_info("link: '%s'", udev_list_entry_get_name(list_entry));
count++;
}
if (count > 0)
- printf("found %i links\n", count);
+ log_info("found %i links", count);
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
- printf("property: '%s=%s'\n",
+ log_info("property: '%s=%s'",
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
count++;
}
if (count > 0)
- printf("found %i properties\n", count);
+ log_info("found %i properties", count);
str = udev_device_get_property_value(device, "MAJOR");
if (str != NULL)
- printf("MAJOR: '%s'\n", str);
+ log_info("MAJOR: '%s'", str);
str = udev_device_get_sysattr_value(device, "dev");
if (str != NULL)
- printf("attr{dev}: '%s'\n", str);
-
- printf("\n");
+ log_info("attr{dev}: '%s'", str);
}
-static int test_device(struct udev *udev, const char *syspath) {
+static void test_device(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
- if (device == NULL) {
- printf("no device found\n");
- return -1;
- }
- print_device(device);
-
- return 0;
+ if (device == NULL)
+ log_warning_errno(errno, "udev_device_new_from_syspath: %m");
+ else
+ print_device(device);
}
-static int test_device_parents(struct udev *udev, const char *syspath) {
+static void test_device_parents(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
struct udev_device *device_parent;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
if (device == NULL)
- return -1;
+ return;
- printf("looking at parents\n");
+ log_info("looking at parents");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
- printf("looking at parents again\n");
+ log_info("looking at parents again");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
-
- return 0;
}
-static int test_device_devnum(struct udev *udev) {
+static void test_device_devnum(struct udev *udev) {
dev_t devnum = makedev(1, 3);
- struct udev_device *device;
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+ log_info("looking up device: %u:%u", major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_devnum: %m");
+ else
+ print_device(device);
}
-static int test_device_subsys_name(struct udev *udev) {
- struct udev_device *device;
-
- printf("looking up device: 'block':'sda'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'subsystem':'pci'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'drivers':'scsi:sd'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
+static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) {
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: 'module':'printk'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
+ log_info("looking up device: '%s:%s'", subsys, dev);
+ device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m");
+ else
+ print_device(device);
}
static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
@@ -200,63 +170,45 @@ static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
udev_list_entry_get_name(list_entry));
if (device != NULL) {
- printf("device: '%s' (%s)\n",
- udev_device_get_syspath(device),
- udev_device_get_subsystem(device));
+ log_info("device: '%s' (%s)",
+ udev_device_get_syspath(device),
+ udev_device_get_subsystem(device));
udev_device_unref(device);
count++;
}
}
- printf("found %i devices\n\n", count);
+ log_info("found %i devices", count);
return count;
}
-static int test_monitor(struct udev *udev) {
- struct udev_monitor *udev_monitor = NULL;
- int fd_ep;
- int fd_udev = -1;
- struct epoll_event ep_udev, ep_stdin;
+static void test_monitor(struct udev *udev) {
+ _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor;
+ _cleanup_close_ int fd_ep;
+ int fd_udev;
+ struct epoll_event ep_udev = {
+ .events = EPOLLIN,
+ }, ep_stdin = {
+ .events = EPOLLIN,
+ .data.fd = STDIN_FILENO,
+ };
fd_ep = epoll_create1(EPOLL_CLOEXEC);
- if (fd_ep < 0) {
- printf("error creating epoll fd: %m\n");
- goto out;
- }
+ assert_se(fd_ep >= 0);
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
- if (udev_monitor == NULL) {
- printf("no socket\n");
- goto out;
- }
+ assert_se(udev_monitor != NULL);
+
fd_udev = udev_monitor_get_fd(udev_monitor);
+ ep_udev.data.fd = fd_udev;
- if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) {
- printf("filter failed\n");
- goto out;
- }
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") >= 0);
- if (udev_monitor_enable_receiving(udev_monitor) < 0) {
- printf("bind failed\n");
- goto out;
- }
+ assert_se(udev_monitor_enable_receiving(udev_monitor) >= 0);
- memzero(&ep_udev, sizeof(struct epoll_event));
- ep_udev.events = EPOLLIN;
- ep_udev.data.fd = fd_udev;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
-
- memzero(&ep_stdin, sizeof(struct epoll_event));
- ep_stdin.events = EPOLLIN;
- ep_stdin.data.fd = STDIN_FILENO;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) >= 0);
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) >= 0);
for (;;) {
int fdcount;
@@ -265,7 +217,7 @@ static int test_monitor(struct udev *udev) {
int i;
printf("waiting for events from udev, press ENTER to exit\n");
- fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
+ fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
printf("epoll fd count: %i\n", fdcount);
for (i = 0; i < fdcount; i++) {
@@ -279,36 +231,29 @@ static int test_monitor(struct udev *udev) {
udev_device_unref(device);
} else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
printf("exiting loop\n");
- goto out;
+ return;
}
}
}
-out:
- if (fd_ep >= 0)
- close(fd_ep);
- udev_monitor_unref(udev_monitor);
- return 0;
}
-static int test_queue(struct udev *udev) {
+static void test_queue(struct udev *udev) {
struct udev_queue *udev_queue;
+ bool empty;
udev_queue = udev_queue_new(udev);
- if (udev_queue == NULL)
- return -1;
-
- if (udev_queue_get_queue_is_empty(udev_queue))
- printf("queue is empty\n");
+ assert_se(udev_queue);
+ empty = udev_queue_get_queue_is_empty(udev_queue);
+ log_info("queue is %s", empty ? "empty" : "not empty");
udev_queue_unref(udev_queue);
- return 0;
}
static int test_enumerate(struct udev *udev, const char *subsystem) {
struct udev_enumerate *udev_enumerate;
int r;
- printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
+ log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -317,7 +262,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'net' + duplicated scan + null + zero\n");
+ log_info("enumerate 'net' + duplicated scan + null + zero");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -337,7 +282,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'block'\n");
+ log_info("enumerate 'block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -351,7 +296,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'not block'\n");
+ log_info("enumerate 'not block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -360,7 +305,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'pci, mem, vc'\n");
+ log_info("enumerate 'pci, mem, vc'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -371,7 +316,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'subsystem'\n");
+ log_info("enumerate 'subsystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -379,7 +324,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'property IF_FS_*=filesystem'\n");
+ log_info("enumerate 'property IF_FS_*=filesystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -397,32 +342,32 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
hwdb = udev_hwdb_new(udev);
udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
- printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
- printf("\n");
+ log_info("'%s'='%s'", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
hwdb = udev_hwdb_unref(hwdb);
assert_se(hwdb == NULL);
}
int main(int argc, char *argv[]) {
- struct udev *udev = NULL;
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ bool arg_monitor = false;
static const struct option options[] = {
- { "syspath", required_argument, NULL, 'p' },
+ { "syspath", required_argument, NULL, 'p' },
{ "subsystem", required_argument, NULL, 's' },
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'V' },
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "monitor", no_argument, NULL, 'm' },
{}
};
const char *syspath = "/devices/virtual/mem/null";
const char *subsystem = NULL;
- char path[1024];
int c;
udev = udev_new();
- printf("context: %p\n", udev);
+ log_info("context: %p", udev);
if (udev == NULL) {
- printf("no context\n");
+ log_info("no context");
return 1;
}
@@ -444,14 +389,18 @@ int main(int argc, char *argv[]) {
case 'h':
printf("--debug --syspath= --subsystem= --help\n");
- goto out;
+ return EXIT_SUCCESS;
case 'V':
printf("%s\n", VERSION);
- goto out;
+ return EXIT_SUCCESS;
+
+ case 'm':
+ arg_monitor = true;
+ break;
case '?':
- goto out;
+ return EXIT_FAILURE;
default:
assert_not_reached("Unhandled option code.");
@@ -459,14 +408,16 @@ int main(int argc, char *argv[]) {
/* add sys path if needed */
- if (!startswith(syspath, "/sys")) {
- xsprintf(path, "/sys/%s", syspath);
- syspath = path;
- }
+ if (!startswith(syspath, "/sys"))
+ syspath = strjoina("/sys/", syspath);
test_device(udev, syspath);
test_device_devnum(udev);
- test_device_subsys_name(udev);
+ test_device_subsys_name(udev, "block", "sda");
+ test_device_subsys_name(udev, "subsystem", "pci");
+ test_device_subsys_name(udev, "drivers", "scsi:sd");
+ test_device_subsys_name(udev, "module", "printk");
+
test_device_parents(udev, syspath);
test_enumerate(udev, subsystem);
@@ -475,8 +426,8 @@ int main(int argc, char *argv[]) {
test_hwdb(udev, "usb:v0D50p0011*");
- test_monitor(udev);
-out:
- udev_unref(udev);
- return 0;
+ if (arg_monitor)
+ test_monitor(udev);
+
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index 2748395ade..7b67337331 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -31,7 +31,7 @@ int main(int argc, char* argv[]) {
r = loopback_setup();
if (r < 0)
- fprintf(stderr, "loopback: %s\n", strerror(-r));
+ log_error("loopback: %m");
- return 0;
+ return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 53a585290a..d376dd56c5 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -433,6 +433,50 @@ static void test_path_is_mount_point(void) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
+static void test_file_in_same_dir(void) {
+ char *t;
+
+ t = file_in_same_dir("/", "a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("/", "/a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("", "a");
+ assert_se(streq(t, "a"));
+ free(t);
+
+ t = file_in_same_dir("a/", "a");
+ assert_se(streq(t, "a/a"));
+ free(t);
+
+ t = file_in_same_dir("bar/foo", "bar");
+ assert_se(streq(t, "bar/bar"));
+ free(t);
+}
+
+static void test_filename_is_valid(void) {
+ char foo[FILENAME_MAX+2];
+ int i;
+
+ assert_se(!filename_is_valid(""));
+ assert_se(!filename_is_valid("/bar/foo"));
+ assert_se(!filename_is_valid("/"));
+ assert_se(!filename_is_valid("."));
+ assert_se(!filename_is_valid(".."));
+
+ for (i=0; i<FILENAME_MAX+1; i++)
+ foo[i] = 'a';
+ foo[FILENAME_MAX+1] = '\0';
+
+ assert_se(!filename_is_valid(foo));
+
+ assert_se(filename_is_valid("foo_bar-333"));
+ assert_se(filename_is_valid("o.o"));
+}
+
int main(int argc, char **argv) {
test_path();
test_find_binary(argv[0]);
@@ -444,6 +488,8 @@ int main(int argc, char **argv) {
test_path_startswith();
test_prefix_root();
test_path_is_mount_point();
+ test_file_in_same_dir();
+ test_filename_is_valid();
return 0;
}
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
new file mode 100644
index 0000000000..a7a8f621a2
--- /dev/null
+++ b/src/test/test-proc-cmdline.c
@@ -0,0 +1,52 @@
+/***
+ 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 "alloc-util.h"
+#include "log.h"
+#include "macro.h"
+#include "proc-cmdline.h"
+#include "special.h"
+#include "string-util.h"
+
+static int parse_item(const char *key, const char *value) {
+ assert_se(key);
+
+ log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
+ return 0;
+}
+
+static void test_parse_proc_cmdline(void) {
+ assert_se(parse_proc_cmdline(parse_item) >= 0);
+}
+
+static void test_runlevel_to_target(void) {
+ assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+ assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
+}
+
+int main(void) {
+ log_parse_environment();
+ log_open();
+
+ test_parse_proc_cmdline();
+ test_runlevel_to_target();
+
+ return 0;
+}
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
index c2152269f8..7545ad3764 100644
--- a/src/test/test-selinux.c
+++ b/src/test/test-selinux.c
@@ -23,7 +23,9 @@
#include "fd-util.h"
#include "log.h"
#include "selinux-util.h"
+#include "string-util.h"
#include "time-util.h"
+#include "util.h"
static void test_testing(void) {
bool b;
@@ -31,18 +33,18 @@ static void test_testing(void) {
log_info("============ %s ==========", __func__);
b = mac_selinux_use();
- log_info("mac_selinux_use → %d", b);
+ log_info("mac_selinux_use → %s", yes_no(b));
b = mac_selinux_have();
- log_info("mac_selinux_have → %d", b);
+ log_info("mac_selinux_have → %s", yes_no(b));
mac_selinux_retest();
b = mac_selinux_use();
- log_info("mac_selinux_use → %d", b);
+ log_info("mac_selinux_use → %s", yes_no(b));
b = mac_selinux_have();
- log_info("mac_selinux_have → %d", b);
+ log_info("mac_selinux_have → %s", yes_no(b));
}
static void test_loading(void) {
@@ -76,16 +78,19 @@ static void test_misc(const char* fname) {
log_info("============ %s ==========", __func__);
r = mac_selinux_get_our_label(&label);
- log_info_errno(r, "mac_selinux_get_our_label → %d (%m), \"%s\"", r, label);
+ log_info_errno(r, "mac_selinux_get_our_label → %d (%m), \"%s\"",
+ r, strnull(label));
r = mac_selinux_get_create_label_from_exe(fname, &label2);
- log_info_errno(r, "mac_selinux_create_label_from_exe → %d (%m), \"%s\"", r, label2);
+ log_info_errno(r, "mac_selinux_create_label_from_exe → %d (%m), \"%s\"",
+ r, strnull(label2));
fd = socket(AF_INET, SOCK_DGRAM, 0);
assert_se(fd >= 0);
r = mac_selinux_get_child_mls_label(fd, fname, label2, &label3);
- log_info_errno(r, "mac_selinux_get_child_mls_label → %d (%m), \"%s\"", r, label3);
+ log_info_errno(r, "mac_selinux_get_child_mls_label → %d (%m), \"%s\"",
+ r, strnull(label3));
}
static void test_create_file_prepare(const char* fname) {
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
index 3083501ce9..671eb869cb 100644
--- a/src/test/test-signal-util.c
+++ b/src/test/test-signal-util.c
@@ -17,6 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <signal.h>
+#include <unistd.h>
+
+#include "macro.h"
#include "signal-util.h"
static void test_block_signals(void) {
@@ -44,6 +48,20 @@ static void test_block_signals(void) {
assert_se(sigismember(&ss, SIGVTALRM) == 0);
}
+static void test_ignore_signals(void) {
+ assert_se(ignore_signals(SIGINT, -1) >= 0);
+ assert_se(kill(getpid(), SIGINT) >= 0);
+ assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+ assert_se(kill(getpid(), SIGUSR1) >= 0);
+ assert_se(kill(getpid(), SIGUSR2) >= 0);
+ assert_se(kill(getpid(), SIGTERM) >= 0);
+ assert_se(kill(getpid(), SIGPIPE) >= 0);
+ assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_block_signals();
+ test_ignore_signals();
+
+ return 0;
}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
new file mode 100644
index 0000000000..a10227f823
--- /dev/null
+++ b/src/test/test-stat-util.c
@@ -0,0 +1,68 @@
+/***
+ 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+#include "stat-util.h"
+
+static void test_files_same(void) {
+ _cleanup_close_ int fd = -1;
+ char name[] = "/tmp/test-files_same.XXXXXX";
+ char name_alias[] = "/tmp/test-files_same.alias";
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_alias) >= 0);
+
+ assert_se(files_same(name, name));
+ assert_se(files_same(name, name_alias));
+
+ unlink(name);
+ unlink(name_alias);
+}
+
+static void test_is_symlink(void) {
+ char name[] = "/tmp/test-is_symlink.XXXXXX";
+ char name_link[] = "/tmp/test-is_symlink.link";
+ _cleanup_close_ int fd = -1;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_link) >= 0);
+
+ assert_se(is_symlink(name) == 0);
+ assert_se(is_symlink(name_link) == 1);
+ assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
+
+
+ unlink(name);
+ unlink(name_link);
+}
+
+int main(int argc, char *argv[]) {
+ test_files_same();
+ test_is_symlink();
+
+ return 0;
+}
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 9b48e95998..d0f84d70bc 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -17,7 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "macro.h"
#include "string-util.h"
+#include "strv.h"
static void test_string_erase(void) {
char *x;
@@ -97,9 +100,271 @@ static void test_ascii_strcasecmp_nn(void) {
assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
}
+static void test_streq_ptr(void) {
+ assert_se(streq_ptr(NULL, NULL));
+ assert_se(!streq_ptr("abc", "cdef"));
+}
+
+static void test_strstrip(void) {
+ char *r;
+ char input[] = " hello, waldo. ";
+
+ r = strstrip(input);
+ assert_se(streq(r, "hello, waldo."));
+}
+
+static void test_strextend(void) {
+ _cleanup_free_ char *str = strdup("0123");
+ strextend(&str, "456", "78", "9", NULL);
+ assert_se(streq(str, "0123456789"));
+}
+
+static void test_strrep(void) {
+ _cleanup_free_ char *one, *three, *zero;
+ one = strrep("waldo", 1);
+ three = strrep("waldo", 3);
+ zero = strrep("waldo", 0);
+
+ assert_se(streq(one, "waldo"));
+ assert_se(streq(three, "waldowaldowaldo"));
+ assert_se(streq(zero, ""));
+}
+
+
+static void test_strappend(void) {
+ _cleanup_free_ char *t1, *t2, *t3, *t4;
+
+ t1 = strappend(NULL, NULL);
+ assert_se(streq(t1, ""));
+
+ t2 = strappend(NULL, "suf");
+ assert_se(streq(t2, "suf"));
+
+ t3 = strappend("pre", NULL);
+ assert_se(streq(t3, "pre"));
+
+ t4 = strappend("pre", "suf");
+ assert_se(streq(t4, "presuf"));
+}
+
+static void test_string_has_cc(void) {
+ assert_se(string_has_cc("abc\1", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t\a"));
+
+ assert_se(!string_has_cc("abc\t\t", "\t"));
+ assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
+ assert_se(!string_has_cc("a\ab\tc", "\t\a"));
+}
+
+static void test_ascii_strlower(void) {
+ char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
+ assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
+}
+
+static void test_strshorten(void) {
+ char s[] = "foobar";
+
+ assert_se(strlen(strshorten(s, 6)) == 6);
+ assert_se(strlen(strshorten(s, 12)) == 6);
+ assert_se(strlen(strshorten(s, 2)) == 2);
+ assert_se(strlen(strshorten(s, 0)) == 0);
+}
+
+static void test_strjoina(void) {
+ char *actual;
+
+ actual = strjoina("", "foo", "bar");
+ assert_se(streq(actual, "foobar"));
+
+ actual = strjoina("foo", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo", "", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo");
+ assert_se(streq(actual, "foo"));
+
+ actual = strjoina(NULL);
+ assert_se(streq(actual, ""));
+
+ actual = strjoina(NULL, "foo");
+ assert_se(streq(actual, ""));
+
+ actual = strjoina("foo", NULL, "bar");
+ assert_se(streq(actual, "foo"));
+}
+
+static void test_strcmp_ptr(void) {
+ assert_se(strcmp_ptr(NULL, NULL) == 0);
+ assert_se(strcmp_ptr("", NULL) > 0);
+ assert_se(strcmp_ptr("foo", NULL) > 0);
+ assert_se(strcmp_ptr(NULL, "") < 0);
+ assert_se(strcmp_ptr(NULL, "bar") < 0);
+ assert_se(strcmp_ptr("foo", "bar") > 0);
+ assert_se(strcmp_ptr("bar", "baz") < 0);
+ assert_se(strcmp_ptr("foo", "foo") == 0);
+ assert_se(strcmp_ptr("", "") == 0);
+}
+
+static void test_foreach_word(void) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+ const char test[] = "test abc d\te f ";
+ const char * const expected[] = {
+ "test",
+ "abc",
+ "d",
+ "e",
+ "f",
+ "",
+ NULL
+ };
+
+ FOREACH_WORD(word, l, test, state)
+ assert_se(strneq(expected[i++], word, l));
+}
+
+static void check(const char *test, char** expected, bool trailing) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+
+ printf("<<<%s>>>\n", test);
+ FOREACH_WORD_QUOTED(word, l, test, state) {
+ _cleanup_free_ char *t = NULL;
+
+ assert_se(t = strndup(word, l));
+ assert_se(strneq(expected[i++], word, l));
+ printf("<%s>\n", t);
+ }
+ printf("<<<%s>>>\n", state);
+ assert_se(expected[i] == NULL);
+ assert_se(isempty(state) == !trailing);
+}
+
+static void test_foreach_word_quoted(void) {
+ check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
+ STRV_MAKE("test",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "",
+ "",
+ "hhh",
+ "",
+ "",
+ "a b c"),
+ false);
+
+ check("test \"xxx",
+ STRV_MAKE("test"),
+ true);
+
+ check("test\\",
+ STRV_MAKE_EMPTY,
+ true);
+}
+
+static void test_endswith(void) {
+ assert_se(endswith("foobar", "bar"));
+ assert_se(endswith("foobar", ""));
+ assert_se(endswith("foobar", "foobar"));
+ assert_se(endswith("", ""));
+
+ assert_se(!endswith("foobar", "foo"));
+ assert_se(!endswith("foobar", "foobarfoofoo"));
+}
+
+static void test_endswith_no_case(void) {
+ assert_se(endswith_no_case("fooBAR", "bar"));
+ assert_se(endswith_no_case("foobar", ""));
+ assert_se(endswith_no_case("foobar", "FOOBAR"));
+ assert_se(endswith_no_case("", ""));
+
+ assert_se(!endswith_no_case("foobar", "FOO"));
+ assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
+}
+
+static void test_delete_chars(void) {
+ char *r;
+ char input[] = " hello, waldo. abc";
+
+ r = delete_chars(input, WHITESPACE);
+ assert_se(streq(r, "hello,waldo.abc"));
+}
+
+static void test_in_charset(void) {
+ assert_se(in_charset("dddaaabbbcccc", "abcd"));
+ assert_se(!in_charset("dddaaabbbcccc", "abc f"));
+}
+
+static void test_split_pair(void) {
+ _cleanup_free_ char *a = NULL, *b = NULL;
+
+ assert_se(split_pair("", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("", "=", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
+ assert_se(streq(a, "foo"));
+ assert_se(streq(b, "bar"));
+ free(a);
+ free(b);
+ assert_se(split_pair("==", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, ""));
+ free(a);
+ free(b);
+
+ assert_se(split_pair("===", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, "="));
+}
+
+static void test_first_word(void) {
+ assert_se(first_word("Hello", ""));
+ assert_se(first_word("Hello", "Hello"));
+ assert_se(first_word("Hello world", "Hello"));
+ assert_se(first_word("Hello\tworld", "Hello"));
+ assert_se(first_word("Hello\nworld", "Hello"));
+ assert_se(first_word("Hello\rworld", "Hello"));
+ assert_se(first_word("Hello ", "Hello"));
+
+ assert_se(!first_word("Hello", "Hellooo"));
+ assert_se(!first_word("Hello", "xxxxx"));
+ assert_se(!first_word("Hellooo", "Hello"));
+}
+
int main(int argc, char *argv[]) {
test_string_erase();
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
+ test_streq_ptr();
+ test_strstrip();
+ test_strextend();
+ test_strrep();
+ test_strappend();
+ test_string_has_cc();
+ test_ascii_strlower();
+ test_strshorten();
+ test_strjoina();
+ test_strcmp_ptr();
+ test_foreach_word();
+ test_foreach_word_quoted();
+ test_endswith();
+ test_endswith_no_case();
+ test_delete_chars();
+ test_in_charset();
+ test_split_pair();
+ test_first_word();
+
return 0;
}
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index ef451c6abf..fea1f848cd 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -660,6 +660,25 @@ static void test_strv_make_nulstr(void) {
test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
}
+static void test_foreach_string(void) {
+ const char * const t[] = {
+ "foo",
+ "bar",
+ "waldo",
+ NULL
+ };
+ const char *x;
+ unsigned i = 0;
+
+ FOREACH_STRING(x, "foo", "bar", "waldo")
+ assert_se(streq_ptr(t[i++], x));
+
+ assert_se(i == 3);
+
+ FOREACH_STRING(x, "zzz")
+ assert_se(streq(x, "zzz"));
+}
+
int main(int argc, char *argv[]) {
test_specifier_printf();
test_strv_foreach();
@@ -724,5 +743,7 @@ int main(int argc, char *argv[]) {
test_strv_extend_n();
test_strv_make_nulstr();
+ test_foreach_string();
+
return 0;
}
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index d01789fe08..64ef08652c 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -40,11 +40,11 @@ static int fake_filesystems(void) {
const char *target;
const char *error;
} fakefss[] = {
- { "test/sys", "/sys", "failed to mount test /sys" },
- { "test/dev", "/dev", "failed to mount test /dev" },
- { "test/run", "/run", "failed to mount test /run" },
- { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" },
- { "test/run", UDEVLIBEXECDIR "/rules.d","failed to mount empty " UDEVLIBEXECDIR "/rules.d" },
+ { "test/tmpfs/sys", "/sys", "failed to mount test /sys" },
+ { "test/dev", "/dev", "failed to mount test /dev" },
+ { "test/run", "/run", "failed to mount test /run" },
+ { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" },
+ { "test/run", UDEVLIBEXECDIR "/rules.d","failed to mount empty " UDEVLIBEXECDIR "/rules.d" },
};
unsigned int i;
int err;
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index 42c6a8d5e2..8d1ec19f17 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -37,6 +37,30 @@ static void test_gid_to_name_one(gid_t gid, const char *name) {
assert_se(streq_ptr(t, name));
}
+static void test_parse_uid(void) {
+ int r;
+ uid_t uid;
+
+ r = parse_uid("100", &uid);
+ assert_se(r == 0);
+ assert_se(uid == 100);
+
+ r = parse_uid("65535", &uid);
+ assert_se(r == -ENXIO);
+
+ r = parse_uid("asdsdas", &uid);
+ assert_se(r == -EINVAL);
+}
+
+static void test_uid_ptr(void) {
+
+ assert_se(UID_TO_PTR(0) != NULL);
+ assert_se(UID_TO_PTR(1000) != NULL);
+
+ assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
+ assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
+}
+
int main(int argc, char*argv[]) {
test_uid_to_name_one(0, "root");
@@ -48,5 +72,8 @@ int main(int argc, char*argv[]) {
test_gid_to_name_one(0xFFFF, "65535");
test_gid_to_name_one(0xFFFFFFFF, "4294967295");
+ test_parse_uid();
+ test_uid_ptr();
+
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9a8a265790..05cb1eae76 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -19,47 +19,16 @@
***/
#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/xattr.h>
#include <unistd.h>
-#include "alloc-util.h"
-#include "conf-parser.h"
-#include "cpu-set-util.h"
#include "def.h"
-#include "escape.h"
-#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
-#include "fstab-util.h"
-#include "glob-util.h"
-#include "hexdecoct.h"
-#include "io-util.h"
-#include "mkdir.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
#include "rm-rf.h"
-#include "signal-util.h"
-#include "special.h"
-#include "stat-util.h"
#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
#include "util.h"
-#include "virt.h"
-#include "web-util.h"
-#include "xattr-util.h"
-
-static void test_streq_ptr(void) {
- assert_se(streq_ptr(NULL, NULL));
- assert_se(!streq_ptr("abc", "cdef"));
-}
static void test_align_power2(void) {
unsigned long i, p2;
@@ -151,19 +120,6 @@ static void test_container_of(void) {
v1) == &myval);
}
-static void test_alloca(void) {
- static const uint8_t zero[997] = { };
- char *t;
-
- t = alloca_align(17, 512);
- assert_se(!((uintptr_t)t & 0xff));
- memzero(t, 17);
-
- t = alloca0_align(997, 1024);
- assert_se(!((uintptr_t)t & 0x1ff));
- assert_se(!memcmp(t, zero, 997));
-}
-
static void test_div_round_up(void) {
int div;
@@ -197,544 +153,6 @@ static void test_div_round_up(void) {
assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
}
-static void test_first_word(void) {
- assert_se(first_word("Hello", ""));
- assert_se(first_word("Hello", "Hello"));
- assert_se(first_word("Hello world", "Hello"));
- assert_se(first_word("Hello\tworld", "Hello"));
- assert_se(first_word("Hello\nworld", "Hello"));
- assert_se(first_word("Hello\rworld", "Hello"));
- assert_se(first_word("Hello ", "Hello"));
-
- assert_se(!first_word("Hello", "Hellooo"));
- assert_se(!first_word("Hello", "xxxxx"));
- assert_se(!first_word("Hellooo", "Hello"));
-}
-
-static void test_close_many(void) {
- int fds[3];
- char name0[] = "/tmp/test-close-many.XXXXXX";
- char name1[] = "/tmp/test-close-many.XXXXXX";
- char name2[] = "/tmp/test-close-many.XXXXXX";
-
- fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
- fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
- fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
-
- close_many(fds, 2);
-
- assert_se(fcntl(fds[0], F_GETFD) == -1);
- assert_se(fcntl(fds[1], F_GETFD) == -1);
- assert_se(fcntl(fds[2], F_GETFD) >= 0);
-
- safe_close(fds[2]);
-
- unlink(name0);
- unlink(name1);
- unlink(name2);
-}
-
-static void test_parse_uid(void) {
- int r;
- uid_t uid;
-
- r = parse_uid("100", &uid);
- assert_se(r == 0);
- assert_se(uid == 100);
-
- r = parse_uid("65535", &uid);
- assert_se(r == -ENXIO);
-
- r = parse_uid("asdsdas", &uid);
- assert_se(r == -EINVAL);
-}
-
-static void test_strappend(void) {
- _cleanup_free_ char *t1, *t2, *t3, *t4;
-
- t1 = strappend(NULL, NULL);
- assert_se(streq(t1, ""));
-
- t2 = strappend(NULL, "suf");
- assert_se(streq(t2, "suf"));
-
- t3 = strappend("pre", NULL);
- assert_se(streq(t3, "pre"));
-
- t4 = strappend("pre", "suf");
- assert_se(streq(t4, "presuf"));
-}
-
-static void test_strstrip(void) {
- char *r;
- char input[] = " hello, waldo. ";
-
- r = strstrip(input);
- assert_se(streq(r, "hello, waldo."));
-}
-
-static void test_delete_chars(void) {
- char *r;
- char input[] = " hello, waldo. abc";
-
- r = delete_chars(input, WHITESPACE);
- assert_se(streq(r, "hello,waldo.abc"));
-}
-
-static void test_in_charset(void) {
- assert_se(in_charset("dddaaabbbcccc", "abcd"));
- assert_se(!in_charset("dddaaabbbcccc", "abc f"));
-}
-
-static void test_hexchar(void) {
- assert_se(hexchar(0xa) == 'a');
- assert_se(hexchar(0x0) == '0');
-}
-
-static void test_unhexchar(void) {
- assert_se(unhexchar('a') == 0xA);
- assert_se(unhexchar('A') == 0xA);
- assert_se(unhexchar('0') == 0x0);
-}
-
-static void test_base32hexchar(void) {
- assert_se(base32hexchar(0) == '0');
- assert_se(base32hexchar(9) == '9');
- assert_se(base32hexchar(10) == 'A');
- assert_se(base32hexchar(31) == 'V');
-}
-
-static void test_unbase32hexchar(void) {
- assert_se(unbase32hexchar('0') == 0);
- assert_se(unbase32hexchar('9') == 9);
- assert_se(unbase32hexchar('A') == 10);
- assert_se(unbase32hexchar('V') == 31);
- assert_se(unbase32hexchar('=') == -EINVAL);
-}
-
-static void test_base64char(void) {
- assert_se(base64char(0) == 'A');
- assert_se(base64char(26) == 'a');
- assert_se(base64char(63) == '/');
-}
-
-static void test_unbase64char(void) {
- assert_se(unbase64char('A') == 0);
- assert_se(unbase64char('Z') == 25);
- assert_se(unbase64char('a') == 26);
- assert_se(unbase64char('z') == 51);
- assert_se(unbase64char('0') == 52);
- assert_se(unbase64char('9') == 61);
- assert_se(unbase64char('+') == 62);
- assert_se(unbase64char('/') == 63);
- assert_se(unbase64char('=') == -EINVAL);
-}
-
-static void test_octchar(void) {
- assert_se(octchar(00) == '0');
- assert_se(octchar(07) == '7');
-}
-
-static void test_unoctchar(void) {
- assert_se(unoctchar('0') == 00);
- assert_se(unoctchar('7') == 07);
-}
-
-static void test_decchar(void) {
- assert_se(decchar(0) == '0');
- assert_se(decchar(9) == '9');
-}
-
-static void test_undecchar(void) {
- assert_se(undecchar('0') == 0);
- assert_se(undecchar('9') == 9);
-}
-
-static void test_unhexmem(void) {
- const char *hex = "efa214921";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
- _cleanup_free_ void *mem = NULL;
- size_t len;
-
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
-
- assert_se((hex2 = hexmem(mem, len)));
-
- free(mem);
-
- assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
-
- free(hex2);
-
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base32hexmem(void) {
- char *b32;
-
- b32 = base32hexmem("", strlen(""), true);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), true);
- assert_se(b32);
- assert_se(streq(b32, "CO======"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNG===="));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU==="));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG="));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8======"));
- free(b32);
-
- b32 = base32hexmem("", strlen(""), false);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), false);
- assert_se(b32);
- assert_se(streq(b32, "CO"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNG"));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU"));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG"));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8"));
- free(b32);
-}
-
-static void test_unbase32hexmem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base64mem(void) {
- char *b64;
-
- assert_se(base64mem("", strlen(""), &b64) == 0);
- assert_se(streq(b64, ""));
- free(b64);
-
- assert_se(base64mem("f", strlen("f"), &b64) == 4);
- assert_se(streq(b64, "Zg=="));
- free(b64);
-
- assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
- assert_se(streq(b64, "Zm8="));
- free(b64);
-
- assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
- assert_se(streq(b64, "Zm9v"));
- free(b64);
-
- assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYg=="));
- free(b64);
-
- assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYmE="));
- free(b64);
-
- assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYmFy"));
- free(b64);
-}
-
-static void test_unbase64mem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
-}
-
-static void test_cescape(void) {
- _cleanup_free_ char *escaped;
-
- assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
- assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
-}
-
-static void test_cunescape(void) {
- _cleanup_free_ char *unescaped;
-
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
- unescaped = mfree(unescaped);
-
- /* incomplete sequences */
- assert_se(cunescape("\\x0", 0, &unescaped) < 0);
- assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x0"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\x", 0, &unescaped) < 0);
- assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\", 0, &unescaped) < 0);
- assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\11", 0, &unescaped) < 0);
- assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\11"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\1", 0, &unescaped) < 0);
- assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\1"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
- assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "ßßΠA"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\073", 0, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, ";"));
-}
-
-static void test_foreach_word(void) {
- const char *word, *state;
- size_t l;
- int i = 0;
- const char test[] = "test abc d\te f ";
- const char * const expected[] = {
- "test",
- "abc",
- "d",
- "e",
- "f",
- "",
- NULL
- };
-
- FOREACH_WORD(word, l, test, state)
- assert_se(strneq(expected[i++], word, l));
-}
-
-static void check(const char *test, char** expected, bool trailing) {
- const char *word, *state;
- size_t l;
- int i = 0;
-
- printf("<<<%s>>>\n", test);
- FOREACH_WORD_QUOTED(word, l, test, state) {
- _cleanup_free_ char *t = NULL;
-
- assert_se(t = strndup(word, l));
- assert_se(strneq(expected[i++], word, l));
- printf("<%s>\n", t);
- }
- printf("<<<%s>>>\n", state);
- assert_se(expected[i] == NULL);
- assert_se(isempty(state) == !trailing);
-}
-
-static void test_foreach_word_quoted(void) {
- check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
- STRV_MAKE("test",
- "a",
- "b",
- "c",
- "d",
- "e",
- "",
- "",
- "hhh",
- "",
- "",
- "a b c"),
- false);
-
- check("test \"xxx",
- STRV_MAKE("test"),
- true);
-
- check("test\\",
- STRV_MAKE_EMPTY,
- true);
-}
-
-static void test_memdup_multiply(void) {
- int org[] = {1, 2, 3};
- int *dup;
-
- dup = (int*)memdup_multiply(org, sizeof(int), 3);
-
- assert_se(dup);
- assert_se(dup[0] == 1);
- assert_se(dup[1] == 2);
- assert_se(dup[2] == 3);
- free(dup);
-}
-
static void test_u64log2(void) {
assert_se(u64log2(0) == 0);
assert_se(u64log2(8) == 3);
@@ -754,210 +172,6 @@ static void test_protect_errno(void) {
assert_se(errno == 12);
}
-static void test_parse_cpu_set(void) {
- cpu_set_t *c = NULL;
- int ncpus;
- int cpu;
-
- /* Simple range (from CPUAffinity example) */
- ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
- c = mfree(c);
-
- /* A more interesting range */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Quoted strings */
- ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Use commas as separators */
- ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Commas with spaces (and trailing comma, space) */
- ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 8; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Ranges */
- ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Ranges with trailing comma, space */
- ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Negative range (returns empty cpu_set) */
- ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
- c = mfree(c);
-
- /* Overlapping ranges */
- ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
- for (cpu = 0; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Mix ranges and individual CPUs */
- ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
- assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 4; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Garbage */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-
- /* Range with garbage */
- ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-
- /* Empty string */
- c = NULL;
- ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus == 0); /* empty string returns 0 */
- assert_se(!c);
-
- /* Runnaway quoted string */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-}
-
-static void test_config_parse_iec_uint64(void) {
- uint64_t offset = 0;
- assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
- assert_se(offset == 4 * 1024 * 1024);
-
- assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
-}
-
-static void test_strextend(void) {
- _cleanup_free_ char *str = strdup("0123");
- strextend(&str, "456", "78", "9", NULL);
- assert_se(streq(str, "0123456789"));
-}
-
-static void test_strrep(void) {
- _cleanup_free_ char *one, *three, *zero;
- one = strrep("waldo", 1);
- three = strrep("waldo", 3);
- zero = strrep("waldo", 0);
-
- assert_se(streq(one, "waldo"));
- assert_se(streq(three, "waldowaldowaldo"));
- assert_se(streq(zero, ""));
-}
-
-static void test_split_pair(void) {
- _cleanup_free_ char *a = NULL, *b = NULL;
-
- assert_se(split_pair("", "", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
- assert_se(split_pair("", "=", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
- assert_se(streq(a, "foo"));
- assert_se(streq(b, "bar"));
- free(a);
- free(b);
- assert_se(split_pair("==", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, ""));
- free(a);
- free(b);
-
- assert_se(split_pair("===", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, "="));
-}
-
-static void test_fstab_node_to_udev_node(void) {
- char *n;
-
- n = fstab_node_to_udev_node("LABEL=applé/jack");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
- free(n);
-
- n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PONIES=awesome");
- puts(n);
- assert_se(streq(n, "PONIES=awesome"));
- free(n);
-
- n = fstab_node_to_udev_node("/dev/xda1");
- puts(n);
- assert_se(streq(n, "/dev/xda1"));
- free(n);
-}
-
-static void test_get_files_in_directory(void) {
- _cleanup_strv_free_ char **l = NULL, **t = NULL;
-
- assert_se(get_files_in_directory("/tmp", &l) >= 0);
- assert_se(get_files_in_directory(".", &t) >= 0);
- assert_se(get_files_in_directory(".", NULL) >= 0);
-}
-
static void test_in_set(void) {
assert_se(IN_SET(1, 1));
assert_se(IN_SET(1, 1, 2, 3, 4));
@@ -968,50 +182,6 @@ static void test_in_set(void) {
assert_se(!IN_SET(0, 1, 2, 3, 4));
}
-static void test_writing_tmpfile(void) {
- char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
- _cleanup_free_ char *contents = NULL;
- size_t size;
- int fd, r;
- struct iovec iov[3];
-
- IOVEC_SET_STRING(iov[0], "abc\n");
- IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
- IOVEC_SET_STRING(iov[2], "");
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- printf("tmpfile: %s", name);
-
- r = writev(fd, iov, 3);
- assert_se(r >= 0);
-
- r = read_full_file(name, &contents, &size);
- assert_se(r == 0);
- printf("contents: %s", contents);
- assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
-
- unlink(name);
-}
-
-static void test_hexdump(void) {
- uint8_t data[146];
- unsigned i;
-
- hexdump(stdout, NULL, 0);
- hexdump(stdout, "", 0);
- hexdump(stdout, "", 1);
- hexdump(stdout, "x", 1);
- hexdump(stdout, "x", 2);
- hexdump(stdout, "foobar", 7);
- hexdump(stdout, "f\nobar", 7);
- hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
-
- for (i = 0; i < ELEMENTSOF(data); i++)
- data[i] = i*2;
-
- hexdump(stdout, data, sizeof(data));
-}
-
static void test_log2i(void) {
assert_se(log2i(1) == 0);
assert_se(log2i(2) == 1);
@@ -1023,341 +193,6 @@ static void test_log2i(void) {
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
}
-static void test_foreach_string(void) {
- const char * const t[] = {
- "foo",
- "bar",
- "waldo",
- NULL
- };
- const char *x;
- unsigned i = 0;
-
- FOREACH_STRING(x, "foo", "bar", "waldo")
- assert_se(streq_ptr(t[i++], x));
-
- assert_se(i == 3);
-
- FOREACH_STRING(x, "zzz")
- assert_se(streq(x, "zzz"));
-}
-
-static void test_filename_is_valid(void) {
- char foo[FILENAME_MAX+2];
- int i;
-
- assert_se(!filename_is_valid(""));
- assert_se(!filename_is_valid("/bar/foo"));
- assert_se(!filename_is_valid("/"));
- assert_se(!filename_is_valid("."));
- assert_se(!filename_is_valid(".."));
-
- for (i=0; i<FILENAME_MAX+1; i++)
- foo[i] = 'a';
- foo[FILENAME_MAX+1] = '\0';
-
- assert_se(!filename_is_valid(foo));
-
- assert_se(filename_is_valid("foo_bar-333"));
- assert_se(filename_is_valid("o.o"));
-}
-
-static void test_string_has_cc(void) {
- assert_se(string_has_cc("abc\1", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t\a"));
-
- assert_se(!string_has_cc("abc\t\t", "\t"));
- assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
- assert_se(!string_has_cc("a\ab\tc", "\t\a"));
-}
-
-static void test_ascii_strlower(void) {
- char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
- assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
-}
-
-static void test_files_same(void) {
- _cleanup_close_ int fd = -1;
- char name[] = "/tmp/test-files_same.XXXXXX";
- char name_alias[] = "/tmp/test-files_same.alias";
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_alias) >= 0);
-
- assert_se(files_same(name, name));
- assert_se(files_same(name, name_alias));
-
- unlink(name);
- unlink(name_alias);
-}
-
-static void test_is_valid_documentation_url(void) {
- assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
- assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
- assert_se(documentation_url_is_valid("file:/foo/foo"));
- assert_se(documentation_url_is_valid("man:systemd.special(7)"));
- assert_se(documentation_url_is_valid("info:bar"));
-
- assert_se(!documentation_url_is_valid("foo:"));
- assert_se(!documentation_url_is_valid("info:"));
- assert_se(!documentation_url_is_valid(""));
-}
-
-static void test_file_in_same_dir(void) {
- char *t;
-
- t = file_in_same_dir("/", "a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("/", "/a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("", "a");
- assert_se(streq(t, "a"));
- free(t);
-
- t = file_in_same_dir("a/", "a");
- assert_se(streq(t, "a/a"));
- free(t);
-
- t = file_in_same_dir("bar/foo", "bar");
- assert_se(streq(t, "bar/bar"));
- free(t);
-}
-
-static void test_endswith(void) {
- assert_se(endswith("foobar", "bar"));
- assert_se(endswith("foobar", ""));
- assert_se(endswith("foobar", "foobar"));
- assert_se(endswith("", ""));
-
- assert_se(!endswith("foobar", "foo"));
- assert_se(!endswith("foobar", "foobarfoofoo"));
-}
-
-static void test_endswith_no_case(void) {
- assert_se(endswith_no_case("fooBAR", "bar"));
- assert_se(endswith_no_case("foobar", ""));
- assert_se(endswith_no_case("foobar", "FOOBAR"));
- assert_se(endswith_no_case("", ""));
-
- assert_se(!endswith_no_case("foobar", "FOO"));
- assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
-}
-
-static void test_close_nointr(void) {
- char name[] = "/tmp/test-test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
- assert_se(close_nointr(fd) < 0);
-
- unlink(name);
-}
-
-
-static void test_unlink_noerrno(void) {
- char name[] = "/tmp/test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
-
- {
- PROTECT_ERRNO;
- errno = -42;
- assert_se(unlink_noerrno(name) >= 0);
- assert_se(errno == -42);
- assert_se(unlink_noerrno(name) < 0);
- assert_se(errno == -42);
- }
-}
-
-static void test_readlink_and_make_absolute(void) {
- char tempdir[] = "/tmp/test-readlink_and_make_absolute";
- char name[] = "/tmp/test-readlink_and_make_absolute/original";
- char name2[] = "test-readlink_and_make_absolute/original";
- char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
- char *r = NULL;
-
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
- assert_se(touch(name) >= 0);
-
- assert_se(symlink(name, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(chdir(tempdir) >= 0);
- assert_se(symlink(name2, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
-}
-
-static void test_ignore_signals(void) {
- assert_se(ignore_signals(SIGINT, -1) >= 0);
- assert_se(kill(getpid(), SIGINT) >= 0);
- assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
- assert_se(kill(getpid(), SIGUSR1) >= 0);
- assert_se(kill(getpid(), SIGUSR2) >= 0);
- assert_se(kill(getpid(), SIGTERM) >= 0);
- assert_se(kill(getpid(), SIGPIPE) >= 0);
- assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
-}
-
-static void test_strshorten(void) {
- char s[] = "foobar";
-
- assert_se(strlen(strshorten(s, 6)) == 6);
- assert_se(strlen(strshorten(s, 12)) == 6);
- assert_se(strlen(strshorten(s, 2)) == 2);
- assert_se(strlen(strshorten(s, 0)) == 0);
-}
-
-static void test_strjoina(void) {
- char *actual;
-
- actual = strjoina("", "foo", "bar");
- assert_se(streq(actual, "foobar"));
-
- actual = strjoina("foo", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- actual = strjoina("foo", "", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- actual = strjoina("foo");
- assert_se(streq(actual, "foo"));
-
- actual = strjoina(NULL);
- assert_se(streq(actual, ""));
-
- actual = strjoina(NULL, "foo");
- assert_se(streq(actual, ""));
-
- actual = strjoina("foo", NULL, "bar");
- assert_se(streq(actual, "foo"));
-}
-
-static void test_is_symlink(void) {
- char name[] = "/tmp/test-is_symlink.XXXXXX";
- char name_link[] = "/tmp/test-is_symlink.link";
- _cleanup_close_ int fd = -1;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_link) >= 0);
-
- assert_se(is_symlink(name) == 0);
- assert_se(is_symlink(name_link) == 1);
- assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
-
-
- unlink(name);
- unlink(name_link);
-}
-
-static void test_search_and_fopen(void) {
- const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(basename(name), "r", "/", dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-
-static void test_search_and_fopen_nulstr(void) {
- const char dirs[] = "/tmp/foo/bar\0/tmp\0";
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-static void test_glob_exists(void) {
- char name[] = "/tmp/test-glob_exists.XXXXXX";
- int fd = -1;
- int r;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 1);
-
- r = unlink(name);
- assert_se(r == 0);
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 0);
-}
-
static void test_execute_directory(void) {
char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
@@ -1402,17 +237,6 @@ static void test_execute_directory(void) {
(void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
}
-static int parse_item(const char *key, const char *value) {
- assert_se(key);
-
- log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
- return 0;
-}
-
-static void test_parse_proc_cmdline(void) {
- assert_se(parse_proc_cmdline(parse_item) >= 0);
-}
-
static void test_raw_clone(void) {
pid_t parent, pid, pid2;
@@ -1438,285 +262,20 @@ static void test_raw_clone(void) {
}
}
-static void test_same_fd(void) {
- _cleanup_close_pair_ int p[2] = { -1, -1 };
- _cleanup_close_ int a = -1, b = -1, c = -1;
-
- assert_se(pipe2(p, O_CLOEXEC) >= 0);
- assert_se((a = dup(p[0])) >= 0);
- assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
- assert_se((c = dup(a)) >= 0);
-
- assert_se(same_fd(p[0], p[0]) > 0);
- assert_se(same_fd(p[1], p[1]) > 0);
- assert_se(same_fd(a, a) > 0);
- assert_se(same_fd(b, b) > 0);
-
- assert_se(same_fd(a, p[0]) > 0);
- assert_se(same_fd(p[0], a) > 0);
- assert_se(same_fd(c, p[0]) > 0);
- assert_se(same_fd(p[0], c) > 0);
- assert_se(same_fd(a, c) > 0);
- assert_se(same_fd(c, a) > 0);
-
- assert_se(same_fd(p[0], p[1]) == 0);
- assert_se(same_fd(p[1], p[0]) == 0);
- assert_se(same_fd(p[0], b) == 0);
- assert_se(same_fd(b, p[0]) == 0);
- assert_se(same_fd(p[1], a) == 0);
- assert_se(same_fd(a, p[1]) == 0);
- assert_se(same_fd(p[1], b) == 0);
- assert_se(same_fd(b, p[1]) == 0);
-
- assert_se(same_fd(a, b) == 0);
- assert_se(same_fd(b, a) == 0);
-}
-
-static void test_uid_ptr(void) {
-
- assert_se(UID_TO_PTR(0) != NULL);
- assert_se(UID_TO_PTR(1000) != NULL);
-
- assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
- assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
-}
-
-static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
- char check[n];
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(ftruncate(fd, 0) >= 0);
- assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
-
- assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
- assert_se(ftruncate(fd, n) >= 0);
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(read(fd, check, n) == (ssize_t) n);
-
- assert_se(memcmp(buffer, check, n) == 0);
-}
-
-static void test_sparse_write(void) {
- const char test_a[] = "test";
- const char test_b[] = "\0\0\0\0test\0\0\0\0";
- const char test_c[] = "\0\0test\0\0\0\0";
- const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
- const char test_e[] = "test\0\0\0\0test";
- _cleanup_close_ int fd = -1;
- char fn[] = "/tmp/sparseXXXXXX";
-
- fd = mkostemp(fn, O_CLOEXEC);
- assert_se(fd >= 0);
- unlink(fn);
-
- test_sparse_write_one(fd, test_a, sizeof(test_a));
- test_sparse_write_one(fd, test_b, sizeof(test_b));
- test_sparse_write_one(fd, test_c, sizeof(test_c));
- test_sparse_write_one(fd, test_d, sizeof(test_d));
- test_sparse_write_one(fd, test_e, sizeof(test_e));
-}
-
-static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
- _cleanup_free_ char *r;
-
- assert_se(r = shell_escape(s, bad));
- assert_se(streq_ptr(r, expected));
-}
-
-static void test_shell_escape(void) {
- test_shell_escape_one("", "", "");
- test_shell_escape_one("\\", "", "\\\\");
- test_shell_escape_one("foobar", "", "foobar");
- test_shell_escape_one("foobar", "o", "f\\o\\obar");
- test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
-}
-
-static void test_shell_maybe_quote_one(const char *s, const char *expected) {
- _cleanup_free_ char *r;
-
- assert_se(r = shell_maybe_quote(s));
- assert_se(streq(r, expected));
-}
-
-static void test_shell_maybe_quote(void) {
-
- test_shell_maybe_quote_one("", "");
- test_shell_maybe_quote_one("\\", "\"\\\\\"");
- test_shell_maybe_quote_one("\"", "\"\\\"\"");
- test_shell_maybe_quote_one("foobar", "foobar");
- test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
- test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
- test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
-}
-
-static void test_tempfn(void) {
- char *ret = NULL, *p;
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-}
-
-static void test_strcmp_ptr(void) {
- assert_se(strcmp_ptr(NULL, NULL) == 0);
- assert_se(strcmp_ptr("", NULL) > 0);
- assert_se(strcmp_ptr("foo", NULL) > 0);
- assert_se(strcmp_ptr(NULL, "") < 0);
- assert_se(strcmp_ptr(NULL, "bar") < 0);
- assert_se(strcmp_ptr("foo", "bar") > 0);
- assert_se(strcmp_ptr("bar", "baz") < 0);
- assert_se(strcmp_ptr("foo", "foo") == 0);
- assert_se(strcmp_ptr("", "") == 0);
-}
-
-static void test_fgetxattrat_fake(void) {
- char t[] = "/var/tmp/xattrtestXXXXXX";
- _cleanup_close_ int fd = -1;
- const char *x;
- char v[3] = {};
- int r;
-
- assert_se(mkdtemp(t));
- x = strjoina(t, "/test");
- assert_se(touch(x) >= 0);
-
- r = setxattr(x, "user.foo", "bar", 3, 0);
- if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
- goto cleanup;
- assert_se(r >= 0);
-
- fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
- assert_se(fd >= 0);
-
- assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
- assert_se(memcmp(v, "bar", 3) == 0);
-
- safe_close(fd);
- fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
- assert_se(fd >= 0);
- assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
-
-cleanup:
- assert_se(unlink(x) >= 0);
- assert_se(rmdir(t) >= 0);
-}
-
-static void test_runlevel_to_target(void) {
- assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
- assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
- assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
-}
-
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- test_streq_ptr();
test_align_power2();
test_max();
test_container_of();
- test_alloca();
test_div_round_up();
- test_first_word();
- test_close_many();
- test_parse_uid();
- test_strappend();
- test_strstrip();
- test_delete_chars();
- test_in_charset();
- test_hexchar();
- test_unhexchar();
- test_base32hexchar();
- test_unbase32hexchar();
- test_base64char();
- test_unbase64char();
- test_octchar();
- test_unoctchar();
- test_decchar();
- test_undecchar();
- test_unhexmem();
- test_base32hexmem();
- test_unbase32hexmem();
- test_base64mem();
- test_unbase64mem();
- test_cescape();
- test_cunescape();
- test_foreach_word();
- test_foreach_word_quoted();
- test_memdup_multiply();
test_u64log2();
test_protect_errno();
- test_parse_cpu_set();
- test_config_parse_iec_uint64();
- test_strextend();
- test_strrep();
- test_split_pair();
- test_fstab_node_to_udev_node();
- test_get_files_in_directory();
test_in_set();
- test_writing_tmpfile();
- test_hexdump();
test_log2i();
- test_foreach_string();
- test_filename_is_valid();
- test_string_has_cc();
- test_ascii_strlower();
- test_files_same();
- test_is_valid_documentation_url();
- test_file_in_same_dir();
- test_endswith();
- test_endswith_no_case();
- test_close_nointr();
- test_unlink_noerrno();
- test_readlink_and_make_absolute();
- test_ignore_signals();
- test_strshorten();
- test_strjoina();
- test_is_symlink();
- test_search_and_fopen();
- test_search_and_fopen_nulstr();
- test_glob_exists();
test_execute_directory();
- test_parse_proc_cmdline();
test_raw_clone();
- test_same_fd();
- test_uid_ptr();
- test_sparse_write();
- test_shell_escape();
- test_shell_maybe_quote();
- test_tempfn();
- test_strcmp_ptr();
- test_fgetxattrat_fake();
- test_runlevel_to_target();
return 0;
}
diff --git a/src/test/test-web-util.c b/src/test/test-web-util.c
new file mode 100644
index 0000000000..79a3a13af6
--- /dev/null
+++ b/src/test/test-web-util.c
@@ -0,0 +1,39 @@
+/***
+ 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 "macro.h"
+#include "web-util.h"
+
+static void test_is_valid_documentation_url(void) {
+ assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
+ assert_se(documentation_url_is_valid("file:/foo/foo"));
+ assert_se(documentation_url_is_valid("man:systemd.special(7)"));
+ assert_se(documentation_url_is_valid("info:bar"));
+
+ assert_se(!documentation_url_is_valid("foo:"));
+ assert_se(!documentation_url_is_valid("info:"));
+ assert_se(!documentation_url_is_valid(""));
+}
+
+int main(int argc, char *argv[]) {
+ test_is_valid_documentation_url();
+
+ return 0;
+}
diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c
new file mode 100644
index 0000000000..267f29426c
--- /dev/null
+++ b/src/test/test-xattr-util.c
@@ -0,0 +1,69 @@
+/***
+ 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 <fcntl.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "xattr-util.h"
+
+static void test_fgetxattrat_fake(void) {
+ char t[] = "/var/tmp/xattrtestXXXXXX";
+ _cleanup_close_ int fd = -1;
+ const char *x;
+ char v[3] = {};
+ int r;
+
+ assert_se(mkdtemp(t));
+ x = strjoina(t, "/test");
+ assert_se(touch(x) >= 0);
+
+ r = setxattr(x, "user.foo", "bar", 3, 0);
+ if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
+ goto cleanup;
+ assert_se(r >= 0);
+
+ fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+
+ assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
+ assert_se(memcmp(v, "bar", 3) == 0);
+
+ safe_close(fd);
+ fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+ assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
+
+cleanup:
+ assert_se(unlink(x) >= 0);
+ assert_se(rmdir(t) >= 0);
+}
+
+int main(void) {
+ test_fgetxattrat_fake();
+
+ return 0;
+}
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index f3487013cf..efd264b34d 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -613,7 +613,7 @@ static int path_set_perms(Item *i, const char *path) {
* with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
* O_PATH. */
- fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Adjusting owner and mode for %s failed: %m", path);
@@ -804,7 +804,7 @@ static int path_set_acls(Item *item, const char *path) {
assert(item);
assert(path);
- fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
@@ -917,10 +917,7 @@ static int parse_attribute_from_arg(Item *item) {
v = attributes[i].value;
- if (mode == MODE_ADD || mode == MODE_SET)
- value |= v;
- else
- value &= ~v;
+ SET_FLAG(value, v, (mode == MODE_ADD || mode == MODE_SET));
mask |= v;
}
diff --git a/src/udev/udev.h b/src/udev/udev.h
index 56590517ef..8433e8d9f2 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -19,6 +19,7 @@
*/
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include "libudev.h"
diff --git a/test/TEST-08-ISSUE-2730/Makefile b/test/TEST-08-ISSUE-2730/Makefile
new file mode 100644
index 0000000000..5e89a29eff
--- /dev/null
+++ b/test/TEST-08-ISSUE-2730/Makefile
@@ -0,0 +1,10 @@
+all:
+ @make -s --no-print-directory -C ../.. all
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all
+setup:
+ @make --no-print-directory -C ../.. all
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup
+clean:
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean
+run:
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run
diff --git a/test/TEST-08-ISSUE-2730/test.sh b/test/TEST-08-ISSUE-2730/test.sh
new file mode 100755
index 0000000000..92e70b828b
--- /dev/null
+++ b/test/TEST-08-ISSUE-2730/test.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2730"
+
+. $TEST_BASE_DIR/test-functions
+SKIP_INITRD=yes
+QEMU_TIMEOUT=180
+FSTYPE=ext4
+
+check_result_qemu() {
+ ret=1
+ mkdir -p $TESTDIR/root
+ mount ${LOOPDEV}p1 $TESTDIR/root
+ [[ -e $TESTDIR/root/testok ]] && ret=0
+ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
+ cp -a $TESTDIR/root/var/log/journal $TESTDIR
+ umount $TESTDIR/root
+ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+ ls -l $TESTDIR/journal/*/*.journal
+ test -s $TESTDIR/failed && ret=$(($ret+1))
+ return $ret
+}
+
+test_run() {
+ run_qemu || return 1
+ check_result_qemu || return 1
+ return 0
+}
+
+test_setup() {
+ create_empty_image
+ mkdir -p $TESTDIR/root
+ mount ${LOOPDEV}p1 $TESTDIR/root
+
+ # Create what will eventually be our root filesystem onto an overlay
+ (
+ LOG_LEVEL=5
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+ setup_basic_environment
+
+ # setup the testsuite service
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/bin/sh -x -c 'mount -o remount,rw /dev/sda1 && echo OK > /testok; systemctl poweroff'
+Type=oneshot
+EOF
+
+ rm $initdir/etc/fstab
+ cat >$initdir/etc/systemd/system/-.mount <<EOF
+[Unit]
+Before=local-fs.target
+
+[Mount]
+What=/dev/sda1
+Where=/
+Type=ext4
+Options=errors=remount-ro,noatime
+
+[Install]
+WantedBy=local-fs.target
+Alias=root.mount
+EOF
+
+ setup_testsuite
+ ) || return 1
+
+ ln -s /etc/systemd/system/-.mount $initdir/etc/systemd/system/root.mount
+ mkdir -p $initdir/etc/systemd/system/local-fs.target.wants
+ ln -s /etc/systemd/system/-.mount $initdir/etc/systemd/system/local-fs.target.wants/-.mount
+
+ # mask some services that we do not want to run in these tests
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+test_cleanup() {
+ umount $TESTDIR/root 2>/dev/null
+ [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+ return 0
+}
+
+do_test "$@"
diff --git a/test/test-execute/exec-capabilityambientset-merge-nfsnobody.service b/test/test-execute/exec-capabilityambientset-merge-nfsnobody.service
new file mode 100644
index 0000000000..00bec581b5
--- /dev/null
+++ b/test/test-execute/exec-capabilityambientset-merge-nfsnobody.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000003000"'
+Type=oneshot
+User=nfsnobody
+AmbientCapabilities=CAP_NET_ADMIN
+AmbientCapabilities=CAP_NET_RAW
diff --git a/test/test-execute/exec-capabilityambientset-nfsnobody.service b/test/test-execute/exec-capabilityambientset-nfsnobody.service
new file mode 100644
index 0000000000..614cfdd584
--- /dev/null
+++ b/test/test-execute/exec-capabilityambientset-nfsnobody.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000003000"'
+Type=oneshot
+User=nfsnobody
+AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
diff --git a/test/test-execute/exec-group-nfsnobody.service b/test/test-execute/exec-group-nfsnobody.service
new file mode 100644
index 0000000000..e02100a869
--- /dev/null
+++ b/test/test-execute/exec-group-nfsnobody.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Group
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nfsnobody"'
+Type=oneshot
+Group=nfsnobody
diff --git a/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service b/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service
new file mode 100644
index 0000000000..e962af8a4b
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
+
+[Service]
+ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G /tmp/test-exec_runtimedirectory-owner); test "$$group" = "nfsnobody"'
+Type=oneshot
+Group=nfsnobody
+User=root
+RuntimeDirectory=test-exec_runtimedirectory-owner
diff --git a/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service b/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service
new file mode 100644
index 0000000000..9393e0a998
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for SystemCallFilter in system mode with User set
+
+[Service]
+ExecStart=/bin/echo "Foo bar"
+Type=oneshot
+User=nfsnobody
+SystemCallFilter=~read write open execve ioperm
+SystemCallFilter=ioctl
+SystemCallFilter=read write open execve
+SystemCallFilter=~ioperm
diff --git a/test/test-execute/exec-systemcallfilter-system-user.service b/test/test-execute/exec-systemcallfilter-system-user.service
new file mode 100644
index 0000000000..462f94133d
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-system-user.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for SystemCallFilter in system mode with User set
+
+[Service]
+ExecStart=/bin/echo "Foo bar"
+Type=oneshot
+User=nobody
+SystemCallFilter=~read write open execve ioperm
+SystemCallFilter=ioctl
+SystemCallFilter=read write open execve
+SystemCallFilter=~ioperm
diff --git a/test/test-execute/exec-user-nfsnobody.service b/test/test-execute/exec-user-nfsnobody.service
new file mode 100644
index 0000000000..aafda3aa26
--- /dev/null
+++ b/test/test-execute/exec-user-nfsnobody.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for User
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$USER" = "nfsnobody"'
+Type=oneshot
+User=nfsnobody
diff --git a/test/test-functions b/test/test-functions
index 6667e0524f..8bbcddab59 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -7,6 +7,8 @@ export PATH
LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || "$ID_LIKE" = "debian" ]] && echo yes)
KERNEL_VER=${KERNEL_VER-$(uname -r)}
KERNEL_MODS="/lib/modules/$KERNEL_VER/"
+QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}"
+FSTYPE="${FSTYPE:-ext3}"
if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2
@@ -78,7 +80,7 @@ $KERNEL_APPEND \
-kernel $KERNEL_BIN \
"
- if [ "$INITRD" ]; then
+ if [[ "$INITRD" && "$SKIP_INITRD" != "yes" ]]; then
QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD"
fi
@@ -86,6 +88,9 @@ $KERNEL_APPEND \
QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
fi
+ if [[ "$QEMU_TIMEOUT" != "infinity" ]]; then
+ QEMU_BIN="timeout --foreground $QEMU_TIMEOUT $QEMU_BIN"
+ fi
( set -x
$QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND" $TESTDIR/rootdisk.img ) || return 1
}
@@ -194,9 +199,23 @@ EOF
chmod 0755 $_valgrind_wrapper
}
+create_strace_wrapper() {
+ local _strace_wrapper=$initdir/$ROOTLIBDIR/systemd-under-strace
+ ddebug "Create $_strace_wrapper"
+ cat >$_strace_wrapper <<EOF
+#!/bin/bash
+
+exec strace -D -o /strace.out $ROOTLIBDIR/systemd "\$@"
+EOF
+ chmod 0755 $_strace_wrapper
+}
+
install_fsck() {
dracut_install /sbin/fsck*
dracut_install -o /bin/fsck*
+
+ # fskc.reiserfs calls reiserfsck. so, install it
+ dracut_install -o reiserfsck
}
install_dmevent() {
@@ -241,7 +260,13 @@ create_empty_image() {
,
EOF
- mkfs.ext3 -L systemd "${LOOPDEV}p1"
+ local _label="-L systemd"
+ # mkfs.reiserfs doesn't know -L. so, use --label instead
+ [[ "$FSTYPE" == "reiserfs" ]] && _label="--label systemd"
+ if ! mkfs -t "${FSTYPE}" ${_label} "${LOOPDEV}p1" -q; then
+ dfatal "Failed to mkfs -t ${FSTYPE}"
+ exit 1
+ fi
}
check_result_nspawn() {
@@ -335,7 +360,7 @@ install_config_files() {
echo systemd-testsuite > $initdir/etc/hostname
# fstab
cat >$initdir/etc/fstab <<EOF
-LABEL=systemd / ext3 rw 0 1
+LABEL=systemd / ${FSTYPE} rw 0 1
EOF
}
diff --git a/test/udev-test.pl b/test/udev-test.pl
index b047493f6b..3c8a480d0f 100755
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -29,6 +29,7 @@ my $udev_bin_gdb = "gdb --args $udev_bin";
my $udev_bin_strace = "strace -efile $udev_bin";
my $udev_dev = "test/dev";
my $udev_run = "test/run";
+my $udev_tmpfs = "test/tmpfs";
my $udev_rules_dir = "$udev_run/udev/rules.d";
my $udev_rules = "$udev_rules_dir/udev-test.rules";
my $EXIT_TEST_SKIP = 77;
@@ -1412,6 +1413,12 @@ sub udev_setup {
chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n";
chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n";
+ system("umount", "$udev_tmpfs");
+ system("rm", "-rf", "$udev_tmpfs");
+ mkdir($udev_tmpfs) || die "unable to create udev_tmpfs: $udev_tmpfs\n";
+ system("mount", "-o", "rw,mode=755,nosuid,noexec,nodev", "-t", "tmpfs", "tmpfs", "$udev_tmpfs") && die "unable to mount tmpfs";
+ system("cp", "-r", "test/sys/", "$udev_tmpfs") && die "unable to copy test/sys";
+
system("rm", "-rf", "$udev_run");
}
@@ -1545,6 +1552,8 @@ print "$error errors occurred\n\n";
# cleanup
system("rm", "-rf", "$udev_dev");
system("rm", "-rf", "$udev_run");
+system("umount", "$udev_tmpfs");
+system("rm", "-rf", "$udev_tmpfs");
if ($error > 0) {
exit(1);
diff --git a/units/ldconfig.service b/units/ldconfig.service
index 994edd9908..0910fff054 100644
--- a/units/ldconfig.service
+++ b/units/ldconfig.service
@@ -10,9 +10,8 @@ Description=Rebuild Dynamic Linker Cache
Documentation=man:ldconfig(8)
DefaultDependencies=no
Conflicts=shutdown.target
-After=systemd-remount-fs.service
+After=local-fs.target
Before=sysinit.target shutdown.target systemd-update-done.service
-ConditionNeedsUpdate=|/etc
ConditionFileNotEmpty=|!/etc/ld.so.cache
[Service]