]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #6847 from keszybz/disable-enable-generators
authorLennart Poettering <lennart@poettering.net>
Wed, 20 Sep 2017 17:51:44 +0000 (19:51 +0200)
committerGitHub <noreply@github.com>
Wed, 20 Sep 2017 17:51:44 +0000 (19:51 +0200)
Disable and optionally again enable generators in test mode

45 files changed:
.mailmap
NEWS
man/machinectl.xml
man/meson.build
man/sd-login.xml
man/sd_bus_default.xml
man/sd_is_fifo.xml
man/systemd-journald.service.xml
man/systemd-logind.service.xml
man/systemd-networkd.service.xml
man/systemd.link.xml
man/systemd.network.xml
man/systemd.resource-control.xml
man/systemd.service.xml
man/systemd.special.xml
man/systemd.time.xml
man/systemd.unit.xml
man/tmpfiles.d.xml
man/udevadm.xml
src/basic/calendarspec.c
src/basic/calendarspec.h
src/basic/conf-files.c
src/basic/time-util.c
src/core/dbus-execute.c
src/core/execute.c
src/libsystemd-network/sd-radv.c
src/libsystemd/sd-bus/test-bus-cleanup.c
src/libsystemd/sd-bus/test-bus-gvariant.c
src/libsystemd/sd-bus/test-bus-marshal.c
src/libsystemd/sd-bus/test-bus-match.c
src/libsystemd/sd-bus/test-bus-track.c
src/libsystemd/sd-netlink/rtnl-message.c
src/network/networkd-manager.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-route.c
src/network/networkd-route.h
src/systemd/sd-netlink.h
src/test/test-calendarspec.c
src/test/test-date.c
src/test/test-exec-util.c
src/udev/net/ethtool-util.c
src/udev/net/ethtool-util.h
src/udev/net/link-config-gperf.gperf
src/udev/udev-event.c

index 73b0700f59c80f5cb7c5c03724b83b8f5a87d512..fb64c767e514857089311014e0c0ae24b29d5c32 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -124,3 +124,4 @@ Josef Andersson <josef.andersson@fripost.org>
 Josef Andersson <l10nl18nsweja@gmail.com>
 Hendrik Westerberg <hendrik@gestorf.com>
 Stefan Pietsch <mail.ipv4v6@gmail.com>
+Jérémy Rosen <jeremy.rosen@enst-bretagne.fr>
diff --git a/NEWS b/NEWS
index 4940902451ec708c453cafda9c94453fbd50ab81..32c01bb8dd9d9f71a0f925f7ada2e65a7b994d86 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,11 @@ CHANGES WITH 235:
           respectively. They complement the existing "set-log-level" and
           "set-log-target" verbs, which can be used to change those values.
 
+        * systemd-networkd .network DHCP setting UseMTU default has changed
+          from false to true. Meaning, DHCP server advertised mtu setting is
+          now applied by default. This resolves networking issues on low-mtu
+          networks.
+
 CHANGES WITH 234:
 
         * Meson is now supported as build system in addition to Automake. It is
index 46dcb44ca675ab4f058ca61294adf5eb8edaac81..cf46fe80248c990ac10db4e692207288ef695bc1 100644 (file)
       OS kernel with the host OS, in order to run
       OS userspace instances on top the host OS.</para></listitem>
 
-      <listitem><para>The host system itself</para></listitem>
+      <listitem><para>The host system itself.</para></listitem>
     </itemizedlist>
 
     <para>Machines are identified by names that follow the same rules
-    as UNIX and DNS host names, for details, see below. Machines are
-    instantiated from disk or file system images that frequently — but not
-    necessarily — carry the same name as machines running from
-    them. Images in this sense are considered:</para>
+    as UNIX and DNS host names. For details, see below.</para>
+
+    <para>Machines are instantiated from disk or file system images that
+    frequently — but not necessarily — carry the same name as machines running
+    from them. Images in this sense may be:</para>
 
     <itemizedlist>
-      <listitem><para>Directory trees containing an OS, including its
+      <listitem><para>Directory trees containing an OS, including the
       top-level directories <filename>/usr</filename>,
       <filename>/etc</filename>, and so on.</para></listitem>
 
       </varlistentry>
 
       <xi:include href="user-system-options.xml" xpointer="host" />
-      <xi:include href="user-system-options.xml" xpointer="machine" />
+
+      <varlistentry>
+        <term><option>-M</option></term>
+        <term><option>--machine=</option></term>
+
+        <listitem><para>Connect to
+        <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        running in a local container, to perform the specified operation within
+        the container.</para></listitem>
+      </varlistentry>
 
       <xi:include href="standard-options.xml" xpointer="no-pager" />
       <xi:include href="standard-options.xml" xpointer="no-legend" />
         qcow2 or raw disk image, possibly compressed with xz, gzip or
         bzip2. If the second argument (the resulting image name) is
         not specified, it is automatically derived from the file
-        name. If the file name is passed as <literal>-</literal>, the
+        name. If the filename is passed as <literal>-</literal>, the
         image is read from standard input, in which case the second
         argument is mandatory.</para>
 
index 8ddbd5557cbcf488642c05f8a8e1b481f5be8211..5b6a21fb9f4c63950232877698f063865546f336 100644 (file)
@@ -11,6 +11,7 @@ want_html = want_html != 'false' and xsltproc.found()
 xsltproc_flags = [
         '--nonet',
         '--xinclude',
+        '--maxdepth', '9000',
         '--stringparam', 'man.output.quietly', '1',
         '--stringparam', 'funcsynopsis.style', 'ansi',
         '--stringparam', 'man.authors.section.enabled', '0',
index 6861fbe2576076c54e3ee8861639af33404fa0e4..b2131a9af93f6ff7ef2f384030f2a48da7811a03 100644 (file)
     and monitor seat, login session and user status information on the
     local system. </para>
 
-    <para>See <ulink
-    url="https://www.freedesktop.org/wiki/Software/systemd/multiseat">Multi-Seat
-    on Linux</ulink> for an introduction into multi-seat support on
-    Linux, the background for this set of APIs.</para>
-
     <para>Note that these APIs only allow purely passive access and
     monitoring of seats, sessions and users. To actively make changes
     to the seat configuration, terminate login sessions, or switch
     implemented.</para>
   </refsect1>
 
+  <refsect1>
+    <title>Definition of Terms</title>
+
+    <variablelist>
+      <varlistentry>
+        <term>seat</term>
+
+        <listitem><para>A seat consists of all hardware devices assigned to a specific
+        workplace. It consists of at least one graphics device, and usually also includes
+        keyboard, mouse. It can also include video cameras, sound cards and more. Seats
+        are identified by seat names, which are strings (&lt;= 255 characters), that start
+        with the four characters <literal>seat</literal> followed by at least one
+        character from the range [a-zA-Z0-9], <literal>_</literal> and
+        <literal>-</literal>. They are suitable for use as file names. Seat names may or
+        may not be stable and may be reused if a seat becomes available again.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>session</term>
+
+        <listitem><para>A session is defined by the time a user is logged in until they
+        log out. A session is bound to one or no seats (the latter for 'virtual' ssh
+        logins). Multiple sessions can be attached to the same seat, but only one of them
+        can be active, the others are in the background. A session is identified by a
+        short string.</para>
+
+        <para>
+        <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        ensures that audit sessions are identical to systemd sessions, and uses the audit
+        session ID as session ID in systemd (if auditing is enabled). In general the
+        session identifier is a short string consisting only of [a-zA-Z0-9],
+        <literal>_</literal> and <literal>-</literal>, suitable for use as a file name.
+        Session IDs are unique on the local machine and are
+        never reused as long as the machine is online. A user (the way we know it on UNIX)
+        corresponds to the person using a computer. A single user can have multiple
+        sessions open at the same time. A user is identified by a numeric user id (UID) or
+        a user name (a string). A multi-session system allows multiple user sessions on
+        the same seat at the same time. A multi-seat system allows multiple independent
+        seats that can be individually and simultaneously used by different users.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>All hardware devices that are eligible to being assigned to a seat, are assigned
+    to one. A device can be assigned to only one seat at a time. If a device is not
+    assigned to any particular other seat it is implicitly assigned to the special default
+    seat called <literal>seat0</literal>.</para>
+
+    <para>Note that hardware like printers, hard disks or network cards is generally not
+    assigned to a specific seat. They are available to all seats equally. (Well, with one
+    exception: USB sticks can be assigned to a seat.)</para>
+
+    <para><literal>seat0</literal> always exists.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>udev Rules</title>
+
+    <para>Assignment of hardware devices to seats is managed inside the udev database, via
+    settings on the devices:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term>Tag <literal>seat</literal></term>
+
+        <listitem><para>When set, a device is eligible to be assigned to a seat. This tag
+        is set for graphics devices, mice, keyboards, video cards, sound cards and
+        more. Note that some devices like sound cards consist of multiple subdevices
+        (i.e. a PCM for input and another one for output). This tag will be set only for
+        the originating device, not for the individual subdevices. A UI for configuring
+        assignment of devices to seats should enumerate and subscribe to all devices with
+        this tag set and show them in the UI. Note that USB hubs can be assigned to a seat
+        as well, in which case all (current and future) devices plugged into it will also
+        be assigned to the same seat (unless they are explicitly assigned to another
+        seat).
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>Tag <literal>master-of-seat</literal></term>
+
+        <listitem><para>When set, this device is enough for a seat to be considered
+        existent. This tag is usually set for the framebuffer device of graphics cards. A
+        seat hence consists of an arbitrary number of devices marked with the
+        <literal>seat</literal> tag, but (at least) one of these devices needs to be
+        tagged with <literal>master-of-seat</literal> before the seat is actually
+        considered to be around.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>Property <varname>ID_SEAT</varname></term>
+
+        <listitem><para>This property specifies the name of the seat a specific device is
+        assigned to. If not set the device is assigned to <literal>seat0</literal>. Also,
+        to speed up enumeration of hardware belonging to a specific seat, the seat is also
+        set as tag on the device. I.e. if the property
+        <varname>ID_SEAT=seat-waldo</varname> is set for a device, the tag
+        <literal>seat-waldo</literal> will be set as well. Note that if a device is
+        assigned to <literal>seat0</literal>, it will usually not carry such a tag and you
+        need to enumerate all devices and check the <varname>ID_SEAT</varname> property
+        manually. Again, if a device is assigned to seat0 this is visible on the device in
+        two ways: with a property <varname>ID_SEAT=seat0</varname> and with no property
+        <varname>ID_SEAT</varname> set for it at all.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>Property <varname>ID_AUTOSEAT</varname></term>
+
+        <listitem><para>When set to <literal>1</literal>, this device automatically
+        generates a new and independent seat, which is named after the path of the
+        device. This is set for specialized USB hubs like the Plugable devices, which when
+        plugged in should create a hotplug seat without further configuration.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>Property <varname>ID_FOR_SEAT</varname></term>
+
+        <listitem><para>When creating additional (manual) seats starting from a graphics
+        device this is a good choice to name the seat after. It is created from the path
+        of the device. This is useful in UIs for configuring seats: as soon as you create
+        a new seat from a graphics device, read this property and prefix it with
+        <literal>seat-</literal> and use it as name for the seat.</para></listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>A seat exists only and exclusively because a properly tagged device with the
+    right <varname>ID_SEAT</varname> property exists. Besides udev rules there is no
+    persistent data about seats stored on disk.</para>
+
+    <para>Note that
+    <citerefentry><refentrytitle>systemd-logind</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    manages ACLs on a number of device classes, to allow user code to access the device
+    nodes attached to a seat as long as the user has an active session on it. This is
+    mostly transparent to applications. As mentioned above, for certain user software it
+    might be a good idea to watch whether they can access device nodes instead of thinking
+    about seats.</para>
+  </refsect1>
+
   <xi:include href="libsystemd-pkgconfig.xml" />
 
   <refsect1>
       <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     </para>
+
+    <para>
+      <ulink url="https://www.freedesktop.org/wiki/Software/systemd/multiseat">Multi-Seat on Linux</ulink>
+      for an introduction to multi-seat support on Linux and the background for this set of APIs.
+    </para>
   </refsect1>
 
 </refentry>
index 6d5a90de72fa2c27756dbc5273db31813f23a5ee..d9102a36ce1de1a25beead31783dc6f9174df3cb 100644 (file)
     not set, a suitable default for the default system D-Bus instance
     will be used.</para>
 
-    <para><function>sd_bus_open_system_remote()</function> connects to
-    the system bus on the specified <parameter>host</parameter> using
-    <citerefentry
-    project='die-net'><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>. <parameter>host</parameter>
-    consists of an optional user name followed by the
-    <literal>@</literal> symbol, and the hostname.
-    </para>
+    <para><function>sd_bus_open_system_remote()</function> connects to the system bus on
+    the specified host using
+    <citerefentry project='die-net'><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+    <parameter>host</parameter> consists of an optional user name followed by the
+    <literal>@</literal> symbol, and the hostname, optionally followed by a
+    <literal>:</literal> and a machine name. If the machine name is given, a connection
+    is created to the system bus in the specified container on the remote machine, and
+    otherwise a connection to the system bus on the specified host is created.</para>
+
+    <para>Note that entering a container is a privileged operation, and will likely only
+    work for the root user on the remote machine.</para>
 
     <para><function>sd_bus_open_system_machine()</function> connects
     to the system bus in the specified <parameter>machine</parameter>,
index 1192ca168152083c94bbbb2ffb613d73422460f2..3bd388d80e70991120926b70ea9578a9a706acfd 100644 (file)
     whether the specified file descriptor refers to a special file. If
     the <parameter>path</parameter> parameter is not
     <constant>NULL</constant>, it is checked whether the file
-    descriptor is bound to the specified file name. Special files in
+    descriptor is bound to the specified filename. Special files in
     this context are character device nodes and files in
     <filename>/proc</filename> or <filename>/sys</filename>.</para>
   </refsect1>
index 2810638bc26f46f58212412bf130e93678be49af..559ef1090a271c467b8ae279eb27ce3d1d1f28db 100644 (file)
     <itemizedlist>
       <listitem><para>Kernel log messages, via kmsg</para></listitem>
 
-      <listitem><para>Simple system log messages, via the libc
-      <citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <listitem><para>Simple system log messages, via the <filename>libc</filename> <citerefentry
+      project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
       call</para></listitem>
 
       <listitem><para>Structured system log messages via the native
       Journal API, see
       <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>4</manvolnum></citerefentry></para></listitem>
 
-      <listitem><para>Standard output and standard error of system
-      services</para></listitem>
+      <listitem><para>Standard output and standard error of service units. For further details see
+      below.</para></listitem>
 
-      <listitem><para>Audit records, via the audit
-      subsystem</para></listitem>
+      <listitem><para>Audit records, originating from the kernel audit subsystem</para></listitem>
     </itemizedlist>
 
     <para>The daemon will implicitly collect numerous metadata fields
@@ -111,6 +110,49 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
     for information about the configuration of this service.</para>
   </refsect1>
 
+  <refsect1>
+    <title>Stream logging</title>
+
+    <para>The systemd service manager invokes all service processes with standard output and standard error connected
+    to the journal by default. This behaviour may be altered via the
+    <varname>StandardOutput=</varname>/<varname>StandardError=</varname> unit file settings, see
+    <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details. The
+    journal converts the log byte stream received this way into individual log records, splitting the stream at newline
+    (<literal>\n</literal>, ASCII <constant>10</constant>) and <constant>NUL</constant> bytes.</para>
+
+    <para>If <filename>systemd-journald.service</filename> is stopped, the stream connections associated with all
+    services are terminated. Further writes to those streams by the service will result in <constant>EPIPE</constant>
+    errors. In order to react gracefully in this case it is recommended that programs logging to standard output/error
+    ignore such errors. If the the <constant>SIGPIPE</constant> UNIX signal handler is not blocked or turned off, such
+    write attempts will also result in such process signals being generated, see
+    <citerefentry><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>. To mitigate this issue,
+    systemd service manager explicitly turns off the <constant>SIGPIPE</constant> signal for all invoked processes by
+    default (this may be changed for each unit individually via the <varname>IgnoreSIGPIPE=</varname> option, see
+    <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+    details). After the standard output/standard error streams have been terminated they may not be recovered until the
+    services they are associated with are restarted. Note that during normal operation,
+    <filename>systemd-journald.service</filename> stores copies of the file descriptors for those streams in the
+    service manager. If <filename>systemd-journald.service</filename> is restarted using <command>systemctl
+    restart</command> or equivalent operation instead of a pair of separate <command>systemctl stop</command> and
+    <command>systemctl start</command> commands (or equivalent operations), these stream connections are not terminated
+    and survive the restart. It is thus safe to restart <filename>systemd-journald.service</filename>, but stopping it
+    is not recommended.</para>
+
+    <para>Note that the log record metadata for records transferred via such standard output/error streams reflect the
+    metadata of the peer the stream was originally created for. If the stream connection is passed on to other
+    processes (such as further child processes forked off the main service process), the log records will not reflect
+    their metadata, but will continue to describe the original process. This is different from the other logging
+    transports listed above, which are inherently record based and where the metadata is always associated with the
+    individual record.</para>
+
+    <para>In addition to the the implicit standard output/error logging of services, stream logging is also available
+    via the <citerefentry><refentrytitle>systemd-cat</refentrytitle><manvolnum>1</manvolnum></citerefentry> command
+    line tool.</para>
+
+    <para> Currently, the number of parallel log streams <filename>systemd-journald</filename> will accept is limited
+    to 4096.</para>
+  </refsect1>
+
   <refsect1>
     <title>Signals</title>
 
index 5433269638809adda00d142b6e0b47bac7effd5d..47089fd8c7478a18fda955c1b676399d78625117 100644 (file)
       <listitem><para>Keeping track of users and sessions, their processes and their idle state. This is implemented by
       allocating a systemd slice unit for each user below <filename>user.slice</filename>, and a scope unit below it
       for each concurrent session of a user. Also, a per-user service manager is started as system service instance of
-      <filename>user@.service</filename> for each user logged in.</para></listitem>
+      <filename>user@.service</filename> for each logged in user.</para></listitem>
 
-      <listitem><para>Generating and managing session IDs. If auditing is available and an audit session ID is set for
-      a session already, the session ID is initialized from it. Otherwise, an independent session counter is
+      <listitem><para>Generating and managing session IDs. If auditing is available and an audit session ID is already set for
+      a session, then this ID is reused as the session ID. Otherwise, an independent session counter is
       used.</para></listitem>
 
-      <listitem><para>Providing PolicyKit-based access for users to
+      <listitem><para>Providing PolicyKit-based access for users for
       operations such as system shutdown or sleep</para></listitem>
 
       <listitem><para>Implementing a shutdown/sleep inhibition logic
index 0bfe5519bc497d1adfc3da6d9df47ca3dfc5d1bd..a6e079c8871e4306ab87019438cf41d0d722a8d7 100644 (file)
     networks, see
     <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
 
-    <para>Network configurations applied before networkd is started
-    are not removed, and static configuration applied by networkd is
-    not removed when networkd exits. Dynamic configuration applied by
-    networkd may also optionally be left in place on shutdown. This
-    ensures restarting networkd does not cut the network connection,
-    and, in particular, that it is safe to transition between the
-    initrd and the real root, and back.</para>
+    <para><command>systemd-networkd</command> will create network devices based
+    on the configuration in
+    <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    files, respecting the [Match] sections in those files.</para>
+
+    <para><command>systemd-networkd</command> will manage network addresses and
+    routes for any link for which it finds a <filename>.network</filename> file
+    with an appropriate [Match] section, see
+    <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    For those links, it will flush existing network addresses and routes when
+    bringing up the device. Any links not matched by one of the
+    <filename>.network</filename> files will be ignored. It is also possible to
+    explicitly tell <filename>systemd-networkd</filename> to ignore a link by
+    using <varname>Unmanaged=yes</varname> option, see
+    <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    </para>
+
+    <para>When <filename>systemd-networkd</filename> exits, it generally leaves
+    existing network devices and configuration intact. This makes it possible to
+    transition from the initrams and to restart the service without breaking
+    connectivity. This also means that when configuration is updated and
+    <filename>systemd-networkd</filename> is restarted, netdev interfaces for
+    which configuration was removed will not be dropped, and may need to be
+    cleaned up manually.</para>
   </refsect1>
 
   <refsect1><title>Configuration Files</title>
index 066bed126b84c7c9944037cdaaa36abfe18bc851..99bb6a19fb0ceecae7e420fd130766b3ac781de4 100644 (file)
           TCP segmentation offload. Takes a boolean value.
           Defaults to "unset".</para>
         </listitem>
+      </varlistentry>
+       <varlistentry>
+      <term><varname>TCP6SegmentationOffload=</varname></term>
+        <listitem>
+          <para>The TCP6 Segmentation Offload (tx-tcp6-segmentation) when true enables
+          TCP6 segmentation offload. Takes a boolean value.
+          Defaults to "unset".</para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>GenericSegmentationOffload=</varname></term>
index 2055808741a40cfba22d649639d60e29467dc7bb..97509026619b983b87fe50df5611fac5905ff71a 100644 (file)
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>Type=</varname></term>
+          <listitem>
+            <para>The Type identifier for special route types, which can be
+            <literal>unicast</literal> route to a destination network address which describes the path to the destination,
+            <literal>blackhole</literal> packets are discarded silently,
+            <literal>unreachable</literal> packets are discarded and the ICMP message host unreachable is generated,
+            <literal>prohibit</literal> packets are discarded and the ICMP message communication administratively
+            prohibited is generated. Defaults to <literal>unicast</literal>.
+            </para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
   </refsect1>
 
           <listitem>
             <para>When true, the interface maximum transmission unit
             from the DHCP server will be used on the current link.
-            Defaults to false.</para>
+            Defaults to true.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index ed75e737ace1afbee6b256cf3bf980389a003185..bb69599f9981fe21437a054c59b45eca9f5e5a47 100644 (file)
           <filename>/proc/devices</filename>. The latter is useful to
           whitelist all current and future devices belonging to a
           specific device group at once. The device group is matched
-          according to file name globbing rules, you may hence use the
+          according to filename globbing rules, you may hence use the
           <literal>*</literal> and <literal>?</literal>
           wildcards. Examples: <filename>/dev/sda5</filename> is a
           path to a device node, referring to an ATA or SCSI block
index 0b8963b7b8973d3b45b4fbcda2c38b1ba361c8f9..2b183a9ceff5b6f5542135056fc3afe61b3a0ad6 100644 (file)
       <varlistentry>
         <term><varname>PIDFile=</varname></term>
 
-        <listitem><para>Takes an absolute file name pointing to the
+        <listitem><para>Takes an absolute filename pointing to the
         PID file of this daemon. Use of this option is recommended for
         services where <varname>Type=</varname> is set to
         <option>forking</option>. systemd will read the PID of the
         <varname>ExecStop=</varname> are not valid.)</para>
 
         <para>For each of the specified commands, the first argument must be an absolute path to an
-        executable. Optionally, this file name may be prefixed with a number of special characters:</para>
+        executable. Optionally, this filename may be prefixed with a number of special characters:</para>
 
         <table>
           <title>Special executable prefixes</title>
         considered clean service terminations.
         </para>
 
-        <para>Note that if a process has a signal handler installed
-        and exits by calling
-        <citerefentry><refentrytitle>_exit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        in response to a signal, the information about the signal is
-        lost. Programs should instead perform cleanup and kill
-        themselves with the same signal instead. See
-        <ulink url="http://www.cons.org/cracauer/sigint.html">Proper
-        handling of SIGINT/SIGQUIT — How to be a proper
-        program</ulink>.</para>
-
         <para>This option may appear more than once, in which case the
         list of successful exit statuses is merged. If the empty
         string is assigned to this option, the list is reset, all
index 2993d67c7660397cbada3c60bf86483ea6181be9..73e1e720e9c4c4e8f7d861088447a05627ef7e35 100644 (file)
         <listitem>
           <para>A special target unit that sets up all slice units (see
           <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
-          details) that shall be active after boot. By default the generic <filename>user.slice</filename>,
-          <filename>system.slice</filename>, <filename>machines.slice</filename> slice units, as well as the root
-          slice unit <filename>-.slice</filename> are pulled in and ordered before this unit (see below).</para>
+          details) that shall be active after boot. By default the generic <filename>system.slice</filename>
+          slice unit, as well as the root slice unit <filename>-.slice</filename>, is pulled in and ordered before
+          this unit (see below).</para>
 
           <para>It's a good idea to add <varname>WantedBy=slices.target</varname> lines to the <literal>[Install]</literal>
           section of all slices units that may be installed dynamically.</para>
@@ -1036,7 +1036,8 @@ PartOf=graphical-session.target
         <listitem>
           <para>By default, all user processes and services started on
           behalf of the user, including the per-user systemd instance
-          are found in this slice.</para>
+          are found in this slice.  This is pulled in by
+          <filename>systemd-logind.service</filename></para>
         </listitem>
       </varlistentry>
 
@@ -1045,8 +1046,8 @@ PartOf=graphical-session.target
         <listitem>
           <para>By default, all virtual machines and containers
           registered with <command>systemd-machined</command> are
-          found in this slice.
-          </para>
+          found in this slice.  This is pulled in by
+          <filename>systemd-machined.service</filename></para>
         </listitem>
       </varlistentry>
     </variablelist>
index 659f14328e79b96a0cce90cb49c9fdb50e77f462..a4f6a785d5e5b4c8e23750bf22880cca04932464 100644 (file)
     <title>Parsing Timestamps</title>
 
     <para>When parsing, systemd will accept a similar syntax, but expects no timezone specification, unless it is given
-    as the literal string <literal>UTC</literal> (for the UTC timezone) or is specified to be the locally configured
-    timezone. Other timezones than the local and UTC are not supported. The weekday specification is optional, but when
+    as the literal string <literal>UTC</literal> (for the UTC timezone), or is specified to be the locally configured
+    timezone, or the timezone name in the IANA timezone database format. The complete list of timezones
+    supported on your system can be obtained using the <literal>timedatectl list-timezones</literal>
+    (see <citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
+    Using IANA format is recommended over local timezone names, as less prone to errors (eg: with local timezone it's possible to
+    specify daylight saving time in winter, while it's incorrect). The weekday specification is optional, but when
     the weekday is specified, it must either be in the abbreviated (<literal>Wed</literal>) or non-abbreviated
     (<literal>Wednesday</literal>) English language form (case does not matter), and is not subject to the locale
     choice of the user.  Either the date, or the time part may be omitted, in which case the current date or 00:00:00,
     (assuming the current time was 2012-11-23 18:15:22 and the timezone
     was UTC+8, for example TZ=Asia/Shanghai):</para>
 
-    <programlisting>Fri 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13
-    2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13
-2012-11-23 11:12:13 UTC → Fri 2012-11-23 19:12:13
-             2012-11-23 → Fri 2012-11-23 00:00:00
-               12-11-23 → Fri 2012-11-23 00:00:00
-               11:12:13 → Fri 2012-11-23 11:12:13
-                  11:12 → Fri 2012-11-23 11:12:00
-                    now → Fri 2012-11-23 18:15:22
-                  today → Fri 2012-11-23 00:00:00
-              today UTC → Fri 2012-11-23 16:00:00
-              yesterday → Fri 2012-11-22 00:00:00
-               tomorrow → Fri 2012-11-24 00:00:00
-               +3h30min → Fri 2012-11-23 21:45:22
-                    -5s → Fri 2012-11-23 18:15:17
-              11min ago → Fri 2012-11-23 18:04:22
-            @1395716396 → Tue 2014-03-25 03:59:56</programlisting>
+    <programlisting>  Fri 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13
+      2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13
+  2012-11-23 11:12:13 UTC → Fri 2012-11-23 19:12:13
+               2012-11-23 → Fri 2012-11-23 00:00:00
+                 12-11-23 → Fri 2012-11-23 00:00:00
+                 11:12:13 → Fri 2012-11-23 11:12:13
+                    11:12 → Fri 2012-11-23 11:12:00
+                      now → Fri 2012-11-23 18:15:22
+                    today → Fri 2012-11-23 00:00:00
+                today UTC → Fri 2012-11-23 16:00:00
+                yesterday → Fri 2012-11-22 00:00:00
+                 tomorrow → Fri 2012-11-24 00:00:00
+tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00
+                 +3h30min → Fri 2012-11-23 21:45:22
+                      -5s → Fri 2012-11-23 18:15:17
+                11min ago → Fri 2012-11-23 18:04:22
+              @1395716396 → Tue 2014-03-25 03:59:56</programlisting>
 
     <para>Note that timestamps displayed by remote systems with a non-matching timezone are usually not parsable
     locally, as the timezone component is not understood (unless it happens to be <literal>UTC</literal>).</para>
     second component is not specified, <literal>:00</literal> is
     assumed.</para>
 
-    <para>A timezone specification is not expected, unless it is given as the literal string <literal>UTC</literal>, or
-    the local timezone, similar to the supported syntax of timestamps (see above). Non-local timezones except for UTC
-    are not supported.</para>
+    <para>Timezone can be specified as the literal string <literal>UTC</literal>, or
+    the local timezone, similar to the supported syntax of timestamps (see above), or the timezone
+    in the IANA timezone database format (also see above).</para>
 
   <para>The following special expressions may be used as shorthands for longer normalized forms:</para>
 
@@ -286,6 +291,7 @@ Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03
                   daily UTC → *-*-* 00:00:00 UTC
                     monthly → *-*-01 00:00:00
                      weekly → Mon *-*-* 00:00:00
+    weekly Pacific/Auckland → Mon *-*-* 00:00:00 Pacific/Auckland
                      yearly → *-01-01 00:00:00
                    annually → *-01-01 00:00:00
                       *:2/3 → *-*-* *:02/3:00</programlisting>
index 69000aab31f0ae550fab207013681bbd64c8beec..64ad4c2b60e4f2736268a9e56c6bbabff39684ac 100644 (file)
         <term><varname>Alias=</varname></term>
 
         <listitem><para>A space-separated list of additional names this unit shall be installed under. The names listed
-        here must have the same suffix (i.e. type) as the unit file name. This option may be specified more than once,
+        here must have the same suffix (i.e. type) as the unit filename. This option may be specified more than once,
         in which case all listed names are used. At installation time, <command>systemctl enable</command> will create
         symlinks from these names to the unit filename. Note that not all unit types support such alias names, and this
         setting is not supported for them. Specifically, mount, slice, swap, and automount units do not support
index a5c2b59e7e1f50e3d5057310aaca3af00cf03172..68ae43eb90baa6b5976aa073f113f4044084823c 100644 (file)
@@ -682,11 +682,11 @@ d /var/tmp/abrt 0755 abrt abrt -
 r! /var/cache/dnf/*/*/download_lock.pid
 r! /var/cache/dnf/*/*/metadata_lock.pid
 r! /var/lib/dnf/rpmdb_lock.pid
-e  /var/chache/dnf/ - - - 30d
+e  /var/cache/dnf/ - - - 30d
 </programlisting>
 
      <para>The lock files will be removed during boot. Any files and directories in
-     <filename>/var/chache/dnf/</filename> will be removed after they have not been
+     <filename>/var/cache/dnf/</filename> will be removed after they have not been
      accessed in 30 days.</para>
     </example>
 
index 8d4fe31ec1c3a3b3060818a07a454c0b7ea81538..7ace4f982681f076efa22c7de5b090cfb540a490 100644 (file)
           <term><option>-y</option></term>
           <term><option>--sysname-match=<replaceable>PATH</replaceable></option></term>
           <listitem>
-            <para>Trigger events for devices with a matching sys
-            device path. This option can be specified multiple times
-            and supports shell style pattern matching.</para>
+           <para>Trigger events for devices for which the last component
+           (i.e. the filename) of the <filename>/sys</filename> path matches
+           the specified <replaceable>PATH</replaceable>. This option can be
+           specified multiple times and also supports shell style pattern
+           matching.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index b0712a4bada7e44c2b3dc5c315169a351dcde9d5..be7328af408755d3e94f6fed52764a972f132f76 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mman.h>
 #include <time.h>
 
 #include "alloc-util.h"
@@ -33,6 +34,7 @@
 #include "macro.h"
 #include "parse-util.h"
 #include "string-util.h"
+#include "time-util.h"
 
 #define BITS_WEEKDAYS 127
 #define MIN_YEAR 1970
@@ -59,6 +61,7 @@ void calendar_spec_free(CalendarSpec *c) {
         free_chain(c->hour);
         free_chain(c->minute);
         free_chain(c->microsecond);
+        free(c->timezone);
 
         free(c);
 }
@@ -351,7 +354,10 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
 
         if (c->utc)
                 fputs_unlocked(" UTC", f);
-        else if (IN_SET(c->dst, 0, 1)) {
+        else if (c->timezone != NULL) {
+                fputc_unlocked(' ', f);
+                fputs_unlocked(c->timezone, f);
+        } else if (IN_SET(c->dst, 0, 1)) {
 
                 /* If daylight saving is explicitly on or off, let's show the used timezone. */
 
@@ -888,6 +894,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         if (!c)
                 return -ENOMEM;
         c->dst = -1;
+        c->timezone = NULL;
 
         utc = endswith_no_case(p, " UTC");
         if (utc) {
@@ -919,6 +926,19 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (IN_SET(j, 0, 1)) {
                         p = strndupa(p, e - p - 1);
                         c->dst = j;
+                } else {
+                        const char *last_space;
+
+                        last_space = strrchr(p, ' ');
+                        if (last_space != NULL && timezone_is_valid(last_space + 1)) {
+                                c->timezone = strdup(last_space + 1);
+                                if (!c->timezone) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                p = strndupa(p, last_space - p);
+                        }
                 }
         }
 
@@ -1293,7 +1313,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
         }
 }
 
-int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) {
+static int calendar_spec_next_usec_impl(const CalendarSpec *spec, usec_t usec, usec_t *next) {
         struct tm tm;
         time_t t;
         int r;
@@ -1321,3 +1341,58 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
         *next = (usec_t) t * USEC_PER_SEC + tm_usec;
         return 0;
 }
+
+typedef struct SpecNextResult {
+        usec_t next;
+        int return_value;
+} SpecNextResult;
+
+int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) {
+        pid_t pid;
+        SpecNextResult *shared;
+        SpecNextResult tmp;
+        int r;
+
+        if (isempty(spec->timezone))
+                return calendar_spec_next_usec_impl(spec, usec, next);
+
+        shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+        if (shared == MAP_FAILED)
+                return negative_errno();
+
+        pid = fork();
+
+        if (pid == -1) {
+                int fork_errno = errno;
+                (void) munmap(shared, sizeof *shared);
+                return -fork_errno;
+        }
+
+        if (pid == 0) {
+                if (setenv("TZ", spec->timezone, 1) != 0) {
+                        shared->return_value = negative_errno();
+                        _exit(EXIT_FAILURE);
+                }
+
+                tzset();
+
+                shared->return_value = calendar_spec_next_usec_impl(spec, usec, &shared->next);
+
+                _exit(EXIT_SUCCESS);
+        }
+
+        r = wait_for_terminate(pid, NULL);
+        if (r < 0) {
+                (void) munmap(shared, sizeof *shared);
+                return r;
+        }
+
+        tmp = *shared;
+        if (munmap(shared, sizeof *shared) != 0)
+                return negative_errno();
+
+        if (tmp.return_value == 0)
+                *next = tmp.next;
+
+        return tmp.return_value;
+}
index 3d8798de0b08e0834bdd3d6dd081da329430f4d1..8888251705f491710ff1e702eb1e0804c2843608 100644 (file)
@@ -40,6 +40,7 @@ typedef struct CalendarSpec {
         bool end_of_month;
         bool utc;
         int dst;
+        char *timezone;
 
         CalendarComponent *year;
         CalendarComponent *month;
index d776583c05d9532e1571b19a8ef5873f358bb84b..907d1350fe604b6f85773295f1818271ac59be6d 100644 (file)
@@ -74,16 +74,21 @@ static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned
                                 continue;
                         }
 
-                        /* We only want executable regular files (or symlinks to them), or symlinks to /dev/null */
-                        if (S_ISREG(st.st_mode)) {
-                                if ((st.st_mode & 0111) == 0) { /* not executable */
-                                        log_debug("Ignoring %s/%s, as it is not marked executable.", dirpath, de->d_name);
+                        if (!null_or_empty(&st)) {
+                                /* A mask is a symlink to /dev/null or an empty file. It does not even
+                                 * have to be executable. Other entries must be regular executable files
+                                 * or symlinks to them. */
+                                if (S_ISREG(st.st_mode)) {
+                                        if ((st.st_mode & 0111) == 0) { /* not executable */
+                                                log_debug("Ignoring %s/%s, as it is not marked executable.",
+                                                          dirpath, de->d_name);
+                                                continue;
+                                        }
+                                } else {
+                                        log_debug("Ignoring %s/%s, as it is neither a regular file nor a mask.",
+                                                  dirpath, de->d_name);
                                         continue;
                                 }
-
-                        } else if (!null_or_empty(&st)) { /* /dev/null? */
-                                log_debug("Ignoring %s/%s, as it is not a regular file (or symlink to /dev/null).", dirpath, de->d_name);
-                                continue;
                         }
                 }
 
index 68ba86f6a55902ced6484646a325c03fc54fc84d..00979bfe594a7b2b05973002683790afa93fb528 100644 (file)
@@ -21,6 +21,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/timerfd.h>
@@ -596,7 +597,7 @@ int timestamp_deserialize(const char *value, usec_t *timestamp) {
         return r;
 }
 
-int parse_timestamp(const char *t, usec_t *usec) {
+static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
         static const struct {
                 const char *name;
                 const int nr;
@@ -617,7 +618,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 { "Sat",       6 },
         };
 
-        const char *k, *utc, *tzn = NULL;
+        const char *k, *utc = NULL, *tzn = NULL;
         struct tm tm, copy;
         time_t x;
         usec_t x_usec, plus = 0, minus = 0, ret;
@@ -645,84 +646,86 @@ int parse_timestamp(const char *t, usec_t *usec) {
         assert(t);
         assert(usec);
 
-        if (t[0] == '@')
+        if (t[0] == '@' && !with_tz)
                 return parse_sec(t + 1, usec);
 
         ret = now(CLOCK_REALTIME);
 
-        if (streq(t, "now"))
-                goto finish;
+        if (!with_tz) {
+                if (streq(t, "now"))
+                        goto finish;
 
-        else if (t[0] == '+') {
-                r = parse_sec(t+1, &plus);
-                if (r < 0)
-                        return r;
+                else if (t[0] == '+') {
+                        r = parse_sec(t+1, &plus);
+                        if (r < 0)
+                                return r;
 
-                goto finish;
+                        goto finish;
 
-        } else if (t[0] == '-') {
-                r = parse_sec(t+1, &minus);
-                if (r < 0)
-                        return r;
+                } else if (t[0] == '-') {
+                        r = parse_sec(t+1, &minus);
+                        if (r < 0)
+                                return r;
 
-                goto finish;
+                        goto finish;
 
-        } else if ((k = endswith(t, " ago"))) {
-                t = strndupa(t, k - t);
+                } else if ((k = endswith(t, " ago"))) {
+                        t = strndupa(t, k - t);
 
-                r = parse_sec(t, &minus);
-                if (r < 0)
-                        return r;
+                        r = parse_sec(t, &minus);
+                        if (r < 0)
+                                return r;
 
-                goto finish;
+                        goto finish;
 
-        } else if ((k = endswith(t, " left"))) {
-                t = strndupa(t, k - t);
+                } else if ((k = endswith(t, " left"))) {
+                        t = strndupa(t, k - t);
 
-                r = parse_sec(t, &plus);
-                if (r < 0)
-                        return r;
+                        r = parse_sec(t, &plus);
+                        if (r < 0)
+                                return r;
 
-                goto finish;
-        }
+                        goto finish;
+                }
 
-        /* See if the timestamp is suffixed with UTC */
-        utc = endswith_no_case(t, " UTC");
-        if (utc)
-                t = strndupa(t, utc - t);
-        else {
-                const char *e = NULL;
-                int j;
+                /* See if the timestamp is suffixed with UTC */
+                utc = endswith_no_case(t, " UTC");
+                if (utc)
+                        t = strndupa(t, utc - t);
+                else {
+                        const char *e = NULL;
+                        int j;
 
-                tzset();
+                        tzset();
 
-                /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
-                 * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
-                 * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
-                 * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
-                 * support arbitrary timezone specifications.  */
+                        /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
+                        * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+                        * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+                        * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+                        * support arbitrary timezone specifications.  */
 
-                for (j = 0; j <= 1; j++) {
+                        for (j = 0; j <= 1; j++) {
 
-                        if (isempty(tzname[j]))
-                                continue;
+                                if (isempty(tzname[j]))
+                                        continue;
 
-                        e = endswith_no_case(t, tzname[j]);
-                        if (!e)
-                                continue;
-                        if (e == t)
-                                continue;
-                        if (e[-1] != ' ')
-                                continue;
+                                e = endswith_no_case(t, tzname[j]);
+                                if (!e)
+                                        continue;
+                                if (e == t)
+                                        continue;
+                                if (e[-1] != ' ')
+                                        continue;
 
-                        break;
-                }
+                                break;
+                        }
 
-                if (IN_SET(j, 0, 1)) {
-                        /* Found one of the two timezones specified. */
-                        t = strndupa(t, e - t - 1);
-                        dst = j;
-                        tzn = tzname[j];
+                        if (IN_SET(j, 0, 1)) {
+                                /* Found one of the two timezones specified. */
+                                t = strndupa(t, e - t - 1);
+                                dst = j;
+                                tzn = tzname[j];
+                        }
                 }
         }
 
@@ -733,7 +736,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 return -EINVAL;
 
         tm.tm_isdst = dst;
-        if (tzn)
+        if (!with_tz && tzn)
                 tm.tm_zone = tzn;
 
         if (streq(t, "today")) {
@@ -874,6 +877,67 @@ finish:
         return 0;
 }
 
+typedef struct ParseTimestampResult {
+        usec_t usec;
+        int return_value;
+} ParseTimestampResult;
+
+int parse_timestamp(const char *t, usec_t *usec) {
+        char *last_space, *timezone = NULL;
+        ParseTimestampResult *shared, tmp;
+        int r;
+        pid_t pid;
+
+        last_space = strrchr(t, ' ');
+        if (last_space != NULL && timezone_is_valid(last_space + 1))
+                timezone = last_space + 1;
+
+        if (timezone == NULL || endswith_no_case(t, " UTC"))
+                return parse_timestamp_impl(t, usec, false);
+
+        t = strndupa(t, last_space - t);
+
+        shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+        if (shared == MAP_FAILED)
+                return negative_errno();
+
+        pid = fork();
+
+        if (pid == -1) {
+                int fork_errno = errno;
+                (void) munmap(shared, sizeof *shared);
+                return -fork_errno;
+        }
+
+        if (pid == 0) {
+                if (setenv("TZ", timezone, 1) != 0) {
+                        shared->return_value = negative_errno();
+                        _exit(EXIT_FAILURE);
+                }
+
+                tzset();
+
+                shared->return_value = parse_timestamp_impl(t, &shared->usec, true);
+
+                _exit(EXIT_SUCCESS);
+        }
+
+        r = wait_for_terminate(pid, NULL);
+        if (r < 0) {
+                (void) munmap(shared, sizeof *shared);
+                return r;
+        }
+
+        tmp = *shared;
+        if (munmap(shared, sizeof *shared) != 0)
+                return negative_errno();
+
+        if (tmp.return_value == 0)
+                *usec = tmp.usec;
+
+        return tmp.return_value;
+}
+
 static char* extract_multiplier(char *p, usec_t *multiplier) {
         static const struct {
                 const char *suffix;
index 86799b13e787702558100920b2563cf29a533942..a8cdae5bf2f1df7519dbb0311c440ef36cc0b1ee 100644 (file)
@@ -2150,7 +2150,7 @@ int bus_exec_context_set_transient_property(
 
                 m = exec_keyring_mode_from_string(s);
                 if (m < 0)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid key ring mode");
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid keyring mode");
 
                 if (mode != UNIT_CHECK) {
                         c->keyring_mode = m;
index 094bb6f7a75aa3ce9fba0e75f1795b6154d0f273..00f709fd802cd5b7af7279f33ae8f24219fe837b 100644 (file)
@@ -2270,7 +2270,7 @@ static int setup_keyring(
                         if (setregid(saved_gid, -1) < 0)
                                 return log_error_errno(errno, "Failed to change GID back for user keyring: %m");
                 }
-       }
+        }
 
         return 0;
 }
index f05c44032d261d0acaa7a73b63b58bc69a16378b..a3aa5c9c628782432764dc5fecdc76b3bd9f5cb0 100644 (file)
@@ -129,6 +129,7 @@ _public_ sd_radv *sd_radv_unref(sd_radv *ra) {
         }
 
         free(ra->rdnss);
+        free(ra->dnssl);
 
         radv_reset(ra);
 
index 250a5b29087de05f5a81dcf90bc261bd6cbc10e2..9a088a5bf5bd560661a34e22870c54398ba3d833 100644 (file)
@@ -37,7 +37,7 @@ static int test_bus_open(void) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
-        r = sd_bus_open_system(&bus);
+        r = sd_bus_open_user(&bus);
         if (r == -ECONNREFUSED || r == -ENOENT)
                 return r;
 
@@ -51,7 +51,7 @@ static void test_bus_new_method_call(void) {
         sd_bus *bus = NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-        assert_se(sd_bus_open_system(&bus) >= 0);
+        assert_se(sd_bus_open_user(&bus) >= 0);
 
         assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path", "an.interface.name", "AMethodName") >= 0);
 
@@ -65,7 +65,7 @@ static void test_bus_new_signal(void) {
         sd_bus *bus = NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-        assert_se(sd_bus_open_system(&bus) >= 0);
+        assert_se(sd_bus_open_user(&bus) >= 0);
 
         assert_se(sd_bus_message_new_signal(bus, &m, "/an/object/path", "an.interface.name", "Name") >= 0);
 
index 83f114a0fe78d34a3b0b15962fb8cff617faa3dd..e8301f95560224dc854daeb30db461e184f3b692 100644 (file)
@@ -137,7 +137,7 @@ static void test_marshal(void) {
         size_t sz;
         int r;
 
-        r = sd_bus_open_system(&bus);
+        r = sd_bus_open_user(&bus);
         if (r < 0)
                 exit(EXIT_TEST_SKIP);
 
index a28cc5b79e69c41c7637012f76d446b608991f4f..e60c30b1b4059298ad603e264495bfb1dc3b9657 100644 (file)
@@ -137,7 +137,7 @@ int main(int argc, char *argv[]) {
         double dbl;
         uint64_t u64;
 
-        r = sd_bus_default_system(&bus);
+        r = sd_bus_default_user(&bus);
         if (r < 0)
                 return EXIT_TEST_SKIP;
 
index 29c4529f95e0766a142e6f3441ee2510c71e18ee..8fd9d03ddf90b11c69e7f74d0ba9d6d632cbfc2a 100644 (file)
@@ -94,7 +94,7 @@ int main(int argc, char *argv[]) {
         sd_bus_slot slots[19];
         int r;
 
-        r = sd_bus_open_system(&bus);
+        r = sd_bus_open_user(&bus);
         if (r < 0)
                 return EXIT_TEST_SKIP;
 
index 06c61675113d16dcf5f3a9d302b6d48a59a31475..5f5661cb334a2414588e9e1e07a24ca22db90197 100644 (file)
@@ -64,7 +64,7 @@ int main(int argc, char *argv[]) {
         r = sd_event_default(&event);
         assert_se(r >= 0);
 
-        r = sd_bus_open_system(&a);
+        r = sd_bus_open_user(&a);
         if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
                 log_info("Failed to connect to bus, skipping tests.");
                 return EXIT_TEST_SKIP;
@@ -74,7 +74,7 @@ int main(int argc, char *argv[]) {
         r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL);
         assert_se(r >= 0);
 
-        r = sd_bus_open_system(&b);
+        r = sd_bus_open_user(&b);
         assert_se(r >= 0);
 
         r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL);
index 586d94f624a35273e1640844b19014578a02e551..d6c52b5b437f860143f50718d88714c2ec0d8640 100644 (file)
@@ -155,6 +155,35 @@ int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) {
         return 0;
 }
 
+int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type) {
+        struct rtmsg *rtm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+        assert_return(type, -EINVAL);
+
+        rtm = NLMSG_DATA(m->hdr);
+
+        *type = rtm->rtm_type;
+
+        return 0;
+}
+
+int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type) {
+        struct rtmsg *rtm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+
+        rtm = NLMSG_DATA(m->hdr);
+
+        rtm->rtm_type = type;
+
+        return 0;
+}
+
 int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) {
         struct rtmsg *rtm;
 
index 82b9663019a6fd896331ab093d3373ee63d942dd..b9cf42d72f3b53fd6e6493d949852074c195befc 100644 (file)
@@ -296,7 +296,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
         Link *link = NULL;
         uint16_t type;
         uint32_t ifindex, priority = 0;
-        unsigned char protocol, scope, tos, table;
+        unsigned char protocol, scope, tos, table, rt_type;
         int family;
         unsigned char dst_prefixlen, src_prefixlen;
         union in_addr_union dst = {}, gw = {}, src = {}, prefsrc = {};
@@ -441,6 +441,12 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
                 return 0;
         }
 
+        r = sd_rtnl_message_route_get_type(message, &rt_type);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "rtnl: received route with invalid type, ignoring: %m");
+                return 0;
+        }
+
         r = sd_rtnl_message_route_get_table(message, &table);
         if (r < 0) {
                 log_link_warning_errno(link, r, "rtnl: received route with invalid table, ignoring: %m");
@@ -464,7 +470,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
                                 return 0;
                 }
 
-                route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, protocol);
+                route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, rt_type, protocol);
 
                 break;
 
index 274d2a8bbee6b188b8b5544be09f2bbafc19b4cc..5947f6dc15652c2d719a915ad0bfd222c944081c 100644 (file)
@@ -100,6 +100,7 @@ Route.Table,                            config_parse_route_table,
 Route.GatewayOnlink,                    config_parse_gateway_onlink,                    0,                             0
 Route.IPv6Preference,                   config_parse_ipv6_route_preference,             0,                             0
 Route.Protocol,                         config_parse_route_protocol,                    0,                             0
+Route.Type,                             config_parse_route_type,                        0,                             0
 DHCP.ClientIdentifier,                  config_parse_dhcp_client_identifier,            0,                             offsetof(Network, dhcp_client_identifier)
 DHCP.UseDNS,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
 DHCP.UseNTP,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_ntp)
index f2da3141f81806f3b7c61077bc9ecfb001747a19..24f8ee6e9c0a6579bb9ff54ec5b02fc6e916fdad 100644 (file)
@@ -222,8 +222,7 @@ static int network_load_one(Manager *manager, const char *filename) {
          * even if they are commented in the man?
          * These vars might be overwriten by network_apply_anonymize_if_set */
         network->dhcp_vendor_class_identifier = false;
-        /* NOTE: from man: UseMTU=... Defaults to false*/
-        network->dhcp_use_mtu = false;
+        network->dhcp_use_mtu = true;
         /* NOTE: from man: UseTimezone=... Defaults to "no".*/
         network->dhcp_use_timezone = false;
 
index e5d61ce8cc6452560a42816758b0f4a74de5b36e..5b4874795a7dfd78a1cba054779756fda8c43000 100644 (file)
@@ -70,6 +70,7 @@ int route_new(Route **ret) {
         route->family = AF_UNSPEC;
         route->scope = RT_SCOPE_UNIVERSE;
         route->protocol = RTPROT_UNSPEC;
+        route->type = RTN_UNICAST;
         route->table = RT_TABLE_MAIN;
         route->lifetime = USEC_INFINITY;
 
@@ -372,7 +373,8 @@ int route_update(Route *route,
                  const union in_addr_union *gw,
                  const union in_addr_union *prefsrc,
                  unsigned char scope,
-                 unsigned char protocol) {
+                 unsigned char protocol,
+                 unsigned char type) {
 
         assert(route);
         assert(src);
@@ -385,6 +387,7 @@ int route_update(Route *route,
         route->prefsrc = *prefsrc;
         route->scope = scope;
         route->protocol = protocol;
+        route->type = type;
 
         return 0;
 }
@@ -458,9 +461,15 @@ int route_remove(Route *route, Link *link,
         if (r < 0)
                 return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
 
-        r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+        r = sd_rtnl_message_route_set_type(req, route->type);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+                return log_error_errno(r, "Could not set route type: %m");
+
+        if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE)) {
+                r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+                if (r < 0)
+                        return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+        }
 
         r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
         if (r < 0)
@@ -612,9 +621,15 @@ int route_configure(
         if (r < 0)
                 return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
 
-        r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+        r = sd_rtnl_message_route_set_type(req, route->type);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+                return log_error_errno(r, "Could not set route type: %m");
+
+        if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE)) {
+                r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+                if (r < 0)
+                        return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+        }
 
         r = sd_netlink_message_open_container(req, RTA_METRICS);
         if (r < 0)
@@ -1023,3 +1038,39 @@ int config_parse_route_protocol(const char *unit,
 
         return 0;
 }
+
+int config_parse_route_type(const char *unit,
+                            const char *filename,
+                            unsigned line,
+                            const char *section,
+                            unsigned section_line,
+                            const char *lvalue,
+                            int ltype,
+                            const char *rvalue,
+                            void *data,
+                            void *userdata) {
+        Network *network = userdata;
+        _cleanup_route_free_ Route *n = NULL;
+        int r;
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        if (streq(rvalue, "unicast"))
+                n->type = RTN_UNICAST;
+        else if (streq(rvalue, "blackhole"))
+                n->type = RTN_BLACKHOLE;
+        else if (streq(rvalue, "unreachable"))
+                n->type = RTN_UNREACHABLE;
+        else if (streq(rvalue, "prohibit"))
+                n->type = RTN_PROHIBIT;
+        else {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
+                return 0;
+        }
+
+        n = NULL;
+
+        return 0;
+}
index 3f389489da921a782a568fda7ba1d38bf218badc..89d32e921449e492931bfce0f90467a9eb3c9ca2 100644 (file)
@@ -35,6 +35,7 @@ struct Route {
         unsigned char src_prefixlen;
         unsigned char scope;
         unsigned char protocol;  /* RTPROT_* */
+        unsigned char type; /* RTN_* */
         unsigned char tos;
         uint32_t priority; /* note that ip(8) calls this 'metric' */
         uint32_t table;
@@ -62,7 +63,7 @@ int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback
 int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
 int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
 int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
-int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
+int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type);
 
 int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
 
@@ -78,3 +79,4 @@ int config_parse_route_table(const char *unit, const char *filename, unsigned li
 int config_parse_gateway_onlink(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_ipv6_route_preference(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_route_protocol(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_route_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
index 2289269eef9b0d182b342fffc598bad168ad1bc7..b28fc0da00ce6b48635cfcf597626da63ebd97cf 100644 (file)
@@ -138,6 +138,7 @@ int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char
 int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
 int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags);
 int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table);
+int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type);
 int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags);
 int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family);
 int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family);
@@ -147,6 +148,7 @@ int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos);
 int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table);
 int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len);
 int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);
+int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type);
 
 int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
 int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);
index a026ce4ef12d2370aee361d01d33391d7d0282f2..bd5bebe66d7f5d72f0be92001d021171edfdd24a 100644 (file)
@@ -170,6 +170,8 @@ int main(int argc, char* argv[]) {
         test_one("annually", "*-01-01 00:00:00");
         test_one("*:2/3", "*-*-* *:02/3:00");
         test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC");
+        test_one("2015-10-25 01:00:00 Asia/Vladivostok", "2015-10-25 01:00:00 Asia/Vladivostok");
+        test_one("weekly Pacific/Auckland", "Mon *-*-* 00:00:00 Pacific/Auckland");
         test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001");
         test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
         test_one("9..11,13:00,30", "*-*-* 09..11,13:00,30:00");
@@ -219,6 +221,16 @@ int main(int argc, char* argv[]) {
         test_next("2017-08-06 9,11,13,15,17:00 UTC", "", 1502029800000000, 1502031600000000);
         test_next("2017-08-06 9..17/2:00 UTC", "", 1502029800000000, 1502031600000000);
         test_next("2016-12-* 3..21/6:00 UTC", "", 1482613200000001, 1482634800000000);
+        test_next("2017-09-24 03:30:00 Pacific/Auckland", "", 12345, 1506177000000000);
+        // Due to daylight saving time - 2017-09-24 02:30:00 does not exist
+        test_next("2017-09-24 02:30:00 Pacific/Auckland", "", 12345, -1);
+        test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 12345, 1491053400000000);
+        // Confirm that even though it's a time change here (backward) 02:30 happens only once
+        test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 1491053400000000, -1);
+        test_next("2017-04-02 03:30:00 Pacific/Auckland", "", 12345, 1491060600000000);
+        // Confirm that timezones in the Spec work regardless of current timezone
+        test_next("2017-09-09 20:42:00 Pacific/Auckland", "", 12345, 1504946520000000);
+        test_next("2017-09-09 20:42:00 Pacific/Auckland", "EET", 12345, 1504946520000000);
 
         assert_se(calendar_spec_from_string("test", &c) < 0);
         assert_se(calendar_spec_from_string(" utc", &c) < 0);
index 0e7d44fade9f5d1e03e3d82c7d5642b7e642027c..c09d61539648041f3c4f57c0097301a4d59a5f64 100644 (file)
@@ -33,6 +33,12 @@ static void test_should_pass(const char *p) {
         log_info("\"%s\" → \"%s\"", p, buf);
 
         assert_se(parse_timestamp(buf, &q) >= 0);
+        if (q != t) {
+                char tmp[FORMAT_TIMESTAMP_MAX];
+
+                log_error("round-trip failed: \"%s\" → \"%s\"",
+                          buf, format_timestamp_us(tmp, sizeof(tmp), q));
+        }
         assert_se(q == t);
 
         assert_se(format_timestamp_relative(buf_relative, sizeof(buf_relative), t));
@@ -77,6 +83,10 @@ static void test_one_noutc(const char *p) {
 }
 
 int main(int argc, char *argv[]) {
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
         test_one("17:41");
         test_one("18:42:44");
         test_one("18:42:44.0");
@@ -90,6 +100,10 @@ int main(int argc, char *argv[]) {
         test_one("yesterday");
         test_one("today");
         test_one("tomorrow");
+        test_one_noutc("16:20 UTC");
+        test_one_noutc("16:20 Asia/Seoul");
+        test_one_noutc("tomorrow Asia/Seoul");
+        test_one_noutc("2012-12-30 18:42 Asia/Seoul");
         test_one_noutc("now");
         test_one_noutc("+2d");
         test_one_noutc("+2y 4d");
@@ -100,6 +114,9 @@ int main(int argc, char *argv[]) {
         test_should_fail("1969-12-31 UTC");
         test_should_fail("-100y");
         test_should_fail("today UTC UTC");
+        test_should_fail("now Asia/Seoul");
+        test_should_fail("+2d Asia/Seoul");
+        test_should_fail("@1395716396 Asia/Seoul");
 #if SIZEOF_TIME_T == 8
         test_should_pass("9999-12-30 23:59:59 UTC");
         test_should_fail("9999-12-31 00:00:00 UTC");
index 30c92019d910a52d908c5e17e96a5e5179cd8128..c192d3522c3c9f6e4cf14b899bc3944b2daf165d 100644 (file)
@@ -71,10 +71,14 @@ static const gather_stdout_callback_t ignore_stdout[] = {
 };
 
 static void test_execute_directory(bool gather_stdout) {
-        char template_lo[] = "/tmp/test-exec-util.XXXXXXX";
-        char template_hi[] = "/tmp/test-exec-util.XXXXXXX";
+        char template_lo[] = "/tmp/test-exec-util.lo.XXXXXXX";
+        char template_hi[] = "/tmp/test-exec-util.hi.XXXXXXX";
         const char * dirs[] = {template_hi, template_lo, NULL};
-        const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
+        const char *name, *name2, *name3,
+                *overridden, *override,
+                *masked, *mask,
+                *masked2, *mask2,   /* the mask is non-executable */
+                *masked2e, *mask2e; /* the mask is executable */
 
         log_info("/* %s (%s) */", __func__, gather_stdout ? "gathering stdout" : "asynchronous");
 
@@ -88,6 +92,10 @@ static void test_execute_directory(bool gather_stdout) {
         override = strjoina(template_hi, "/overridden");
         masked = strjoina(template_lo, "/masked");
         mask = strjoina(template_hi, "/masked");
+        masked2 = strjoina(template_lo, "/masked2");
+        mask2 = strjoina(template_hi, "/masked2");
+        masked2e = strjoina(template_lo, "/masked2e");
+        mask2e = strjoina(template_hi, "/masked2e");
 
         assert_se(write_string_file(name,
                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works",
@@ -104,7 +112,15 @@ static void test_execute_directory(bool gather_stdout) {
         assert_se(write_string_file(masked,
                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
                                     WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(write_string_file(masked2,
+                                    "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
+                                    WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(write_string_file(masked2e,
+                                    "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
+                                    WRITE_STRING_FILE_CREATE) == 0);
         assert_se(symlink("/dev/null", mask) == 0);
+        assert_se(touch(mask2) == 0);
+        assert_se(touch(mask2e) == 0);
         assert_se(touch(name3) >= 0);
 
         assert_se(chmod(name, 0755) == 0);
@@ -112,6 +128,9 @@ static void test_execute_directory(bool gather_stdout) {
         assert_se(chmod(overridden, 0755) == 0);
         assert_se(chmod(override, 0755) == 0);
         assert_se(chmod(masked, 0755) == 0);
+        assert_se(chmod(masked2, 0755) == 0);
+        assert_se(chmod(masked2e, 0755) == 0);
+        assert_se(chmod(mask2e, 0755) == 0);
 
         if (gather_stdout)
                 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
index 3e1481e4f7e0afd95752f5017b6bded1219937d6..a5b87cf51a0698e8c240860a80844dd080f874ed 100644 (file)
@@ -66,11 +66,12 @@ DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");
 
 static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {
-        [NET_DEV_FEAT_GSO] = "tx-generic-segmentation",
-        [NET_DEV_FEAT_GRO] = "rx-gro",
-        [NET_DEV_FEAT_LRO] = "rx-lro",
-        [NET_DEV_FEAT_TSO] = "tx-tcp-segmentation",
-        [NET_DEV_FEAT_UFO] = "tx-udp-fragmentation",
+        [NET_DEV_FEAT_GSO]  = "tx-generic-segmentation",
+        [NET_DEV_FEAT_GRO]  = "rx-gro",
+        [NET_DEV_FEAT_LRO]  = "rx-lro",
+        [NET_DEV_FEAT_TSO]  = "tx-tcp-segmentation",
+        [NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation",
+        [NET_DEV_FEAT_UFO]  = "tx-udp-fragmentation",
 };
 
 int ethtool_connect(int *ret) {
index 89c531ae081683e31f37a08fd2b72358fed2feae..909b56b1e68e633569b73afcf4c835d20ca3a5d6 100644 (file)
@@ -53,6 +53,7 @@ typedef enum NetDevFeature {
         NET_DEV_FEAT_GRO,
         NET_DEV_FEAT_LRO,
         NET_DEV_FEAT_TSO,
+        NET_DEV_FEAT_TSO6,
         NET_DEV_FEAT_UFO,
         _NET_DEV_FEAT_MAX,
         _NET_DEV_FEAT_INVALID = -1
index 5488867ba71fb8b0ecd0112108f805592b9dc1aa..52bb4775dd1d4ae6ecfe3dfb08b83b3c678e848e 100644 (file)
@@ -39,6 +39,7 @@ Link.WakeOnLan,                  config_parse_wol,           0,
 Link.Port,                       config_parse_port,          0,                             offsetof(link_config, port)
 Link.GenericSegmentationOffload, config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_GSO])
 Link.TCPSegmentationOffload,     config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_TSO])
+Link.TCP6SegmentationOffload,    config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_TSO6])
 Link.UDPSegmentationOffload,     config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_UFO])
 Link.GenericReceiveOffload,      config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_GRO])
 Link.LargeReceiveOffload,        config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_LRO])
index 601f0ee13d11d396eefc0f6248f5873a43fe6a6e..09f7baf08220460d97d496850a26ebea5977d056 100644 (file)
@@ -362,7 +362,7 @@ size_t udev_event_apply_format(struct udev_event *event,
                         }
 copy:
                         /* copy char */
-                        if (l == 0)
+                        if (l < 2) /* need space for this char and the terminating NUL */
                                 goto out;
                         s[0] = from[0];
                         from++;
@@ -377,12 +377,12 @@ subst:
                         unsigned int i;
 
                         from++;
-                        for (i = 0; from[i] != '}'; i++) {
+                        for (i = 0; from[i] != '}'; i++)
                                 if (from[i] == '\0') {
                                         log_error("missing closing brace for format '%s'", src);
                                         goto out;
                                 }
-                        }
+
                         if (i >= sizeof(attrbuf))
                                 goto out;
                         memcpy(attrbuf, from, i);
@@ -407,6 +407,7 @@ subst:
         }
 
 out:
+        assert(l >= 1);
         s[0] = '\0';
         return l;
 }