diff options
89 files changed, 1031 insertions, 263 deletions
diff --git a/Makefile-man.am b/Makefile-man.am index f436361074..f21cc527f0 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -11,7 +11,6 @@ MANPAGES += \ man/bootup.7 \ man/busctl.1 \ man/daemon.7 \ - man/environment.d.5 \ man/file-hierarchy.7 \ man/halt.8 \ man/hostname.5 \ @@ -111,15 +110,12 @@ MANPAGES += \ man/systemd-debug-generator.8 \ man/systemd-delta.1 \ man/systemd-detect-virt.1 \ - man/systemd-environment-d-generator.8 \ man/systemd-escape.1 \ man/systemd-fsck@.service.8 \ man/systemd-fstab-generator.8 \ man/systemd-getty-generator.8 \ man/systemd-gpt-auto-generator.8 \ man/systemd-halt.service.8 \ - man/systemd-hibernate-resume-generator.8 \ - man/systemd-hibernate-resume@.service.8 \ man/systemd-inhibit.1 \ man/systemd-initctl.service.8 \ man/systemd-journald.service.8 \ @@ -130,7 +126,6 @@ MANPAGES += \ man/systemd-nspawn.1 \ man/systemd-path.1 \ man/systemd-remount-fs.service.8 \ - man/systemd-resolve.1 \ man/systemd-run.1 \ man/systemd-sleep.conf.5 \ man/systemd-socket-activate.1 \ @@ -148,7 +143,6 @@ MANPAGES += \ man/systemd.1 \ man/systemd.automount.5 \ man/systemd.device.5 \ - man/systemd.environment-generator.7 \ man/systemd.exec.5 \ man/systemd.generator.7 \ man/systemd.journal-fields.7 \ @@ -187,7 +181,6 @@ MANPAGES += \ man/udev_new.3 \ man/udevadm.8 MANPAGES_ALIAS += \ - man/30-systemd-environment-d-generator.8 \ man/SD_ALERT.3 \ man/SD_BUS_ERROR_ACCESS_DENIED.3 \ man/SD_BUS_ERROR_ADDRESS_IN_USE.3 \ @@ -463,7 +456,6 @@ MANPAGES_ALIAS += \ man/systemd-ask-password-wall.service.8 \ man/systemd-fsck-root.service.8 \ man/systemd-fsck.8 \ - man/systemd-hibernate-resume.8 \ man/systemd-hibernate.service.8 \ man/systemd-hybrid-sleep.service.8 \ man/systemd-initctl.8 \ @@ -547,7 +539,6 @@ MANPAGES_ALIAS += \ man/udev_ref.3 \ man/udev_unref.3 \ man/user.conf.d.5 -man/30-systemd-environment-d-generator.8: man/systemd-environment-d-generator.8 man/SD_ALERT.3: man/sd-daemon.3 man/SD_BUS_ERROR_ACCESS_DENIED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_ADDRESS_IN_USE.3: man/sd-bus-errors.3 @@ -823,7 +814,6 @@ man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8 man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8 man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8 man/systemd-fsck.8: man/systemd-fsck@.service.8 -man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8 man/systemd-hibernate.service.8: man/systemd-suspend.service.8 man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8 man/systemd-initctl.8: man/systemd-initctl.service.8 @@ -907,9 +897,6 @@ man/udev_monitor_unref.3: man/udev_monitor_new_from_netlink.3 man/udev_ref.3: man/udev_new.3 man/udev_unref.3: man/udev_new.3 man/user.conf.d.5: man/systemd-system.conf.5 -man/30-systemd-environment-d-generator.html: man/systemd-environment-d-generator.html - $(html-alias) - man/SD_ALERT.html: man/sd-daemon.html $(html-alias) @@ -1735,9 +1722,6 @@ man/systemd-fsck-root.service.html: man/systemd-fsck@.service.html man/systemd-fsck.html: man/systemd-fsck@.service.html $(html-alias) -man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html - $(html-alias) - man/systemd-hibernate.service.html: man/systemd-suspend.service.html $(html-alias) @@ -2043,6 +2027,19 @@ MANPAGES_ALIAS += \ endif +if ENABLE_ENVIRONMENT_D +MANPAGES += \ + man/environment.d.5 \ + man/systemd-environment-d-generator.8 \ + man/systemd.environment-generator.7 +MANPAGES_ALIAS += \ + man/30-systemd-environment-d-generator.8 +man/30-systemd-environment-d-generator.8: man/systemd-environment-d-generator.8 +man/30-systemd-environment-d-generator.html: man/systemd-environment-d-generator.html + $(html-alias) + +endif + if ENABLE_FIRSTBOOT MANPAGES += \ man/systemd-firstboot.1 @@ -2054,6 +2051,18 @@ man/systemd-firstboot.service.html: man/systemd-firstboot.html endif +if ENABLE_HIBERNATE +MANPAGES += \ + man/systemd-hibernate-resume-generator.8 \ + man/systemd-hibernate-resume@.service.8 +MANPAGES_ALIAS += \ + man/systemd-hibernate-resume.8 +man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8 +man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html + $(html-alias) + +endif + if ENABLE_HOSTNAMED MANPAGES += \ man/hostnamectl.1 \ @@ -2188,6 +2197,7 @@ MANPAGES += \ man/dnssec-trust-anchors.d.5 \ man/nss-resolve.8 \ man/resolved.conf.5 \ + man/systemd-resolve.1 \ man/systemd-resolved.service.8 MANPAGES_ALIAS += \ man/libnss_resolve.so.2.8 \ @@ -2605,6 +2615,16 @@ man/systemd-user-sessions.html: man/systemd-user-sessions.service.html endif +if HAVE_PYTHON +MANPAGES += \ + man/systemd.directives.7 \ + man/systemd.index.7 +MANPAGES_ALIAS += \ + # + + +endif + if HAVE_SYSV_COMPAT MANPAGES += \ man/systemd-sysv-generator.8 diff --git a/Makefile.am b/Makefile.am index f5f2793f5b..d565978266 100644 --- a/Makefile.am +++ b/Makefile.am @@ -749,9 +749,11 @@ man/index.html: man/systemd.index.html $(AM_V_LN)$(LN_S) -f systemd.index.html $@ if HAVE_PYTHON +if ENABLE_MANPAGES noinst_DATA += \ man/index.html endif +endif CLEANFILES += \ man/index.html @@ -5812,6 +5814,8 @@ libnetworkd_core_la_SOURCES = \ src/network/networkd-network-bus.c \ src/network/networkd-address.h \ src/network/networkd-address.c \ + src/network/networkd-address-label.h \ + src/network/networkd-address-label.c \ src/network/networkd-route.h \ src/network/networkd-route.c \ src/network/networkd-fdb.h \ diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index 5b7d31ace1..d3b920bb99 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -115,6 +115,13 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pn?550C?:* EVDEV_ABS_35=::31 EVDEV_ABS_36=::30 +# Asus UX301L +evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX301LAA:* + EVDEV_ABS_00=::30 + EVDEV_ABS_01=::29 + EVDEV_ABS_35=::30 + EVDEV_ABS_36=::29 + # Asus UX305 evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX305UA:* EVDEV_ABS_00=0:3097:32 @@ -338,6 +345,13 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/ EVDEV_ABS_35=0:2480:28 EVDEV_ABS_36=0:1116:24 +# Samsung 880Z5E +evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E* + EVDEV_ABS_00=::30 + EVDEV_ABS_01=::29 + EVDEV_ABS_35=::30 + EVDEV_ABS_36=::29 + ######################################### # Toshiba ######################################### diff --git a/hwdb/acpi-update.py b/hwdb/acpi-update.py index 50da531dc6..2c23b057fb 100755 --- a/hwdb/acpi-update.py +++ b/hwdb/acpi-update.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 from html.parser import HTMLParser from enum import Enum diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index e2c65c4be0..adf8a1963e 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. It is distrubuted under the MIT license, see diff --git a/man/90-rearrange-path.py b/man/90-rearrange-path.py index c6ff32210f..7537d5e915 100755 --- a/man/90-rearrange-path.py +++ b/man/90-rearrange-path.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 """ diff --git a/man/environment.d.xml b/man/environment.d.xml index be7758a2f9..78b949160b 100644 --- a/man/environment.d.xml +++ b/man/environment.d.xml @@ -20,7 +20,8 @@ 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="environment.d" xmlns:xi="http://www.w3.org/2001/XInclude"> +<refentry id="environment.d" conditional='ENABLE_ENVIRONMENT_D' + xmlns:xi="http://www.w3.org/2001/XInclude"> <refentryinfo> <title>environment.d</title> diff --git a/man/meson.build b/man/meson.build index 6f7b1e8793..4f2ddad31a 100644 --- a/man/meson.build +++ b/man/meson.build @@ -61,15 +61,32 @@ foreach tuple : manpages install_dir : mandirn) man_pages += [p1] - p2 = custom_target( + p2 = [] + foreach htmlalias : htmlaliases + link = custom_target( + htmlalias, + input : p2, + output : htmlalias, + command : ['ln', '-fs', html, '@OUTPUT@']) + if want_html + dst = join_paths(docdir, 'html', htmlalias) + cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst) + meson.add_install_script('sh', '-c', cmd) + p2 += [link] + endif + html_pages += [link] + endforeach + + p3 = custom_target( html, input : xml, - output : [html] + htmlaliases, + output : html, command : xslt_cmd + [custom_html_xsl, '@INPUT@'], depend_files : custom_entities_ent, + depends : p2, install : want_html, install_dir : join_paths(docdir, 'html')) - html_pages += [p2] + html_pages += [p3] source_xml_files += files(tuple[0] + '.xml') else @@ -117,14 +134,33 @@ foreach tuple : [['systemd.directives', '7', systemd_directives_xml], install_dir : mandirn) man_pages += [p1] - p2 = custom_target( + p2 = [] + if html == 'systemd.index.html' + htmlalias = 'index.html' + link = custom_target( + htmlalias, + input : p2, + output : htmlalias, + command : ['ln', '-fs', html, '@OUTPUT@']) + if want_html + dst = join_paths(docdir, 'html', htmlalias) + cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst) + meson.add_install_script('sh', '-c', cmd) + p2 += [link] + endif + html_pages += [link] + endif + + p3 = custom_target( html, input : xml, output : html, command : xslt_cmd + [custom_html_xsl, '@INPUT@'], + depend_files : custom_entities_ent, + depends : p2, install : want_html and have_lxml, install_dir : join_paths(docdir, 'html')) - html_pages += [p2] + html_pages += [p3] endforeach # cannot use run_target until https://github.com/mesonbuild/meson/issues/1644 is resolved diff --git a/man/rules/meson.build b/man/rules/meson.build index 21c996f9b4..1508b012df 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -12,7 +12,7 @@ manpages = [ '5', ['systemd.negative', 'systemd.positive'], 'ENABLE_RESOLVED'], - ['environment.d', '5', [], ''], + ['environment.d', '5', [], 'ENABLE_ENVIRONMENT_D'], ['file-hierarchy', '7', [], ''], ['halt', '8', ['poweroff', 'reboot'], ''], ['hostname', '5', [], ''], @@ -521,7 +521,7 @@ manpages = [ ['systemd-environment-d-generator', '8', ['30-systemd-environment-d-generator'], - ''], + 'ENABLE_ENVIRONMENT_D'], ['systemd-escape', '1', [], ''], ['systemd-firstboot', '1', ['systemd-firstboot.service'], 'ENABLE_FIRSTBOOT'], ['systemd-fsck@.service', @@ -538,8 +538,11 @@ manpages = [ 'systemd-reboot.service', 'systemd-shutdown'], ''], - ['systemd-hibernate-resume-generator', '8', [], ''], - ['systemd-hibernate-resume@.service', '8', ['systemd-hibernate-resume'], ''], + ['systemd-hibernate-resume-generator', '8', [], 'ENABLE_HIBERNATE'], + ['systemd-hibernate-resume@.service', + '8', + ['systemd-hibernate-resume'], + 'ENABLE_HIBERNATE'], ['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'], ['systemd-hwdb', '8', [], 'ENABLE_HWDB'], ['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'], @@ -585,7 +588,7 @@ manpages = [ ['systemd-random-seed'], 'ENABLE_RANDOMSEED'], ['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''], - ['systemd-resolve', '1', [], ''], + ['systemd-resolve', '1', [], 'ENABLE_RESOLVED'], ['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVED'], ['systemd-rfkill.service', '8', @@ -644,7 +647,7 @@ manpages = [ ['systemd', '1', ['init'], ''], ['systemd.automount', '5', [], ''], ['systemd.device', '5', [], ''], - ['systemd.environment-generator', '7', [], ''], + ['systemd.environment-generator', '7', [], 'ENABLE_ENVIRONMENT_D'], ['systemd.exec', '5', [], ''], ['systemd.generator', '7', [], ''], ['systemd.journal-fields', '7', [], ''], diff --git a/man/systemd-environment-d-generator.xml b/man/systemd-environment-d-generator.xml index cc00a5256d..7950aa98a5 100644 --- a/man/systemd-environment-d-generator.xml +++ b/man/systemd-environment-d-generator.xml @@ -23,7 +23,7 @@ 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-environment-d-generator"> +<refentry id="systemd-environment-d-generator" conditional='ENABLE_ENVIRONMENT_D'> <refentryinfo> <title>systemd-environment-d-generator</title> diff --git a/man/systemd-hibernate-resume-generator.xml b/man/systemd-hibernate-resume-generator.xml index d811b9b551..3bbb6ab989 100644 --- a/man/systemd-hibernate-resume-generator.xml +++ b/man/systemd-hibernate-resume-generator.xml @@ -19,7 +19,7 @@ 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-hibernate-resume-generator"> +<refentry id="systemd-hibernate-resume-generator" conditional='ENABLE_HIBERNATE'> <refentryinfo> <title>systemd-hibernate-resume-generator</title> diff --git a/man/systemd-hibernate-resume@.service.xml b/man/systemd-hibernate-resume@.service.xml index 7d00827447..a968adf0a9 100644 --- a/man/systemd-hibernate-resume@.service.xml +++ b/man/systemd-hibernate-resume@.service.xml @@ -19,7 +19,7 @@ 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-hibernate-resume@.service"> +<refentry id="systemd-hibernate-resume@.service" conditional='ENABLE_HIBERNATE'> <refentryinfo> <title>systemd-hibernate-resume@.service</title> diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml index 50da971b07..e3ef26bb81 100644 --- a/man/systemd-resolve.xml +++ b/man/systemd-resolve.xml @@ -21,7 +21,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. --> -<refentry id="systemd-resolve" +<refentry id="systemd-resolve" conditional='ENABLE_RESOLVED' xmlns:xi="http://www.w3.org/2001/XInclude"> <refentryinfo> diff --git a/man/systemd.environment-generator.xml b/man/systemd.environment-generator.xml index fedbd60175..ff8be92833 100644 --- a/man/systemd.environment-generator.xml +++ b/man/systemd.environment-generator.xml @@ -24,7 +24,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. --> -<refentry id="systemd.environment-generator" xmlns:xi="http://www.w3.org/2001/XInclude"> +<refentry id="systemd.environment-generator" conditional='ENABLE_ENVIRONMENT_D' + xmlns:xi="http://www.w3.org/2001/XInclude"> <refentryinfo> <title>systemd.environment-generator</title> <productname>systemd</productname> diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index cb2bd23f71..f9b558520b 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -600,8 +600,8 @@ <listitem> <para>Configures the default destination UDP port on a per-device basis. If destination port is not specified then Linux kernel default will be used. - Set destination port 4789 to get the IANA assigned value, - and destination port 0 to get default values.</para> + Set destination port 4789 to get the IANA assigned value. If not set or if the + destination port is assigned the empty string the default port of 4789 is used.</para> </listitem> </varlistentry> <varlistentry> @@ -646,13 +646,13 @@ <varlistentry> <term><varname>TOS=</varname></term> <listitem> - <para>Specifies the TOS value to use in outgoing packets. Ranges [1-255]. </para> + <para>Specifies the TOS value to use in outgoing packets. Ranges [1-255].</para> </listitem> </varlistentry> <varlistentry> <term><varname>TTL=</varname></term> <listitem> - <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255]. </para> + <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255].</para> </listitem> </varlistentry> <varlistentry> @@ -676,7 +676,8 @@ <varlistentry> <term><varname>DestinationPort=</varname></term> <listitem> - <para>Specifies destination port. Defaults to 6081.</para> + <para>Specifies destination port. Defaults to 6081. If not set or assigned the empty string, the default + port of 6081 is used.</para> </listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 4b80578333..ad0e0cf48a 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -796,6 +796,33 @@ </variablelist> </refsect1> + <refsect1> + <title>[IPv6AddressLabel] Section Options</title> + + <para>An <literal>[IPv6AddressLabel]</literal> section accepts the + following keys. Specify several <literal>[IPv6AddressLabel]</literal> + sections to configure several addresse labels. IPv6 address labels are + used for address selection. See <ulink url="https://tools.ietf.org/html/rfc3484">RFC 3484</ulink>. + Precedence is managed by userspace, and only the label itself is stored in the kernel</para> + + <variablelist class='network-directives'> + <varlistentry> + <term><varname>Label=</varname></term> + <listitem> + <para> The label for the prefix (an unsigned integer) ranges 0 to 4294967294. + 0xffffffff is reserved. This key is mandatory.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>Prefix=</varname></term> + <listitem> + <para>IPv6 prefix is an address with a prefix length, separated by a slash <literal>/</literal> character. + This key is mandatory. </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1> <title>[Route] Section Options</title> <para>The <literal>[Route]</literal> section accepts the diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 68bf0b2407..a7c37a0018 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -718,17 +718,20 @@ <varlistentry> <term><varname>JobTimeoutSec=</varname></term> + <term><varname>JobRunningTimeoutSec=</varname></term> <term><varname>JobTimeoutAction=</varname></term> <term><varname>JobTimeoutRebootArgument=</varname></term> - <listitem><para>When a job for this unit is queued, a time-out may be configured. If this time limit is - reached, the job will be cancelled, the unit however will not change state or even enter the - <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts disabled), - except for device units. NB: this timeout is independent from any unit-specific timeout (for example, the - timeout set with <varname>TimeoutStartSec=</varname> in service units) as the job timeout has no effect on the - unit itself, only on the job that might be pending for it. Or in other words: unit-specific timeouts are useful - to abort unit state changes, and revert them. The job timeout set with this option however is useful to abort - only the job waiting for the unit state to change.</para> + <listitem><para>When a job for this unit is queued, a time-out <varname>JobTimeoutSec=</varname> may be + configured. Similarly, <varname>JobRunningTimeoutSec=</varname> starts counting when the queued job is actually + started. If either time limit is reached, the job will be cancelled, the unit however will not change state or + even enter the <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts + disabled), except for device units (<varname>JobRunningTimeoutSec=</varname> defaults to + <varname>DefaultTimeoutStartSec=</varname>). NB: this timeout is independent from any unit-specific timeout + (for example, the timeout set with <varname>TimeoutStartSec=</varname> in service units) as the job timeout has + no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific + timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however + is useful to abort only the job waiting for the unit state to change.</para> <para><varname>JobTimeoutAction=</varname> optionally configures an additional diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c index 6b9d26773e..5bf58bcdc3 100644 --- a/src/basic/dirent-util.c +++ b/src/basic/dirent-util.c @@ -75,3 +75,14 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { return endswith(de->d_name, suffix); } + +struct dirent* readdir_no_dot(DIR *dirp) { + struct dirent* d; + + for (;;) { + d = readdir(dirp); + if (d && dot_or_dot_dot(d->d_name)) + continue; + return d; + } +} diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h index b91d04908f..18b9db9b28 100644 --- a/src/basic/dirent-util.h +++ b/src/basic/dirent-util.h @@ -31,6 +31,8 @@ int dirent_ensure_type(DIR *d, struct dirent *de); bool dirent_is_file(const struct dirent *de) _pure_; bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; +struct dirent* readdir_no_dot(DIR *dirp); + #define FOREACH_DIRENT(de, d, on_error) \ for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ if (!de) { \ diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c index f8cac3e911..804f14c44c 100644 --- a/src/basic/extract-word.c +++ b/src/basic/extract-word.c @@ -241,7 +241,12 @@ int extract_first_word_and_warn( return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue); } -int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) { +/* We pass ExtractFlags as unsigned int (to avoid undefined behaviour when passing + * an object that undergoes default argument promotion as an argument to va_start). + * Let's make sure that ExtractFlags fits into an unsigned int. */ +assert_cc(sizeof(enum ExtractFlags) <= sizeof(unsigned)); + +int extract_many_words(const char **p, const char *separators, unsigned flags, ...) { va_list ap; char **l; int n = 0, i, c, r; diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h index 21db5ef33f..04746c6d08 100644 --- a/src/basic/extract-word.h +++ b/src/basic/extract-word.h @@ -32,4 +32,4 @@ typedef enum ExtractFlags { int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue); -int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_; +int extract_many_words(const char **p, const char *separators, unsigned flags, ...) _sentinel_; diff --git a/src/basic/generate-gperfs.py b/src/basic/generate-gperfs.py index 2e7d8931dd..d4cc9aa45c 100644 --- a/src/basic/generate-gperfs.py +++ b/src/basic/generate-gperfs.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 """Generate %-from-name.gperf from %-list.txt """ diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c index 007198c269..f611c42e4c 100644 --- a/src/basic/glob-util.c +++ b/src/basic/glob-util.c @@ -17,54 +17,70 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <dirent.h> #include <errno.h> #include <glob.h> +#include <sys/types.h> +#include "dirent-util.h" #include "glob-util.h" #include "macro.h" +#include "path-util.h" #include "strv.h" -int glob_exists(const char *path) { - _cleanup_globfree_ glob_t g = {}; +int safe_glob(const char *path, int flags, glob_t *pglob) { int k; - assert(path); + /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */ + assert(!(flags & GLOB_ALTDIRFUNC)); + + if (!pglob->gl_closedir) + pglob->gl_closedir = (void (*)(void *)) closedir; + if (!pglob->gl_readdir) + pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot; + if (!pglob->gl_opendir) + pglob->gl_opendir = (void *(*)(const char *)) opendir; + if (!pglob->gl_lstat) + pglob->gl_lstat = lstat; + if (!pglob->gl_stat) + pglob->gl_stat = stat; errno = 0; - k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob); if (k == GLOB_NOMATCH) - return 0; + return -ENOENT; if (k == GLOB_NOSPACE) return -ENOMEM; if (k != 0) return errno > 0 ? -errno : -EIO; + if (strv_isempty(pglob->gl_pathv)) + return -ENOENT; - return !strv_isempty(g.gl_pathv); + return 0; } -int glob_extend(char ***strv, const char *path) { +int glob_exists(const char *path) { _cleanup_globfree_ glob_t g = {}; int k; - char **p; - errno = 0; - k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + assert(path); - if (k == GLOB_NOMATCH) - return -ENOENT; - if (k == GLOB_NOSPACE) - return -ENOMEM; - if (k != 0) - return errno > 0 ? -errno : -EIO; - if (strv_isempty(g.gl_pathv)) - return -ENOENT; + k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k == -ENOENT) + return false; + if (k < 0) + return k; + return true; +} + +int glob_extend(char ***strv, const char *path) { + _cleanup_globfree_ glob_t g = {}; + int k; - STRV_FOREACH(p, g.gl_pathv) { - k = strv_extend(strv, *p); - if (k < 0) - return k; - } + k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k < 0) + return k; - return 0; + return strv_extend_strv(strv, g.gl_pathv, false); } diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h index 5d8fb47a26..e1f6083afa 100644 --- a/src/basic/glob-util.h +++ b/src/basic/glob-util.h @@ -19,12 +19,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <glob.h> #include <stdbool.h> #include <string.h> #include "macro.h" #include "string-util.h" +/* Note: this function modifies pglob to set various functions. */ +int safe_glob(const char *path, int flags, glob_t *pglob); + int glob_exists(const char *path); int glob_extend(char ***strv, const char *path); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index bdaca264ff..ff040e7a55 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -182,18 +182,11 @@ int rm_rf(const char *path, RemoveFlags flags) { /* We refuse to clean the root file system with this * call. This is extra paranoia to never cause a really * seriously broken system. */ - if (path_equal(path, "/")) { + if (path_equal_or_files_same(path, "/")) { log_error("Attempted to remove entire root file system, and we can't allow that."); return -EPERM; } - /* Another safe-check. Removing "/path/.." could easily remove entire root as well. - * It's especially easy to do using globs in tmpfiles, like "/path/.*", which the glob() - * function expands to both "/path/." and "/path/..". - * Return -EINVAL to be consistent with rmdir("/path/."). */ - if (endswith(path, "/..") || endswith(path, "/../")) - return -EINVAL; - if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) { /* Try to remove as subvolume first */ r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c index 4ac11a9bb0..b22d37b62d 100644 --- a/src/boot/efi/measure.c +++ b/src/boot/efi/measure.c @@ -199,7 +199,7 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p event_number = 1; status = uefi_call_wrapper(tcg->HashLogExtendEvent, 7, - tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last); + (EFI_TCG *) tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last); if (EFI_ERROR(status)) return status; @@ -219,7 +219,7 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p */ static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg) { - return uefi_call_wrapper(tcg->GetEventLog, 5, tcg, + return uefi_call_wrapper(tcg->GetEventLog, 5, (EFI_TCG2 *) tcg, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL, NULL, NULL); } @@ -254,7 +254,7 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32 CopyMem((VOID *) tcg_event->Event, (VOID *) description, desc_len); - status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, tcg, 0, buffer, buffer_size, tcg_event); + status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, (EFI_TCG2 *) tcg, 0, buffer, buffer_size, tcg_event); uefi_call_wrapper(BS->FreePool, 1, tcg_event); diff --git a/src/boot/efi/measure.h b/src/boot/efi/measure.h index a2cfe817d0..43aa8a0058 100644 --- a/src/boot/efi/measure.h +++ b/src/boot/efi/measure.h @@ -13,9 +13,6 @@ #ifndef __SDBOOT_MEASURE_H #define __SDBOOT_MEASURE_H -#ifndef SD_TPM_PCR -#define SD_TPM_PCR 8 -#endif - EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description); + #endif diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 67f3a99860..7ebb02fa8c 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -75,6 +75,7 @@ static usec_t arg_delay = 1*USEC_PER_SEC; static char* arg_machine = NULL; static char* arg_root = NULL; static bool arg_recursive = true; +static bool arg_recursive_unset = false; static enum { COUNT_PIDS, @@ -732,7 +733,6 @@ static int parse_argv(int argc, char *argv[]) { {} }; - bool recursive_unset = false; int c, r; assert(argc >= 1); @@ -852,7 +852,7 @@ static int parse_argv(int argc, char *argv[]) { } arg_recursive = r; - recursive_unset = r == 0; + arg_recursive_unset = r == 0; break; case 'M': @@ -873,11 +873,6 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (recursive_unset && arg_count == COUNT_PIDS) { - log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k."); - return -EINVAL; - } - return 1; } @@ -902,6 +897,10 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + r = cg_mask_supported(&mask); if (r < 0) { log_error_errno(r, "Failed to determine supported controllers: %m"); @@ -910,9 +909,10 @@ int main(int argc, char *argv[]) { arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES; - r = parse_argv(argc, argv); - if (r <= 0) - goto finish; + if (arg_recursive_unset && arg_count == COUNT_PIDS) { + log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k."); + return -EINVAL; + } r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root); if (r < 0) { diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index f15bb2196c..b0645ce294 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -748,6 +748,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), diff --git a/src/core/device.c b/src/core/device.c index 0e67c96552..da008f6041 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -112,7 +112,7 @@ static void device_init(Unit *u) { * indefinitely for plugged in devices, something which cannot * happen for the other units since their operations time out * anyway. */ - u->job_timeout = u->manager->default_timeout_start_usec; + u->job_running_timeout = u->manager->default_timeout_start_usec; u->ignore_on_isolate = true; } diff --git a/src/core/execute.c b/src/core/execute.c index 2056e2273c..9c1aa4cf98 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3231,11 +3231,10 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) { STRV_FOREACH(i, c->environment_files) { char *fn; - int k; + int k, n; bool ignore = false; char **p; _cleanup_globfree_ glob_t pglob = {}; - int count, n; fn = *i; @@ -3253,23 +3252,19 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) { } /* Filename supports globbing, take all matching files */ - errno = 0; - if (glob(fn, 0, NULL, &pglob) != 0) { + k = safe_glob(fn, 0, &pglob); + if (k < 0) { if (ignore) continue; strv_free(r); - return errno > 0 ? -errno : -EINVAL; + return k; } - count = pglob.gl_pathc; - if (count == 0) { - if (ignore) - continue; - strv_free(r); - return -EINVAL; - } - for (n = 0; n < count; n++) { + /* When we don't match anything, -ENOENT should be returned */ + assert(pglob.gl_pathc > 0); + + for (n = 0; n < pglob.gl_pathc; n++) { k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p); if (k < 0) { if (ignore) diff --git a/src/core/job.c b/src/core/job.c index a02f1bb2bc..5067006d63 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -576,6 +576,7 @@ int job_run_and_invalidate(Job *j) { if (!job_is_runnable(j)) return -EAGAIN; + job_start_timer(j, true); job_set_state(j, JOB_RUNNING); job_add_to_dbus_queue(j); @@ -949,22 +950,45 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user return 0; } -int job_start_timer(Job *j) { +int job_start_timer(Job *j, bool job_running) { int r; + usec_t run_begin, timeout_time, old_timeout_time; - if (j->timer_event_source) - return 0; + if (job_running) { + if (j->unit->job_running_timeout == USEC_INFINITY) + return 0; - j->begin_usec = now(CLOCK_MONOTONIC); + run_begin = now(CLOCK_MONOTONIC); + timeout_time = usec_add(run_begin, j->unit->job_running_timeout); - if (j->unit->job_timeout == USEC_INFINITY) - return 0; + if (j->timer_event_source) { + /* Update only if JobRunningTimeoutSec= results in earlier timeout */ + r = sd_event_source_get_time(j->timer_event_source, &old_timeout_time); + if (r < 0) + return r; + + if (old_timeout_time <= timeout_time) + return 0; + + return sd_event_source_set_time(j->timer_event_source, timeout_time); + } + } else { + if (j->timer_event_source) + return 0; + + j->begin_usec = now(CLOCK_MONOTONIC); + + if (j->unit->job_timeout == USEC_INFINITY) + return 0; + + timeout_time = usec_add(j->begin_usec, j->unit->job_timeout); + } r = sd_event_add_time( j->manager->event, &j->timer_event_source, CLOCK_MONOTONIC, - usec_add(j->begin_usec, j->unit->job_timeout), 0, + timeout_time, 0, job_dispatch_timer, j); if (r < 0) return r; diff --git a/src/core/job.h b/src/core/job.h index bea743f462..8b3d38fc60 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -220,7 +220,7 @@ int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u); void job_add_to_run_queue(Job *j); void job_add_to_dbus_queue(Job *j); -int job_start_timer(Job *j); +int job_start_timer(Job *j, bool job_running); int job_run_and_invalidate(Job *j); int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index cb9e6fea27..97adbdd7bb 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -194,6 +194,7 @@ Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate) Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0 Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout) +Unit.JobRunningTimeoutSec, config_parse_sec, 0, offsetof(Unit, job_running_timeout) Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action) Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg) Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval) diff --git a/src/core/service.c b/src/core/service.c index a63c6d8bc3..b45929e535 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2163,7 +2163,6 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command unsigned idx; const char *type; char **arg; - _cleanup_strv_free_ char **escaped_args = NULL; _cleanup_free_ char *args = NULL, *p = NULL; size_t allocated = 0, length = 0; @@ -2306,7 +2305,7 @@ static int service_deserialize_exec_command(Unit *u, const char *key, const char bool control, found = false; ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID; ExecCommand *command = NULL; - _cleanup_free_ char *args = NULL, *path = NULL; + _cleanup_free_ char *path = NULL; _cleanup_strv_free_ char **argv = NULL; enum ExecCommandState { diff --git a/src/core/transaction.c b/src/core/transaction.c index b6d1062414..a2dfd8ae90 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -632,7 +632,7 @@ static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) { job_add_to_run_queue(j); job_add_to_dbus_queue(j); - job_start_timer(j); + job_start_timer(j, false); job_shutdown_magic(j); } diff --git a/src/core/unit.c b/src/core/unit.c index 25ea5a8591..01fa0d0d46 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -99,6 +99,7 @@ Unit *unit_new(Manager *m, size_t size) { u->on_failure_job_mode = JOB_REPLACE; u->cgroup_inotify_wd = -1; u->job_timeout = USEC_INFINITY; + u->job_running_timeout = USEC_INFINITY; u->ref_uid = UID_INVALID; u->ref_gid = GID_INVALID; u->cpu_usage_last = NSEC_INFINITY; @@ -1336,6 +1337,9 @@ int unit_load(Unit *u) { goto fail; } + if (u->job_running_timeout != USEC_INFINITY && u->job_running_timeout > u->job_timeout) + log_unit_warning(u, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect."); + unit_update_cgroup_members_masks(u); } diff --git a/src/core/unit.h b/src/core/unit.h index 8052c234fd..cf21b37e22 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -114,6 +114,7 @@ struct Unit { /* Job timeout and action to take */ usec_t job_timeout; + usec_t job_running_timeout; EmergencyAction job_timeout_action; char *job_timeout_reboot_arg; diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 50d350fce8..b6c1a8781b 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -399,6 +399,10 @@ static int add_mount( if (r < 0) return r; + r = generator_write_device_deps(dest, what, where, opts); + if (r < 0) + return r; + r = write_mount_timeout(f, where, opts); if (r < 0) return r; diff --git a/src/import/pull-common.c b/src/import/pull-common.c index 4c745288f5..78840dd882 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -394,7 +394,6 @@ int pull_verify(PullJob *main_job, PullJob *signature_job) { _cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 }; - _cleanup_free_ char *fn = NULL; _cleanup_close_ int sig_file = -1; char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX"; _cleanup_(sigkill_waitp) pid_t pid = 0; diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index fd2e472f09..a15eac1f1f 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -580,7 +580,6 @@ static int raw_pull_job_on_open_disk_generic( const char *extra, char **temp_path) { - _cleanup_free_ char *p = NULL; int r; assert(i); diff --git a/src/journal-remote/log-generator.py b/src/journal-remote/log-generator.py index 7b434b334e..c2f945bb47 100755 --- a/src/journal-remote/log-generator.py +++ b/src/journal-remote/log-generator.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import sys import argparse diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 14cb01a600..243d5198d9 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -613,6 +613,9 @@ static int journal_file_verify_header(JournalFile *f) { return -EBUSY; } + if (f->header->field_hash_table_size == 0 || f->header->data_hash_table_size == 0) + return -EBADMSG; + /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks * bisection. */ diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index 092a1eabb0..337241a815 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -349,6 +349,45 @@ int config_parse_iaid(const char *unit, return 0; } +int config_parse_bridge_port_priority( + 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) { + + uint16_t i; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse bridge port priority, ignoring: %s", rvalue); + return 0; + } + + if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue); + return 0; + } + + *((uint16_t *)data) = i; + + 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 5bcd577167..4666f174e9 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -26,6 +26,9 @@ #include "condition.h" #include "udev.h" +#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 +#define LINK_BRIDGE_PORT_PRIORITY_MAX 63 + bool net_match_config(const struct ether_addr *match_mac, char * const *match_path, char * const *match_driver, @@ -62,6 +65,10 @@ int config_parse_iaid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_bridge_port_priority(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-ndisc.c b/src/libsystemd-network/sd-ndisc.c index 1d3be9b862..83e57d43f7 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -131,6 +131,7 @@ static int ndisc_reset(sd_ndisc *nd) { nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source); nd->recv_event_source = sd_event_source_unref(nd->recv_event_source); nd->fd = safe_close(nd->fd); + nd->nd_sent = 0; return 0; } diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 248bc90788..923f7dd10c 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -26,6 +26,7 @@ #include <linux/veth.h> #include <linux/if_bridge.h> #include <linux/if_addr.h> +#include <linux/if_addrlabel.h> #include <linux/if.h> #include <linux/ip.h> #include <linux/if_link.h> @@ -586,22 +587,35 @@ static const NLTypeSystem rtnl_neigh_type_system = { .types = rtnl_neigh_types, }; +static const NLType rtnl_addrlabel_types[] = { + [IFAL_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) }, + [IFAL_LABEL] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_addrlabel_type_system = { + .count = ELEMENTSOF(rtnl_addrlabel_types), + .types = rtnl_addrlabel_types, +}; + static const NLType rtnl_types[] = { - [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 }, - [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, - [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, - [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, - [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 }, + [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, + [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) }, + [RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) }, + [RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) }, }; const NLTypeSystem type_system_root = { diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index f49bf4eaa6..49bb226ef3 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -32,6 +32,10 @@ bool rtnl_message_type_is_addr(uint16_t type); bool rtnl_message_type_is_route(uint16_t type); bool rtnl_message_type_is_neigh(uint16_t type); +static inline bool rtnl_message_type_is_addrlabel(uint16_t type) { + return IN_SET(type, RTM_NEWADDRLABEL, RTM_DELADDRLABEL, RTM_GETADDRLABEL); +} + int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name); int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu); diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c index b543b5f20c..d5f8b7d15e 100644 --- a/src/libsystemd/sd-netlink/rtnl-message.c +++ b/src/libsystemd/sd-netlink/rtnl-message.c @@ -18,6 +18,7 @@ ***/ #include <netinet/in.h> +#include <linux/if_addrlabel.h> #include <stdbool.h> #include <unistd.h> @@ -700,3 +701,42 @@ int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) { return -EOPNOTSUPP; } + +int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family) { + struct ifaddrlblmsg *addrlabel; + int r; + + assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWADDRLABEL) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; + + addrlabel = NLMSG_DATA((*ret)->hdr); + + addrlabel->ifal_family = ifal_family; + addrlabel->ifal_index = ifindex; + + return 0; +} + +int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { + struct ifaddrlblmsg *addrlabel; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL); + + addrlabel = NLMSG_DATA(m->hdr); + + if (prefixlen > 128) + return -ERANGE; + + addrlabel->ifal_prefixlen = prefixlen; + + return 0; +} diff --git a/src/network/meson.build b/src/network/meson.build index ebd4e62eb3..5f97cc197b 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -27,6 +27,8 @@ sources = files(''' netdev/vxlan.h netdev/geneve.c netdev/geneve.h + networkd-address-label.c + networkd-address-label.h networkd-address-pool.c networkd-address-pool.h networkd-address.c diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c index 07c69f4711..e71ea58a10 100644 --- a/src/network/netdev/geneve.c +++ b/src/network/netdev/geneve.c @@ -238,36 +238,6 @@ int config_parse_geneve_address(const char *unit, return 0; } -int config_parse_geneve_destination_port(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) { - Geneve *v = userdata; - uint16_t port; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = parse_ip_port(rvalue, &port); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve destination port '%s'.", rvalue); - return 0; - } - - v->dest_port = port; - - return 0; -} - int config_parse_geneve_flow_label(const char *unit, const char *filename, unsigned line, diff --git a/src/network/netdev/geneve.h b/src/network/netdev/geneve.h index d97dac892c..bde28bac55 100644 --- a/src/network/netdev/geneve.h +++ b/src/network/netdev/geneve.h @@ -25,7 +25,6 @@ typedef struct Geneve Geneve; #include "netdev.h" #include "networkd-link.h" #include "networkd-network.h" -#include "netdev.h" #define GENEVE_VID_MAX (1u << 24) - 1 @@ -74,17 +73,6 @@ int config_parse_geneve_address(const char *unit, void *data, void *userdata); -int config_parse_geneve_destination_port(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_geneve_flow_label(const char *unit, const char *filename, unsigned line, diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 6016b99b54..ed943789d7 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -79,7 +79,7 @@ VXLAN.FDBAgeingSec, config_parse_sec, 0, VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) VXLAN.PortRange, config_parse_port_range, 0, 0 -VXLAN.DestinationPort, config_parse_destination_port, 0, offsetof(VxLan, dest_port) +VXLAN.DestinationPort, config_parse_ip_port, 0, offsetof(VxLan, dest_port) VXLAN.FlowLabel, config_parse_flow_label, 0, 0 GENEVE.Id, config_parse_geneve_vni, 0, offsetof(Geneve, id) GENEVE.Remote, config_parse_geneve_address, 0, offsetof(Geneve, remote) @@ -88,7 +88,7 @@ GENEVE.TTL, config_parse_uint8, 0, GENEVE.UDPChecksum, config_parse_bool, 0, offsetof(Geneve, udpcsum) GENEVE.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumrx) GENEVE.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumtx) -GENEVE.DestinationPort, config_parse_geneve_destination_port, 0, offsetof(Geneve, dest_port) +GENEVE.DestinationPort, config_parse_ip_port, 0, offsetof(Geneve, dest_port) GENEVE.FlowLabel, config_parse_geneve_flow_label, 0, 0 Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 3848c863c5..43884581ca 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -28,6 +28,7 @@ #include "network-internal.h" #include "netdev/netdev.h" #include "networkd-manager.h" +#include "networkd-link.h" #include "siphash24.h" #include "stat-util.h" #include "string-table.h" @@ -221,6 +222,13 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h assert(link); assert(callback); + if (link->flags & IFF_UP) { + log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname); + r = link_down(link); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not bring link down: %m"); + } + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c index 7f20e6cdfe..b5b7aec2c0 100644 --- a/src/network/netdev/vxlan.c +++ b/src/network/netdev/vxlan.c @@ -271,36 +271,6 @@ int config_parse_port_range(const char *unit, return 0; } -int config_parse_destination_port(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) { - VxLan *v = userdata; - uint16_t port; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = parse_ip_port(rvalue, &port); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue); - return 0; - } - - v->dest_port = port; - - return 0; -} - int config_parse_flow_label(const char *unit, const char *filename, unsigned line, diff --git a/src/network/netdev/vxlan.h b/src/network/netdev/vxlan.h index 7f97a9edc4..1eeda022a2 100644 --- a/src/network/netdev/vxlan.h +++ b/src/network/netdev/vxlan.h @@ -86,17 +86,6 @@ int config_parse_port_range(const char *unit, void *data, void *userdata); -int config_parse_destination_port(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_flow_label(const char *unit, const char *filename, unsigned line, diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c new file mode 100644 index 0000000000..1248719cf3 --- /dev/null +++ b/src/network/networkd-address-label.c @@ -0,0 +1,257 @@ +/*** + This file is part of systemd. + + Copyright 2017 Susant Sahani + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <net/if.h> +#include <linux/if_addrlabel.h> + +#include "alloc-util.h" +#include "conf-parser.h" +#include "networkd-address-label.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "socket-util.h" + +int address_label_new(AddressLabel **ret) { + _cleanup_address_label_free_ AddressLabel *addrlabel = NULL; + + addrlabel = new0(AddressLabel, 1); + if (!addrlabel) + return -ENOMEM; + + *ret = addrlabel; + addrlabel = NULL; + + return 0; +} + +void address_label_free(AddressLabel *label) { + if (!label) + return; + + if (label->network) { + LIST_REMOVE(labels, label->network->address_labels, label); + assert(label->network->n_address_labels > 0); + label->network->n_address_labels--; + + if (label->section) { + hashmap_remove(label->network->address_labels_by_section, label->section); + network_config_section_free(label->section); + } + } + + free(label); +} + +static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) { + _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL; + _cleanup_address_label_free_ AddressLabel *label = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + label = hashmap_get(network->address_labels_by_section, n); + if (label) { + *ret = label; + label = NULL; + + return 0; + } + + r = address_label_new(&label); + if (r < 0) + return r; + + label->section = n; + n = NULL; + + r = hashmap_put(network->address_labels_by_section, label->section, label); + if (r < 0) + return r; + + label->network = network; + LIST_APPEND(labels, network->address_labels, label); + network->n_address_labels++; + + *ret = label; + label = NULL; + + return 0; +} + +int address_label_configure( + AddressLabel *label, + Link *link, + sd_netlink_message_handler_t callback, + bool update) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(label); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL, + link->ifindex, label->family); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m"); + + r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen); + if (r < 0) + return log_error_errno(r, "Could not set prefixlen: %m"); + + r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label); + if (r < 0) + return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m"); + + r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6); + if (r < 0) + return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m"); + + r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); + if (r < 0) + return log_error_errno(r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +int config_parse_address_label_prefix(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) { + + _cleanup_address_label_free_ AddressLabel *n = NULL; + Network *network = userdata; + const char *prefix, *e; + union in_addr_union buffer; + int r, f; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_label_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + /* AddressLabel=prefix/prefixlen */ + + /* prefixlen */ + e = strchr(rvalue, '/'); + if (e) { + unsigned i; + + r = safe_atou(e + 1, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is invalid, ignoring assignment: %s", e + 1); + return 0; + } + + if (i > 128) { + log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is out of range, ignoring assignment: %s", e + 1); + return 0; + } + + n->prefixlen = (unsigned char) i; + + prefix = strndupa(rvalue, e - rvalue); + } else + prefix = rvalue; + + r = in_addr_from_string_auto(prefix, &f, &buffer); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", prefix); + return 0; + } + + if (f != AF_INET6) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Address label family is not IPv6, ignoring assignment: %s", prefix); + return 0; + } + + n->family = f; + n->in_addr = buffer; + + n = NULL; + + return 0; +} + +int config_parse_address_label( + 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) { + + _cleanup_address_label_free_ AddressLabel *n = NULL; + Network *network = userdata; + uint32_t k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_label_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue); + return 0; + } + + if (k == 0xffffffffUL) { + log_syntax(unit, LOG_ERR, filename, line, r, "Adress label is invalid, ignoring: %s", rvalue); + return 0; + } + + n->label = k; + n = NULL; + + return 0; +} diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h new file mode 100644 index 0000000000..05bb24924c --- /dev/null +++ b/src/network/networkd-address-label.h @@ -0,0 +1,59 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2017 Susant Sahani + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <inttypes.h> +#include <stdbool.h> + +#include "in-addr-util.h" + +typedef struct AddressLabel AddressLabel; + +#include "networkd-link.h" +#include "networkd-network.h" + +typedef struct Network Network; +typedef struct Link Link; +typedef struct NetworkConfigSection NetworkConfigSection; + +struct AddressLabel { + Network *network; + Link *link; + NetworkConfigSection *section; + + int family; + unsigned char prefixlen; + uint32_t label; + + union in_addr_union in_addr; + + LIST_FIELDS(AddressLabel, labels); +}; + +int address_label_new(AddressLabel **ret); +void address_label_free(AddressLabel *label); + +DEFINE_TRIVIAL_CLEANUP_FUNC(AddressLabel*, address_label_free); +#define _cleanup_address_label_free_ _cleanup_(address_label_freep) + +int address_label_configure(AddressLabel *address, Link *link, sd_netlink_message_handler_t callback, bool update); + +int config_parse_address_label(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_address_label_prefix(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-link.c b/src/network/networkd-link.c index 1797f144b6..6ed8380942 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -853,6 +853,35 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda return 1; } +static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + _cleanup_link_unref_ Link *link = userdata; + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->link_messages > 0); + + link->link_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + log_link_warning_errno(link, r, "could not set address label: %m"); + else if (r >= 0) + manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->link_messages == 0) { + log_link_debug(link, "Addresses label set"); + link_enter_set_routes(link); + } + + return 1; +} + static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { _cleanup_free_ struct in_addr *addresses = NULL; size_t n_addresses = 0, n_allocated = 0; @@ -965,6 +994,7 @@ static int link_set_bridge_fdb(Link *link) { } static int link_enter_set_addresses(Link *link) { + AddressLabel *label; Address *ad; int r; @@ -989,6 +1019,17 @@ static int link_enter_set_addresses(Link *link) { link->link_messages++; } + LIST_FOREACH(labels, label, link->network->address_labels) { + r = address_label_configure(label, link, address_label_handler, false); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set address label: %m"); + link_enter_failed(link); + return r; + } + + link->link_messages++; + } + /* now that we can figure out a default address for the dhcp server, start it */ if (link_dhcp4_server_enabled(link)) { @@ -1603,7 +1644,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda return 1; } -static int link_up(Link *link) { +int link_up(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; uint8_t ipv6ll_mode; int r; @@ -1724,7 +1765,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user return 1; } -static int link_down(Link *link) { +int link_down(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 010b38248a..be5c4f3284 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -33,8 +33,6 @@ #include "list.h" #include "set.h" -#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 - typedef enum LinkState { LINK_STATE_PENDING, LINK_STATE_ENSLAVING, @@ -140,6 +138,9 @@ int link_get(Manager *m, int ifindex, Link **ret); int link_add(Manager *manager, sd_netlink_message *message, Link **ret); void link_drop(Link *link); +int link_up(Link *link); +int link_down(Link *link); + int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3743113825..ee8bd6faf7 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -79,6 +79,8 @@ Address.DuplicateAddressDetection, config_parse_address_flags, Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0 Address.PrefixRoute, config_parse_address_flags, 0, 0 Address.AutoJoin, config_parse_address_flags, 0, 0 +IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 +IPv6AddressLabel.Label, config_parse_address_label, 0, 0 Route.Gateway, config_parse_gateway, 0, 0 Route.Destination, config_parse_destination, 0, 0 Route.Source, config_parse_destination, 0, 0 @@ -127,7 +129,7 @@ Bridge.HairPin, config_parse_bool, Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave) Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root) Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood) -Bridge.Priority, config_parse_uint16, 0, offsetof(Network, priority) +Bridge.Priority, config_parse_bridge_port_priority, 0, offsetof(Network, priority) BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index dd29b4ca48..0c0e661909 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -114,6 +114,7 @@ static int network_load_one(Manager *manager, const char *filename) { LIST_HEAD_INIT(network->static_routes); LIST_HEAD_INIT(network->static_fdb_entries); LIST_HEAD_INIT(network->ipv6_proxy_ndp_addresses); + LIST_HEAD_INIT(network->address_labels); network->stacked_netdevs = hashmap_new(&string_hash_ops); if (!network->stacked_netdevs) @@ -131,6 +132,10 @@ static int network_load_one(Manager *manager, const char *filename) { if (!network->fdb_entries_by_section) return log_oom(); + network->address_labels_by_section = hashmap_new(&network_config_hash_ops); + if (!network->address_labels_by_section) + return log_oom(); + network->filename = strdup(filename); if (!network->filename) return log_oom(); @@ -192,6 +197,7 @@ static int network_load_one(Manager *manager, const char *filename) { "Link\0" "Network\0" "Address\0" + "IPv6AddressLabel\0" "Route\0" "DHCP\0" "DHCPv4\0" /* compat */ @@ -271,6 +277,7 @@ void network_free(Network *network) { Address *address; FdbEntry *fdb_entry; IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; + AddressLabel *label; Iterator i; if (!network) @@ -318,9 +325,13 @@ void network_free(Network *network) { while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); + while ((label = network->address_labels)) + address_label_free(label); + hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); hashmap_free(network->fdb_entries_by_section); + hashmap_free(network->address_labels_by_section); if (network->manager) { if (network->manager->networks) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index d6f418d521..28ef285be6 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -28,6 +28,7 @@ #include "resolve-util.h" #include "networkd-address.h" +#include "networkd-address-label.h" #include "networkd-brvlan.h" #include "networkd-fdb.h" #include "networkd-lldp-tx.h" @@ -202,15 +203,18 @@ struct Network { LIST_HEAD(Route, static_routes); LIST_HEAD(FdbEntry, static_fdb_entries); LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); + LIST_HEAD(AddressLabel, address_labels); unsigned n_static_addresses; unsigned n_static_routes; unsigned n_static_fdb_entries; unsigned n_ipv6_proxy_ndp_addresses; + unsigned n_address_labels; Hashmap *addresses_by_section; Hashmap *routes_by_section; Hashmap *fdb_entries_by_section; + Hashmap *address_labels_by_section; struct in_addr_data *dns; unsigned n_dns; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index fd00d0957a..905dbc4c74 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1158,6 +1158,10 @@ static int parse_argv(int argc, char *argv[]) { arg_caps_retain = (arg_caps_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus; + r = cg_unified_flush(); + if (r < 0) + return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); + e = getenv("SYSTEMD_NSPAWN_CONTAINER_SERVICE"); if (e) arg_container_service_name = e; @@ -3545,10 +3549,6 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - r = cg_unified_flush(); - if (r < 0) - return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); - /* Make sure rename_process() in the stub init process can work */ saved_argv = argv; saved_argc = argc; diff --git a/src/resolve/generate-dns_type-gperf.py b/src/resolve/generate-dns_type-gperf.py index fb36c850af..8a0b43c277 100644 --- a/src/resolve/generate-dns_type-gperf.py +++ b/src/resolve/generate-dns_type-gperf.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 """Generate %-from-name.gperf from %-list.txt """ diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index d8393cbc8d..dae521ef9f 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -960,3 +960,40 @@ int config_parse_ifname( return 0; } + +int config_parse_ip_port( + 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) { + + uint16_t *s = data; + uint16_t port; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *s = 0; + return 0; + } + + r = parse_ip_port(rvalue, &port); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse port '%s'.", rvalue); + return 0; + } + + *s = port; + + return 0; +} diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 82ea5c1288..ce1113485d 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -140,6 +140,7 @@ int config_parse_log_level(const char *unit, const char *filename, unsigned line int config_parse_signal(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_personality(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_ifname(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_ip_port(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); #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \ int function(const char *unit, \ diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 8631a5a5d9..8229e6b183 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -269,6 +269,7 @@ int efi_set_variable( _cleanup_close_ int fd = -1; assert(name); + assert(value); if (asprintf(&p, "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", diff --git a/src/shared/generator.c b/src/shared/generator.c index 9a069b2f97..19ec133772 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -188,10 +188,49 @@ int generator_write_timeouts( return write_drop_in_format(dir, unit, 50, "device-timeout", "# Automatically generated by %s\n\n" - "[Unit]\nJobTimeoutSec=%s", + "[Unit]\nJobRunningTimeoutSec=%s", program_invocation_short_name, timeout); } +int generator_write_device_deps( + const char *dir, + const char *what, + const char *where, + const char *opts) { + + /* fstab records that specify _netdev option should apply the network + * ordering on the actual device depending on network connection. If we + * are not mounting real device (NFS, CIFS), we rely on _netdev effect + * on the mount unit itself. */ + + _cleanup_free_ char *node = NULL, *unit = NULL; + int r; + + if (!fstab_test_option(opts, "_netdev\0")) + return 0; + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + /* Nothing to apply dependencies to. */ + if (!is_device_path(node)) + return 0; + + r = unit_name_from_path(node, ".device", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path: %m"); + + /* See mount_add_default_dependencies for explanation why we create such + * dependencies. */ + return write_drop_in_format(dir, unit, 50, "netdev-dependencies", + "# Automatically generated by %s\n\n" + "[Unit]\n" + "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n" + "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n", + program_invocation_short_name); +} + int generator_write_initrd_root_device_deps(const char *dir, const char *what) { _cleanup_free_ char *unit = NULL; int r; diff --git a/src/shared/generator.h b/src/shared/generator.h index a6017c1b76..825d934c8e 100644 --- a/src/shared/generator.h +++ b/src/shared/generator.h @@ -35,6 +35,12 @@ int generator_write_timeouts( const char *opts, char **filtered); +int generator_write_device_deps( + const char *dir, + const char *what, + const char *where, + const char *opts); + int generator_write_initrd_root_device_deps( const char *dir, const char *what); diff --git a/src/shared/meson.build b/src/shared/meson.build index 49a7d9f30b..b684e5b543 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -127,10 +127,10 @@ libshared = shared_library( basic_sources, journal_internal_sources, libsystemd_internal_sources, + libudev_sources, include_directories : includes, link_args : ['-shared'], c_args : ['-fvisibility=default'], - link_with : [libudev], dependencies : [threads, librt, libcap, diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h index 7efa8ebe5a..aa39e0a0db 100644 --- a/src/systemd/sd-netlink.h +++ b/src/systemd/sd-netlink.h @@ -155,6 +155,9 @@ int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *family); int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state); int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags); +int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family); +int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref); diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py index a3350c8a81..357cce8e44 100644 --- a/src/test/generate-sym-test.py +++ b/src/test/generate-sym-test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import sys, re print('#include <stdio.h>') diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c index 9eea3eb608..af866e004b 100644 --- a/src/test/test-glob-util.c +++ b/src/test/test-glob-util.c @@ -18,12 +18,17 @@ ***/ #include <fcntl.h> +#include <glob.h> +#include <sys/stat.h> #include <unistd.h> #include "alloc-util.h" +#include "dirent-util.h" #include "fileio.h" +#include "fs-util.h" #include "glob-util.h" #include "macro.h" +#include "rm-rf.h" static void test_glob_exists(void) { char name[] = "/tmp/test-glob_exists.XXXXXX"; @@ -43,8 +48,69 @@ static void test_glob_exists(void) { assert_se(r == 0); } +static void test_glob_no_dot(void) { + char template[] = "/tmp/test-glob-util.XXXXXXX"; + const char *fn; + + _cleanup_globfree_ glob_t g = { + .gl_closedir = (void (*)(void *)) closedir, + .gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot, + .gl_opendir = (void *(*)(const char *)) opendir, + .gl_lstat = lstat, + .gl_stat = stat, + }; + + int r; + + assert_se(mkdtemp(template)); + + fn = strjoina(template, "/*"); + r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); + assert_se(r == GLOB_NOMATCH); + + fn = strjoina(template, "/.*"); + r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); + assert_se(r == GLOB_NOMATCH); + + (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_safe_glob(void) { + char template[] = "/tmp/test-glob-util.XXXXXXX"; + const char *fn, *fn2, *fname; + + _cleanup_globfree_ glob_t g = {}; + int r; + + assert_se(mkdtemp(template)); + + fn = strjoina(template, "/*"); + r = safe_glob(fn, 0, &g); + assert_se(r == -ENOENT); + + fn2 = strjoina(template, "/.*"); + r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g); + assert_se(r == -ENOENT); + + fname = strjoina(template, "/.foobar"); + assert_se(touch(fname) == 0); + + r = safe_glob(fn, 0, &g); + assert_se(r == -ENOENT); + + r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g); + assert_se(r == 0); + assert_se(g.gl_pathc == 1); + assert_se(streq(g.gl_pathv[0], fname)); + assert_se(g.gl_pathv[1] == NULL); + + (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL); +} + int main(void) { test_glob_exists(); + test_glob_no_dot(); + test_safe_glob(); return 0; } diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 22df20a1eb..ab62d0dad2 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -27,6 +27,7 @@ #include "mount-util.h" #include "path-util.h" #include "rm-rf.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "util.h" @@ -104,6 +105,38 @@ static void test_path(void) { assert_se(!path_equal_ptr(NULL, "/a")); } +static void test_path_equal_root(void) { + /* Nail down the details of how path_equal("/", ...) works. */ + + assert_se(path_equal("/", "/")); + assert_se(path_equal("/", "//")); + + assert_se(!path_equal("/", "/./")); + assert_se(!path_equal("/", "/../")); + + assert_se(!path_equal("/", "/.../")); + + /* Make sure that files_same works as expected. */ + + assert_se(files_same("/", "/") > 0); + assert_se(files_same("/", "//") > 0); + + assert_se(files_same("/", "/./") > 0); + assert_se(files_same("/", "/../") > 0); + + assert_se(files_same("/", "/.../") == -ENOENT); + + /* The same for path_equal_or_files_same. */ + + assert_se(path_equal_or_files_same("/", "/")); + assert_se(path_equal_or_files_same("/", "//")); + + assert_se(path_equal_or_files_same("/", "/./")); + assert_se(path_equal_or_files_same("/", "/../")); + + assert_se(!path_equal_or_files_same("/", "/.../")); +} + static void test_find_binary(const char *self) { char *p; @@ -551,6 +584,7 @@ int main(int argc, char **argv) { log_open(); test_path(); + test_path_equal_root(); test_find_binary(argv[0]); test_prefixes(); test_path_join(); diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c index 36389b7710..269adfd18f 100644 --- a/src/test/test-sizeof.c +++ b/src/test/test-sizeof.c @@ -32,6 +32,14 @@ strstr(STRINGIFY(t), "signed") ? "" : \ ((t)-1 < (t)0 ? ", signed" : ", unsigned")); +enum Enum { + enum_value, +}; + +enum BigEnum { + big_enum_value = UINT64_C(-1), +}; + int main(void) { info(char); info(signed char); @@ -53,5 +61,8 @@ int main(void) { info(usec_t); info(__time_t); + info(enum Enum); + info(enum BigEnum); + return 0; } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index ed6a9adaa6..36488c9a5c 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1093,19 +1093,14 @@ static int item_do_children(Item *i, const char *path, action_t action) { static int glob_item(Item *i, action_t action, bool recursive) { _cleanup_globfree_ glob_t g = { - .gl_closedir = (void (*)(void *)) closedir, - .gl_readdir = (struct dirent *(*)(void *)) readdir, .gl_opendir = (void *(*)(const char *)) opendir_nomod, - .gl_lstat = lstat, - .gl_stat = stat, }; int r = 0, k; char **fn; - errno = 0; - k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); - if (k != 0 && k != GLOB_NOMATCH) - return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path); + k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k < 0 && k != -ENOENT) + return log_error_errno(k, "glob(%s) failed: %m", i->path); STRV_FOREACH(fn, g.gl_pathv) { k = action(i, *fn); diff --git a/test/README.testsuite b/test/README.testsuite index fa7e73ce3a..58f67f50fd 100644 --- a/test/README.testsuite +++ b/test/README.testsuite @@ -3,7 +3,7 @@ subdirectories named "test/TEST-??-*", which are run one by one. To run the extended testsuite do the following: -$ make all +$ make all # Avoid the "sudo make" below building anything as root $ cd test $ sudo make clean check ... diff --git a/test/create-sys-script.py b/test/create-sys-script.py index 4b7abd24ae..402b4f83ab 100755 --- a/test/create-sys-script.py +++ b/test/create-sys-script.py @@ -1,6 +1,6 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 -OUTFILE_HEADER = """#!/usr/bin/python3 +OUTFILE_HEADER = """#!/usr/bin/env python3 # # create-sys-script.py # diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py index dab01f1d8a..14739df493 100755 --- a/test/rule-syntax-check.py +++ b/test/rule-syntax-check.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # Simple udev rules syntax checker # # (C) 2010 Canonical Ltd. diff --git a/test/sys-script.py b/test/sys-script.py index a9c0046667..6c9ee5ff83 100755 --- a/test/sys-script.py +++ b/test/sys-script.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # # sys-script.py # diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py index 16ea65690a..d116fffe38 100755 --- a/test/sysv-generator-test.py +++ b/test/sysv-generator-test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # # systemd-sysv-generator integration test # diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py index b974b1c133..39a9e62e15 100755 --- a/test/test-exec-deserialization.py +++ b/test/test-exec-deserialization.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # # Copyright 2017 Michal Sekletar <msekleta@redhat.com> diff --git a/tools/catalog-report.py b/tools/catalog-report.py index b220060cc8..357e498cdc 100644 --- a/tools/catalog-report.py +++ b/tools/catalog-report.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. It is distrubuted under the MIT license, see diff --git a/tools/gdb-sd_dump_hashmaps.py b/tools/gdb-sd_dump_hashmaps.py index d20016e005..62ce8006f5 100644 --- a/tools/gdb-sd_dump_hashmaps.py +++ b/tools/gdb-sd_dump_hashmaps.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. diff --git a/tools/make-directive-index.py b/tools/make-directive-index.py index 8ce09ca2fa..1b287997fa 100755 --- a/tools/make-directive-index.py +++ b/tools/make-directive-index.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. diff --git a/tools/make-man-index.py b/tools/make-man-index.py index 50ad9532cd..abc33e7394 100755 --- a/tools/make-man-index.py +++ b/tools/make-man-index.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py index ecb9d2d9b5..e9e39f10af 100644 --- a/tools/make-man-rules.py +++ b/tools/make-man-rules.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. diff --git a/tools/xml_helper.py b/tools/xml_helper.py index b2c036909d..0088be5bd9 100644 --- a/tools/xml_helper.py +++ b/tools/xml_helper.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. |