]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #8735 from keszybz/small-docs-updates
authorLennart Poettering <lennart@poettering.net>
Wed, 18 Apr 2018 09:50:56 +0000 (11:50 +0200)
committerGitHub <noreply@github.com>
Wed, 18 Apr 2018 09:50:56 +0000 (11:50 +0200)
Small docs updates

64 files changed:
hwdb/60-sensor.hwdb
man/machinectl.xml
man/pam_systemd.xml
man/systemd-path.xml
man/systemd-time-wait-sync.service.xml
man/systemd-timesyncd.service.xml
man/systemd.service.xml
src/analyze/analyze-verify.c
src/basic/copy.c
src/basic/path-util.h
src/basic/unit-name.c
src/core/load-fragment.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/libsystemd/sd-path/sd-path.c
src/login/logind-dbus.c
src/login/logind-session.c
src/login/logind-session.h
src/login/logind.c
src/login/logind.h
src/login/pam_systemd.c
src/machine/machinectl.c
src/machine/machined.c
src/machine/machined.h
src/network/networkd-dhcp4.c
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/path/path.c
src/resolve/resolved-bus.c
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/shared/bus-util.c
src/shared/bus-util.h
src/shared/spawn-polkit-agent.h
src/systemd/sd-path.h
src/test/meson.build
src/test/test-cgroup-mask.c
src/test/test-engine.c
src/test/test-execute.c
src/test/test-path.c
src/test/test-sched-prio.c
src/time-wait-sync/time-wait-sync.c
src/timesync/timesyncd-manager.c
test/meson.build
test/test-execute/exec-basic.service [new file with mode: 0644]
test/test-execute/exec-bindpaths.service
test/test-execute/exec-dynamicuser-statedir-migrate-step1.service
test/test-execute/exec-dynamicuser-statedir-migrate-step2.service
test/test-execute/exec-dynamicuser-statedir.service
test/test-execute/exec-restrictnamespaces-mnt-blacklist.service
test/test-execute/exec-restrictnamespaces-mnt.service
test/test-execute/exec-restrictnamespaces-no.service
test/test-execute/exec-restrictnamespaces-yes.service
test/test-execute/exec-specifier.service
test/test-execute/exec-specifier@.service
test/test-execute/exec-temporaryfilesystem-rw.service
tmpfiles.d/meson.build
units/console-getty.service.m4 [moved from units/console-getty.service.m4.in with 100% similarity]
units/container-getty@.service.m4 [moved from units/container-getty@.service.m4.in with 100% similarity]
units/meson.build
units/system-update-cleanup.service [moved from units/system-update-cleanup.service.in with 100% similarity]
units/systemd-timesyncd.service.in

index 3c1125dc4e15a0d3d34d92bbcf12e70621541e25..5250ff709496fc3760b5109ead19c8937a456f66 100644 (file)
@@ -235,8 +235,9 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnLENOVO:*:pvrLenovoMIIX3-1030:*
 sensor:modalias:acpi:KIOX000A*:dmi:bvnLENOVO:bvr1HCN4?WW:*:svnLENOVO:pn80SG:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
-# IdeaPad Miix 320
+# IdeaPad Miix 320, different batches use a different sensor
 sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XF:*
+sensor:modalias:acpi:SMO8840*:dmi:*:svnLENOVO:pn80XF:pvrLenovoMIIX320*
  ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
 
 #########################################
index 44a96e8cc4fbd634874f244c43c520913045758b..c37fb88c38f555bf1d3cf15952238697641a705c 100644 (file)
         </listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><option>--no-ask-password</option></term>
-
-        <listitem><para>Do not query the user for authentication for
-        privileged operations.</para></listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><option>--kill-who=</option></term>
 
 
       <xi:include href="standard-options.xml" xpointer="no-pager" />
       <xi:include href="standard-options.xml" xpointer="no-legend" />
+      <xi:include href="standard-options.xml" xpointer="no-ask-password" />
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
   <refsect1>
     <title>See Also</title>
     <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
index 5aa12c704b7e756c4b690e151952498ee6de53aa..cdf45f8c20199e1bde94dcb482cffda8b1e5e55f 100644 (file)
     based on the <varname>$DISPLAY</varname> variable.</para>
   </refsect1>
 
+  <refsect1>
+    <title>Session limits</title>
+
+    <para>PAM modules earlier in the stack, that is those that come before <command>pam_systemd.so</command>,
+    can set session scope limits using the PAM context objects. The data for these objects is provided as NUL-terminated C strings
+    and maps directly to the respective unit resource control directives. Note that these limits apply to individual sessions of the user,
+    they do not apply to all user processes as a combined whole. In particular, the per-user <command>user@.service</command> unit instance,
+    which runs the <command>systemd --user</command> manager process and its children, and is tracked outside of any session, being shared
+    by all the user's sessions, is not covered by these limits.
+    </para>
+
+    <para> See
+    <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information about the resources.
+    Also, see <citerefentry><refentrytitle>pam_set_data</refentrytitle><manvolnum>3</manvolnum></citerefentry> for additional information about how to set
+    the context objects.
+    </para>
+
+    <variablelist>
+      <varlistentry>
+        <term><varname>systemd.memory_max</varname></term>
+
+        <listitem><para>Sets unit <varname>MemoryMax=</varname>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.tasks_max</varname></term>
+
+        <listitem><para>Sets unit <varname>TasksMax=</varname>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.cpu_weight</varname></term>
+
+        <listitem><para>Sets unit <varname>CPUWeight=</varname>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.io_weight</varname></term>
+
+        <listitem><para>Sets unit <varname>IOWeight=</varname>.</para></listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>Example data as can be provided from an another PAM module:
+      <programlisting>
+pam_set_data(handle, "systemd.memory_max", (void *)"200M", cleanup);
+pam_set_data(handle, "systemd.tasks_max",  (void *)"50",   cleanup);
+pam_set_data(handle, "systemd.cpu_weight", (void *)"100",  cleanup);
+pam_set_data(handle, "systemd.io_weight",  (void *)"340",  cleanup);
+      </programlisting>
+    </para>
+
+  </refsect1>
+
   <refsect1>
     <title>Example</title>
 
index 882d0d1a2a646a0354bf8820901ba3519b3c6f26..2e52e5b8742d7de2c4d912130d8d4fb21e5bb9a9 100644 (file)
@@ -39,7 +39,9 @@
 
   <refsynopsisdiv>
     <cmdsynopsis>
-      <command>systemd-path <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
+      <command>systemd-path</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="opt" rep="repeat">NAME</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -68,8 +70,7 @@
       <varlistentry>
         <term><option>--suffix=</option></term>
 
-        <listitem><para>The printed paths are suffixed by the
-        specified string.</para></listitem>
+        <listitem><para>Printed paths are suffixed by the specified string.</para></listitem>
       </varlistentry>
 
       <xi:include href="standard-options.xml" xpointer="help" />
index a707102dab63a798a2bd28bedf19bf7bd7e56294..d0c861f9211008ef283cce6316f1039ff34257b7 100644 (file)
     <title>Description</title>
 
     <para><filename>systemd-time-wait-sync</filename> is a system service that delays the start of units that depend on
-    <filename>time-sync.target</filename> until <filename>systemd-timesyncd.service</filename> or something else has
-    set the system time and marked it as synchronized.  Reaching this state generally requires synchronization with an
-    external source, such as an NTP server.</para>
+    <filename>time-sync.target</filename> until the system time has been synchronized with an accurate time source by
+    <filename>systemd-timesyncd.service</filename>.</para>
 
-    <para>When this unit is not enabled the <filename>time-sync.target</filename> synchronization point may be reached
-    as soon as the system time is advanced by <filename>systemd-timesyncd.service</filename> to the time stored at the
-    last shutdown.  That time may not meet the expectations of dependent services that require an accurate
-    clock.</para>
+    <para><filename>systemd-timesyncd.service</filename> notifies on successful synchronization.
+    <filename>systemd-time-wait-sync</filename> also tries to detect when the kernel marks the time as synchronized,
+    but this detection is not reliable and is intended only as a fallback for other servies that can be used to
+    synchronize time (e.g., ntpd, chronyd).</para>
 
   </refsect1>
 
   <refsect1>
-    <title>Notes</title>
+    <title>Files</title>
+
+    <variablelist>
+      <varlistentry>
+        <term><filename>/run/systemd/timesync/synchronized</filename></term>
+
+        <listitem>
+          <para>The presence of this file indicates to this service that the system clock has been synchronized.</para>
+        </listitem>
+
+      </varlistentry>
+    </variablelist>
 
-    <para>This service works correctly with a time synchronization service like
-    <filename>systemd-timesyncd.service</filename> that uses the same protocol as NTP to set the time from a
-    synchronized source.  When used with time synchronization services that follow a different protocol the event of
-    setting synchronized time may not be detected in which case this service will not complete.</para>
   </refsect1>
 
   <refsect1>
index 26f783767b57b1cebe9da7bce267a1eb7b615706..49e00e2b916523903902f5dee576aa6ca58e3e7f 100644 (file)
         <term><filename>/var/lib/systemd/timesync/clock</filename></term>
 
         <listitem>
-          <para>This file contains the timestamp of the last successful
+          <para>The modification time of this file indicates the timestamp of the last successful
           synchronization.</para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><filename>/run/systemd/timesync/synchronized</filename></term>
+
+        <listitem>
+          <para>A file that is touched on each successful synchronization, to assist
+          <filename>systemd-time-wait-sync</filename> and other applications to detecting synchronization
+          events.</para>
+        </listitem>
+
+      </varlistentry>
     </variablelist>
   </refsect1>
 
       <citerefentry><refentrytitle>timesyncd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-time-wait-sync.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>localtime</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry project='man-pages'><refentrytitle>hwclock</refentrytitle><manvolnum>8</manvolnum></citerefentry>
index 5c29ecb46098991652aec54d204c4584161161d1..03c7b01b3bb6861d56226cc0daeaa500b9b73124 100644 (file)
         <varname>ExecStop=</varname> line set. (Services lacking both <varname>ExecStart=</varname> and
         <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 filename may be prefixed with a number of special characters:</para>
+        <para>For each of the specified commands, the first argument must be either an absolute path to an executable
+        or a simple file name without any slashes. Optionally, this filename may be prefixed with a number of special
+        characters:</para>
 
         <table>
           <title>Special executable prefixes</title>
     <literal>&amp;</literal>, and <emphasis>other elements of shell
     syntax are not supported</emphasis>.</para>
 
-    <para>The command to execute must be an absolute path name. It may
-    contain spaces, but control characters are not allowed.</para>
+    <para>The command to execute may contain spaces, but control characters are not allowed.</para>
 
-    <para>The command line accepts <literal>%</literal> specifiers as
-    described in
+    <para>The command line accepts <literal>%</literal> specifiers as described in
     <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
 
     <para>Basic environment variable substitution is supported. Use
     For this type of expansion, quotes are respected when splitting
     into words, and afterwards removed.</para>
 
+    <para>If the command is not a full (absolute) path, it will be resolved to a full path using a
+    fixed search path determinted at compilation time. Searched directories include
+    <filename>/usr/local/bin/</filename>, <filename>/usr/bin/</filename>, <filename>/bin/</filename>
+    on systems using split <filename>/usr/bin/</filename> and <filename>/bin/</filename>
+    directories, and their <filename>sbin/</filename> counterparts on systems using split
+    <filename>bin/</filename> and <filename>sbin/</filename>. It is thus safe to use just the
+    executable name in case of executables located in any of the "standard" directories, and an
+    absolute path must be used in other cases. Using an absolute path is recommended to avoid
+    ambiguity. Hint: this search path may be queried using
+    <command>systemd-path search-binaries-default</command>.</para>
+
     <para>Example:</para>
 
     <programlisting>Environment="ONE=one" 'TWO=two two'
-ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
+ExecStart=echo $ONE $TWO ${TWO}</programlisting>
 
     <para>This will execute <command>/bin/echo</command> with four
     arguments: <literal>one</literal>, <literal>two</literal>,
@@ -1040,7 +1050,7 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
     <programlisting>Environment=ONE='one' "TWO='two two' too" THREE=
 ExecStart=/bin/echo ${ONE} ${TWO} ${THREE}
 ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
-    <para>This results in <filename>echo</filename> being
+    <para>This results in <filename>/bin/echo</filename> being
     called twice, the first time with arguments
     <literal>'one'</literal>,
     <literal>'two two' too</literal>, <literal></literal>,
@@ -1066,27 +1076,27 @@ ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
     <para>Note that shell command lines are not directly supported. If
     shell command lines are to be used, they need to be passed
     explicitly to a shell implementation of some kind. Example:</para>
-    <programlisting>ExecStart=/bin/sh -c 'dmesg | tac'</programlisting>
+    <programlisting>ExecStart=sh -c 'dmesg | tac'</programlisting>
 
     <para>Example:</para>
 
-    <programlisting>ExecStart=/bin/echo one ; /bin/echo "two two"</programlisting>
+    <programlisting>ExecStart=echo one ; echo "two two"</programlisting>
 
-    <para>This will execute <command>/bin/echo</command> two times,
+    <para>This will execute <command>echo</command> two times,
     each time with one argument: <literal>one</literal> and
     <literal>two two</literal>, respectively. Because two commands are
     specified, <varname>Type=oneshot</varname> must be used.</para>
 
     <para>Example:</para>
 
-    <programlisting>ExecStart=/bin/echo / &gt;/dev/null &amp; \; \
-/bin/ls</programlisting>
+    <programlisting>ExecStart=echo / &gt;/dev/null &amp; \; \
+ls</programlisting>
 
-    <para>This will execute <command>/bin/echo</command>
+    <para>This will execute <command>echo</command>
     with five arguments: <literal>/</literal>,
     <literal>&gt;/dev/null</literal>,
     <literal>&amp;</literal>, <literal>;</literal>, and
-    <literal>/bin/ls</literal>.</para>
+    <literal>ls</literal>.</para>
 
     <table>
       <title>C escapes supported in command lines and environment variables</title>
index fdaf90c7fc0a6d13498c3d61cd25f7078a2f9e55..90c10f575a4e604c8baeb975fac6d713fa49588b 100644 (file)
@@ -231,7 +231,6 @@ static int verify_unit(Unit *u, bool check_man) {
 }
 
 int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) {
-        _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *var = NULL;
         Manager *m = NULL;
         FILE *serial = NULL;
@@ -284,12 +283,10 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
                         continue;
                 }
 
-                k = manager_load_unit(m, NULL, prepared, &err, &units[count]);
-                if (k < 0) {
-                        log_error_errno(k, "Failed to load %s: %m", *filename);
-                        if (r == 0)
-                                r = k;
-                } else
+                k = manager_load_startable_unit_or_warn(m, NULL, prepared, &units[count]);
+                if (k < 0 && r == 0)
+                        r = k;
+                else
                         count++;
         }
 
index 55394871fdff0930326cdca16ae3f412b90f983a..5b6cae39d056dfcbf570053c1594210f43b5f5f4 100644 (file)
@@ -69,7 +69,7 @@ static int fd_is_nonblock_pipe(int fd) {
         struct stat st;
         int flags;
 
-        /* Checks whether the specified file descriptor refers to a pipe, and if so if is has O_NONBLOCK set. */
+        /* Checks whether the specified file descriptor refers to a pipe, and if so if O_NONBLOCK is set. */
 
         if (fstat(fd, &st) < 0)
                 return -errno;
index 898eeb439540f6a989100701bbf65c81b3b07e71..7ec0a3eb0fda64872327609aef0ba93d3a59b13c 100644 (file)
 
 #if HAVE_SPLIT_BIN
 #  define PATH_SBIN_BIN(x) x "sbin:" x "bin"
+#  define PATH_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
 #else
 #  define PATH_SBIN_BIN(x) x "bin"
+#  define PATH_SBIN_BIN_NULSTR(x) x "bin\0"
 #endif
 
 #define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
+#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
 #define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
+#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
 
 #if HAVE_SPLIT_USR
 #  define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
+#  define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
 #else
 #  define DEFAULT_PATH DEFAULT_PATH_NORMAL
+#  define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
 #endif
 
 bool is_path(const char *p) _pure_;
index 6fb9cbc3618afadc87b3db3b474dbb9ccfcd0bee..13653d9b7838c469a8ed11bd008f1e855c0e7ccb 100644 (file)
@@ -247,8 +247,6 @@ int unit_name_build(const char *prefix, const char *instance, const char *suffix
         assert(suffix);
         assert(ret);
 
-        if (isempty(suffix))
-                return -EINVAL;
         if (suffix[0] != '.')
                 return -EINVAL;
 
index c3ff27b518a2267421fcf70d2ae6042f4868e151..767355adf6d866c9e9da8a0b3e3e602ab1c5e160 100644 (file)
@@ -639,23 +639,51 @@ int config_parse_exec(
                 }
                 if (!string_is_safe(path)) {
                         log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Executable path contains special characters%s: %s",
-                                   ignore ? ", ignoring" : "", rvalue);
-                        return ignore ? 0 : -ENOEXEC;
-                }
-                if (!path_is_absolute(path)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Executable path is not absolute%s: %s",
-                                   ignore ? ", ignoring" : "", rvalue);
+                                   "Executable name contains special characters%s: %s",
+                                   ignore ? ", ignoring" : "", path);
                         return ignore ? 0 : -ENOEXEC;
                 }
                 if (endswith(path, "/")) {
                         log_syntax(unit, LOG_ERR, filename, line, 0,
                                    "Executable path specifies a directory%s: %s",
-                                   ignore ? ", ignoring" : "", rvalue);
+                                   ignore ? ", ignoring" : "", path);
                         return ignore ? 0 : -ENOEXEC;
                 }
 
+                if (!path_is_absolute(path)) {
+                        const char *prefix;
+                        bool found = false;
+
+                        if (!filename_is_valid(path)) {
+                                log_syntax(unit, LOG_ERR, filename, line, 0,
+                                           "Neither a valid executable name nor an absolute path%s: %s",
+                                           ignore ? ", ignoring" : "", path);
+                                return ignore ? 0 : -ENOEXEC;
+                        }
+
+                        /* Resolve a single-component name to a full path */
+                        NULSTR_FOREACH(prefix, DEFAULT_PATH_NULSTR) {
+                                _cleanup_free_ char *fullpath = NULL;
+
+                                fullpath = strjoin(prefix, "/", path);
+                                if (!fullpath)
+                                        return log_oom();
+
+                                if (access(fullpath, F_OK) >= 0) {
+                                        free_and_replace(path, fullpath);
+                                        found = true;
+                                        break;
+                                }
+                        }
+
+                        if (!found) {
+                                log_syntax(unit, LOG_ERR, filename, line, 0,
+                                           "Executable \"%s\" not found in path \"%s\"%s",
+                                           path, DEFAULT_PATH, ignore ? ", ignoring" : "");
+                                return ignore ? 0 : -ENOEXEC;
+                        }
+                }
+
                 if (!separate_argv0) {
                         char *w = NULL;
 
index 701cbab99bcadb37f74c67648e322627bb864309..201882ca95c029277c0bbceb181b4c94315f4319 100644 (file)
@@ -1890,28 +1890,15 @@ static int do_queue_default_job(
 
         log_debug("Activating default unit: %s", arg_default_unit);
 
-        r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
-        if (r < 0)
-                log_error("Failed to load default target: %s", bus_error_message(&error, r));
-        else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
-                log_error_errno(target->load_error, "Failed to load default target: %m");
-        else if (target->load_state == UNIT_MASKED)
-                log_error("Default target masked.");
-
-        if (!target || target->load_state != UNIT_LOADED) {
-                log_info("Trying to load rescue target...");
+        r = manager_load_startable_unit_or_warn(m, arg_default_unit, NULL, &target);
+        if (r < 0) {
+                log_info("Falling back to rescue target: " SPECIAL_RESCUE_TARGET);
 
-                r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
+                r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target);
                 if (r < 0) {
-                        *ret_error_message = "Failed to load rescue target";
-                        return log_emergency_errno(r, "Failed to load rescue target: %s", bus_error_message(&error, r));
-                } else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND)) {
-                        *ret_error_message = "Failed to load rescue target";
-                        return log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
-                } else if (target->load_state == UNIT_MASKED) {
-                        *ret_error_message = "Rescue target masked";
-                        log_emergency("Rescue target masked.");
-                        return -ERFKILL;
+                        *ret_error_message = r == -ERFKILL ? "Rescue target masked"
+                                                           : "Failed to load rescue target";
+                        return r;
                 }
         }
 
index 74e36a7521afe0cef3ec40b4376e1a1a741180d9..a42fccd8e43eb793084a1176bcf935f5df933324 100644 (file)
@@ -1810,7 +1810,36 @@ int manager_load_unit(
         manager_dispatch_load_queue(m);
 
         *_ret = unit_follow_merge(*_ret);
+        return 0;
+}
+
+int manager_load_startable_unit_or_warn(
+                Manager *m,
+                const char *name,
+                const char *path,
+                Unit **ret) {
+
+        /* Load a unit, make sure it loaded fully and is not masked. */
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *unit;
+        int r;
+
+        r = manager_load_unit(m, name, path, &error, &unit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to load %s %s: %s",
+                                       name ? "unit" : "file", name ?: path,
+                                       bus_error_message(&error, r));
+        else if (IN_SET(unit->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
+                return log_error_errno(unit->load_error, "Failed to load %s %s: %m",
+                                       name ? "unit" : "file", name ?: path);
+        else if (unit->load_state == UNIT_MASKED) {
+                log_error("%s %s is masked.",
+                          name ? "Unit" : "File", name ?: path);
+                return -ERFKILL;
+        }
 
+        *ret = unit;
         return 0;
 }
 
index 6047c025322d6828768f5314d46b71fe732e8dd3..cab89d819276ddf99ab41d320ac78a2532533055 100644 (file)
@@ -383,6 +383,7 @@ int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
 
 int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
 int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
+int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
 int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
 
 int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret);
index d8867bc4390de056f5b1eef49498753604bc2979..c75a39613baa22d553b2f131fc450d41f7f455dd 100644 (file)
@@ -335,6 +335,7 @@ _public_ int sd_path_home(uint64_t type, const char *suffix, char **path) {
 
         if (IN_SET(type,
                    SD_PATH_SEARCH_BINARIES,
+                   SD_PATH_SEARCH_BINARIES_DEFAULT,
                    SD_PATH_SEARCH_LIBRARY_PRIVATE,
                    SD_PATH_SEARCH_LIBRARY_ARCH,
                    SD_PATH_SEARCH_SHARED,
@@ -553,7 +554,17 @@ static int get_search(uint64_t type, char ***list) {
                                                false,
                                                "/etc",
                                                NULL);
-        }
+
+        case SD_PATH_SEARCH_BINARIES_DEFAULT: {
+                char **t;
+
+                t = strv_split_nulstr(DEFAULT_PATH_NULSTR);
+                if (!t)
+                        return -ENOMEM;
+
+                *list = t;
+                return 0;
+        }}
 
         return -EOPNOTSUPP;
 }
@@ -566,6 +577,7 @@ _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
 
         if (!IN_SET(type,
                     SD_PATH_SEARCH_BINARIES,
+                    SD_PATH_SEARCH_BINARIES_DEFAULT,
                     SD_PATH_SEARCH_LIBRARY_PRIVATE,
                     SD_PATH_SEARCH_LIBRARY_ARCH,
                     SD_PATH_SEARCH_SHARED,
index 563c7fef9f9dbfd50c9cad466f42a44f018a57f0..d92437b67f3f023e9652263029b7d28b336bf112 100644 (file)
@@ -744,10 +744,6 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
                 }
         }
 
-        r = sd_bus_message_enter_container(message, 'a', "(sv)");
-        if (r < 0)
-                return r;
-
         if (t == _SESSION_TYPE_INVALID) {
                 if (!isempty(display))
                         t = SESSION_X11;
@@ -903,7 +899,15 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
                         goto fail;
         }
 
-        r = session_start(session);
+        r = sd_bus_message_enter_container(message, 'a', "(sv)");
+        if (r < 0)
+                return r;
+
+        r = session_start(session, message);
+        if (r < 0)
+                goto fail;
+
+        r = sd_bus_message_exit_container(message);
         if (r < 0)
                 goto fail;
 
@@ -3056,7 +3060,7 @@ int manager_start_scope(
                 const char *description,
                 const char *after,
                 const char *after2,
-                uint64_t tasks_max,
+                sd_bus_message *more_properties,
                 sd_bus_error *error,
                 char **job) {
 
@@ -3120,9 +3124,17 @@ int manager_start_scope(
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
+        /* disable TasksMax= for the session scope, rely on the slice setting for it */
+        r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1);
         if (r < 0)
-                return r;
+                return bus_log_create_error(r);
+
+        if (more_properties) {
+                /* If TasksMax also appears here, it will overwrite the default value set above */
+                r = sd_bus_message_copy(m, more_properties, true);
+                if (r < 0)
+                        return r;
+        }
 
         r = sd_bus_message_close_container(m);
         if (r < 0)
index bfdc21c2772a063c65a6cd5d1de4125979c6c80a..d9277501d2070bbc0104be299160448c6444046a 100644 (file)
@@ -545,7 +545,7 @@ int session_activate(Session *s) {
         return 0;
 }
 
-static int session_start_scope(Session *s) {
+static int session_start_scope(Session *s, sd_bus_message *properties) {
         int r;
 
         assert(s);
@@ -570,7 +570,7 @@ static int session_start_scope(Session *s) {
                                 description,
                                 "systemd-logind.service",
                                 "systemd-user-sessions.service",
-                                (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
+                                properties,
                                 &error,
                                 &job);
                 if (r < 0) {
@@ -591,7 +591,7 @@ static int session_start_scope(Session *s) {
         return 0;
 }
 
-int session_start(Session *s) {
+int session_start(Session *s, sd_bus_message *properties) {
         int r;
 
         assert(s);
@@ -607,7 +607,7 @@ int session_start(Session *s) {
                 return r;
 
         /* Create cgroup */
-        r = session_start_scope(s);
+        r = session_start_scope(s, properties);
         if (r < 0)
                 return r;
 
index d81a339379ef5a68a78bc7e60819092a6fbfceb1..6043048ae9dae4a9c4bc09a515fb5a190aa4116c 100644 (file)
@@ -127,7 +127,7 @@ void session_set_idle_hint(Session *s, bool b);
 int session_get_locked_hint(Session *s);
 void session_set_locked_hint(Session *s, bool b);
 int session_create_fifo(Session *s);
-int session_start(Session *s);
+int session_start(Session *s, sd_bus_message *properties);
 int session_stop(Session *s, bool force);
 int session_finalize(Session *s);
 int session_release(Session *s);
index 726eca73f91b0e1ac8d32d0ea8fe285bdea0302a..6bddcb541fc60a0212f6c49b78eee3f77a74909b 100644 (file)
@@ -1195,7 +1195,7 @@ static int manager_startup(Manager *m) {
                 user_start(user);
 
         HASHMAP_FOREACH(session, m->sessions, i)
-                session_start(session);
+                session_start(session, NULL);
 
         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
                 inhibitor_start(inhibitor);
index 4786392f8e27aafe3e10b97fc9f61dddd792b96d..5574fcd591919bfa72919ddd25b58e62b303bd87 100644 (file)
@@ -164,7 +164,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
 int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
 
 int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_message *more_properties, sd_bus_error *error, char **job);
 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
index b811e62a067adf8427c018706cf1b96a4b1e69ad..e1c2615f61f73d4b1560c82b14fda492dbee04a9 100644 (file)
@@ -35,6 +35,7 @@
 #include "terminal-util.h"
 #include "util.h"
 #include "path-util.h"
+#include "cgroup-util.h"
 
 static int parse_argv(
                 pam_handle_t *handle,
@@ -198,13 +199,93 @@ error:
         return r;
 }
 
+static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
+        uint64_t val;
+        int r;
+
+        if (isempty(limit))
+                return 0;
+
+        if (streq(limit, "infinity")) {
+                r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", (uint64_t)-1);
+                if (r < 0) {
+                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                        return r;
+                }
+        } else {
+                r = parse_percent(limit);
+                if (r >= 0) {
+                        r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U));
+                        if (r < 0) {
+                                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                                return r;
+                        }
+                } else {
+                        r = parse_size(limit, 1024, &val);
+                        if (r >= 0) {
+                                r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
+                                if (r < 0) {
+                                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                                        return r;
+                                }
+                        } else
+                                pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.limit: %s, ignoring.", limit);
+                }
+        }
+
+        return 0;
+}
+
+static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, const char *limit)
+{
+        uint64_t val;
+        int r;
+
+        /* No need to parse "infinity" here, it will be set unconditionally later in manager_start_scope() */
+        if (isempty(limit) || streq(limit, "infinity"))
+                return 0;
+
+        r = safe_atou64(limit, &val);
+        if (r >= 0) {
+                r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
+                if (r < 0) {
+                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                        return r;
+                }
+        } else
+                pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.limit: %s, ignoring.", limit);
+
+        return 0;
+}
+
+static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) {
+        uint64_t val;
+        int r;
+
+        if (!isempty(limit)) {
+                r = cg_weight_parse(limit, &val);
+                if (r >= 0) {
+                        r = sd_bus_message_append(m, "(sv)", field, "t", val);
+                        if (r < 0) {
+                                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                                return r;
+                        }
+                } else if (streq(field, "CPUWeight"))
+                        pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight: %s, ignoring.", limit);
+                else
+                        pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight: %s, ignoring.", limit);
+        }
+
+        return 0;
+}
+
 _public_ PAM_EXTERN int pam_sm_open_session(
                 pam_handle_t *handle,
                 int flags,
                 int argc, const char **argv) {
 
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         const char
                 *username, *id, *object_path, *runtime_path,
                 *service = NULL,
@@ -212,7 +293,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                 *remote_user = NULL, *remote_host = NULL,
                 *seat = NULL,
                 *type = NULL, *class = NULL,
-                *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
+                *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL,
+                *memory_max = NULL, *tasks_max = NULL, *cpu_weight = NULL, *io_weight = NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int session_fd = -1, existing, r;
         bool debug = false, remote;
@@ -353,6 +435,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 
         remote = !isempty(remote_host) && !is_localhost(remote_host);
 
+        (void) pam_get_data(handle, "systemd.memory_max", (const void **)&memory_max);
+        (void) pam_get_data(handle, "systemd.tasks_max",  (const void **)&tasks_max);
+        (void) pam_get_data(handle, "systemd.cpu_weight", (const void **)&cpu_weight);
+        (void) pam_get_data(handle, "systemd.io_weight",  (const void **)&io_weight);
+
         /* Talk to logind over the message bus */
 
         r = sd_bus_open_system(&bus);
@@ -361,7 +448,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                 return PAM_SESSION_ERR;
         }
 
-        if (debug)
+        if (debug) {
                 pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
                            "uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
                            pw->pw_uid, getpid_cached(),
@@ -369,29 +456,71 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                            type, class, strempty(desktop),
                            strempty(seat), vtnr, strempty(tty), strempty(display),
                            yes_no(remote), strempty(remote_user), strempty(remote_host));
+                pam_syslog(handle, LOG_DEBUG, "Session limits: "
+                           "memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s",
+                           strna(memory_max), strna(tasks_max), strna(cpu_weight), strna(io_weight));
+        }
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &m,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "CreateSession");
+        if (r < 0) {
+                pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror(-r));
+                return PAM_SESSION_ERR;
+        }
+
+        r = sd_bus_message_append(m, "uusssssussbss",
+                        (uint32_t) pw->pw_uid,
+                        (uint32_t) getpid_cached(),
+                        service,
+                        type,
+                        class,
+                        desktop,
+                        seat,
+                        vtnr,
+                        tty,
+                        display,
+                        remote,
+                        remote_user,
+                        remote_host);
+        if (r < 0) {
+                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                return PAM_SESSION_ERR;
+        }
+
+        r = sd_bus_message_open_container(m, 'a', "(sv)");
+        if (r < 0) {
+                pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror(-r));
+                return PAM_SYSTEM_ERR;
+        }
+
+        r = append_session_memory_max(handle, m, memory_max);
+        if (r < 0)
+                return PAM_SESSION_ERR;
+
+        r = append_session_tasks_max(handle, m, tasks_max);
+        if (r < 0)
+                return PAM_SESSION_ERR;
+
+        r = append_session_cg_weight(handle, m, cpu_weight, "CPUWeight");
+        if (r < 0)
+                return PAM_SESSION_ERR;
+
+        r = append_session_cg_weight(handle, m, io_weight, "IOWeight");
+        if (r < 0)
+                return PAM_SESSION_ERR;
+
+        r = sd_bus_message_close_container(m);
+        if (r < 0) {
+                pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror(-r));
+                return PAM_SYSTEM_ERR;
+        }
 
-        r = sd_bus_call_method(bus,
-                               "org.freedesktop.login1",
-                               "/org/freedesktop/login1",
-                               "org.freedesktop.login1.Manager",
-                               "CreateSession",
-                               &error,
-                               &reply,
-                               "uusssssussbssa(sv)",
-                               (uint32_t) pw->pw_uid,
-                               (uint32_t) getpid_cached(),
-                               service,
-                               type,
-                               class,
-                               desktop,
-                               seat,
-                               vtnr,
-                               tty,
-                               display,
-                               remote,
-                               remote_user,
-                               remote_host,
-                               0);
+        r = sd_bus_call(bus, m, 0, &error, &reply);
         if (r < 0) {
                 if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
                         pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
index 1ed0f9e657816e3348f26e59180194a5381d7ecf..f79617ee06feede36b533341dd67783afbd199c1 100644 (file)
@@ -2638,12 +2638,14 @@ static int set_limit(int argc, char *argv[], void *userdata) {
         uint64_t limit;
         int r;
 
+        polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
         if (STR_IN_SET(argv[argc-1], "-", "none", "infinity"))
                 limit = (uint64_t) -1;
         else {
                 r = parse_size(argv[argc-1], 1024, &limit);
                 if (r < 0)
-                        return log_error("Failed to parse size: %s", argv[argc-1]);
+                        return log_error_errno(r, "Failed to parse size: %s", argv[argc-1]);
         }
 
         if (argc > 2)
@@ -2670,10 +2672,8 @@ static int set_limit(int argc, char *argv[], void *userdata) {
                                 NULL,
                                 "t", limit);
 
-        if (r < 0) {
-                log_error("Could not set limit: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r));
 
         return 0;
 }
@@ -2688,6 +2688,8 @@ static int clean_images(int argc, char *argv[], void *userdata) {
         unsigned c = 0;
         int r;
 
+        polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
         r = sd_bus_message_new_method_call(
                         bus,
                         &m,
@@ -3139,7 +3141,7 @@ int main(int argc, char*argv[]) {
                 goto finish;
         }
 
-        sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
+        (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
 
         r = machinectl_main(argc, argv, bus);
 
index 8fb6db77467bc8c532a6a1c4d27add49c99bcaca..3577c809a4b20868c99eb962502f3873f69105e3 100644 (file)
 #include "signal-util.h"
 #include "special.h"
 
-Manager *manager_new(void) {
-        Manager *m;
+static Manager* manager_unref(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
+
+static int manager_new(Manager **ret) {
+        _cleanup_(manager_unrefp) Manager *m = NULL;
         int r;
 
+        assert(ret);
+
         m = new0(Manager, 1);
         if (!m)
-                return NULL;
+                return -ENOMEM;
 
         m->machines = hashmap_new(&string_hash_ops);
         m->machine_units = hashmap_new(&string_hash_ops);
         m->machine_leaders = hashmap_new(NULL);
 
-        if (!m->machines || !m->machine_units || !m->machine_leaders) {
-                manager_free(m);
-                return NULL;
-        }
+        if (!m->machines || !m->machine_units || !m->machine_leaders)
+                return -ENOMEM;
 
         r = sd_event_default(&m->event);
-        if (r < 0) {
-                manager_free(m);
-                return NULL;
-        }
+        if (r < 0)
+                return r;
+
+        r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+        if (r < 0)
+                return r;
 
-        sd_event_set_watchdog(m->event, true);
+        (void) sd_event_set_watchdog(m->event, true);
 
-        return m;
+        *ret = TAKE_PTR(m);
+        return 0;
 }
 
-void manager_free(Manager *m) {
+static Manager* manager_unref(Manager *m) {
         Machine *machine;
 
         assert(m);
@@ -80,7 +90,7 @@ void manager_free(Manager *m) {
         sd_bus_unref(m->bus);
         sd_event_unref(m->event);
 
-        free(m);
+        return mfree(m);
 }
 
 static int manager_add_host_machine(Manager *m) {
@@ -121,7 +131,7 @@ static int manager_add_host_machine(Manager *m) {
         return 0;
 }
 
-int manager_enumerate_machines(Manager *m) {
+static int manager_enumerate_machines(Manager *m) {
         _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
         int r = 0;
@@ -268,7 +278,7 @@ static int manager_connect_bus(Manager *m) {
         return 0;
 }
 
-void manager_gc(Manager *m, bool drop_not_started) {
+static void manager_gc(Manager *m, bool drop_not_started) {
         Machine *machine;
 
         assert(m);
@@ -292,7 +302,7 @@ void manager_gc(Manager *m, bool drop_not_started) {
         }
 }
 
-int manager_startup(Manager *m) {
+static int manager_startup(Manager *m) {
         Machine *machine;
         Iterator i;
         int r;
@@ -328,7 +338,7 @@ static bool check_idle(void *userdata) {
         return hashmap_isempty(m->machines);
 }
 
-int manager_run(Manager *m) {
+static int manager_run(Manager *m) {
         assert(m);
 
         return bus_event_loop_with_idle(
@@ -340,7 +350,7 @@ int manager_run(Manager *m) {
 }
 
 int main(int argc, char *argv[]) {
-        Manager *m = NULL;
+        _cleanup_(manager_unrefp) Manager *m = NULL;
         int r;
 
         log_set_target(LOG_TARGET_AUTO);
@@ -356,18 +366,16 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        /* Always create the directories people can create inotify
-         * watches in. Note that some applications might check for the
-         * existence of /run/systemd/machines/ to determine whether
-         * machined is available, so please always make sure this
-         * check stays in. */
-        mkdir_label("/run/systemd/machines", 0755);
+        /* Always create the directories people can create inotify watches in. Note that some applications might check
+         * for the existence of /run/systemd/machines/ to determine whether machined is available, so please always
+         * make sure this check stays in. */
+        (void) mkdir_label("/run/systemd/machines", 0755);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0);
 
-        m = manager_new();
-        if (!m) {
-                r = log_oom();
+        r = manager_new(&m);
+        if (r < 0) {
+                log_error_errno(r, "Failed to allocate manager object: %m");
                 goto finish;
         }
 
@@ -388,7 +396,5 @@ int main(int argc, char *argv[]) {
         log_debug("systemd-machined stopped as pid "PID_FMT, getpid_cached());
 
 finish:
-        manager_free(m);
-
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
index 2e6fe4c1877df0bd15a8b70b17ab081bd29c2310..2f204f0549093cd447caec3be1bfe343e9fe3496 100644 (file)
@@ -43,17 +43,7 @@ struct Manager {
         unsigned n_operations;
 };
 
-Manager *manager_new(void);
-void manager_free(Manager *m);
-
 int manager_add_machine(Manager *m, const char *name, Machine **_machine);
-int manager_enumerate_machines(Manager *m);
-
-int manager_startup(Manager *m);
-int manager_run(Manager *m);
-
-void manager_gc(Manager *m, bool drop_not_started);
-
 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine);
 
 extern const sd_bus_vtable manager_vtable[];
index acd0e68a61ebe31e6c0df3a3633b4f6a01d8df77..6bab7647d67b7ee96aa0e16d993be5d387f3b1d7 100644 (file)
@@ -319,6 +319,11 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
 
         link_set_dhcp_routes(link);
 
+        if (link->dhcp4_messages == 0) {
+                link->dhcp4_configured = true;
+                link_check_ready(link);
+        }
+
         return 1;
 }
 
index 2a231c2eaec2999decfe6b15c467d4c8a96a4f82..c921f92d148cd67d93fa9dc95964498ae4ba642e 100644 (file)
@@ -2970,7 +2970,7 @@ network_file_fail:
                         goto dhcp4_address_fail;
                 }
 
-                r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
+                r = sd_dhcp_client_new(&link->dhcp_client, link->network ? link->network->dhcp_anonymize : 0);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m");
 
index 88252020046bf3884661e1f5fd7213bf8aa8c36c..0d85ba6e727db8f333c2f45fad46144db3aa2f9d 100644 (file)
@@ -131,7 +131,7 @@ int manager_connect_bus(Manager *m) {
         if (m->bus)
                 return 0;
 
-        r = bus_open_system_watch_bind(&m->bus);
+        r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-network");
         if (r < 0)
                 return log_error_errno(r, "Failed to connect to bus: %m");
 
@@ -1484,7 +1484,6 @@ void manager_free(Manager *m) {
         sd_bus_unref(m->bus);
         sd_bus_slot_unref(m->prepare_for_sleep_slot);
         sd_bus_slot_unref(m->connected_slot);
-        sd_event_source_unref(m->bus_retry_event_source);
 
         free(m->dynamic_timezone);
         free(m->dynamic_hostname);
index b59f62bc846ca88e8e274e2b9eef2abca9abc03c..b1d6585df2c0f1e19c577183c2dc0552b5a084ef 100644 (file)
@@ -31,7 +31,6 @@ struct Manager {
         sd_netlink *genl;
         sd_event *event;
         sd_resolve *resolve;
-        sd_event_source *bus_retry_event_source;
         sd_bus *bus;
         sd_bus_slot *prepare_for_sleep_slot;
         sd_bus_slot *connected_slot;
index 16a12875a8da689180458191aa94baeb0dc9350c..52758457501a160b2541ccd5375e072b7e267b53 100644 (file)
@@ -54,6 +54,7 @@ static const char* const path_table[_SD_PATH_MAX] = {
         [SD_PATH_USER_TEMPLATES] = "user-templates",
         [SD_PATH_USER_DESKTOP] = "user-desktop",
         [SD_PATH_SEARCH_BINARIES] = "search-binaries",
+        [SD_PATH_SEARCH_BINARIES_DEFAULT] = "search-binaries-default",
         [SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private",
         [SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch",
         [SD_PATH_SEARCH_SHARED] = "search-shared",
index 3845eafaa3b3f9fa6f5d551bcac2bfd24210be58..fda43b84cfe37b406a57eeac1b091f78d8bd544b 100644 (file)
@@ -1883,7 +1883,7 @@ int manager_connect_bus(Manager *m) {
         if (m->bus)
                 return 0;
 
-        r = bus_open_system_watch_bind(&m->bus);
+        r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve");
         if (r < 0)
                 return log_error_errno(r, "Failed to connect to system bus: %m");
 
index 4c0d391ba5955b63c6bc05b12498e443264c03da..c17622a074e661aa128be95ac5a4f0c80c508829 100644 (file)
@@ -688,7 +688,6 @@ Manager *manager_free(Manager *m) {
         manager_dns_stub_stop(m);
 
         sd_bus_slot_unref(m->prepare_for_sleep_slot);
-        sd_event_source_unref(m->bus_retry_event_source);
         sd_bus_unref(m->bus);
 
         sd_event_source_unref(m->sigusr1_event_source);
index 8bdff5cb4bd73c83bdab02eff6df113e81310c1d..372d43c1a51ccc62a13b5885f734a0480ec82006 100644 (file)
@@ -97,7 +97,6 @@ struct Manager {
 
         /* dbus */
         sd_bus *bus;
-        sd_event_source *bus_retry_event_source;
 
         /* The hostname we publish on LLMNR and mDNS */
         char *full_hostname;
index 10f047026e55332e8d30097c85cc06bd798adad0..a14e87d1ba16af917ac7f3583d320adaa41adec5 100644 (file)
@@ -1657,7 +1657,7 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
         return r;
 }
 
-int bus_open_system_watch_bind(sd_bus **ret) {
+int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         const char *e;
         int r;
@@ -1670,6 +1670,12 @@ int bus_open_system_watch_bind(sd_bus **ret) {
         if (r < 0)
                 return r;
 
+        if (description) {
+                r = sd_bus_set_description(bus, description);
+                if (r < 0)
+                        return r;
+        }
+
         e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
         if (!e)
                 e = DEFAULT_SYSTEM_BUS_ADDRESS;
index 668c7cc982c5ec66c692f38c82e839619da5b3fa..d03d0f82d9562a20c238ed27478a74b12376d5a3 100644 (file)
@@ -159,4 +159,7 @@ int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface
 
 int bus_track_add_name_many(sd_bus_track *t, char **l);
 
-int bus_open_system_watch_bind(sd_bus **ret);
+int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description);
+static inline int bus_open_system_watch_bind(sd_bus **ret) {
+        return bus_open_system_watch_bind_with_description(ret, NULL);
+}
index ea72c1281cfab4bee20b614335eba366c8a6a13c..c4316ea473949dbe93635ba073a48c221f4fb515 100644 (file)
 int polkit_agent_open(void);
 void polkit_agent_close(void);
 
-static inline void polkit_agent_open_if_enabled(
+static inline int polkit_agent_open_if_enabled(
                 BusTransport transport,
                 bool ask_password) {
 
         /* Open the polkit agent as a child process if necessary */
 
         if (transport != BUS_TRANSPORT_LOCAL)
-                return;
+                return 0;
 
         if (!ask_password)
-                return;
+                return 0;
 
-        polkit_agent_open();
+        return polkit_agent_open();
 }
index 2dfc8967b4bf8218426ce462001a58ee0a9f6b24..19f48b73ebb41e97aaf2d134925ca9e51d922fc6 100644 (file)
@@ -74,6 +74,7 @@ enum {
 
         /* Search paths */
         SD_PATH_SEARCH_BINARIES,
+        SD_PATH_SEARCH_BINARIES_DEFAULT,
         SD_PATH_SEARCH_LIBRARY_PRIVATE,
         SD_PATH_SEARCH_LIBRARY_ARCH,
         SD_PATH_SEARCH_SHARED,
index c138481df81171e7b5e6dbb86c789364ed26988b..61bb23ef7e250f41e81581c084d50c10b854f39d 100644 (file)
@@ -553,7 +553,8 @@ tests += [
           libseccomp,
           libselinux,
           libmount,
-          libblkid]],
+          libblkid],
+         '', 'timeout=360'],
 
         [['src/test/test-siphash24.c'],
          [],
index 1e59bb02bb322d1d57f28ee2f4e6dd424bccaaec..90e2cc8edbeceb7b3438f60f32907ec7e30e6ab2 100644 (file)
@@ -53,16 +53,11 @@ static int test_cgroup_mask(void) {
         assert_se(manager_startup(m, serial, fdset) >= 0);
 
         /* Load units and verify hierarchy. */
-        assert_se(manager_load_unit(m, "parent.slice", NULL, NULL, &parent) >= 0);
-        assert_se(manager_load_unit(m, "son.service", NULL, NULL, &son) >= 0);
-        assert_se(manager_load_unit(m, "daughter.service", NULL, NULL, &daughter) >= 0);
-        assert_se(manager_load_unit(m, "grandchild.service", NULL, NULL, &grandchild) >= 0);
-        assert_se(manager_load_unit(m, "parent-deep.slice", NULL, NULL, &parent_deep) >= 0);
-        assert_se(parent->load_state == UNIT_LOADED);
-        assert_se(son->load_state == UNIT_LOADED);
-        assert_se(daughter->load_state == UNIT_LOADED);
-        assert_se(grandchild->load_state == UNIT_LOADED);
-        assert_se(parent_deep->load_state == UNIT_LOADED);
+        assert_se(manager_load_startable_unit_or_warn(m, "parent.slice", NULL, &parent) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "son.service", NULL, &son) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "daughter.service", NULL, &daughter) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "grandchild.service", NULL, &grandchild) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "parent-deep.slice", NULL, &parent_deep) >= 0);
         assert_se(UNIT_DEREF(son->slice) == parent);
         assert_se(UNIT_DEREF(daughter->slice) == parent);
         assert_se(UNIT_DEREF(parent_deep->slice) == parent);
index 1c12a8644d01d3e86001e568eecbcdcad936db0e..6d3b0a162768eecc9b7c0327bdae93a8c66af4b3 100644 (file)
@@ -47,9 +47,9 @@ int main(int argc, char *argv[]) {
         assert_se(manager_startup(m, serial, fdset) >= 0);
 
         printf("Load1:\n");
-        assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);
-        assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0);
-        assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "a.service", NULL, &a) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "b.service", NULL, &b) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "c.service", NULL, &c) >= 0);
         manager_dump_units(m, stdout, "\t");
 
         printf("Test1: (Trivial)\n");
@@ -61,8 +61,8 @@ int main(int argc, char *argv[]) {
 
         printf("Load2:\n");
         manager_clear_jobs(m);
-        assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0);
-        assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "d.service", NULL, &d) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "e.service", NULL, &e) >= 0);
         manager_dump_units(m, stdout, "\t");
 
         printf("Test2: (Cyclic Order, Unfixable)\n");
@@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
         manager_dump_jobs(m, stdout, "\t");
 
         printf("Load3:\n");
-        assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "g.service", NULL, &g) >= 0);
         manager_dump_units(m, stdout, "\t");
 
         printf("Test5: (Colliding transaction, fail)\n");
@@ -100,7 +100,7 @@ int main(int argc, char *argv[]) {
         manager_dump_jobs(m, stdout, "\t");
 
         printf("Load4:\n");
-        assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "h.service", NULL, &h) >= 0);
         manager_dump_units(m, stdout, "\t");
 
         printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
index 0bb2b85918786817037b9b888b7276e9f652dd00..59d996c11b1cbd5159cb78b4e97cf087cac49c56 100644 (file)
@@ -132,7 +132,7 @@ static void test(Manager *m, const char *unit_name, int status_expected, int cod
 
         assert_se(unit_name);
 
-        assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
         check(m, unit, status_expected, code_expected);
 }
@@ -536,6 +536,10 @@ static void test_exec_capabilityboundingset(Manager *m) {
         test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
 }
 
+static void test_exec_basic(Manager *m) {
+        test(m, "exec-basic.service", 0, CLD_EXITED);
+}
+
 static void test_exec_ambientcapabilities(Manager *m) {
         int r;
 
@@ -635,6 +639,7 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
 int main(int argc, char *argv[]) {
         _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
         static const test_function_t user_tests[] = {
+                test_exec_basic,
                 test_exec_ambientcapabilities,
                 test_exec_bindpaths,
                 test_exec_capabilityboundingset,
index 1fd1a75990562e2adeb1ee3174f48d39afe2f8e1..3d990407b38e781390e851739497942e99987132 100644 (file)
@@ -121,7 +121,7 @@ static void test_path_exists(Manager *m) {
 
         assert_se(m);
 
-        assert_se(manager_load_unit(m, "path-exists.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         assert_se(touch(test_path) >= 0);
@@ -134,7 +134,7 @@ static void test_path_existsglob(Manager *m) {
         Unit *unit = NULL;
 
         assert_se(m);
-        assert_se(manager_load_unit(m, "path-existsglob.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         assert_se(touch(test_path) >= 0);
@@ -151,7 +151,7 @@ static void test_path_changed(Manager *m) {
 
         assert_se(touch(test_path) >= 0);
 
-        assert_se(manager_load_unit(m, "path-changed.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         f = fopen(test_path, "w");
@@ -170,7 +170,7 @@ static void test_path_modified(Manager *m) {
 
         assert_se(touch(test_path) >= 0);
 
-        assert_se(manager_load_unit(m, "path-modified.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         f = fopen(test_path, "w");
@@ -186,7 +186,7 @@ static void test_path_unit(Manager *m) {
 
         assert_se(m);
 
-        assert_se(manager_load_unit(m, "path-unit.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         assert_se(touch(test_path) >= 0);
@@ -202,7 +202,7 @@ static void test_path_directorynotempty(Manager *m) {
 
         assert_se(access(test_path, F_OK) < 0);
 
-        assert_se(manager_load_unit(m, "path-directorynotempty.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         /* MakeDirectory default to no */
@@ -223,7 +223,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
 
         assert_se(access(test_path, F_OK) < 0);
 
-        assert_se(manager_load_unit(m, "path-makedirectory.path", NULL, NULL, &unit) >= 0);
+        assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0);
         assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
 
         /* Check if the directory has been created */
index cede70b0536b5a4df93eb7262e140170900c7c19..7d8fc445ec085087b5d3250b78e00265de96f546 100644 (file)
@@ -40,8 +40,7 @@ int main(int argc, char *argv[]) {
         assert_se(manager_startup(m, serial, fdset) >= 0);
 
         /* load idle ok */
-        assert_se(manager_load_unit(m, "sched_idle_ok.service", NULL, NULL, &idle_ok) >= 0);
-        assert_se(idle_ok->load_state == UNIT_LOADED);
+        assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_ok.service", NULL, &idle_ok) >= 0);
         ser = SERVICE(idle_ok);
         assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER);
         assert_se(ser->exec_context.cpu_sched_priority == 0);
@@ -49,8 +48,7 @@ int main(int argc, char *argv[]) {
         /*
          * load idle bad. This should print a warning but we have no way to look at it.
          */
-        assert_se(manager_load_unit(m, "sched_idle_bad.service", NULL, NULL, &idle_bad) >= 0);
-        assert_se(idle_bad->load_state == UNIT_LOADED);
+        assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_bad.service", NULL, &idle_bad) >= 0);
         ser = SERVICE(idle_ok);
         assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER);
         assert_se(ser->exec_context.cpu_sched_priority == 0);
@@ -59,8 +57,7 @@ int main(int argc, char *argv[]) {
          * load rr ok.
          * Test that the default priority is moving from 0 to 1.
          */
-        assert_se(manager_load_unit(m, "sched_rr_ok.service", NULL, NULL, &rr_ok) >= 0);
-        assert_se(rr_ok->load_state == UNIT_LOADED);
+        assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_ok.service", NULL, &rr_ok) >= 0);
         ser = SERVICE(rr_ok);
         assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
         assert_se(ser->exec_context.cpu_sched_priority == 1);
@@ -69,8 +66,7 @@ int main(int argc, char *argv[]) {
          * load rr bad.
          * Test that the value of 0 and 100 is ignored.
          */
-        assert_se(manager_load_unit(m, "sched_rr_bad.service", NULL, NULL, &rr_bad) >= 0);
-        assert_se(rr_bad->load_state == UNIT_LOADED);
+        assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_bad.service", NULL, &rr_bad) >= 0);
         ser = SERVICE(rr_bad);
         assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
         assert_se(ser->exec_context.cpu_sched_priority == 1);
@@ -79,8 +75,7 @@ int main(int argc, char *argv[]) {
          * load rr change.
          * Test that anything between 1 and 99 can be set.
          */
-        assert_se(manager_load_unit(m, "sched_rr_change.service", NULL, NULL, &rr_sched) >= 0);
-        assert_se(rr_sched->load_state == UNIT_LOADED);
+        assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_change.service", NULL, &rr_sched) >= 0);
         ser = SERVICE(rr_sched);
         assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
         assert_se(ser->exec_context.cpu_sched_priority == 99);
index 9b558532ce8eff327747e350f25f553d95fc19f5..198c0556505c47a695d7035ad89aff734904c4f0 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/inotify.h>
 #include <sys/timerfd.h>
 #include <sys/timex.h>
 #include <unistd.h>
 #include "sd-event.h"
 
 #include "fd-util.h"
+#include "fs-util.h"
 #include "missing.h"
 #include "signal-util.h"
 #include "time-util.h"
 
 typedef struct ClockState {
-        int fd;                        /* non-negative is descriptor from timerfd_create */
-        int adjtime_state;             /* return value from last adjtimex(2) call */
-        sd_event_source *event_source; /* non-null is the active io event source */
+        int timerfd_fd;                  /* non-negative is descriptor from timerfd_create */
+        int adjtime_state;               /* return value from last adjtimex(2) call */
+        sd_event_source *timerfd_event_source; /* non-null is the active io event source */
+        int inotify_fd;
+        sd_event_source *inotify_event_source;
+        int run_systemd_wd;
+        int run_systemd_timesync_wd;
+        bool has_watchfile;
 } ClockState;
 
+static void clock_state_release_timerfd(ClockState *sp) {
+        sp->timerfd_event_source = sd_event_source_unref(sp->timerfd_event_source);
+        sp->timerfd_fd = safe_close(sp->timerfd_fd);
+}
+
 static void clock_state_release(ClockState *sp) {
-        sp->event_source = sd_event_source_unref(sp->event_source);
-        sp->fd = safe_close(sp->fd);
+        clock_state_release_timerfd(sp);
+        sp->inotify_event_source = sd_event_source_unref(sp->inotify_event_source);
+        sp->inotify_fd = safe_close(sp->inotify_fd);
 }
 
 static int clock_state_update(ClockState *sp, sd_event *event);
 
-static int io_handler(sd_event_source * s,
-                      int fd,
-                      uint32_t revents,
-                      void *userdata) {
+static int update_notify_run_systemd_timesync(ClockState *sp) {
+        sp->run_systemd_timesync_wd = inotify_add_watch(sp->inotify_fd, "/run/systemd/timesync", IN_CREATE|IN_DELETE_SELF);
+        return sp->run_systemd_timesync_wd;
+}
+
+static int timerfd_handler(sd_event_source *s,
+                           int fd,
+                           uint32_t revents,
+                           void *userdata) {
         ClockState *sp = userdata;
 
         return clock_state_update(sp, sd_event_source_get_event(s));
 }
 
+static void process_inotify_event(sd_event *event, ClockState *sp, struct inotify_event *e) {
+        if (e->wd == sp->run_systemd_wd) {
+                /* Only thing we care about is seeing if we can start watching /run/systemd/timesync. */
+                if (sp->run_systemd_timesync_wd < 0)
+                        update_notify_run_systemd_timesync(sp);
+        } else if (e->wd == sp->run_systemd_timesync_wd) {
+                if (e->mask & IN_DELETE_SELF) {
+                        /* Somebody removed /run/systemd/timesync. */
+                        (void) inotify_rm_watch(sp->inotify_fd, sp->run_systemd_timesync_wd);
+                        sp->run_systemd_timesync_wd = -1;
+                } else
+                        /* Somebody might have created /run/systemd/timesync/synchronized. */
+                        clock_state_update(sp, event);
+        }
+}
+
+static int inotify_handler(sd_event_source *s,
+                           int fd,
+                           uint32_t revents,
+                           void *userdata) {
+        sd_event *event = sd_event_source_get_event(s);
+        ClockState *sp = userdata;
+        union inotify_event_buffer buffer;
+        struct inotify_event *e;
+        ssize_t l;
+
+        l = read(fd, &buffer, sizeof(buffer));
+        if (l < 0) {
+                if (IN_SET(errno, EAGAIN, EINTR))
+                        return 0;
+
+                return log_warning_errno(errno, "Lost access to inotify: %m");
+        }
+        FOREACH_INOTIFY_EVENT(e, buffer, l)
+                process_inotify_event(event, sp, e);
+
+        return 0;
+}
+
 static int clock_state_update(ClockState *sp,
                               sd_event *event) {
         static const struct itimerspec its = {
@@ -69,34 +126,39 @@ static int clock_state_update(ClockState *sp,
         usec_t t;
         const char * ts;
 
-        clock_state_release(sp);
+        clock_state_release_timerfd(sp);
 
         /* The kernel supports cancelling timers whenever its realtime clock is "set" (which can happen in a variety of
-         * ways, generally adjustments of at least 500 ms). The way this module works is we set up a timer that will
+         * ways, generally adjustments of at least 500 ms). The way this module works is we set up a timerfd that will
          * wake when the clock is set, and when that happens we read the clock synchronization state from the return
          * value of adjtimex(2), which supports the NTP time adjustment protocol.
          *
          * The kernel determines whether the clock is synchronized using driver-specific tests, based on time
-         * information passed by an application, generally through adjtimex(2). If the application asserts the clock
-         * is synchronized, but does not also do something that "sets the clock", the timer will not be cancelled and
-         * synchronization will not be detected. Should this behavior be observed with a time synchronization provider
-         * this code might be reworked to do a periodic check as well.
+         * information passed by an application, generally through adjtimex(2). If the application asserts the clock is
+         * synchronized, but does not also do something that "sets the clock", the timer will not be cancelled and
+         * synchronization will not be detected.
          *
          * Similarly, this service will never complete if the application sets the time without also providing
-         * information that adjtimex(2) can use to determine that the clock is synchronized.
+         * information that adjtimex(2) can use to determine that the clock is synchronized. This generally doesn't
+         * happen, but can if the system has a hardware clock that is accurate enough that the adjustment is too small
+         * to be a "set".
+         *
+         * Both these failure-to-detect situations are covered by having the presence/creation of
+         * /run/systemd/timesync/synchronized, which is considered sufficient to indicate a synchronized clock even if
+         * the kernel has not been updated.
          *
-         * Well-behaved implementations including systemd-timesyncd should not produce either situation. For timesyncd
-         * the initial setting of the time uses settimeofday(2), which sets the clock but does not mark it
-         * synchronized. When an NTP source is selected it sets the clock again with clock_adjtime(2) which does mark
-         * it synchronized. */
+         * For timesyncd the initial setting of the time uses settimeofday(2), which sets the clock but does not mark
+         * it synchronized. When an NTP source is selected it sets the clock again with clock_adjtime(2) which marks it
+         * synchronized and also touches /run/systemd/timesync/synchronized which covers the case when the clock wasn't
+         * "set". */
         r = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
         if (r < 0) {
                 log_error_errno(errno, "Failed to create timerfd: %m");
                 goto finish;
         }
-        sp->fd = r;
+        sp->timerfd_fd = r;
 
-        r = timerfd_settime(sp->fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &its, NULL);
+        r = timerfd_settime(sp->timerfd_fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &its, NULL);
         if (r < 0) {
                 log_error_errno(errno, "Failed to set timerfd conditions: %m");
                 goto finish;
@@ -117,24 +179,26 @@ static int clock_state_update(ClockState *sp,
                 strcpy(buf, "unrepresentable");
         log_info("adjtime state %d status %x time %s", sp->adjtime_state, tx.status, ts);
 
-        if (sp->adjtime_state == TIME_ERROR) {
-                /* Not synchronized. Do a one-shot wait on the descriptor and inform the caller we need to keep
+        sp->has_watchfile = access("/run/systemd/timesync/synchronized", F_OK) >= 0;
+        if (sp->has_watchfile)
+                /* Presence of watch file overrides adjtime_state */
+                r = 0;
+        else if (sp->adjtime_state == TIME_ERROR) {
+                /* Not synchronized.  Do a one-shot wait on the descriptor and inform the caller we need to keep
                  * running. */
-                r = sd_event_add_io(event, &sp->event_source, sp->fd,
-                                    EPOLLIN, io_handler, sp);
+                r = sd_event_add_io(event, &sp->timerfd_event_source, sp->timerfd_fd,
+                                    EPOLLIN, timerfd_handler, sp);
                 if (r < 0) {
                         log_error_errno(r, "Failed to create time change monitor source: %m");
                         goto finish;
                 }
                 r = 1;
-        } else {
+        } else
                 /* Synchronized; we can exit. */
-                (void) sd_event_exit(event, 0);
                 r = 0;
-        }
 
  finish:
-        if (r < 0)
+        if (r <= 0)
                 (void) sd_event_exit(event, r);
         return r;
 }
@@ -143,7 +207,10 @@ int main(int argc, char * argv[]) {
         int r;
         _cleanup_(sd_event_unrefp) sd_event *event;
         ClockState state = {
-                .fd = -1,
+                .timerfd_fd = -1,
+                .inotify_fd = -1,
+                .run_systemd_wd = -1,
+                .run_systemd_timesync_wd = -1,
         };
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
@@ -172,17 +239,42 @@ int main(int argc, char * argv[]) {
                 goto finish;
         }
 
+        r = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
+        if (r < 0) {
+                log_error_errno(errno, "Failed to create inotify descriptor: %m");
+                goto finish;
+        }
+        state.inotify_fd = r;
+
+        r = sd_event_add_io(event, &state.inotify_event_source, state.inotify_fd,
+                            EPOLLIN, inotify_handler, &state);
+        if (r < 0) {
+                log_error_errno(r, "Failed to create notify event source: %m");
+                goto finish;
+        }
+
+        r = inotify_add_watch(state.inotify_fd, "/run/systemd/", IN_CREATE);
+        if (r < 0) {
+                log_error_errno(errno, "Failed to watch /run/systemd/: %m");
+                goto finish;
+        }
+        state.run_systemd_wd = r;
+
+        (void) update_notify_run_systemd_timesync(&state);
+
         r = clock_state_update(&state, event);
         if (r > 0) {
                 r = sd_event_loop(event);
                 if (r < 0)
                         log_error_errno(r, "Failed in event loop: %m");
-                else if (state.adjtime_state == TIME_ERROR) {
-                        log_error("Event loop terminated without synchronizing");
-                        r = -ECANCELED;
-                }
         }
 
+        if (state.has_watchfile)
+                log_debug("Exit enabled by: /run/systemd/timesync/synchonized");
+
+        if (state.adjtime_state == TIME_ERROR)
+                log_info("Exit without adjtimex synchronized.");
+
  finish:
         clock_state_release(&state);
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
index cfdc43b0ff2106b80dfcb9bc3cc6a2489429f1f8..c5721a57523e295e1d60c69550b9c67945656553 100644 (file)
@@ -355,6 +355,7 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
 
         /* If touch fails, there isn't much we can do. Maybe it'll work next time. */
         (void) touch("/var/lib/systemd/timesync/clock");
+        (void) touch("/run/systemd/timesync/synchronized");
 
         m->drift_ppm = tmx.freq / 65536;
 
@@ -1036,6 +1037,12 @@ clear:
         return r;
 }
 
+static bool manager_is_connected(Manager *m) {
+        /* Return true when the manager is sending a request, resolving a server name, or
+         * in a poll interval. */
+        return m->server_socket >= 0 || m->resolve_query || m->event_timer;
+}
+
 static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         Manager *m = userdata;
         bool changed, connected, online;
@@ -1051,13 +1058,13 @@ static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t re
         online = network_is_online();
 
         /* check if the client is currently connected */
-        connected = m->server_socket >= 0 || m->resolve_query || m->exhausted_servers;
+        connected = manager_is_connected(m);
 
         if (connected && !online) {
                 log_info("No network connectivity, watching for changes.");
                 manager_disconnect(m);
 
-        } else if (!connected && online && changed) {
+        } else if ((!connected || changed) && online) {
                 log_info("Network configuration changed, trying to establish connection.");
 
                 if (m->current_server_address)
index c112e09577308cd3f572d2cb5ce63e33eebb8236..c65e7e4538b328b1b5f7d63e07265061310b1d54 100644 (file)
@@ -32,6 +32,7 @@ test_data_files = '''
         sockets.target
         son.service
         sysinit.target
+        test-execute/exec-basic.service
         test-execute/exec-ambientcapabilities-merge-nfsnobody.service
         test-execute/exec-ambientcapabilities-merge-nobody.service
         test-execute/exec-ambientcapabilities-merge.service
diff --git a/test/test-execute/exec-basic.service b/test/test-execute/exec-basic.service
new file mode 100644 (file)
index 0000000..456f069
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=Test for basic execution
+
+[Service]
+ExecStart=touch /tmp/a ; /bin/touch /tmp/b ; touch /tmp/c
+ExecStart=test -f /tmp/a
+ExecStart=!test -f /tmp/b
+ExecStart=!!test -f /tmp/c
+ExecStart=+test -f /tmp/c
+ExecStartPost=rm /tmp/a /tmp/b /tmp/c
+
+PrivateTmp=true
+Type=oneshot
index 7bd8fa7402e425c0611db75f0d273bb76a80d631..edab18bb0fe7255710755dba623c999c9237bb43 100644 (file)
@@ -4,14 +4,14 @@ Description=Test for BindPaths= and BindReadOnlyPaths=
 [Service]
 Type=oneshot
 # Create a file in /tmp/test-exec-bindpaths
-ExecStart=/bin/sh -c 'touch /tmp/test-exec-bindpaths/thisisasimpletest'
+ExecStart=touch /tmp/test-exec-bindpaths/thisisasimpletest
 # Then, the file can be access through /tmp
-ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest'
+ExecStart=test -f /tmp/thisisasimpletest
 # Also, through /tmp/test-exec-bindreadonlypaths
-ExecStart=/bin/sh -c 'test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest'
+ExecStart=test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest
 # The file cannot modify through /tmp/test-exec-bindreadonlypaths
 ExecStart=/bin/sh -x -c '! touch /tmp/test-exec-bindreadonlypaths/thisisasimpletest'
 # Cleanup
-ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest'
+ExecStart=rm /tmp/thisisasimpletest
 BindPaths=/tmp:/tmp/test-exec-bindpaths
 BindReadOnlyPaths=/tmp:/tmp/test-exec-bindreadonlypaths
index 83bdfb311a3bb89782f12e0ff61ed33837fdd9c1..72e6d7686fc794ef7df2616a1b5d51b960823ef5 100644 (file)
@@ -2,14 +2,14 @@
 Description=Test DynamicUser= migrate StateDirectory= (preparation)
 
 [Service]
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test ! -L /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test ! -L /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay'
+ExecStart=test -w /var/lib/test-dynamicuser-migrate
+ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test ! -L /var/lib/test-dynamicuser-migrate
+ExecStart=test ! -L /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -d /var/lib/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
 
 Type=oneshot
 DynamicUser=no
index 8154922a2f19d1767614e1ac3560b708878451fe..5a61228c9f715fe812a30da92fa954e6a456ceeb 100644 (file)
@@ -2,22 +2,22 @@
 Description=Test DynamicUser= migrate StateDirectory= (preparation)
 
 [Service]
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -L /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -L /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -f /var/lib/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay'
-ExecStart=/bin/sh -c 'test -d /var/lib/private/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -d /var/lib/private/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay'
-ExecStart=/bin/sh -c 'touch /var/lib/private/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay'
+ExecStart=test -w /var/lib/test-dynamicuser-migrate
+ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -L /var/lib/test-dynamicuser-migrate
+ExecStart=test -L /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -d /var/lib/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -f /var/lib/test-dynamicuser-migrate/yay
+ExecStart=test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=test -d /var/lib/private/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/private/test-dynamicuser-migrate2/hoge
+ExecStart=test -f /var/lib/private/test-dynamicuser-migrate/yay
+ExecStart=test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
 
 Type=oneshot
 DynamicUser=yes
index 5ea6d9da425c277927c11d1bd478993e830b6d0b..f459f3c1eb9a7af7866b98f455eeb0ad410e3d9a 100644 (file)
@@ -2,17 +2,17 @@
 Description=Test DynamicUser= with StateDirectory=
 
 [Service]
-ExecStart=/bin/sh -c 'test -w /var/lib/waldo'
-ExecStart=/bin/sh -c 'test -w /var/lib/quux/pief'
-ExecStart=/bin/sh -c 'touch /var/lib/waldo/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/quux/pief/yayyay'
-ExecStart=/bin/sh -c 'test -f /var/lib/waldo/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/quux/pief/yayyay'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/waldo/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/quux/pief/yayyay'
+ExecStart=test -w /var/lib/waldo
+ExecStart=test -w /var/lib/quux/pief
+ExecStart=touch /var/lib/waldo/yay
+ExecStart=touch /var/lib/quux/pief/yayyay
+ExecStart=test -f /var/lib/waldo/yay
+ExecStart=test -f /var/lib/quux/pief/yayyay
+ExecStart=test -f /var/lib/private/waldo/yay
+ExecStart=test -f /var/lib/private/quux/pief/yayyay
 
 # Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates
-ExecStart=/bin/sh -x -c 'test $$(find / -type d -writable 2> /dev/null | egrep -v -e \'^(/var/tmp$$|/tmp$$|/proc/|/dev/mqueue$$|/dev/shm$$|/sys/fs/bpf$$)\' | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo'
+ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo'
 
 Type=oneshot
 DynamicUser=yes
index ab909cbd942049ac822acac6592fd02f2c33f7e7..7756a2575e5b186ebca76a0be5c4ab09c6eff216 100644 (file)
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=~mnt
 
 [Service]
 RestrictNamespaces=~mnt
-ExecStart=/bin/sh -x -c 'unshare -m'
+ExecStart=unshare -m
 Type=oneshot
index 1aeed7271714d0181c3e5e3a66553c488e1a58c1..2c5b942601c972eb3dfe3fecd3707070c9af4b16 100644 (file)
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=mnt
 
 [Service]
 RestrictNamespaces=mnt
-ExecStart=/bin/sh -x -c 'unshare -m'
+ExecStart=unshare -m
 Type=oneshot
index 33500302d2b7f806a82c0d1c35a4706de42fac4e..5ffe081e45b70e9a0f9cacbd8b5a90777cefd66d 100644 (file)
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=no
 
 [Service]
 RestrictNamespaces=no
-ExecStart=/bin/sh -x -c 'unshare -m -u -i -n -p -f'
+ExecStart=unshare -m -u -i -n -p -f
 Type=oneshot
index 3fe70e2bea245182b9e15c12646b396bbe359781..8e077ed3a0f8a7438cd343acf0f63f4c42a14fa0 100644 (file)
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=yes
 
 [Service]
 RestrictNamespaces=yes
-ExecStart=/bin/sh -x -c 'unshare -m'
+ExecStart=unshare -m
 Type=oneshot
index 37852390ac27bd231870ee3b9474d33ea38e3873..65a64bc95ed4a9bf300902402273cc620e9d4d3c 100644 (file)
@@ -3,22 +3,22 @@ Description=Test for specifiers
 
 [Service]
 Type=oneshot
-ExecStart=/usr/bin/test %n = exec-specifier.service
-ExecStart=/usr/bin/test %N = exec-specifier
-ExecStart=/usr/bin/test %p = exec-specifier
-ExecStart=/usr/bin/test %P = exec/specifier
-ExecStart=/usr/bin/test %i = ""
-ExecStart=/usr/bin/test %I = ""
-ExecStart=/usr/bin/test %f = /exec/specifier
-ExecStart=/usr/bin/test %t = /run
-ExecStart=/usr/bin/test %S = /var/lib
-ExecStart=/usr/bin/test %C = /var/cache
-ExecStart=/usr/bin/test %L = /var/log
-ExecStart=/bin/sh -c 'test %u = $$(id -un 0)'
-ExecStart=/usr/bin/test %U = 0
-ExecStart=/bin/sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)
-ExecStart=/bin/sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)
-ExecStart=/bin/sh -c 'test %m = $$(cat /etc/machine-id)'
-ExecStart=/bin/sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
-ExecStart=/bin/sh -c 'test %H = $$(hostname)'
-ExecStart=/bin/sh -c 'test %v = $$(uname -r)'
+ExecStart=test %n = exec-specifier.service
+ExecStart=test %N = exec-specifier
+ExecStart=test %p = exec-specifier
+ExecStart=test %P = exec/specifier
+ExecStart=test %i = ""
+ExecStart=test %I = ""
+ExecStart=test %f = /exec/specifier
+ExecStart=test %t = /run
+ExecStart=test %S = /var/lib
+ExecStart=test %C = /var/cache
+ExecStart=test %L = /var/log
+ExecStart=sh -c 'test %u = $$(id -un 0)'
+ExecStart=test %U = 0
+ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'
+ExecStart=sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)'
+ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
+ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
+ExecStart=sh -c 'test %H = $$(hostname)'
+ExecStart=sh -c 'test %v = $$(uname -r)'
index 0015dffca641eb283a557083fc30211338ce2e53..f8d7dce680a9386f46f9a9bf0811f20c8ff74de1 100644 (file)
@@ -3,22 +3,22 @@ Description=Test for specifiers (template unit)
 
 [Service]
 Type=oneshot
-ExecStart=/usr/bin/test %n = exec-specifier@foo-bar.service
-ExecStart=/usr/bin/test %N = exec-specifier@foo-bar
-ExecStart=/usr/bin/test %p = exec-specifier
-ExecStart=/usr/bin/test %P = exec/specifier
-ExecStart=/usr/bin/test %i = foo-bar
-ExecStart=/usr/bin/test %I = foo/bar
-ExecStart=/usr/bin/test %f = /foo/bar
-ExecStart=/usr/bin/test %t = /run
-ExecStart=/usr/bin/test %S = /var/lib
-ExecStart=/usr/bin/test %C = /var/cache
-ExecStart=/usr/bin/test %L = /var/log
-ExecStart=/bin/sh -c 'test %u = $$(id -un 0)'
-ExecStart=/usr/bin/test %U = 0
-ExecStart=/bin/sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)
-ExecStart=/bin/sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)
-ExecStart=/bin/sh -c 'test %m = $$(cat /etc/machine-id)'
-ExecStart=/bin/sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
-ExecStart=/bin/sh -c 'test %H = $$(hostname)'
-ExecStart=/bin/sh -c 'test %v = $$(uname -r)'
+ExecStart=test %n = exec-specifier@foo-bar.service
+ExecStart=test %N = exec-specifier@foo-bar
+ExecStart=test %p = exec-specifier
+ExecStart=test %P = exec/specifier
+ExecStart=test %i = foo-bar
+ExecStart=test %I = foo/bar
+ExecStart=test %f = /foo/bar
+ExecStart=test %t = /run
+ExecStart=test %S = /var/lib
+ExecStart=test %C = /var/cache
+ExecStart=test %L = /var/log
+ExecStart=sh -c 'test %u = $$(id -un 0)'
+ExecStart=test %U = 0
+ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'
+ExecStart=sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)'
+ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
+ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
+ExecStart=sh -c 'test %H = $$(hostname)'
+ExecStart=sh -c 'test %v = $$(uname -r)'
index fc02ceab1ca8bd6114d108e0b8bdd8fad0241fc8..379ad066fb7b5710067c3b6e9ba6625b018c0aa9 100644 (file)
@@ -5,28 +5,28 @@ Description=Test for TemporaryFileSystem
 Type=oneshot
 
 # Check directories exist
-ExecStart=/bin/sh -c 'test -d /var/test-exec-temporaryfilesystem/rw && test -d /var/test-exec-temporaryfilesystem/ro'
+ExecStart=test -d /var/test-exec-temporaryfilesystem/rw -a -d /var/test-exec-temporaryfilesystem/ro
 
 # Check TemporaryFileSystem= are empty
-ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
+ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
 
 # Create a file in /var
-ExecStart=/bin/sh -c 'touch /var/hoge'
+ExecStart=touch /var/hoge
 
 # Create a file in /var/test-exec-temporaryfilesystem/rw
-ExecStart=/bin/sh -c 'touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem'
+ExecStart=touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem
 
 # Then, the file can be access through /tmp
-ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest-temporaryfilesystem'
+ExecStart=test -f /tmp/thisisasimpletest-temporaryfilesystem
 
 # Also, through /var/test-exec-temporaryfilesystem/ro
-ExecStart=/bin/sh -c 'test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+ExecStart=test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem
 
 # The file cannot modify through /var/test-exec-temporaryfilesystem/ro
-ExecStart=/bin/sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+ExecStart=sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
 
 # Cleanup
-ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest-temporaryfilesystem'
+ExecStart=rm /tmp/thisisasimpletest-temporaryfilesystem
 
 TemporaryFileSystem=/var
 BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw
index 9768f3a94e66900a5e3d794cacf6d1a36313fcff..a7a7d0a1d7aa0d909beef0f513acfa8cb8a22fd9 100644 (file)
@@ -7,7 +7,7 @@ enable_tmpfiles = conf.get('ENABLE_TMPFILES') == 1
 tmpfiles = [['home.conf',            ''],
             ['journal-nocow.conf',   ''],
             ['systemd-nologin.conf', ''],
-            ['systemd-nspawn.conf',  ''],
+            ['systemd-nspawn.conf',  'ENABLE_MACHINED'],
             ['tmp.conf',             ''],
             ['x11.conf',             ''],
             ['legacy.conf',          'HAVE_SYSV_COMPAT'],
index 96f7bd9a07a4abf03f6d3c1f3e0db88cf25e32a5..5e454ab3b18046124d1373afd0233bbd7f621987 100644 (file)
@@ -79,6 +79,7 @@ units = [
         ['sysinit.target',                      ''],
         ['syslog.socket',                       ''],
         ['system-update.target',                ''],
+        ['system-update-cleanup.service',       ''],
         ['systemd-ask-password-console.path',   '',
          'sysinit.target.wants/'],
         ['systemd-ask-password-wall.path',      '',
@@ -127,7 +128,6 @@ in_units = [
         ['quotaon.service',                      'ENABLE_QUOTACHECK'],
         ['rc-local.service',                     'HAVE_SYSV_COMPAT'],
         ['rescue.service',                       ''],
-        ['system-update-cleanup.service',        ''],
         ['systemd-ask-password-console.service', ''],
         ['systemd-ask-password-wall.service',    ''],
         ['systemd-backlight@.service',           'ENABLE_BACKLIGHT'],
@@ -197,8 +197,7 @@ in_units = [
          'dbus-org.freedesktop.timedate1.service'],
         ['systemd-timesyncd.service',            'ENABLE_TIMESYNCD',
          join_paths(pkgsysconfdir, 'system/sysinit.target.wants/')],
-        ['systemd-time-wait-sync.service', '',
-         join_paths(pkgsysconfdir, 'system/sysinit.target.wants/')],
+        ['systemd-time-wait-sync.service',       'ENABLE_TIMESYNCD'],
         ['systemd-tmpfiles-clean.service',       'ENABLE_TMPFILES'],
         ['systemd-tmpfiles-setup-dev.service',   'ENABLE_TMPFILES',
          'sysinit.target.wants/'],
@@ -223,28 +222,14 @@ in_units = [
 ]
 
 m4_units = [
+        ['console-getty.service',              ''],
+        ['container-getty@.service',           ''],
         ['getty@.service',                     '',
          'autovt@.service ' +
          join_paths(pkgsysconfdir, 'system/getty.target.wants/getty@tty1.service')],
         ['serial-getty@.service',              ''],
 ]
 
-m4_in_units = [
-        ['console-getty.service',              ''],
-        ['container-getty@.service',           ''],
-]
-
-foreach tuple : m4_in_units
-        file = tuple[0]
-
-        gen = configure_file(
-                input : file + '.m4.in',
-                output : file + '.m4',
-                configuration : substs)
-
-        m4_units += [[file, tuple.get(1, ''), tuple.get(2, ''), gen]]
-endforeach
-
 foreach tuple : in_units
         file = tuple[0]
 
index d3bc4e98414b4c3b4ec0918e91142b716a635826..5b8b243f171cc291a041d54f076632cab825e317 100644 (file)
@@ -37,6 +37,7 @@ MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+RuntimeDirectory=systemd/timesync
 SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
 LockPersonality=yes