diff options
185 files changed, 5195 insertions, 2716 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..7514e6a24f 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 \ @@ -1849,11 +1850,21 @@ MANPAGES += \ man/coredumpctl.1 \ man/systemd-coredump.8 MANPAGES_ALIAS += \ - man/coredump.conf.d.5 + man/coredump.conf.d.5 \ + man/systemd-coredump.socket.8 \ + man/systemd-coredump@.service.8 man/coredump.conf.d.5: man/coredump.conf.5 +man/systemd-coredump.socket.8: man/systemd-coredump.8 +man/systemd-coredump@.service.8: man/systemd-coredump.8 man/coredump.conf.d.html: man/coredump.conf.html $(html-alias) +man/systemd-coredump.socket.html: man/systemd-coredump.html + $(html-alias) + +man/systemd-coredump@.service.html: man/systemd-coredump.html + $(html-alias) + endif if ENABLE_EFI @@ -1960,15 +1971,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 +2496,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 +2662,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 5651784c99..6ee5aaa403 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 && \ @@ -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). @@ -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: @@ -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..7b9e64a0f6 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> @@ -878,7 +889,7 @@ AM_CONDITIONAL(HAVE_MICROHTTPD, [test "$have_microhttpd" = "yes"]) have_libcurl=no AC_ARG_ENABLE(libcurl, AS_HELP_STRING([--disable-libcurl], [disable libcurl support])) if test "x$enable_libcurl" != "xno"; then - PKG_CHECK_MODULES(LIBCURL, [libcurl], + PKG_CHECK_MODULES(LIBCURL, [libcurl >= 7.32.0], [AC_DEFINE(HAVE_LIBCURL, 1, [Define if libcurl is available]) have_libcurl=yes M4_DEFINES="$M4_DEFINES -DHAVE_LIBCURL"], @@ -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/coredump.conf.xml b/man/coredump.conf.xml index a0a497b467..2064a96523 100644 --- a/man/coredump.conf.xml +++ b/man/coredump.conf.xml @@ -60,7 +60,14 @@ <para>These files configure the behavior of <citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry>, - a handler for core dumps invoked by the kernel.</para> + a handler for core dumps invoked by the kernel. Whether <command>systemd-coredump</command> is used + is determined by the kernel's + <varname>kernel.core_pattern</varname> <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry> + setting. See + <citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry> + and + <citerefentry project='man-pages'><refentrytitle>core</refentrytitle><manvolnum>5</manvolnum></citerefentry> + pages for the details.</para> </refsect1> <xi:include href="standard-conf.xml" xpointer="main-conf" /> 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..0d8f00106c --- /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 Identifier (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-coredump.xml b/man/systemd-coredump.xml index f1598461ef..51dc27e8d3 100644 --- a/man/systemd-coredump.xml +++ b/man/systemd-coredump.xml @@ -45,11 +45,15 @@ <refnamediv> <refname>systemd-coredump</refname> + <refname>systemd-coredump.socket</refname> + <refname>systemd-coredump@.service</refname> <refpurpose>Log and store core dumps</refpurpose> </refnamediv> <refsynopsisdiv> <para><filename>/usr/lib/systemd/systemd-coredump</filename></para> + <para><filename>systemd-coredump@.service</filename></para> + <para><filename>systemd-coredump.socket</filename></para> </refsynopsisdiv> <refsect1> @@ -60,12 +64,13 @@ signal and dumps core. For it to be used in this capacity, it must be specified by the <varname>kernel.core_pattern</varname> <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry> - setting. Systemd installs - <filename>/usr/lib/sysctl.d/50-coredump.conf</filename> which - configures <varname>kernel.core_pattern</varname> to invoke - <command>systemd-coredump</command>. This file may be masked or - overridden to use a different setting following normal - <citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> rules.</para> + setting. The syntax of this setting is explained in + <citerefentry project='man-pages'><refentrytitle>core</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + Systemd installs <filename>/usr/lib/sysctl.d/50-coredump.conf</filename> which configures + <varname>kernel.core_pattern</varname> to invoke <command>systemd-coredump</command>. + This file may be masked or overridden to use a different setting following normal + <citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> + rules.</para> <para>The behavior of a specific program upon reception of a signal is governed by a few factors which are described in detail @@ -77,18 +82,35 @@ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>). </para> - <para><command>systemd-coredump</command> will log the coredump - including a backtrace if possible, and store the core (contents of - process' memory contents) in an external file on disk in - <filename>/var/lib/systemd/coredump</filename>, or directly in - the journal. This behavior may be modified using - <citerefentry><refentrytitle>coredump.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para> - - <para>Apart from the - <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> - log viewer, + <para>The behaviour of <command>systemd-coredump</command> is configured through + <filename>/etc/systemd/coredump.conf</filename> and other configuration files. See + <citerefentry><refentrytitle>coredump.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for details. By default, <command>systemd-coredump</command> will log the coredump including a + backtrace if possible, and store the core (contents of process' memory contents) in an external + file on disk in <filename>/var/lib/systemd/coredump</filename>.</para> + + <para>When the kernel invokes <command>systemd-coredump</command> to handle a coredump, + it will connect to the socket created by the <filename>systemd-coredump.socket</filename> + unit, which in turn will spawn a <filename>systemd-coredump@.service</filename> instance + to process the coredump. Hence <filename>systemd-coredump.socket</filename> + and <filename>systemd-coredump@.service</filename> are helper units which do the actual + processing of coredumps and are subject to normal service management.</para> + + <para>The log entry and a backtrace are stored in the journal, and can be viewed with + <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. <citerefentry><refentrytitle>coredumpctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> - may be used to list and extract coredumps.</para> + may be used to list and extract coredumps or load them in + <citerefentry project='man-pages'><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>. + </para> + + <para>The coredump helper is invoked anew each time. Therefore, any configuration + changes will take effect on the invocation of <command>systemd-coredump</command>. + If the sysctl configuration is modified, it must be updated in the kernel before + it takes effect, see + <citerefentry><refentrytitle>systemd-sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry> + and + <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>. + </para> </refsect1> <refsect1> 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-sysctl.service.xml b/man/systemd-sysctl.service.xml index 9027ff0f3f..686b2cdef4 100644 --- a/man/systemd-sysctl.service.xml +++ b/man/systemd-sysctl.service.xml @@ -62,24 +62,29 @@ <para><filename>systemd-sysctl.service</filename> is an early boot service that configures <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry> - kernel parameters.</para> + kernel parameters by invoking <command>/usr/lib/systemd/systemd-sysctl</command>.</para> - <para>If invoked with no arguments, it applies all directives from - all configuration files in - <citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> - are searched for a matching file. If one or more filenames are passed on - the command line, only the directives in these files are applied. - </para> + <para>When invoked with no arguments, <command>/usr/lib/systemd/systemd-sysctl</command> applies + all directives from configuration files listed in + <citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + If one or more filenames are passed on the command line, only the directives in these files are + applied.</para> + + <para>In addition, <option>--prefix=</option> option may be used to limit which sysctl + settings are applied.</para> <para>See <citerefentry project='man-pages'><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> - for information about the configuration of this service.</para> + for information about the configuration of sysctl settings. After sysctl configuration is + changed on disk, it must be written to the files in <filename>/proc/sys</filename> before it + takes effect. It is possible to update specific settings, or simply to reload all configuration, + see Examples below.</para> </refsect1> <refsect1><title>Options</title> <variablelist> - <varlistentry id='path'> - <term><option>--path=</option></term> + <varlistentry id='prefix'> + <term><option>--prefix=</option></term> <listitem> <para>Only apply rules with the specified prefix.</para> </listitem> @@ -92,6 +97,50 @@ </refsect1> <refsect1> + <title>Examples</title> + + <example> + <title>Reset all sysctl settings</title> + + <programlisting>systemctl restart systemd-sysctl</programlisting> + </example> + + <example> + <title>View coredump handler configuration</title> + + <programlisting># sysctl kernel.core_pattern +kernel.core_pattern = |/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t %P %I +</programlisting> + </example> + + <example> + <title>Update coredump handler configuration</title> + + <programlisting># /usr/lib/systemd/systemd-sysctl --prefix kernel.core_pattern</programlisting> + + <para>This searches all the directories listed in + <citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for configuration files and writes <filename>/proc/sys/kernel/core_pattern</filename>.</para> + </example> + + <example> + <title>Update coredump handler configuration according to a specific file</title> + + <programlisting># /usr/lib/systemd/systemd-sysctl 50-coredump.conf</programlisting> + + <para>This applies all the settings found in <filename>50-coredump.conf</filename>. + Either <filename>/etc/sysctl.d/50-coredump.conf</filename>, or + <filename>/run/sysctl.d/50-coredump.conf</filename>, or + <filename>/usr/lib/sysctl.d/50-coredump.conf</filename> will be used, in the order + of preference.</para> + </example> + + <para>See + <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry> + for various ways to directly apply sysctl settings.</para> + </refsect1> + + <refsect1> <title>See Also</title> <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, 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..c14d3770e2 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 Identifier (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..ce900a5db1 100644 --- a/man/systemd.nspawn.xml +++ b/man/systemd.nspawn.xml @@ -224,6 +224,18 @@ </varlistentry> <varlistentry> + <term><varname>KillSignal=</varname></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..e2db4be9ff 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 is the maximum that sendfile and c_f_r accept */ assert(fdf >= 0); assert(fdt >= 0); @@ -67,56 +88,69 @@ 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 */ - if ((uint64_t) m > max_bytes) - m = (size_t) max_bytes; + if (m > max_bytes) + m = 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/parse-util.h b/src/basic/parse-util.h index d8dc26a36e..c407263e16 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -90,6 +90,18 @@ static inline int safe_atoli(const char *s, long int *ret_u) { } #endif +#if SIZE_MAX == UINT_MAX +static inline int safe_atozu(const char *s, size_t *ret_u) { + assert_cc(sizeof(size_t) == sizeof(unsigned)); + return safe_atou(s, ret_u); +} +#else +static inline int safe_atozu(const char *s, size_t *ret_u) { + assert_cc(sizeof(size_t) == sizeof(long unsigned)); + return safe_atolu(s, ret_u); +} +#endif + int safe_atod(const char *s, double *ret_d); int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); 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/machine-id-setup.c b/src/core/machine-id-setup.c index 9e6b3d3292..7b25349c07 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -120,10 +120,7 @@ static int generate_machine_id(char id[34], const char *root) { assert(id); - if (isempty(root)) - dbus_machine_id = "/var/lib/dbus/machine-id"; - else - dbus_machine_id = strjoina(root, "/var/lib/dbus/machine-id"); + dbus_machine_id = prefix_roota(root, "/var/lib/dbus/machine-id"); /* First, try reading the D-Bus machine id, unless it is a symlink */ fd = open(dbus_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); @@ -203,18 +200,8 @@ int machine_id_setup(const char *root, sd_id128_t machine_id) { char id[34]; /* 32 + \n + \0 */ int r; - if (isempty(root)) { - etc_machine_id = "/etc/machine-id"; - run_machine_id = "/run/machine-id"; - } else { - char *x; - - x = strjoina(root, "/etc/machine-id"); - etc_machine_id = path_kill_slashes(x); - - x = strjoina(root, "/run/machine-id"); - run_machine_id = path_kill_slashes(x); - } + etc_machine_id = prefix_roota(root, "/etc/machine-id"); + run_machine_id = prefix_roota(root, "/run/machine-id"); RUN_WITH_UMASK(0000) { /* We create this 0444, to indicate that this isn't really @@ -301,14 +288,7 @@ int machine_id_commit(const char *root) { char id[34]; /* 32 + \n + \0 */ int r; - if (isempty(root)) - etc_machine_id = "/etc/machine-id"; - else { - char *x; - - x = strjoina(root, "/etc/machine-id"); - etc_machine_id = path_kill_slashes(x); - } + etc_machine_id = prefix_roota(root, "/etc/machine-id"); r = path_is_mount_point(etc_machine_id, 0); if (r < 0) 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/triggers.systemd.in b/src/core/triggers.systemd.in index 9e18a39a67..0d8c303136 100644 --- a/src/core/triggers.systemd.in +++ b/src/core/triggers.systemd.in @@ -18,6 +18,8 @@ # along with systemd; If not, see <http://www.gnu.org/licenses/>. # The contents of this are an example to be copied into systemd.spec. +# +# Minimum rpm version supported: 4.13.0 %transfiletriggerin -P 900900 -p <lua> -- @systemunitdir@ /etc/systemd/system -- This script will run after any package is initially installed or 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/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index dac800ebef..27b1e0fb3f 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -664,7 +664,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { #endif } else { if (r == -ENOENT) - log_error("Cannot retrieve coredump from journal nor disk."); + log_error("Cannot retrieve coredump from journal or disk."); else log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); goto error; 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-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c index e61b6bc68f..8ce8e1895e 100644 --- a/src/journal-remote/journal-upload-journal.c +++ b/src/journal-remote/journal-upload-journal.c @@ -25,6 +25,7 @@ #include "log.h" #include "utf8.h" #include "util.h" +#include "sd-daemon.h" /** * Write up to size bytes to buf. Return negative on error, and number of @@ -242,6 +243,22 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) { assert_not_reached("WTF?"); } +static inline void check_update_watchdog(Uploader *u) { + usec_t after; + usec_t elapsed_time; + + if (u->watchdog_usec <= 0) + return; + + after = now(CLOCK_MONOTONIC); + elapsed_time = usec_sub(after, u->watchdog_timestamp); + if (elapsed_time > u->watchdog_usec / 2) { + log_debug("Update watchdog timer"); + sd_notify(false, "WATCHDOG=1"); + u->watchdog_timestamp = after; + } +} + static size_t journal_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { Uploader *u = userp; int r; @@ -252,6 +269,8 @@ static size_t journal_input_callback(void *buf, size_t size, size_t nmemb, void assert(u); assert(nmemb <= SSIZE_MAX / size); + check_update_watchdog(u); + j = u->journal; while (j && filled < size * nmemb) { diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 6e1c3bb9ef..4647cfdeb3 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -463,6 +463,8 @@ static int setup_uploader(Uploader *u, const char *url, const char *state_file) if (r < 0) return log_error_errno(r, "Failed to set up signals: %m"); + (void) sd_watchdog_enabled(false, &u->watchdog_usec); + return load_cursor_state(u); } @@ -494,6 +496,7 @@ static int perform_upload(Uploader *u) { assert(u); + u->watchdog_timestamp = now(CLOCK_MONOTONIC); code = curl_easy_perform(u->easy); if (code) { if (u->error[0]) diff --git a/src/journal-remote/journal-upload.h b/src/journal-remote/journal-upload.h index b8cd04d527..5711905f86 100644 --- a/src/journal-remote/journal-upload.h +++ b/src/journal-remote/journal-upload.h @@ -4,6 +4,7 @@ #include "sd-event.h" #include "sd-journal.h" +#include "time-util.h" typedef enum { ENTRY_CURSOR = 0, /* Nothing actually written yet. */ @@ -48,6 +49,8 @@ typedef struct Uploader { size_t entries_sent; char *last_cursor, *current_cursor; + usec_t watchdog_timestamp; + usec_t watchdog_usec; } Uploader; #define JOURNAL_UPLOAD_POLL_TIMEOUT (10 * USEC_PER_SEC) diff --git a/src/journal/compress.c b/src/journal/compress.c index c43849c46a..ba734b5561 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -112,7 +112,7 @@ int compress_blob_lz4(const void *src, uint64_t src_size, if (src_size < 9) return -ENOBUFS; - r = LZ4_compress_limitedOutput(src, dst + 8, src_size, (int) dst_alloc_size - 8); + r = LZ4_compress_limitedOutput(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8); if (r <= 0) return -ENOBUFS; @@ -176,7 +176,7 @@ int decompress_blob_xz(const void *src, uint64_t src_size, return -ENOMEM; s.avail_out = space - used; - s.next_out = *dst + used; + s.next_out = *(uint8_t**)dst + used; } *dst_size = space - s.avail_out; @@ -215,7 +215,7 @@ int decompress_blob_lz4(const void *src, uint64_t src_size, } else out = *dst; - r = LZ4_decompress_safe(src + 8, out, src_size - 8, size); + r = LZ4_decompress_safe((char*)src + 8, out, src_size - 8, size); if (r < 0 || r != size) return -EBADMSG; @@ -291,7 +291,7 @@ int decompress_startswith_xz(const void *src, uint64_t src_size, if (!(greedy_realloc(buffer, buffer_size, *buffer_size * 2, 1))) return -ENOMEM; - s.next_out = *buffer + *buffer_size - s.avail_out; + s.next_out = *(uint8_t**)buffer + *buffer_size - s.avail_out; } #else @@ -324,7 +324,7 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size, if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1))) return -ENOMEM; - r = LZ4_decompress_safe_partial(src + 8, *buffer, src_size - 8, + r = LZ4_decompress_safe_partial((char*)src + 8, *buffer, src_size - 8, prefix_len + 1, *buffer_size); if (r >= 0) size = (unsigned) r; diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c index 5b2d130cd6..6f6d71435d 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); @@ -162,7 +164,7 @@ int main(int argc, char *argv[]) { arg_duration = x * USEC_PER_SEC; } if (argc == 3) - (void) safe_atolu(argv[2], &arg_start); + (void) safe_atozu(argv[2], &arg_start); else arg_start = getpid(); 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..e787cb69d3 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) + 2)) + 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/.gitignore b/src/network/.gitignore index 8858596489..aca55206b7 100644 --- a/src/network/.gitignore +++ b/src/network/.gitignore @@ -1,2 +1,3 @@ /networkd-network-gperf.c /networkd-netdev-gperf.c +/networkd-gperf.c 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, ÐER_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..fa6ab9ad3b 100644 --- a/src/systemd/sd-lldp.h +++ b/src/systemd/sd-lldp.h @@ -33,6 +33,86 @@ _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..8522e9925c 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/tmpfs/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/sys.tar.xz b/test/sys.tar.xz Binary files differindex 052c77d182..49ee8027b2 100644 --- a/test/sys.tar.xz +++ b/test/sys.tar.xz 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..da0a4e1f6b 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -27,12 +27,19 @@ my $strace = 0; my $udev_bin_valgrind = "valgrind --tool=memcheck --leak-check=yes --track-origins=yes --quiet $udev_bin"; 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_sys = "${udev_tmpfs}/sys"; +my $udev_dev = "${udev_tmpfs}/dev"; my $udev_rules_dir = "$udev_run/udev/rules.d"; my $udev_rules = "$udev_rules_dir/udev-test.rules"; my $EXIT_TEST_SKIP = 77; +my $rules_10k_tags = ""; +for (my $i = 1; $i <= 10000; ++$i) { + $rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n"; +} + my @tests = ( { desc => "no rules", @@ -702,7 +709,7 @@ EOF desc => "big major number test", devpath => "/devices/virtual/misc/misc-fake1", exp_name => "node", - exp_majorminor => "511:1", + exp_majorminor => "4095:1", rules => <<EOF KERNEL=="misc-fake1", SYMLINK+="node" EOF @@ -711,7 +718,7 @@ EOF desc => "big major and big minor number test", devpath => "/devices/virtual/misc/misc-fake89999", exp_name => "node", - exp_majorminor => "511:89999", + exp_majorminor => "4095:89999", rules => <<EOF KERNEL=="misc-fake89999", SYMLINK+="node" EOF @@ -1317,6 +1324,25 @@ KERNEL=="sda", IMPORT{builtin}="path_id" KERNEL=="sda", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/\$env{ID_PATH}" EOF }, + { + desc => "add and match tag", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad" , + rules => <<EOF +SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", TAG+="green" +TAGS=="green", SYMLINK+="found" +TAGS=="blue", SYMLINK+="bad" +EOF + }, + { + desc => "don't crash with lots of tags", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + rules => $rules_10k_tags . <<EOF +TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="found" +EOF + }, ); sub udev { @@ -1329,13 +1355,13 @@ sub udev { close CONF; if ($valgrind > 0) { - system("$udev_bin_valgrind $action $devpath"); + return system("$udev_bin_valgrind $action $devpath"); } elsif ($gdb > 0) { - system("$udev_bin_gdb $action $devpath"); + return system("$udev_bin_gdb $action $devpath"); } elsif ($strace > 0) { - system("$udev_bin_strace $action $devpath"); + return system("$udev_bin_strace $action $devpath"); } else { - system("$udev_bin", "$action", "$devpath"); + return system("$udev_bin", "$action", "$devpath"); } } @@ -1405,23 +1431,34 @@ sub major_minor_test { } sub udev_setup { - system("rm", "-rf", "$udev_dev"); + system("umount", $udev_tmpfs); + rmdir($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"; + mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n"; # setting group and mode of udev_dev ensures the tests work # even if the parent directory has setgid bit enabled. chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n"; chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n"; + system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys"; + system("rm", "-rf", "$udev_run"); } sub run_test { my ($rules, $number) = @_; + my $rc; print "TEST $number: $rules->{desc}\n"; print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n"; - udev("add", $rules->{devpath}, \$rules->{rules}); + $rc = udev("add", $rules->{devpath}, \$rules->{rules}); + if ($rc != 0) { + print "$udev_bin add failed with code $rc\n"; + $error++; + } if (defined($rules->{not_exp_name})) { if ((-e "$udev_dev/$rules->{not_exp_name}") || (-l "$udev_dev/$rules->{not_exp_name}")) { @@ -1462,7 +1499,11 @@ sub run_test { return; } - udev("remove", $rules->{devpath}, \$rules->{rules}); + $rc = udev("remove", $rules->{devpath}, \$rules->{rules}); + if ($rc != 0) { + print "$udev_bin remove failed with code $rc\n"; + $error++; + } if ((-e "$udev_dev/$rules->{exp_name}") || (-l "$udev_dev/$rules->{exp_name}")) { print "remove: error"; @@ -1543,8 +1584,9 @@ if ($list[0]) { print "$error errors occurred\n\n"; # cleanup -system("rm", "-rf", "$udev_dev"); system("rm", "-rf", "$udev_run"); +system("umount", "$udev_tmpfs"); +rmdir($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] |