diff options
96 files changed, 2919 insertions, 1844 deletions
| diff --git a/.gitignore b/.gitignore index 18db046cac..dd887902ad 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 @@ -181,20 +183,26 @@  /test-ellipsize  /test-engine  /test-env-replace +/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 @@ -235,6 +243,7 @@  /test-path-lookup  /test-path-util  /test-prioq +/test-proc-cmdline  /test-process-util  /test-pty  /test-qcow2 @@ -254,6 +263,7 @@  /test-siphash24  /test-sleep  /test-socket-util +/test-stat-util  /test-strbuf  /test-string-util  /test-strip-tab-ansi @@ -273,6 +283,8 @@  /test-util  /test-verbs  /test-watchdog +/test-web-util +/test-xattr-util  /test-xml  /timedatectl  /udevadm @@ -280,6 +292,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..a7e348b1f1 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -1960,15 +1960,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 +2485,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 \ diff --git a/Makefile.am b/Makefile.am index 0f17bad8b1..0f1f79e62d 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 = @@ -1387,19 +1391,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,7 +1413,11 @@ manual_tests += \  endif  tests += \ +	test-daemon \ +	test-log \ +	test-loopback \  	test-engine \ +	test-watchdog \  	test-cgroup-mask \  	test-job-type \  	test-env-replace \ @@ -1426,6 +1432,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 \ @@ -1651,13 +1669,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 +1773,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 @@ -3703,8 +3793,10 @@ endif  endif  endif +tests += \ +	test-libudev +  manual_tests += \ -	test-libudev \  	test-udev  test_libudev_SOURCES = \ @@ -4115,11 +4207,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 \ @@ -5300,6 +5390,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 \ @@ -5348,6 +5440,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 @@ -5444,6 +5537,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 @@ -6067,7 +6161,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   \ @@ -6076,6 +6169,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 && \ @@ -35,7 +35,7 @@ LICENSE:          - except src/udev/* which is (currently still) GPLv2, GPLv2+  REQUIREMENTS: -        Linux kernel >= 3.11 +        Linux kernel >= 3.12          Linux kernel >= 4.2 for unified cgroup hierarchy support          Kernel Config Options: diff --git a/configure.ac b/configure.ac index e55d1a02a6..79340bcca9 100644 --- a/configure.ac +++ b/configure.ac @@ -1487,9 +1487,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)])], @@ -1611,6 +1612,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/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/man/networkd.conf.xml b/man/networkd.conf.xml new file mode 100644 index 0000000000..5e2927ba54 --- /dev/null +++ b/man/networkd.conf.xml @@ -0,0 +1,112 @@ +<?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 Tom Gundersen + +  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 DUID value used by the DHCP protocol. The DUID value +    specified here overrides the DUID that systemd-networkd generates using the machine-id +    from the <filename>/etc/machine-id</filename> file.</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></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> +      <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/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.network.xml b/man/systemd.network.xml index 752a15a4e0..73b9c00543 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>IAIDValue=</varname></term> +        <listitem> +          <para>Identity Association Identifier for the interface. This is a 32-bit value specified in host byte order.</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> diff --git a/man/systemd.nspawn.xml b/man/systemd.nspawn.xml index c07a4b0243..5ec878512a 100644 --- a/man/systemd.nspawn.xml +++ b/man/systemd.nspawn.xml @@ -224,6 +224,18 @@        </varlistentry>        <varlistentry> +        <term><option>KillSignal=</option></term> + +        <listitem><para>Specify the process signal to send to the +        container's PID 1 when nspawn itself receives SIGTERM, in +        order to trigger an orderly shutdown of the container. +        Defaults to SIGRTMIN+3 if <option>Boot=</option> is used +        (on systemd-compatible init systems SIGRTMIN+3 triggers an +        orderly shutdown). For a list of valid signals, see +        <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem> +      </varlistentry> + +      <varlistentry>          <term><varname>Personality=</varname></term>          <listitem><para>Configures the kernel personality for the diff --git a/src/basic/macro.h b/src/basic/macro.h index c34441d75d..b36a95675a 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -23,6 +23,7 @@  #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))) 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/time-util.c b/src/basic/time-util.c index 7ca764abeb..c16460a198 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -47,12 +47,15 @@ static clockid_t map_clock_id(clockid_t c) {          /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will           * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is           * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on -         * those archs. */ +         * those archs. +         * +         * Also, older kernels don't support CLOCK_BOOTTIME: fall back to CLOCK_MONOTONIC. */          switch (c) { +        case CLOCK_BOOTTIME:          case CLOCK_BOOTTIME_ALARM: -                return CLOCK_BOOTTIME; +                return clock_boottime_or_monotonic ();          case CLOCK_REALTIME_ALARM:                  return CLOCK_REALTIME; 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/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/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/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/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/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/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c index 5b2d130cd6..0ef6d36a50 100644 --- a/src/journal/test-compress-benchmark.c +++ b/src/journal/test-compress-benchmark.c @@ -105,6 +105,8 @@ static void test_compress_decompress(const char* label, const char* type,                  int r;                  size = permute(i); +                if (size == 0) +                        continue;                  log_debug("%s %zu %zu", type, i, size); diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index 1d9ec7be82..1bef368852 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, DHCP_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..cb953cb416 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 DHCPDUIDType { +        DHCP_DUID_TYPE_RAW       = 0, +        DHCP_DUID_TYPE_LLT       = 1, +        DHCP_DUID_TYPE_EN        = 2, +        DHCP_DUID_TYPE_LL        = 3, +        DHCP_DUID_TYPE_UUID      = 4, +        _DHCP_DUID_TYPE_MAX, +        _DHCP_DUID_TYPE_INVALID  = -1, +} DHCPDUIDType; +  /* 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,32 @@ 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(be16_t duid_type, size_t duid_len) { +        struct duid d; + +        assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); + +        switch (be16toh(duid_type)) { +        case DHCP_DUID_TYPE_LLT: +                if (duid_len <= sizeof(d.llt)) +                        return -EINVAL; +                break; +        case DHCP_DUID_TYPE_EN: +                if (duid_len != sizeof(d.en)) +                        return -EINVAL; +                break; +        case DHCP_DUID_TYPE_LL: +                if (duid_len <= sizeof(d.ll)) +                        return -EINVAL; +                break; +        case DHCP_DUID_TYPE_UUID: +                if (duid_len != sizeof(d.uuid)) +                        return -EINVAL; +                break; +        default: +                /* 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..190c9baece 100644 --- a/src/libsystemd-network/lldp-neighbor.c +++ b/src/libsystemd-network/lldp-neighbor.c @@ -446,7 +446,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 +457,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) { diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index cb7252bbeb..7c21f42591 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -335,6 +335,34 @@ int config_parse_hwaddr(const char *unit,          return 0;  } +int config_parse_iaid_value(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_value; +        int r; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); +        assert(data); + +        if ((r = safe_atou32(rvalue, &iaid_value)) < 0) { +                log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue); +                return r; +        } + +        *((be32_t *)data) = htobe32(iaid_value); + +        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..d8b551e8ce 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_value(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..b108e35386 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,51 @@ 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, be32_t iaid, +                                 size_t duid_len, struct duid *duid) { +        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 = 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 - sizeof(client->client_id.type)); +                if (r < 0) +                        return r; +                memcpy(&client->client_id.ns.duid, duid, duid_len); +        } + +        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; @@ -469,7 +514,6 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,          if (client->arp_type == ARPHRD_ETHER)                  memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN); -        /* If no client identifier exists, construct an RFC 4361-compliant one */          if (client->client_id_len == 0) {                  size_t duid_len; diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index af4709d788..7cecba120c 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -180,41 +180,30 @@ 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, size_t duid_len, +                             struct duid *duid) { +        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 - sizeof(duid->type)); +                if (r < 0) +                        return r; + +                memcpy(&client->duid, duid, duid_len); +                client->duid_len = duid_len;          } -        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, be32_t iaid) { +        assert_return(client, -EINVAL); +        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + +        client->ia_na.id = iaid;          return 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-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/network/networkctl.c b/src/network/networkctl.c index 0679114f74..6ec7a911ca 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -45,6 +45,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 +148,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 +174,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..4bc92b8171 --- /dev/null +++ b/src/network/networkd-conf.c @@ -0,0 +1,133 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** +  This file is part of systemd. + +  Copyright 2014 Tom Gundersen <teg@jklm.no> + +  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 dhcp_duid_type_table[_DHCP_DUID_TYPE_MAX] = { +        [DHCP_DUID_TYPE_RAW]  = "raw", +        [DHCP_DUID_TYPE_LLT]  = "link-layer-time", +        [DHCP_DUID_TYPE_EN]   = "vendor", +        [DHCP_DUID_TYPE_LL]   = "link-layer", +        [DHCP_DUID_TYPE_UUID] = "uuid" +}; +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_duid_type, DHCPDUIDType); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_duid_type, dhcp_duid_type, DHCPDUIDType, "Failed to parse DHCP DUID type"); + +int config_parse_dhcp_duid_raw( +                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 = (const char *)rvalue; +        size_t count = 0, duid_len = 0; +        Manager *m = userdata; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); +        assert(m); +        assert(m->dhcp_duid_type != _DHCP_DUID_TYPE_INVALID); + +        switch (m->dhcp_duid_type) { +        case DHCP_DUID_TYPE_LLT: +                /* RawData contains DUID-LLT link-layer address (offset 6) */ +                duid_len = 6; +                break; +        case DHCP_DUID_TYPE_EN: +                /* RawData contains DUID-EN identifier (offset 4) */ +                duid_len = 4; +                break; +        case DHCP_DUID_TYPE_LL: +                /* RawData contains DUID-LL link-layer address (offset 2) */ +                duid_len = 2; +                break; +        case DHCP_DUID_TYPE_UUID: +                /* RawData specifies UUID (offset 0) - fall thru */ +        case DHCP_DUID_TYPE_RAW: +                /* First two bytes of RawData is DUID Type - fall thru */ +        default: +                break; +        } + +        if (m->dhcp_duid_type != DHCP_DUID_TYPE_RAW) +                m->dhcp_duid.type = htobe16(m->dhcp_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_len >= 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 DHCP_DUID_TYPE_RAW, first two bytes holds DUID Type */ +                if ((m->dhcp_duid_type == DHCP_DUID_TYPE_RAW) && (count < 2)) { +                        m->dhcp_duid.type |= (byte << (8 * count)); +                        count++; +                        continue; +                } + +                m->dhcp_duid.raw.data[duid_len++] = byte; +        } + +        m->dhcp_duid_len = sizeof(m->dhcp_duid.type) + duid_len; + +        return 0; +} diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h new file mode 100644 index 0000000000..6d9ce010e3 --- /dev/null +++ b/src/network/networkd-conf.h @@ -0,0 +1,32 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright 2014 Tom Gundersen <teg@jklm.no> + +  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" + + +int manager_parse_config_file(Manager *m); + +const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length); + +int config_parse_dhcp_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_dhcp_duid_raw(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..3bbb21295c 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -625,7 +625,13 @@ 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 */ +                r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, +                                                 link->network->iaid_value, +                                                 link->manager->dhcp_duid_len, +                                                 &link->manager->dhcp_duid); +                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..9f59cb3f8a 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -230,6 +230,16 @@ int dhcp6_configure(Link *link) {          if (r < 0)                  goto error; +        r = sd_dhcp6_client_set_iaid(client, link->network->iaid_value); +        if (r < 0) +                goto error; + +        r = sd_dhcp6_client_set_duid(client, +                                     link->manager->dhcp_duid_len, +                                     &link->manager->dhcp_duid); +        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..3ef4155476 --- /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_dhcp_duid_type,            0,            offsetof(Manager, dhcp_duid_type) +DUID.RawData,        config_parse_dhcp_duid_raw,             0,            offsetof(Manager, dhcp_duid) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index ff4bd76554..67b04560cd 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2781,6 +2781,13 @@ 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"); + +                                r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, +                                                                 link->network->iaid_value, +                                                                 link->manager->dhcp_duid_len, +                                                                 &link->manager->dhcp_duid); +                                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 +2797,17 @@ 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_value); +                                if (r < 0) +                                        return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); + +                                r = sd_dhcp6_client_set_duid(link->dhcp6_client, +                                                             link->manager->dhcp_duid_len, +                                                             &link->manager->dhcp_duid); +                                if (r < 0) +                                        return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");                          }                  }          } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index b8cb7f875d..8d443f7b0f 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->dhcp_duid_type = _DHCP_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..7a9a136d5b 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -26,6 +26,7 @@ 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.IAIDValue,                         config_parse_iaid_value,                        0,                             offsetof(Network, iaid_value)  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..491b9a3efa 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -629,10 +629,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..c5530cdfba 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -30,6 +30,7 @@ typedef struct Network Network;  #include "networkd-route.h"  #include "networkd-util.h"  #include "networkd.h" +#include "sparse-endian.h"  #define DHCP_ROUTE_METRIC 1024  #define IPV4LL_ROUTE_METRIC 2048 @@ -144,6 +145,7 @@ struct Network {          struct ether_addr *mac;          unsigned mtu; +        be32_t iaid_value;          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..d815f30610 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -35,6 +35,7 @@ typedef struct Manager Manager;  #include "networkd-link.h"  #include "networkd-network.h"  #include "networkd-util.h" +#include "dhcp-identifier.h"  struct Manager {          sd_netlink *rtnl; @@ -61,6 +62,10 @@ struct Manager {          LIST_HEAD(AddressPool, address_pools);          usec_t network_dirs_ts_usec; + +        DHCPDUIDType dhcp_duid_type; +        size_t dhcp_duid_len; +        struct duid dhcp_duid;  };  extern const char* const network_dirs[]; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 4851c439c9..be07625a03 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" @@ -3284,6 +3285,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..009cc73aec 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -1280,40 +1280,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..1ed1bd96bf 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" 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/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/systemctl/systemctl.c b/src/systemctl/systemctl.c index a62f4bf2f5..180c8f9656 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -152,7 +152,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; @@ -1630,11 +1630,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());                  } @@ -2399,18 +2415,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 +2443,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 +2461,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 +2477,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 +2499,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 +2518,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 +2616,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 +3186,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 +3203,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 +3221,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) { 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..7873cb1e04 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -27,6 +27,7 @@  #include "sd-dhcp-lease.h"  #include "sd-event.h" +#include "sparse-endian.h"  #include "_sd-common.h" @@ -82,6 +83,7 @@ enum {          SD_DHCP_OPTION_END                         = 255,  }; +struct duid;  typedef struct sd_dhcp_client sd_dhcp_client;  typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, @@ -98,6 +100,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, be32_t iaid, +                                 size_t duid_len, struct duid *duid);  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..ebdd017628 100644 --- a/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/sd-dhcp6-client.h @@ -26,6 +26,7 @@  #include "sd-dhcp6-lease.h"  #include "sd-event.h" +#include "sparse-endian.h"  #include "_sd-common.h" @@ -74,6 +75,7 @@ enum {          /* option codes 144-65535 are unassigned */  }; +struct duid;  typedef struct sd_dhcp6_client sd_dhcp6_client;  typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, @@ -85,8 +87,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, size_t duid_len, +                             struct duid *duid); +int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, be32_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/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-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-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-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-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 946808fbec..efd264b34d 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -917,10 +917,7 @@ static int parse_attribute_from_arg(Item *item) {                  v = attributes[i].value; -                if (mode == MODE_ADD || mode == MODE_SET) -                        value |= v; -                else -                        value &= ~v; +                SET_FLAG(value, v, (mode == MODE_ADD || mode == MODE_SET));                  mask |= v;          } diff --git a/src/udev/udev.h b/src/udev/udev.h index 56590517ef..8433e8d9f2 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -19,6 +19,7 @@   */  #include <sys/param.h> +#include <sys/sysmacros.h>  #include <sys/types.h>  #include "libudev.h" diff --git a/test/TEST-08-ISSUE-2730/Makefile b/test/TEST-08-ISSUE-2730/Makefile new file mode 100644 index 0000000000..5e89a29eff --- /dev/null +++ b/test/TEST-08-ISSUE-2730/Makefile @@ -0,0 +1,10 @@ +all: +	@make -s --no-print-directory -C ../.. all +	@basedir=../.. TEST_BASE_DIR=../ ./test.sh --all +setup: +	@make --no-print-directory -C ../.. all +	@basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup +clean: +	@basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean +run: +	@basedir=../.. TEST_BASE_DIR=../ ./test.sh --run diff --git a/test/TEST-08-ISSUE-2730/test.sh b/test/TEST-08-ISSUE-2730/test.sh new file mode 100755 index 0000000000..92e70b828b --- /dev/null +++ b/test/TEST-08-ISSUE-2730/test.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2730" + +. $TEST_BASE_DIR/test-functions +SKIP_INITRD=yes +QEMU_TIMEOUT=180 +FSTYPE=ext4 + +check_result_qemu() { +    ret=1 +    mkdir -p $TESTDIR/root +    mount ${LOOPDEV}p1 $TESTDIR/root +    [[ -e $TESTDIR/root/testok ]] && ret=0 +    [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR +    cp -a $TESTDIR/root/var/log/journal $TESTDIR +    umount $TESTDIR/root +    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed +    ls -l $TESTDIR/journal/*/*.journal +    test -s $TESTDIR/failed && ret=$(($ret+1)) +    return $ret +} + +test_run() { +    run_qemu || return 1 +    check_result_qemu || return 1 +    return 0 +} + +test_setup() { +    create_empty_image +    mkdir -p $TESTDIR/root +    mount ${LOOPDEV}p1 $TESTDIR/root + +    # Create what will eventually be our root filesystem onto an overlay +    ( +        LOG_LEVEL=5 +        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + +        setup_basic_environment + +        # setup the testsuite service +        cat >$initdir/etc/systemd/system/testsuite.service <<EOF +[Unit] +Description=Testsuite service +After=multi-user.target + +[Service] +ExecStart=/bin/sh -x -c 'mount -o remount,rw /dev/sda1 && echo OK > /testok; systemctl poweroff' +Type=oneshot +EOF + +    rm $initdir/etc/fstab +    cat >$initdir/etc/systemd/system/-.mount <<EOF +[Unit] +Before=local-fs.target + +[Mount] +What=/dev/sda1 +Where=/ +Type=ext4 +Options=errors=remount-ro,noatime + +[Install] +WantedBy=local-fs.target +Alias=root.mount +EOF + +        setup_testsuite +    ) || return 1 + +    ln -s /etc/systemd/system/-.mount $initdir/etc/systemd/system/root.mount +    mkdir -p $initdir/etc/systemd/system/local-fs.target.wants +    ln -s /etc/systemd/system/-.mount $initdir/etc/systemd/system/local-fs.target.wants/-.mount + +    # mask some services that we do not want to run in these tests +    ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service +    ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service +    ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service +    ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket +    ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service + +    ddebug "umount $TESTDIR/root" +    umount $TESTDIR/root +} + +test_cleanup() { +    umount $TESTDIR/root 2>/dev/null +    [[ $LOOPDEV ]] && losetup -d $LOOPDEV +    return 0 +} + +do_test "$@" diff --git a/test/test-functions b/test/test-functions index b3ca4c3171..29f647ece4 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  } @@ -252,7 +257,7 @@ create_empty_image() {  ,  EOF -    mkfs.ext3 -L systemd "${LOOPDEV}p1" +    mkfs -t "$FSTYPE" -L systemd "${LOOPDEV}p1"  }  check_result_nspawn() { | 
