diff options
38 files changed, 1105 insertions, 273 deletions
diff --git a/.gitignore b/.gitignore index 0e1d428ab0..403c16c339 100644 --- a/.gitignore +++ b/.gitignore @@ -238,6 +238,7 @@ /test-network /test-network-tables /test-ns +/test-nss /test-parse-util /test-path /test-path-lookup diff --git a/Makefile-man.am b/Makefile-man.am index db9b090432..7514e6a24f 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -144,6 +144,7 @@ MANPAGES += \ man/systemd.link.5 \ man/systemd.mount.5 \ man/systemd.nspawn.5 \ + man/systemd.offline-updates.7 \ man/systemd.path.5 \ man/systemd.preset.5 \ man/systemd.resource-control.5 \ @@ -2661,6 +2662,7 @@ EXTRA_DIST += \ man/systemd.netdev.xml \ man/systemd.network.xml \ man/systemd.nspawn.xml \ + man/systemd.offline-updates.xml \ man/systemd.path.xml \ man/systemd.preset.xml \ man/systemd.resource-control.xml \ diff --git a/Makefile.am b/Makefile.am index 7668c541cb..4ff9276fdd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4875,6 +4875,17 @@ EXTRA_DIST += \ src/timesync/timesyncd.conf.in # ------------------------------------------------------------------------------ +test_nss_SOURCES = \ + src/test/test-nss.c + +test_nss_LDADD = \ + libsystemd-internal.la \ + -ldl + +tests += \ + test-nss + +# ------------------------------------------------------------------------------ if HAVE_MYHOSTNAME libnss_myhostname_la_SOURCES = \ src/nss-myhostname/nss-myhostname.sym \ @@ -19,10 +19,58 @@ CHANGES WITH 230 in spe: again don't consider turning this on in your stable, LTS or production release just yet. + * systemd-resolve conveniently resolves DANE records with the --tlsa + option and OPENPGPKEY records with the --openpgp option. + * Testing tool /usr/lib/systemd/systemd-activate is renamed to systemd-socket-activate and installed into /usr/bin. It is now fully supported. + * The unified cgroup hierarchy added in Linux 4.5 is now supported. + Use systemd.unified_cgroup_hierarchy=1 on the kernel command line + to enable. + WARNING: it is not possible to use previous systemd versions with + systemd.unified_cgroup_hierarchy=1 and the new kernel. Therefore it + is necessary to also update systemd in the initramfs if using the + unified hierarchy. Updated selinux policy is also required. + + * LLDP support has been extended, and both passive (receive-only) + and active (sender) modes are supported. Passive mode + ("routers-only") is enabled by default in systemd-networkd. + Active LLDP mode is enabled by default for containers on the + internal network. + "networkctl lldp" can be used to list information gathered. + + * Headers for LLDP support (sd-lldp.h) are now public. + + * The Unique Identifier sent in DHCP requests can be configured. + + * systemd-journald now uses separate threads to flush changes to + disk when closing journal files. + + * systemd-ask-password skips printing of the password to stdout + with --no-output which can be useful in scripts. + + * Framebuffer devices (/dev/fb*) and 3D printers and scanners + (devices tagged with ID_MAKER_TOOL) are now tagged with + "uaccess" and are available to logged in users. + + * systemd-bootchart has been split out to a separate repository: + https://github.com/systemd/systemd-bootchart + + * Compatibility libraries libsystemd-daemon.so, libsystemd-journal.so, + libsystemd-id128.so, and libsystemd-login.so which have been + deprecated since systemd-209 have been removed along along with the + corresponding pkg-config files. All symbols provided by the those + libraries are provided by libsystemd.so. + + * Capabilities= setting has been removed (it is ignored for backwards + compatibility). AmbientCapabilities= and CapabilityBoundingSet= + should be used instead. + + * systemd-bus-proxyd has been removed, as kdbus will not be merged + in current form. + CHANGES WITH 229: * The systemd-resolved DNS resolver service has gained a substantial diff --git a/configure.ac b/configure.ac index cb14abda05..464f318dfc 100644 --- a/configure.ac +++ b/configure.ac @@ -1019,9 +1019,9 @@ have_machined=no AC_ARG_ENABLE(machined, AS_HELP_STRING([--disable-machined], [disable machine daemon])) if test "x$enable_machined" != "xno"; then have_machined=yes + AC_DEFINE(HAVE_MACHINED, [1], [systemd-machined is enabled]) fi AM_CONDITIONAL(ENABLE_MACHINED, [test "$have_machined" = "yes"]) -AS_IF([test "$have_machined" = "yes"], [ AC_DEFINE(HAVE_MACHINED, [1], [Machined support available]) ]) # ------------------------------------------------------------------------------ have_importd=no @@ -1131,6 +1131,7 @@ AS_IF([test "x$enable_resolved" != "xno"], [ have_resolved=yes M4_DEFINES="$M4_DEFINES -DENABLE_RESOLVED" + AC_DEFINE(HAVE_RESOLVED, [1], [systemd-resolved is enabled]) ]) AM_CONDITIONAL(ENABLE_RESOLVED, [test "$have_resolved" = "yes"]) @@ -1332,6 +1333,7 @@ if test "x$enable_myhostname" != "xno"; then AC_CHECK_FUNCS([gethostbyaddr gethostbyname gettimeofday inet_ntoa memset select socket strcspn strdup strerror strncasecmp strcasecmp strspn]) have_myhostname=yes + AC_DEFINE(HAVE_MYHOSTNAME, [1], [nss-myhostname is enabled]) fi AM_CONDITIONAL(HAVE_MYHOSTNAME, [test "$have_myhostname" = "yes"]) diff --git a/man/loginctl.xml b/man/loginctl.xml index f41acc6a1b..7f7252a5d9 100644 --- a/man/loginctl.xml +++ b/man/loginctl.xml @@ -94,6 +94,16 @@ </varlistentry> <varlistentry> + <term><option>--value</option></term> + + <listitem> + <para>When printing properties with <command>show</command>, + only print the value, and skip the property name and + <literal>=</literal>.</para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>-a</option></term> <term><option>--all</option></term> diff --git a/man/machinectl.xml b/man/machinectl.xml index 967ca01470..cee4bb72ce 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -136,6 +136,13 @@ (<literal>.</literal>).</para></listitem> </varlistentry> + <varlistentry> + <term><option>--value</option></term> + + <listitem><para>When printing properties with <command>show</command>, only print the value, + and skip the property name and <literal>=</literal>.</para></listitem> + </varlistentry> + <varlistentry> <term><option>-l</option></term> <term><option>--full</option></term> diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml index f8837745ae..a920ec334f 100644 --- a/man/nss-myhostname.xml +++ b/man/nss-myhostname.xml @@ -70,9 +70,10 @@ is on the local loopback) and the IPv6 address ::1 (which is the local host).</para></listitem> - <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in - <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is - resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem> + <listitem><para>The hostnames <literal>localhost</literal> and + <literal>localhost.localdomain</literal> (as well as any hostname + ending in <literal>.localhost</literal> or <literal>.localhost.localdomain</literal>) + are resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem> <listitem><para>The hostname <literal>gateway</literal> is resolved to all current default routing gateway addresses, diff --git a/man/systemctl.xml b/man/systemctl.xml index 1480bf8380..089fb0f5c3 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -233,6 +233,16 @@ </varlistentry> <varlistentry> + <term><option>--value</option></term> + + <listitem> + <para>When printing properties with <command>show</command>, + only print the value, and skip the property name and + <literal>=</literal>.</para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>--show-types</option></term> <listitem> diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml index 7a9e23a2c6..829729ca09 100644 --- a/man/systemd-resolved.service.xml +++ b/man/systemd-resolved.service.xml @@ -87,9 +87,10 @@ is on the local loopback) and the IPv6 address ::1 (which is the local host).</para></listitem> - <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in - <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is - resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem> + <listitem><para>The hostnames <literal>localhost</literal> and + <literal>localhost.localdomain</literal> (as well as any hostname + ending in <literal>.localhost</literal> or <literal>.localhost.localdomain</literal>) + are resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem> <listitem><para>The hostname <literal>gateway</literal> is resolved to all current default routing gateway addresses, diff --git a/man/systemd-run.xml b/man/systemd-run.xml index a92dfb402a..473f83eac6 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -345,7 +345,7 @@ provided by systemd to services:</para> <programlisting># systemd-run env -Running as unit run-19945.service +Running as unit: run-19945.service # journalctl -u run-19945.service Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env... Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env. @@ -366,8 +366,8 @@ Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20. <programlisting># date; systemd-run --on-active=30 --timer-property=AccuracySec=100ms /bin/touch /tmp/foo Mon Dec 8 20:44:24 KST 2014 -Running as unit run-71.timer -Will run service as unit run-71.service +Running as unit: run-71.timer +Will run service as unit: run-71.service # journalctl -b -u run-71.timer -- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- Dec 08 20:44:38 container systemd[1]: Starting /bin/touch /tmp/foo. diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml new file mode 100644 index 0000000000..946234ad90 --- /dev/null +++ b/man/systemd.offline-updates.xml @@ -0,0 +1,169 @@ +<?xml version='1.0'?> <!--*-nxml-*--> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> + +<!-- + This file is part of systemd. + + Copyright 2013 Lennart Poettering + Copyright 2016 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +--> + +<refentry id="systemd.offline-updates"> + <refentryinfo> + <title>systemd.offline-updates</title> + <productname>systemd</productname> + + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Lennart</firstname> + <surname>Poettering</surname> + <email>lennart@poettering.net</email> + </author> + </authorgroup> + </refentryinfo> + + <refmeta> + <refentrytitle>systemd.offline-updates</refentrytitle> + <manvolnum>7</manvolnum> + </refmeta> + + <refnamediv> + <refname>systemd.offline-updates</refname> + <refpurpose>Implementation of offline updates in systemd</refpurpose> + </refnamediv> + + <refsect1> + <title>Implementing Offline System Updates</title> + + <para>This man page describes how to implement "offline" system updates with systemd. By "offline" + OS updates we mean package installations and updates that are run with the system booted into a + special system update mode, in order to avoid problems related to conflicts of libraries and + services that are currently running with those on disk. This document is inspired by this + <ulink url="https://wiki.gnome.org/Design/OS/SoftwareUpdates">GNOME design whiteboard</ulink>. + </para> + + <para>The logic:</para> + + <orderedlist> + <listitem> + <para>The package manager prepares system updates by downloading all (RPM or DEB or + whatever) packages to update off-line in a special directory + <filename noindex="true">/var/lib/system-update</filename> (or + another directory of the package/upgrade manager's choice).</para> + </listitem> + + <listitem> + <para>When the user OK'ed the update, the symlink <filename>/system-update</filename> is + created that points to <filename noindex="true">/var/lib/system-update</filename> (or + wherever the directory with the upgrade files is located) and the system is rebooted. This + symlink is in the root directory, since we need to check for it very early at boot, at a + time where <filename>/var</filename> is not available yet.</para> + </listitem> + + <listitem> + <para>Very early in the new boot + <citerefentry><refentrytitle>systemd-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry> + checks whether <filename>/system-update</filename> exists. If so, it (temporarily and for + this boot only) redirects (i.e. symlinks) <filename>default.target</filename> to + <filename>system-update.target</filename>, a special target that is pulls in the base system + (i.e. <filename>sysinit.target</filename>, so that all file systems are mounted but little + else) and the system update units.</para> + </listitem> + + <listitem> + <para>The system now continues to boot into <filename>default.target</filename>, and thus + into <filename>system-update.target</filename>. This target pulls in the system update unit, + which starts the system update script after all file systems have been mounted.</para> + </listitem> + + <listitem> + <para>As the first step, the update script should check if the + <filename>/system-update</filename> symlink points to the the location used by that update + script. In case it does not exists or points to a different location, the script must exit + without error. It is possible for multiple update services to be installed, and for multiple + update scripts to be launched in parallel, and only the one that corresponds to the tool + that <emphasis>created</emphasis> the symlink before reboot should perform any actions. It + is unsafe to run multiple updates in parallel.</para> + </listitem> + + <listitem> + <para>The update script should now do its job. If applicable and possible, it should + create a file system snapshot, then install all packages. + After completion (regardless whether the update succeeded or failed) the machine + must be rebooted, for example by calling <command>systemctl reboot</command>. + In addition, on failure the script should revert to the old file system snapshot + (without the symlink).</para> + </listitem> + + <listitem> + <para>The system is rebooted. Since the <filename>/system-update</filename> symlink is gone, + the generator won't redirect <filename>default.target</filename> after reboot and the + system now boots into the default target again.</para> + </listitem> + </orderedlist> + </refsect1> + + <refsect1> + <title>Recommendations</title> + + <orderedlist> + <listitem> + <para>To make things a bit more robust we recommend hooking the update script into + <filename>system-update.target</filename> via a <filename noindex='true'>.wants/</filename> + symlink in the distribution package, rather than depending on <command>systemctl + enable</command> in the postinst scriptlets of your package. More specifically, for your + update script create a .service file, without [Install] section, and then add a symlink like + <filename noindex='true'>/usr/lib/systemd/system-update.target.wants/foobar.service</filename> + → <filename noindex='true'>../foobar.service</filename> to your package.</para> + </listitem> + + <listitem> + <para>Make sure to remove the <filename>/system-update</filename> symlink as early as + possible in the update script to avoid reboot loops in case the update fails.</para> + </listitem> + + <listitem> + <para>Use <varname>FailureAction=reboot</varname> in the service file for your update script + to ensure that a reboot is automatically triggered if the update fails. + <varname>FailureAction=</varname> makes sure that the specified unit is activated if your + script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds + you should trigger the reboot in your own code, for example by invoking logind's + <command>Reboot()</command> call or calling <command>systemct reboot</command>. See + <ulink url="http://www.freedesktop.org/wiki/Software/systemd/logind">logind dbus API</ulink> + for details.</para> + </listitem> + + <listitem> + <para>The update service should declare <varname>DefaultDependencies=false</varname>, + and pull in any services it requires explicitly.</para> + </listitem> + </orderedlist> + </refsect1> + + <refsect1> + <title>See also</title> + + <para> + <ulink url="http://www.freedesktop.org/wiki/Software/systemd/SystemUpdates/">Implementing Offline System Updates</ulink>, + <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>, + <citerefentry><refentrytitle>dnf.plugin.system-upgrade</refentrytitle><manvolnum>8</manvolnum></citerefentry> + </para> + </refsect1> +</refentry> diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 08cdf06e23..fd6f7a1b69 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -202,7 +202,7 @@ controls the <literal>memory.limit_in_bytes</literal> control group attribute. For details about this control group attribute, see <ulink - url="https://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>.</para> + url="https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt">memory.txt</ulink>.</para> <para>Implies <literal>MemoryAccounting=true</literal>.</para> </listitem> @@ -239,7 +239,7 @@ controls the <literal>pids.max</literal> control group attribute. For details about this control group attribute, see <ulink - url="https://www.kernel.org/doc/Documentation/cgroups/pids.txt">pids.txt</ulink>.</para> + url="https://www.kernel.org/doc/Documentation/cgroup-v1/pids.txt">pids.txt</ulink>.</para> <para>Implies <literal>TasksAccounting=true</literal>. The system default for this setting may be controlled with @@ -273,7 +273,7 @@ the <literal>blkio.weight</literal> control group attribute, which defaults to 500. For details about this control group attribute, see <ulink - url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>. + url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>. The available I/O bandwidth is split up among all units within one slice relative to their block I/O weight.</para> @@ -305,7 +305,7 @@ attribute, which defaults to 1000. Use this option multiple times to set weights for multiple devices. For details about this control group attribute, see <ulink - url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.</para> + url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>.</para> <para>Implies <literal>BlockIOAccounting=true</literal>.</para> @@ -328,12 +328,12 @@ Gigabytes, or Terabytes, respectively, to the base of 1000. (Example: "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This - controls the <literal>blkio.read_bps_device</literal> and - <literal>blkio.write_bps_device</literal> control group + controls the <literal>blkio.throttle.read_bps_device</literal> and + <literal>blkio.throttle.write_bps_device</literal> control group attributes. Use this option multiple times to set bandwidth limits for multiple devices. For details about these control group attributes, see <ulink - url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>. + url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>. </para> <para>Implies @@ -357,7 +357,7 @@ <literal>devices.deny</literal> control group attributes. For details about these control group attributes, see <ulink - url="https://www.kernel.org/doc/Documentation/cgroups/devices.txt">devices.txt</ulink>.</para> + url="https://www.kernel.org/doc/Documentation/cgroup-v1/devices.txt">devices.txt</ulink>.</para> <para>The device node specifier is either a path to a device node in the file system, starting with @@ -482,10 +482,10 @@ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>, The documentation for control groups and specific controllers in the Linux kernel: - <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>, - <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cpuacct.txt">cpuacct.txt</ulink>, - <ulink url="https://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>, - <ulink url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>. + <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt">cgroups.txt</ulink>, + <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt">cpuacct.txt</ulink>, + <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt">memory.txt</ulink>, + <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>. </para> </refsect1> </refentry> diff --git a/src/activate/activate.c b/src/activate/activate.c index 8ac8dd8e72..a0cfc22000 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -316,19 +316,31 @@ static int do_accept(const char* name, char **argv, char **envp, int fd) { } /* SIGCHLD handler. */ -static void sigchld_hdl(int sig, siginfo_t *t, void *data) { +static void sigchld_hdl(int sig) { PROTECT_ERRNO; - log_info("Child %d died with code %d", t->si_pid, t->si_status); + for (;;) { + siginfo_t si; + int r; - /* Wait for a dead child. */ - (void) waitpid(t->si_pid, NULL, 0); + si.si_pid = 0; + r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG); + if (r < 0) { + if (errno != ECHILD) + log_error_errno(errno, "Failed to reap children: %m"); + return; + } + if (si.si_pid == 0) + return; + + log_info("Child %d died with code %d", si.si_pid, si.si_status); + } } static int install_chld_handler(void) { static const struct sigaction act = { - .sa_flags = SA_SIGINFO, - .sa_sigaction = sigchld_hdl, + .sa_flags = SA_NOCLDSTOP, + .sa_handler = sigchld_hdl, }; int r; diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index 5a7ee87a20..13c3bb6446 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -178,16 +178,16 @@ bool is_localhost(const char *hostname) { assert(hostname); /* This tries to identify local host and domain names - * described in RFC6761 plus the redhatism of .localdomain */ + * described in RFC6761 plus the redhatism of localdomain */ return strcaseeq(hostname, "localhost") || strcaseeq(hostname, "localhost.") || - strcaseeq(hostname, "localdomain.") || - strcaseeq(hostname, "localdomain") || + strcaseeq(hostname, "localhost.localdomain") || + strcaseeq(hostname, "localhost.localdomain.") || endswith_no_case(hostname, ".localhost") || endswith_no_case(hostname, ".localhost.") || - endswith_no_case(hostname, ".localdomain") || - endswith_no_case(hostname, ".localdomain."); + endswith_no_case(hostname, ".localhost.localdomain") || + endswith_no_case(hostname, ".localhost.localdomain."); } bool is_gateway_hostname(const char *hostname) { diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index cda6b2895d..eaad25e65b 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -153,6 +153,8 @@ static int add_locales_from_libdir (Set *locales) { FOREACH_DIRENT(entry, dir, return -errno) { char *z; + dirent_ensure_type(dir, entry); + if (entry->d_type != DT_DIR) continue; diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h index df565a3593..bf7c4854fc 100644 --- a/src/basic/nss-util.h +++ b/src/basic/nss-util.h @@ -154,3 +154,46 @@ enum nss_status _nss_##module##_getgrgid_r( \ struct group *gr, \ char *buffer, size_t buflen, \ int *errnop) _public_ + +typedef enum nss_status (*_nss_gethostbyname4_r_t)( + const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); + +typedef enum nss_status (*_nss_gethostbyname3_r_t)( + const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp); + +typedef enum nss_status (*_nss_gethostbyname2_r_t)( + const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); + +typedef enum nss_status (*_nss_gethostbyname_r_t)( + const char *name, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); + +typedef enum nss_status (*_nss_gethostbyaddr2_r_t)( + const void* addr, socklen_t len, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); +typedef enum nss_status (*_nss_gethostbyaddr_r_t)( + const void* addr, socklen_t len, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); diff --git a/src/basic/string-table.h b/src/basic/string-table.h index b180488fe8..d88625fca7 100644 --- a/src/basic/string-table.h +++ b/src/basic/string-table.h @@ -56,26 +56,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ } -#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ - struct __useless_struct_to_allow_trailing_semicolon__ - -#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ - struct __useless_struct_to_allow_trailing_semicolon__ - -#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) - -#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) - -/* For string conversions where numbers are also acceptable */ -#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ - int name##_to_string_alloc(type i, char **str) { \ +#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \ + scope int name##_to_string_alloc(type i, char **str) { \ char *s; \ if (i < 0 || i > max) \ return -ERANGE; \ @@ -89,7 +71,9 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k } \ *str = s; \ return 0; \ - } \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \ type name##_from_string(const char *s) { \ type i; \ unsigned u = 0; \ @@ -102,4 +86,32 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k return (type) u; \ return (type) -1; \ } \ + + +#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ + +#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ + +#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) + +#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) + +/* For string conversions where numbers are also acceptable */ +#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \ struct __useless_struct_to_allow_trailing_semicolon__ + +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static) diff --git a/src/basic/time-util.c b/src/basic/time-util.c index c16460a198..7ca764abeb 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -47,15 +47,12 @@ 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. - * - * Also, older kernels don't support CLOCK_BOOTTIME: fall back to CLOCK_MONOTONIC. */ + * those archs. */ switch (c) { - case CLOCK_BOOTTIME: case CLOCK_BOOTTIME_ALARM: - return clock_boottime_or_monotonic (); + return CLOCK_BOOTTIME; case CLOCK_REALTIME_ALARM: return CLOCK_REALTIME; diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 2ef966257a..9927621ea0 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -719,8 +719,12 @@ int main(int argc, char *argv[]) { int k; k = crypt_init_by_name(&cd, argv[2]); - if (k) { - log_error_errno(k, "crypt_init() failed: %m"); + if (k == -ENODEV) { + log_info("Volume %s already inactive.", argv[2]); + r = EXIT_SUCCESS; + goto finish; + } else if (k) { + log_error_errno(k, "crypt_init_by_name() failed: %m"); goto finish; } diff --git a/src/import/import-common.c b/src/import/import-common.c index 18a30be36d..287a3382a1 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -136,7 +136,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) { if (r < 0) log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); - execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", NULL); + execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", NULL); log_error_errno(errno, "Failed to execute tar: %m"); _exit(EXIT_FAILURE); } @@ -210,7 +210,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) { if (r < 0) log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); - execlp("tar", "tar", "-C", path, "-c", ".", NULL); + execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", ".", NULL); log_error_errno(errno, "Failed to execute tar: %m"); _exit(EXIT_FAILURE); } diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index babae15c5b..e6486b78f8 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -75,7 +75,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { struct duid d; - assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); + assert(duid_len > 0); switch (duid_type) { case DUID_TYPE_LLT: @@ -95,6 +95,8 @@ static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { return -EINVAL; break; default: + if (duid_len > sizeof(d.raw)) + return -EINVAL; /* accept unknown type in order to be forward compatible */ break; } diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 8657e61cd9..e9f8970d2c 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -1457,15 +1457,20 @@ static int device_properties_prepare(sd_device *device) { return r; if (device->property_devlinks_outdated) { - char *devlinks = NULL; + _cleanup_free_ char *devlinks = NULL; + size_t devlinks_allocated = 0, devlinks_len = 0; const char *devlink; - devlink = sd_device_get_devlink_first(device); - if (devlink) - devlinks = strdupa(devlink); + for (devlink = sd_device_get_devlink_first(device); devlink; devlink = sd_device_get_devlink_next(device)) { + char *e; - while ((devlink = sd_device_get_devlink_next(device))) - devlinks = strjoina(devlinks, " ", devlink); + if (!GREEDY_REALLOC(devlinks, devlinks_allocated, devlinks_len + strlen(devlink) + 2)) + return -ENOMEM; + if (devlinks_len > 0) + stpcpy(devlinks + devlinks_len++, " "); + e = stpcpy(devlinks + devlinks_len, devlink); + devlinks_len = e - devlinks; + } r = device_add_property_internal(device, "DEVLINKS", devlinks); if (r < 0) @@ -1475,17 +1480,23 @@ static int device_properties_prepare(sd_device *device) { } if (device->property_tags_outdated) { - char *tags = NULL; + _cleanup_free_ char *tags = NULL; + size_t tags_allocated = 0, tags_len = 0; const char *tag; - tag = sd_device_get_tag_first(device); - if (tag) - tags = strjoina(":", tag); + if (!GREEDY_REALLOC(tags, tags_allocated, 2)) + return -ENOMEM; + stpcpy(tags, ":"); + tags_len++; - while ((tag = sd_device_get_tag_next(device))) - tags = strjoina(tags, ":", tag); + for (tag = sd_device_get_tag_first(device); tag; tag = sd_device_get_tag_next(device)) { + char *e; - tags = strjoina(tags, ":"); + if (!GREEDY_REALLOC(tags, tags_allocated, tags_len + strlen(tag) + 1)) + return -ENOMEM; + e = stpcpy(stpcpy(tags + tags_len, tag), ":"); + tags_len = e - tags; + } r = device_add_property_internal(device, "TAGS", tags); if (r < 0) diff --git a/src/libsystemd/sd-netlink/local-addresses.c b/src/libsystemd/sd-netlink/local-addresses.c index 6abd8fd0cc..ed9ee041ab 100644 --- a/src/libsystemd/sd-netlink/local-addresses.c +++ b/src/libsystemd/sd-netlink/local-addresses.c @@ -155,8 +155,7 @@ int local_addresses(sd_netlink *context, int ifindex, int af, struct local_addre n_list++; }; - if (n_list > 0) - qsort(list, n_list, sizeof(struct local_address), address_compare); + qsort_safe(list, n_list, sizeof(struct local_address), address_compare); *ret = list; list = NULL; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index c9a5cd796b..01f6fa5db0 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -48,6 +48,7 @@ static char **arg_property = NULL; static bool arg_all = false; +static bool arg_value = false; static bool arg_full = false; static bool arg_no_pager = false; static bool arg_legend = true; @@ -679,6 +680,14 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) return 0; } +#define property(name, fmt, ...) \ + do { \ + if (arg_value) \ + printf(fmt "\n", __VA_ARGS__); \ + else \ + printf("%s=" fmt "\n", name, __VA_ARGS__); \ + } while(0) + static int print_property(const char *name, sd_bus_message *m, const char *contents) { int r; @@ -702,7 +711,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); if (arg_all || !isempty(s)) - printf("%s=%s\n", name, s); + property(name, "%s", s); return 0; @@ -718,8 +727,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return -EINVAL; } - printf("%s=" UID_FMT "\n", name, uid); - + property(name, UID_FMT, uid); return 0; } @@ -735,14 +743,16 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte if (r < 0) return bus_log_parse_error(r); - printf("%s=", name); + if (!arg_value) + printf("%s=", name); while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) { printf("%s%s", space ? " " : "", s); space = true; } - printf("\n"); + if (space || !arg_value) + printf("\n"); if (r < 0) return bus_log_parse_error(r); @@ -757,7 +767,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte break; } - r = bus_print_property(name, m, arg_all); + r = bus_print_property(name, m, arg_value, arg_all); if (r < 0) return bus_log_parse_error(r); @@ -1330,6 +1340,7 @@ static int help(int argc, char *argv[], void *userdata) { " -M --machine=CONTAINER Operate on local container\n" " -p --property=NAME Show only properties by this name\n" " -a --all Show all properties, including empty ones\n" + " --value When showing properties, only print the value\n" " -l --full Do not ellipsize output\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" @@ -1371,6 +1382,7 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, + ARG_VALUE, ARG_NO_PAGER, ARG_NO_LEGEND, ARG_KILL_WHO, @@ -1382,6 +1394,7 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "property", required_argument, NULL, 'p' }, { "all", no_argument, NULL, 'a' }, + { "value", no_argument, NULL, ARG_VALUE }, { "full", no_argument, NULL, 'l' }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, @@ -1427,6 +1440,10 @@ static int parse_argv(int argc, char *argv[]) { arg_all = true; break; + case ARG_VALUE: + arg_value = true; + break; + case 'l': arg_full = true; break; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index e49c90fd1b..1d3264a1de 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -61,6 +61,7 @@ static char **arg_property = NULL; static bool arg_all = false; +static bool arg_value = false; static bool arg_full = false; static bool arg_no_pager = false; static bool arg_legend = true; @@ -129,15 +130,14 @@ static int list_machines(int argc, char *argv[], void *userdata) { pager_open(arg_no_pager, false); - r = sd_bus_call_method( - bus, - "org.freedesktop.machine1", - "/org/freedesktop/machine1", - "org.freedesktop.machine1.Manager", - "ListMachines", - &error, - &reply, - NULL); + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "ListMachines", + &error, + &reply, + NULL); if (r < 0) { log_error("Could not get machines: %s", bus_error_message(&error, -r)); return r; @@ -232,15 +232,14 @@ static int list_images(int argc, char *argv[], void *userdata) { pager_open(arg_no_pager, false); - r = sd_bus_call_method( - bus, - "org.freedesktop.machine1", - "/org/freedesktop/machine1", - "org.freedesktop.machine1.Manager", - "ListImages", - &error, - &reply, - ""); + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "ListImages", + &error, + &reply, + ""); if (r < 0) { log_error("Could not get images: %s", bus_error_message(&error, -r)); return r; @@ -680,7 +679,7 @@ static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line *new_line = true; - r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all); + r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all); if (r < 0) log_error_errno(r, "Could not get properties: %m"); @@ -713,15 +712,14 @@ static int show_machine(int argc, char *argv[], void *userdata) { for (i = 1; i < argc; i++) { const char *path = NULL; - r = sd_bus_call_method( - bus, - "org.freedesktop.machine1", - "/org/freedesktop/machine1", - "org.freedesktop.machine1.Manager", - "GetMachine", - &error, - &reply, - "s", argv[i]); + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachine", + &error, + &reply, + "s", argv[i]); if (r < 0) { log_error("Could not get path to machine: %s", bus_error_message(&error, -r)); return r; @@ -929,7 +927,7 @@ static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) *new_line = true; - r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all); + r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all); if (r < 0) log_error_errno(r, "Could not get properties: %m"); @@ -2183,15 +2181,14 @@ static int list_transfers(int argc, char *argv[], void *userdata) { pager_open(arg_no_pager, false); - r = sd_bus_call_method( - bus, - "org.freedesktop.import1", - "/org/freedesktop/import1", - "org.freedesktop.import1.Manager", - "ListTransfers", - &error, - &reply, - NULL); + r = sd_bus_call_method(bus, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ListTransfers", + &error, + &reply, + NULL); if (r < 0) { log_error("Could not get transfers: %s", bus_error_message(&error, -r)); return r; @@ -2356,6 +2353,7 @@ static int help(int argc, char *argv[], void *userdata) { " -p --property=NAME Show only properties by this name\n" " -q --quiet Suppress output\n" " -a --all Show all properties, including empty ones\n" + " --value When showing properties, only print the value\n" " -l --full Do not ellipsize output\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" @@ -2418,6 +2416,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, + ARG_VALUE, ARG_KILL_WHO, ARG_READ_ONLY, ARG_MKDIR, @@ -2434,6 +2433,7 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "property", required_argument, NULL, 'p' }, { "all", no_argument, NULL, 'a' }, + { "value", no_argument, NULL, ARG_VALUE }, { "full", no_argument, NULL, 'l' }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, @@ -2485,6 +2485,10 @@ static int parse_argv(int argc, char *argv[]) { arg_all = true; break; + case ARG_VALUE: + arg_value = true; + break; + case 'l': arg_full = true; break; diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 64cb6b3ce3..8e2d2d543c 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -438,21 +438,22 @@ static int mount_bind(const char *dest, CustomMount *m) { r = mkdir_parents_label(where, 0755); if (r < 0) return log_error_errno(r, "Failed to make parents of %s: %m", where); + + /* Create the mount point. Any non-directory file can be + * mounted on any non-directory file (regular, fifo, socket, + * char, block). + */ + if (S_ISDIR(source_st.st_mode)) + r = mkdir_label(where, 0755); + else + r = touch(where); + if (r < 0) + return log_error_errno(r, "Failed to create mount point %s: %m", where); + } else { return log_error_errno(errno, "Failed to stat %s: %m", where); } - /* Create the mount point. Any non-directory file can be - * mounted on any non-directory file (regular, fifo, socket, - * char, block). - */ - if (S_ISDIR(source_st.st_mode)) - r = mkdir_label(where, 0755); - else - r = touch(where); - if (r < 0 && r != -EEXIST) - return log_error_errno(r, "Failed to create mount point %s: %m", where); - if (mount(m->source, where, NULL, mount_flags, mount_opts) < 0) return log_error_errno(errno, "mount(%s) failed: %m", where); diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index 2536ad2898..2b83d127b7 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -127,7 +127,8 @@ enum nss_status _nss_myhostname_gethostbyname4_r( memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); - if (n_addresses <= 0) { + assert(n_addresses >= 0); + if (n_addresses == 0) { /* Second, fill in IPv6 tuple */ r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; @@ -453,38 +454,33 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( } n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); - if (n_addresses > 0) { - for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { - if (af != a->family) - continue; + for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { + if (af != a->family) + continue; - if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) - goto found; - } + if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) + goto found; } addresses = mfree(addresses); n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); - if (n_addresses > 0) { - for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { - if (af != a->family) - continue; + for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { + if (af != a->family) + continue; - if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { - canonical = "gateway"; - goto found; - } + if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { + canonical = "gateway"; + goto found; } } *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; found: - if (!canonical || (!additional && additional_from_hostname)) { + if (!canonical || additional_from_hostname) { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; @@ -494,8 +490,7 @@ found: if (!canonical) canonical = hn; - - if (!additional && additional_from_hostname) + else additional = hn; } diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index 0de6bd2241..5ce10f1cbd 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -117,13 +117,6 @@ enum nss_status _nss_resolve_gethostbyname4_r( int *errnop, int *h_errnop, int32_t *ttlp) { - enum nss_status (*fallback)( - const char *name, - struct gaih_addrtuple **pat, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp); - _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; @@ -275,15 +268,15 @@ enum nss_status _nss_resolve_gethostbyname4_r( return NSS_STATUS_SUCCESS; fallback: - fallback = (enum nss_status (*)(const char *name, - struct gaih_addrtuple **pat, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp)) - find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r"); + { + _nss_gethostbyname4_r_t fallback; + + fallback = (_nss_gethostbyname4_r_t) + find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r"); - if (fallback) - return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp); + if (fallback) + return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp); + } fail: *errnop = -r; @@ -300,15 +293,6 @@ enum nss_status _nss_resolve_gethostbyname3_r( int32_t *ttlp, char **canonp) { - enum nss_status (*fallback)( - const char *name, - int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp, - char **canonp); - _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; @@ -480,16 +464,14 @@ enum nss_status _nss_resolve_gethostbyname3_r( return NSS_STATUS_SUCCESS; fallback: - fallback = (enum nss_status (*)(const char *name, - int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp, - char **canonp)) - find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r"); - if (fallback) - return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); + { + _nss_gethostbyname3_r_t fallback; + + fallback = (_nss_gethostbyname3_r_t) + find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r"); + if (fallback) + return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); + } fail: *errnop = -r; @@ -505,15 +487,6 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( int *errnop, int *h_errnop, int32_t *ttlp) { - enum nss_status (*fallback)( - const void* addr, socklen_t len, - int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp); - - _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; @@ -682,17 +655,15 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( return NSS_STATUS_SUCCESS; fallback: - fallback = (enum nss_status (*)( - const void* addr, socklen_t len, - int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp)) - find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r"); - - if (fallback) - return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp); + { + _nss_gethostbyaddr2_r_t fallback; + + fallback = (_nss_gethostbyaddr2_r_t) + find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r"); + + if (fallback) + return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp); + } fail: *errnop = -r; diff --git a/src/run/run.c b/src/run/run.c index 540a612fdf..f92a7f4e2e 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -878,7 +878,7 @@ static int start_transient_service( (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); if (!arg_quiet) - log_info("Running as unit %s\nPress ^] three times within 1s to disconnect TTY.", service); + log_info("Running as unit: %s\nPress ^] three times within 1s to disconnect TTY.", service); r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward); if (r < 0) @@ -896,7 +896,7 @@ static int start_transient_service( fputc('\n', stdout); } else if (!arg_quiet) - log_info("Running as unit %s", service); + log_info("Running as unit: %s", service); return 0; } @@ -1038,7 +1038,7 @@ static int start_transient_scope( return r; if (!arg_quiet) - log_info("Running scope as unit %s", scope); + log_info("Running scope as unit: %s", scope); execvpe(argv[0], argv, env); @@ -1189,9 +1189,9 @@ static int start_transient_timer( if (r < 0) return r; - log_info("Running timer as unit %s", timer); + log_info("Running timer as unit: %s", timer); if (argv[0]) - log_info("Will run service as unit %s", service); + log_info("Will run service as unit: %s", service); return 0; } diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 90b312a1a7..0caaca03c7 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -712,7 +712,15 @@ int bus_connect_user_systemd(sd_bus **_bus) { return 0; } -int bus_print_property(const char *name, sd_bus_message *property, bool all) { +#define print_property(name, fmt, ...) \ + do { \ + if (value) \ + printf(fmt "\n", __VA_ARGS__); \ + else \ + printf("%s=" fmt "\n", name, __VA_ARGS__); \ + } while(0) + +int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) { char type; const char *contents; int r; @@ -740,7 +748,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (!escaped) return -ENOMEM; - printf("%s=%s\n", name, escaped); + print_property(name, "%s", escaped); } return 1; @@ -753,7 +761,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (r < 0) return r; - printf("%s=%s\n", name, yes_no(b)); + print_property(name, "%s", yes_no(b)); return 1; } @@ -773,14 +781,14 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { t = format_timestamp(timestamp, sizeof(timestamp), u); if (t || all) - printf("%s=%s\n", name, strempty(t)); + print_property(name, "%s", strempty(t)); } else if (strstr(name, "USec")) { char timespan[FORMAT_TIMESPAN_MAX]; - printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0)); + print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0)); } else - printf("%s=%llu\n", name, (unsigned long long) u); + print_property(name, "%"PRIu64, u); return 1; } @@ -792,7 +800,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (r < 0) return r; - printf("%s=%lld\n", name, (long long) i); + print_property(name, "%"PRIi64, i); return 1; } @@ -805,9 +813,9 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { return r; if (strstr(name, "UMask") || strstr(name, "Mode")) - printf("%s=%04o\n", name, u); + print_property(name, "%04o", u); else - printf("%s=%u\n", name, (unsigned) u); + print_property(name, "%"PRIu32, u); return 1; } @@ -819,7 +827,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (r < 0) return r; - printf("%s=%i\n", name, (int) i); + print_property(name, "%"PRIi32, i); return 1; } @@ -830,7 +838,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (r < 0) return r; - printf("%s=%g\n", name, d); + print_property(name, "%g", d); return 1; } @@ -846,7 +854,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) { _cleanup_free_ char *escaped = NULL; - if (first) + if (first && !value) printf("%s=", name); escaped = xescape(str, "\n "); @@ -860,7 +868,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (r < 0) return r; - if (first && all) + if (first && all && !value) printf("%s=", name); if (!first || all) puts(""); @@ -882,7 +890,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (all || n > 0) { unsigned int i; - printf("%s=", name); + if (!value) + printf("%s=", name); for (i = 0; i < n; i++) printf("%02x", u[i]); @@ -903,7 +912,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (all || n > 0) { unsigned int i; - printf("%s=", name); + if (!value) + printf("%s=", name); for (i = 0; i < n; i++) printf("%08x", u[i]); @@ -920,7 +930,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { return 0; } -int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) { +int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; @@ -960,7 +970,7 @@ int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, ch if (r < 0) return r; - r = bus_print_property(name, reply, all); + r = bus_print_property(name, reply, value, all); if (r < 0) return r; if (r == 0) { @@ -1068,7 +1078,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ } case SD_BUS_TYPE_UINT32: { - uint64_t u; + uint32_t u; uint32_t *p = userdata; r = sd_bus_message_read_basic(m, type, &u); diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index fcda1b2c6c..1a0841ce81 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -78,8 +78,8 @@ int bus_connect_user_systemd(sd_bus **_bus); int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); -int bus_print_property(const char *name, sd_bus_message *property, bool all); -int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all); +int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all); +int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all); int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c index cf3c8ad5a3..7dae4d14fe 100644 --- a/src/shared/spawn-polkit-agent.c +++ b/src/shared/spawn-polkit-agent.c @@ -44,6 +44,10 @@ int polkit_agent_open(void) { if (agent_pid > 0) return 0; + /* Clients that run as root don't need to activate/query polkit */ + if (geteuid() == 0) + return 0; + /* We check STDIN here, not STDOUT, since this is about input, * not output */ if (!isatty(STDIN_FILENO)) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 2afb7bad1a..62cff3a677 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -103,6 +103,7 @@ static bool arg_no_pager = false; static bool arg_no_wtmp = false; static bool arg_no_wall = false; static bool arg_no_reload = false; +static bool arg_value = false; static bool arg_show_types = false; static bool arg_ignore_inhibitors = false; static bool arg_dry = false; @@ -1896,13 +1897,13 @@ static void output_machines_list(struct machine_info *machine_infos, unsigned n) printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state); if (m->is_host) - printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n", + printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n", (int) (namelen - (sizeof(" (host)")-1)), strna(m->name), on_state, statelen, strna(m->state), off_state, on_failed, failedlen, m->n_failed_units, off_failed, jobslen, m->n_jobs); else - printf("%-*s %s%-*s%s %s%*u%s %*u\n", + printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n", namelen, strna(m->name), on_state, statelen, strna(m->state), off_state, on_failed, failedlen, m->n_failed_units, off_failed, @@ -4116,6 +4117,14 @@ skip: return 0; } +#define print_prop(name, fmt, ...) \ + do { \ + if (arg_value) \ + printf(fmt "\n", __VA_ARGS__); \ + else \ + printf("%s=" fmt "\n", name, __VA_ARGS__); \ + } while(0) + static int print_property(const char *name, sd_bus_message *m, const char *contents) { int r; @@ -4143,9 +4152,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); if (u > 0) - printf("%s=%"PRIu32"\n", name, u); + print_prop(name, "%"PRIu32, u); else if (arg_all) - printf("%s=\n", name); + print_prop(name, "%s", ""); return 0; @@ -4157,7 +4166,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); if (arg_all || !isempty(s)) - printf("%s=%s\n", name, s); + print_prop(name, "%s", s); return 0; @@ -4169,7 +4178,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); if (arg_all || !isempty(a) || !isempty(b)) - printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b)); + print_prop(name, "%s \"%s\"", strempty(a), strempty(b)); return 0; } else if (streq_ptr(name, "SystemCallFilter")) { @@ -4196,8 +4205,10 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte bool first = true; char **i; - fputs(name, stdout); - fputc('=', stdout); + if (!arg_value) { + fputs(name, stdout); + fputc('=', stdout); + } if (!whitelist) fputc('~', stdout); @@ -4229,7 +4240,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0) - printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore)); + print_prop("EnvironmentFile", "%s (ignore_errors=%s)\n", path, yes_no(ignore)); if (r < 0) return bus_log_parse_error(r); @@ -4248,7 +4259,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) - printf("%s=%s\n", type, path); + print_prop(type, "%s", path); if (r < 0) return bus_log_parse_error(r); @@ -4266,7 +4277,10 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) - printf("Listen%s=%s\n", type, path); + if (arg_value) + puts(path); + else + printf("Listen%s=%s\n", type, path); if (r < 0) return bus_log_parse_error(r); @@ -4287,10 +4301,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) { char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX]; - printf("%s={ value=%s ; next_elapse=%s }\n", - base, - format_timespan(timespan1, sizeof(timespan1), value, 0), - format_timespan(timespan2, sizeof(timespan2), next_elapse, 0)); + print_prop(base, "{ value=%s ; next_elapse=%s }", + format_timespan(timespan1, sizeof(timespan1), value, 0), + format_timespan(timespan2, sizeof(timespan2), next_elapse, 0)); } if (r < 0) return bus_log_parse_error(r); @@ -4314,18 +4327,18 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte tt = strv_join(info.argv, " "); - printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n", - name, - strna(info.path), - strna(tt), - yes_no(info.ignore), - strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), - strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), - info.pid, - sigchld_code_to_string(info.code), - info.status, - info.code == CLD_EXITED ? "" : "/", - strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status))); + print_prop(name, + "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }", + strna(info.path), + strna(tt), + yes_no(info.ignore), + strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), + strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), + info.pid, + sigchld_code_to_string(info.code), + info.status, + info.code == CLD_EXITED ? "" : "/", + strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status))); free(info.path); strv_free(info.argv); @@ -4346,7 +4359,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0) - printf("%s=%s %s\n", name, strna(path), strna(rwm)); + print_prop(name, "%s %s", strna(path), strna(rwm)); if (r < 0) return bus_log_parse_error(r); @@ -4365,7 +4378,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0) - printf("%s=%s %" PRIu64 "\n", name, strna(path), weight); + print_prop(name, "%s %"PRIu64, strna(path), weight); if (r < 0) return bus_log_parse_error(r); @@ -4384,7 +4397,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0) - printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth); + print_prop(name, "%s %"PRIu64, strna(path), bandwidth); if (r < 0) return bus_log_parse_error(r); @@ -4398,7 +4411,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte break; } - r = bus_print_property(name, m, arg_all); + r = bus_print_property(name, m, arg_value, arg_all); if (r < 0) return bus_log_parse_error(r); @@ -4637,8 +4650,8 @@ static int show_system_status(sd_bus *bus) { printf(" State: %s%s%s\n", on, strna(mi.state), off); - printf(" Jobs: %u queued\n", mi.n_jobs); - printf(" Failed: %u units\n", mi.n_failed_units); + printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs); + printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units); printf(" Since: %s; %s\n", format_timestamp(since2, sizeof(since2), mi.timestamp), @@ -6243,6 +6256,7 @@ static void systemctl_help(void) { " --job-mode=MODE Specify how to deal with already queued jobs, when\n" " queueing a new job\n" " --show-types When showing sockets, explicitly show their type\n" + " --value When showing properties, only print the value\n" " -i --ignore-inhibitors\n" " When shutting down or sleeping, ignore inhibitors\n" " --kill-who=WHO Who to send signal to\n" @@ -6494,6 +6508,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_SHOW_TYPES, ARG_IRREVERSIBLE, ARG_IGNORE_DEPENDENCIES, + ARG_VALUE, ARG_VERSION, ARG_USER, ARG_SYSTEM, @@ -6535,6 +6550,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */ { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */ { "ignore-inhibitors", no_argument, NULL, 'i' }, + { "value", no_argument, NULL, ARG_VALUE }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, { "global", no_argument, NULL, ARG_GLOBAL }, @@ -6686,6 +6702,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_show_types = true; break; + case ARG_VALUE: + arg_value = true; + break; + case ARG_JOB_MODE: arg_job_mode = optarg; break; diff --git a/src/test/test-nss.c b/src/test/test-nss.c new file mode 100644 index 0000000000..9c13288d2e --- /dev/null +++ b/src/test/test-nss.c @@ -0,0 +1,448 @@ +/*** + This file is part of systemd. + + Copyright 2016 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <dlfcn.h> +#include <stdlib.h> +#include <net/if.h> + +#include "log.h" +#include "nss-util.h" +#include "path-util.h" +#include "string-util.h" +#include "alloc-util.h" +#include "in-addr-util.h" +#include "hexdecoct.h" +#include "af-list.h" +#include "stdio-util.h" +#include "strv.h" +#include "errno-list.h" +#include "hostname-util.h" +#include "local-addresses.h" + +static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) { + switch (status) { + case NSS_STATUS_TRYAGAIN: + return "NSS_STATUS_TRYAGAIN"; + case NSS_STATUS_UNAVAIL: + return "NSS_STATUS_UNAVAIL"; + case NSS_STATUS_NOTFOUND: + return "NSS_STATUS_NOTFOUND"; + case NSS_STATUS_SUCCESS: + return "NSS_STATUS_SUCCESS"; + case NSS_STATUS_RETURN: + return "NSS_STATUS_RETURN"; + default: + snprintf(buf, buf_len, "%i", status); + return buf; + } +}; + +static const char* af_to_string(int family, char *buf, size_t buf_len) { + const char *name; + + if (family == AF_UNSPEC) + return "*"; + + name = af_to_name(family); + if (name) + return name; + + snprintf(buf, buf_len, "%i", family); + return buf; +} + +static void* open_handle(const char* dir, const char* module, int flags) { + const char *path; + void *handle; + + if (dir) + path = strjoina(dir, "/.libs/libnss_", module, ".so.2"); + else + path = strjoina("libnss_", module, ".so.2"); + + handle = dlopen(path, flags); + assert_se(handle); + return handle; +} + +static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) { + const struct gaih_addrtuple *it; + int n = 0; + + for (it = tuples; it; it = it->next) { + _cleanup_free_ char *a = NULL; + union in_addr_union u; + int r; + char family_name[DECIMAL_STR_MAX(int)]; + char ifname[IF_NAMESIZE]; + + memcpy(&u, it->addr, 16); + r = in_addr_to_string(it->family, &u, &a); + assert_se(r == 0 || r == -EAFNOSUPPORT); + if (r == -EAFNOSUPPORT) + assert_se((a = hexmem(it->addr, 16))); + + if (it->scopeid == 0) + goto numerical_index; + + if (if_indextoname(it->scopeid, ifname) == NULL) { + log_warning("if_indextoname(%d) failed: %m", it->scopeid); + numerical_index: + xsprintf(ifname, "%i", it->scopeid); + }; + + log_info(" \"%s\" %s %s %%%s", + it->name, + af_to_string(it->family, family_name, sizeof family_name), + a, + ifname); + n ++; + } + return n; +} + +static void print_struct_hostent(struct hostent *host, const char *canon) { + char **s; + + log_info(" \"%s\"", host->h_name); + STRV_FOREACH(s, host->h_aliases) + log_info(" alias \"%s\"", *s); + STRV_FOREACH(s, host->h_addr_list) { + union in_addr_union u; + _cleanup_free_ char *a = NULL; + char family_name[DECIMAL_STR_MAX(int)]; + int r; + + assert_se((unsigned) host->h_length == FAMILY_ADDRESS_SIZE(host->h_addrtype)); + memcpy(&u, *s, host->h_length); + r = in_addr_to_string(host->h_addrtype, &u, &a); + assert_se(r == 0); + log_info(" %s %s", + af_to_string(host->h_addrtype, family_name, sizeof family_name), + a); + } + if (canon) + log_info(" canonical: \"%s\"", canon); +} + +static void test_gethostbyname4_r(void *handle, const char *module, const char *name) { + const char *fname; + _nss_gethostbyname4_r_t f; + char buffer[2000]; + struct gaih_addrtuple *pat = NULL; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl, + and will access this variable through *ttlp, + so we need to set it to something. + I'm not sure if this is a bug in nss-dns + or not. */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + int n; + + fname = strjoina("_nss_", module, "_gethostbyname4_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, &pat, buffer, sizeof buffer, &errno1, &errno2, &ttl); + if (status == NSS_STATUS_SUCCESS) { + log_info("%s(\"%s\") → status=%s%-20spat=buffer+0x%tx errno=%d/%s h_errno=%d/%s ttl=%"PRIi32, + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + pat ? (char*) pat - buffer : 0, + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2), + ttl); + n = print_gaih_addrtuples(pat); + } else { + log_info("%s(\"%s\") → status=%s%-20spat=0x%p errno=%d/%s h_errno=%d/%s", + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + pat, + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + n = 0; + } + + if (STR_IN_SET(module, "resolve", "mymachines") && status == NSS_STATUS_UNAVAIL) + return; + + if (STR_IN_SET(module, "myhostname", "resolve") && streq(name, "localhost")) { + assert_se(status == NSS_STATUS_SUCCESS); + assert_se(n == 2); + } +} + + +static void test_gethostbyname3_r(void *handle, const char *module, const char *name, int af) { + const char *fname; + _nss_gethostbyname3_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl, + and will access this variable through *ttlp, + so we need to set it to something. + I'm not sure if this is a bug in nss-dns + or not. */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + char *canon; + char family_name[DECIMAL_STR_MAX(int)]; + + fname = strjoina("_nss_", module, "_gethostbyname3_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl, &canon); + log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32, + fname, name, af_to_string(af, family_name, sizeof family_name), + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2), + ttl); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, canon); +} + +static void test_gethostbyname2_r(void *handle, const char *module, const char *name, int af) { + const char *fname; + _nss_gethostbyname2_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + char family_name[DECIMAL_STR_MAX(int)]; + + fname = strjoina("_nss_", module, "_gethostbyname2_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2); + log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s", + fname, name, af_to_string(af, family_name, sizeof family_name), + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_gethostbyname_r(void *handle, const char *module, const char *name) { + const char *fname; + _nss_gethostbyname_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + + fname = strjoina("_nss_", module, "_gethostbyname_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, &host, buffer, sizeof buffer, &errno1, &errno2); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s", + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_gethostbyaddr2_r(void *handle, + const char *module, + const void* addr, socklen_t len, + int af) { + + const char *fname; + _nss_gethostbyaddr2_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + int32_t ttl = INT32_MAX; + _cleanup_free_ char *addr_pretty = NULL; + + fname = strjoina("_nss_", module, "_gethostbyaddr2_r"); + f = dlsym(handle, fname); + + log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno, + "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f); + if (!f) + return; + + assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0); + + status = f(addr, len, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32, + fname, addr_pretty, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2), + ttl); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_gethostbyaddr_r(void *handle, + const char *module, + const void* addr, socklen_t len, + int af) { + + const char *fname; + _nss_gethostbyaddr_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + _cleanup_free_ char *addr_pretty = NULL; + + fname = strjoina("_nss_", module, "_gethostbyaddr_r"); + f = dlsym(handle, fname); + + log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno, + "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f); + if (!f) + return; + + assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0); + + status = f(addr, len, af, &host, buffer, sizeof buffer, &errno1, &errno2); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s", + fname, addr_pretty, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_byname(void *handle, const char *module, const char *name) { + test_gethostbyname4_r(handle, module, name); + puts(""); + + test_gethostbyname3_r(handle, module, name, AF_INET); + puts(""); + test_gethostbyname3_r(handle, module, name, AF_INET6); + puts(""); + test_gethostbyname3_r(handle, module, name, AF_UNSPEC); + puts(""); + test_gethostbyname3_r(handle, module, name, AF_LOCAL); + puts(""); + + test_gethostbyname2_r(handle, module, name, AF_INET); + puts(""); + test_gethostbyname2_r(handle, module, name, AF_INET6); + puts(""); + test_gethostbyname2_r(handle, module, name, AF_UNSPEC); + puts(""); + test_gethostbyname2_r(handle, module, name, AF_LOCAL); + puts(""); + + test_gethostbyname_r(handle, module, name); + puts(""); +} + +static void test_byaddr(void *handle, + const char *module, + const void* addr, socklen_t len, + int af) { + test_gethostbyaddr2_r(handle, module, addr, len, af); + puts(""); + + test_gethostbyaddr_r(handle, module, addr, len, af); + puts(""); +} + +#ifdef HAVE_MYHOSTNAME +# define MODULE1 "myhostname\0" +#endif +#ifdef HAVE_RESOLVED +# define MODULE2 "resolve\0" +#endif +#ifdef HAVE_MACHINED +# define MODULE3 "mymachines\0" +#endif +#define MODULE4 "dns\0" + +int main(int argc, char **argv) { + _cleanup_free_ char *dir = NULL, *hostname = NULL; + const char *module; + + const uint32_t local_address_ipv4 = htonl(0x7F000001); + const uint32_t local_address_ipv4_2 = htonl(0x7F000002); + _cleanup_free_ struct local_address *addresses = NULL; + int n_addresses; + + log_set_max_level(LOG_INFO); + log_parse_environment(); + + dir = dirname_malloc(argv[0]); + assert_se(dir); + + hostname = gethostname_malloc(); + assert_se(hostname); + + n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); + if (n_addresses < 0) { + log_info_errno(n_addresses, "Failed to query local addresses: %m"); + n_addresses = 0; + } + + NULSTR_FOREACH(module, MODULE1 MODULE2 MODULE3 MODULE4) { + void *handle; + const char *name; + int i; + + log_info("======== %s ========", module); + + handle = open_handle(streq(module, "dns") ? NULL : dir, + module, + RTLD_LAZY|RTLD_NODELETE); + NULSTR_FOREACH(name, "localhost\0" "gateway\0" "foo_no_such_host\0") + test_byname(handle, module, name); + + test_byname(handle, module, hostname); + + test_byaddr(handle, module, &local_address_ipv4, sizeof local_address_ipv4, AF_INET); + test_byaddr(handle, module, &local_address_ipv4_2, sizeof local_address_ipv4_2, AF_INET); + test_byaddr(handle, module, &in6addr_loopback, sizeof in6addr_loopback, AF_INET6); + + for (i = 0; i < n_addresses; i++) + test_byaddr(handle, module, + &addresses[i].address, + FAMILY_ADDRESS_SIZE(addresses[i].family), + addresses[i].family); + + dlclose(handle); + + log_info(" "); + } + + return EXIT_SUCCESS; +} diff --git a/src/test/test-udev.c b/src/test/test-udev.c index d01789fe08..64ef08652c 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -40,11 +40,11 @@ static int fake_filesystems(void) { const char *target; const char *error; } fakefss[] = { - { "test/sys", "/sys", "failed to mount test /sys" }, - { "test/dev", "/dev", "failed to mount test /dev" }, - { "test/run", "/run", "failed to mount test /run" }, - { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" }, - { "test/run", UDEVLIBEXECDIR "/rules.d","failed to mount empty " UDEVLIBEXECDIR "/rules.d" }, + { "test/tmpfs/sys", "/sys", "failed to mount test /sys" }, + { "test/dev", "/dev", "failed to mount test /dev" }, + { "test/run", "/run", "failed to mount test /run" }, + { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" }, + { "test/run", UDEVLIBEXECDIR "/rules.d","failed to mount empty " UDEVLIBEXECDIR "/rules.d" }, }; unsigned int i; int err; diff --git a/test/test-functions b/test/test-functions index 29f647ece4..8bbcddab59 100644 --- a/test/test-functions +++ b/test/test-functions @@ -213,6 +213,9 @@ EOF install_fsck() { dracut_install /sbin/fsck* dracut_install -o /bin/fsck* + + # fskc.reiserfs calls reiserfsck. so, install it + dracut_install -o reiserfsck } install_dmevent() { @@ -257,7 +260,13 @@ create_empty_image() { , EOF - mkfs -t "$FSTYPE" -L systemd "${LOOPDEV}p1" + local _label="-L systemd" + # mkfs.reiserfs doesn't know -L. so, use --label instead + [[ "$FSTYPE" == "reiserfs" ]] && _label="--label systemd" + if ! mkfs -t "${FSTYPE}" ${_label} "${LOOPDEV}p1" -q; then + dfatal "Failed to mkfs -t ${FSTYPE}" + exit 1 + fi } check_result_nspawn() { @@ -351,7 +360,7 @@ install_config_files() { echo systemd-testsuite > $initdir/etc/hostname # fstab cat >$initdir/etc/fstab <<EOF -LABEL=systemd / ext3 rw 0 1 +LABEL=systemd / ${FSTYPE} rw 0 1 EOF } diff --git a/test/udev-test.pl b/test/udev-test.pl index b047493f6b..3c8a480d0f 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -29,6 +29,7 @@ my $udev_bin_gdb = "gdb --args $udev_bin"; my $udev_bin_strace = "strace -efile $udev_bin"; my $udev_dev = "test/dev"; my $udev_run = "test/run"; +my $udev_tmpfs = "test/tmpfs"; my $udev_rules_dir = "$udev_run/udev/rules.d"; my $udev_rules = "$udev_rules_dir/udev-test.rules"; my $EXIT_TEST_SKIP = 77; @@ -1412,6 +1413,12 @@ sub udev_setup { chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n"; chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n"; + system("umount", "$udev_tmpfs"); + system("rm", "-rf", "$udev_tmpfs"); + mkdir($udev_tmpfs) || die "unable to create udev_tmpfs: $udev_tmpfs\n"; + system("mount", "-o", "rw,mode=755,nosuid,noexec,nodev", "-t", "tmpfs", "tmpfs", "$udev_tmpfs") && die "unable to mount tmpfs"; + system("cp", "-r", "test/sys/", "$udev_tmpfs") && die "unable to copy test/sys"; + system("rm", "-rf", "$udev_run"); } @@ -1545,6 +1552,8 @@ print "$error errors occurred\n\n"; # cleanup system("rm", "-rf", "$udev_dev"); system("rm", "-rf", "$udev_run"); +system("umount", "$udev_tmpfs"); +system("rm", "-rf", "$udev_tmpfs"); if ($error > 0) { exit(1); |