summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CODING_STYLE14
-rw-r--r--TODO6
-rw-r--r--man/systemd.exec.xml86
-rw-r--r--man/systemd.timer.xml2
-rw-r--r--src/basic/calendarspec.c4
-rw-r--r--src/basic/def.h24
-rw-r--r--src/basic/parse-util.c100
-rw-r--r--src/basic/time-util.c33
-rw-r--r--src/basic/time-util.h1
-rw-r--r--src/basic/virt.c2
-rw-r--r--src/binfmt/binfmt.c2
-rw-r--r--src/bootchart/bootchart.c6
-rw-r--r--src/cgls/cgls.c5
-rw-r--r--src/core/load-fragment-gperf.gperf.m44
-rw-r--r--src/core/load-fragment.c218
-rw-r--r--src/core/load-fragment.h2
-rw-r--r--src/core/main.c10
-rw-r--r--src/journal-remote/journal-remote.c2
-rw-r--r--src/journal-remote/journal-upload.c2
-rw-r--r--src/journal/coredump.c4
-rw-r--r--src/journal/journald-server.c16
-rw-r--r--src/login/logind.c4
-rw-r--r--src/modules-load/modules-load.c2
-rw-r--r--src/resolve/resolved-conf.c4
-rw-r--r--src/shared/sleep-config.c2
-rw-r--r--src/sysctl/sysctl.c2
-rw-r--r--src/sysusers/sysusers.c2
-rw-r--r--src/test/test-time.c23
-rw-r--r--src/test/test-unit-file.c61
-rw-r--r--src/timesync/timesyncd-conf.c4
-rw-r--r--src/tmpfiles/tmpfiles.c2
31 files changed, 482 insertions, 167 deletions
diff --git a/CODING_STYLE b/CODING_STYLE
index 8b945cd3c1..0064303203 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -145,11 +145,15 @@
- Think about the types you use. If a value cannot sensibly be
negative, do not use "int", but use "unsigned".
-- Do not use types like "short". They *never* make sense. Use ints,
- longs, long longs, all in unsigned+signed fashion, and the fixed
- size types uint32_t and so on, as well as size_t, but nothing
- else. Do not use kernel types like u32 and so on, leave that to the
- kernel.
+- Use "char" only for actual characters. Use "uint8_t" or "int8_t"
+ when you actually mean a byte-sized signed or unsigned
+ integers. When referring to a generic byte, we generally prefer the
+ unsigned variant "uint8_t". Do not use types based on "short". They
+ *never* make sense. Use ints, longs, long longs, all in
+ unsigned+signed fashion, and the fixed size types
+ uint8_t/uint16_t/uint32_t/uint64_t/int8_t/int16_t/int32_t and so on,
+ as well as size_t, but nothing else. Do not use kernel types like
+ u32 and so on, leave that to the kernel.
- Public API calls (i.e. functions exported by our shared libraries)
must be marked "_public_" and need to be prefixed with "sd_". No
diff --git a/TODO b/TODO
index 42534989a6..f49cf2b3f4 100644
--- a/TODO
+++ b/TODO
@@ -33,6 +33,12 @@ Janitorial Clean-ups:
Features:
+* add an explicit parser for LimitNICE= and LimitRTPRIO= that verifies
+ the specified range and generates sane error messages for incorrect
+ specifications. Also, for LimitNICE= maybe introduce a syntax such
+ as "+5" or "-7" in order to make the limits more readable as they
+ are otherwise shifted by 20.
+
* do something about "/control" subcgroups in the unified cgroup hierarchy
* when we detect that there are waiting jobs but no running jobs, do something
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 96298f11ed..2b090871ff 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -568,90 +568,133 @@
of various resources for executed processes. See
<citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for details. Use the string <varname>infinity</varname> to
- configure no limit on a specific resource. The multiplicative suffixes
- K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for
- resource limits measured in bytes (e.g. LimitAS=16G).</para></listitem>
+ configure no limit on a specific resource. The multiplicative
+ suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
+ may be used for resource limits measured in bytes
+ (e.g. LimitAS=16G). For the limits referring to time values,
+ the usual time units ms, s, min, h and so on may be used (see
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details). Note that if no time unit is specified for
+ <varname>LimitCPU=</varname> the default unit of seconds is
+ implied, while for <varname>LimitRTTIME=</varname> the default
+ unit of microseconds is implied. Also, note that the effective
+ granularity of the limits might influence their
+ enforcement. For example, time limits specified for
+ <varname>LimitCPU=</varname> will be rounded up implicitly to
+ multiples of 1s.</para>
+
+ <para>Note that most process resource limits configured with
+ these options are per-process, and processes may fork in order
+ to acquire a new set of resources that are accounted
+ independently of the original process, and may thus escape
+ limits set. Also note that <varname>LimitRSS=</varname> is not
+ implemented on Linux, and setting it has no effect. Often it
+ is advisable to prefer the resource controls listed in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ over these per-process limits, as they apply to services as a
+ whole, may be altered dynamically at runtime, and are
+ generally more expressive. For example,
+ <varname>MemoryLimit=</varname> is a more powerful (and
+ working) replacement for <varname>LimitRSS=</varname>.</para>
<table>
<title>Limit directives and their equivalent with ulimit</title>
- <tgroup cols='2'>
+ <tgroup cols='3'>
<colspec colname='directive' />
<colspec colname='equivalent' />
+ <colspec colname='unit' />
<thead>
<row>
<entry>Directive</entry>
<entry>ulimit equivalent</entry>
+ <entry>Unit</entry>
</row>
</thead>
<tbody>
<row>
- <entry>LimitCPU</entry>
+ <entry>LimitCPU=</entry>
<entry>ulimit -t</entry>
+ <entry>Seconds</entry>
</row>
<row>
- <entry>LimitFSIZE</entry>
+ <entry>LimitFSIZE=</entry>
<entry>ulimit -f</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitDATA</entry>
+ <entry>LimitDATA=</entry>
<entry>ulimit -d</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitSTACK</entry>
+ <entry>LimitSTACK=</entry>
<entry>ulimit -s</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitCORE</entry>
+ <entry>LimitCORE=</entry>
<entry>ulimit -c</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitRSS</entry>
+ <entry>LimitRSS=</entry>
<entry>ulimit -m</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitNOFILE</entry>
+ <entry>LimitNOFILE=</entry>
<entry>ulimit -n</entry>
+ <entry>Number of File Descriptors</entry>
</row>
<row>
- <entry>LimitAS</entry>
+ <entry>LimitAS=</entry>
<entry>ulimit -v</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitNPROC</entry>
+ <entry>LimitNPROC=</entry>
<entry>ulimit -u</entry>
+ <entry>Number of Processes</entry>
</row>
<row>
- <entry>LimitMEMLOCK</entry>
+ <entry>LimitMEMLOCK=</entry>
<entry>ulimit -l</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitLOCKS</entry>
+ <entry>LimitLOCKS=</entry>
<entry>ulimit -x</entry>
+ <entry>Number of Locks</entry>
</row>
<row>
- <entry>LimitSIGPENDING</entry>
+ <entry>LimitSIGPENDING=</entry>
<entry>ulimit -i</entry>
+ <entry>Number of Queued Signals</entry>
</row>
<row>
- <entry>LimitMSGQUEUE</entry>
+ <entry>LimitMSGQUEUE=</entry>
<entry>ulimit -q</entry>
+ <entry>Bytes</entry>
</row>
<row>
- <entry>LimitNICE</entry>
+ <entry>LimitNICE=</entry>
<entry>ulimit -e</entry>
+ <entry>Nice Level</entry>
</row>
<row>
- <entry>LimitRTPRIO</entry>
+ <entry>LimitRTPRIO=</entry>
<entry>ulimit -r</entry>
+ <entry>Realtime Priority</entry>
</row>
<row>
- <entry>LimitRTTIME</entry>
+ <entry>LimitRTTIME=</entry>
<entry>No equivalent</entry>
+ <entry>Microseconds</entry>
</row>
</tbody>
</tgroup>
- </table>
+ </table></listitem>
</varlistentry>
<varlistentry>
@@ -1320,6 +1363,7 @@
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>exec</refentrytitle><manvolnum>3</manvolnum></citerefentry>
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
index 20890f2270..c98258a0d7 100644
--- a/man/systemd.timer.xml
+++ b/man/systemd.timer.xml
@@ -127,7 +127,7 @@
boot-up. The argument may also include time units. Example:
"OnBootSec=5h 30min" means 5 hours and 30 minutes after
boot-up. For details about the syntax of time spans, see
- <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
<para>If a timer configured with <varname>OnBootSec=</varname>
or <varname>OnStartupSec=</varname> is already in the past
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index a6a906f453..7151fc3d0c 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -562,7 +562,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
return -EINVAL;
}
-static int parse_time(const char **p, CalendarSpec *c) {
+static int parse_calendar_time(const char **p, CalendarSpec *c) {
CalendarComponent *h = NULL, *m = NULL, *s = NULL;
const char *t;
int r;
@@ -802,7 +802,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
if (r < 0)
goto fail;
- r = parse_time(&p, c);
+ r = parse_calendar_time(&p, c);
if (r < 0)
goto fail;
diff --git a/src/basic/def.h b/src/basic/def.h
index 950f693899..0657ac7367 100644
--- a/src/basic/def.h
+++ b/src/basic/def.h
@@ -76,17 +76,19 @@
#define NOTIFY_FD_MAX 768
#define NOTIFY_BUFFER_MAX PIPE_BUF
-/* Return a nulstr for a standard cascade of configuration directories,
- * suitable to pass to conf_files_list_nulstr or config_parse_many. */
-#define CONF_DIRS_NULSTR(n) \
- "/etc/" n ".d\0" \
- "/run/" n ".d\0" \
- "/usr/local/lib/" n ".d\0" \
- "/usr/lib/" n ".d\0" \
- CONF_DIR_SPLIT_USR(n)
-
#ifdef HAVE_SPLIT_USR
-#define CONF_DIR_SPLIT_USR(n) "/lib/" n ".d\0"
+#define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0"
#else
-#define CONF_DIR_SPLIT_USR(n)
+#define _CONF_PATHS_SPLIT_USR(n)
#endif
+
+/* Return a nulstr for a standard cascade of configuration paths,
+ * suitable to pass to conf_files_list_nulstr() or config_parse_many()
+ * to implement drop-in directories for extending configuration
+ * files. */
+#define CONF_PATHS_NULSTR(n) \
+ "/etc/" n "\0" \
+ "/run/" n "\0" \
+ "/usr/local/lib/" n "\0" \
+ "/usr/lib/" n "\0" \
+ _CONF_PATHS_SPLIT_USR(n)
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index b6358c459a..151067e916 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -67,11 +67,14 @@ int parse_mode(const char *s, mode_t *ret) {
assert(s);
assert(ret);
+ s += strspn(s, WHITESPACE);
+ if (s[0] == '-')
+ return -ERANGE;
+
errno = 0;
l = strtol(s, &x, 8);
if (errno != 0)
return -errno;
-
if (!x || x == s || *x)
return -EINVAL;
if (l < 0 || l > 07777)
@@ -162,15 +165,15 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
unsigned i;
p += strspn(p, WHITESPACE);
- if (*p == '-')
- return -ERANGE;
errno = 0;
l = strtoull(p, &e, 10);
- if (errno > 0)
+ if (errno != 0)
return -errno;
if (e == p)
return -EINVAL;
+ if (*p == '-')
+ return -ERANGE;
if (*e == '.') {
e++;
@@ -181,7 +184,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
char *e2;
l2 = strtoull(e, &e2, 10);
- if (errno > 0)
+ if (errno != 0)
return -errno;
/* Ignore failure. E.g. 10.M is valid */
@@ -307,12 +310,24 @@ int safe_atou(const char *s, unsigned *ret_u) {
assert(s);
assert(ret_u);
- errno = 0;
- l = strtoul(s, &x, 0);
+ /* strtoul() is happy to parse negative values, and silently
+ * converts them to unsigned values without generating an
+ * error. We want a clean error, hence let's look for the "-"
+ * prefix on our own, and generate an error. But let's do so
+ * only after strtoul() validated that the string is clean
+ * otherwise, so that we return EINVAL preferably over
+ * ERANGE. */
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
+ s += strspn(s, WHITESPACE);
+ errno = 0;
+ l = strtoul(s, &x, 0);
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
+ if (s[0] == '-')
+ return -ERANGE;
if ((unsigned long) (unsigned) l != l)
return -ERANGE;
@@ -329,10 +344,10 @@ int safe_atoi(const char *s, int *ret_i) {
errno = 0;
l = strtol(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
if ((long) (int) l != l)
return -ERANGE;
@@ -347,11 +362,16 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
assert(s);
assert(ret_llu);
+ s += strspn(s, WHITESPACE);
+
errno = 0;
l = strtoull(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
+ if (*s == '-')
+ return -ERANGE;
*ret_llu = l;
return 0;
@@ -366,9 +386,10 @@ int safe_atolli(const char *s, long long int *ret_lli) {
errno = 0;
l = strtoll(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
*ret_lli = l;
return 0;
@@ -381,12 +402,16 @@ int safe_atou8(const char *s, uint8_t *ret) {
assert(s);
assert(ret);
+ s += strspn(s, WHITESPACE);
+
errno = 0;
l = strtoul(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
+ if (s[0] == '-')
+ return -ERANGE;
if ((unsigned long) (uint8_t) l != l)
return -ERANGE;
@@ -401,12 +426,16 @@ int safe_atou16(const char *s, uint16_t *ret) {
assert(s);
assert(ret);
+ s += strspn(s, WHITESPACE);
+
errno = 0;
l = strtoul(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
+ if (s[0] == '-')
+ return -ERANGE;
if ((unsigned long) (uint16_t) l != l)
return -ERANGE;
@@ -423,10 +452,10 @@ int safe_atoi16(const char *s, int16_t *ret) {
errno = 0;
l = strtol(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
+ if (errno != 0)
+ return -errno;
+ if (!x || x == s || *x)
+ return -EINVAL;
if ((long) (int16_t) l != l)
return -ERANGE;
@@ -448,10 +477,13 @@ int safe_atod(const char *s, double *ret_d) {
errno = 0;
d = strtod_l(s, &x, loc);
-
- if (!x || x == s || *x || errno) {
+ if (errno != 0) {
freelocale(loc);
- return errno ? -errno : -EINVAL;
+ return -errno;
+ }
+ if (!x || x == s || *x) {
+ freelocale(loc);
+ return -EINVAL;
}
freelocale(loc);
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index e629d91cb2..b36fbe4f09 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -705,7 +705,8 @@ finish:
return 0;
}
-int parse_sec(const char *t, usec_t *usec) {
+int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
+
static const struct {
const char *suffix;
usec_t usec;
@@ -737,7 +738,6 @@ int parse_sec(const char *t, usec_t *usec) {
{ "y", USEC_PER_YEAR },
{ "usec", 1ULL },
{ "us", 1ULL },
- { "", USEC_PER_SEC }, /* default is sec */
};
const char *p, *s;
@@ -746,6 +746,7 @@ int parse_sec(const char *t, usec_t *usec) {
assert(t);
assert(usec);
+ assert(default_unit > 0);
p = t;
@@ -764,6 +765,7 @@ int parse_sec(const char *t, usec_t *usec) {
long long l, z = 0;
char *e;
unsigned i, n = 0;
+ usec_t multiplier, k;
p += strspn(p, WHITESPACE);
@@ -806,21 +808,24 @@ int parse_sec(const char *t, usec_t *usec) {
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
- usec_t k = (usec_t) z * table[i].usec;
-
- for (; n > 0; n--)
- k /= 10;
-
- r += (usec_t) l * table[i].usec + k;
+ multiplier = table[i].usec;
p = e + strlen(table[i].suffix);
-
- something = true;
break;
}
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
+ if (i >= ELEMENTSOF(table)) {
+ multiplier = default_unit;
+ p = e;
+ }
+
+ something = true;
+
+ k = (usec_t) z * multiplier;
+ for (; n > 0; n--)
+ k /= 10;
+
+ r += (usec_t) l * multiplier + k;
}
*usec = r;
@@ -828,6 +833,10 @@ int parse_sec(const char *t, usec_t *usec) {
return 0;
}
+int parse_sec(const char *t, usec_t *usec) {
+ return parse_time(t, usec, USEC_PER_SEC);
+}
+
int parse_nsec(const char *t, nsec_t *nsec) {
static const struct {
const char *suffix;
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 925bf18eb2..0417c29cdd 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -104,6 +104,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
int parse_timestamp(const char *t, usec_t *usec);
int parse_sec(const char *t, usec_t *usec);
+int parse_time(const char *t, usec_t *usec, usec_t default_unit);
int parse_nsec(const char *t, nsec_t *nsec);
bool ntp_synced(void);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index ff006e96c6..d088b7a804 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -400,7 +400,7 @@ int detect_container(void) {
goto finish;
}
- r = VIRTUALIZATION_NONE;
+ r = VIRTUALIZATION_CONTAINER_OTHER;
finish:
cached_found = r;
diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
index 42ad0adb02..03fb413fe5 100644
--- a/src/binfmt/binfmt.c
+++ b/src/binfmt/binfmt.c
@@ -37,7 +37,7 @@
#include "strv.h"
#include "util.h"
-static const char conf_file_dirs[] = CONF_DIRS_NULSTR("binfmt");
+static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d");
static int delete_rule(const char *rule) {
_cleanup_free_ char *x = NULL, *fn = NULL;
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 852febb225..6a0e1d6b14 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -95,8 +95,6 @@ static void signal_handler(int sig) {
exiting = 1;
}
-#define BOOTCHART_CONF "/etc/systemd/bootchart.conf"
-
#define BOOTCHART_MAX (16*1024*1024)
static void parse_conf(void) {
@@ -117,8 +115,8 @@ static void parse_conf(void) {
{ NULL, NULL, NULL, 0, NULL }
};
- config_parse_many(BOOTCHART_CONF,
- CONF_DIRS_NULSTR("systemd/bootchart.conf"),
+ config_parse_many(PKGSYSCONFDIR "/bootchart.conf",
+ CONF_PATHS_NULSTR("systemd/bootchart.conf.d"),
NULL, config_item_table_lookup, items, true, NULL);
if (init != NULL)
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index 4e9a76a100..22efc58ac9 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -165,8 +165,10 @@ static int get_cgroup_root(char **ret) {
}
static void show_cg_info(const char *controller, const char *path) {
- if (cg_unified() <= 0)
+
+ if (cg_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
printf("Controller %s; ", controller);
+
printf("Control group %s:\n", isempty(path) ? "/" : path);
fflush(stdout);
}
@@ -270,6 +272,7 @@ int main(int argc, char *argv[]) {
show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root);
+ printf("-.slice\n");
r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_kernel_threads, output_flags);
}
}
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 5b7954dbf9..75388659e3 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -58,7 +58,7 @@ $1.RestrictAddressFamilies, config_parse_address_families, 0,
$1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
-$1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
+$1.LimitCPU, config_parse_sec_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
$1.LimitFSIZE, config_parse_bytes_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
$1.LimitDATA, config_parse_bytes_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
$1.LimitSTACK, config_parse_bytes_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
@@ -73,7 +73,7 @@ $1.LimitSIGPENDING, config_parse_limit, RLIMIT_SIGP
$1.LimitMSGQUEUE, config_parse_bytes_limit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
$1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
$1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
-$1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
+$1.LimitRTTIME, config_parse_usec_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
$1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_dirs)
$1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_dirs)
$1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_dirs)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index a514052772..79cabd26e7 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -974,23 +974,22 @@ int config_parse_exec_secure_bits(const char *unit,
return 0;
}
-int config_parse_bounding_set(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_bounding_set(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
uint64_t *capability_bounding_set_drop = data;
- uint64_t capability_bounding_set;
+ uint64_t capability_bounding_set, sum = 0;
bool invert = false;
- uint64_t sum = 0;
- const char *prev;
- const char *cur;
+ const char *p;
assert(filename);
assert(lvalue);
@@ -1007,35 +1006,32 @@ int config_parse_bounding_set(const char *unit,
* non-inverted everywhere to have a fully normalized
* interface. */
- prev = cur = rvalue;
+ p = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL;
- int cap;
- int r;
+ int cap, r;
- r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in bounding set, ignoring: %s", prev);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse word, ignoring: %s", rvalue);
break;
}
cap = capability_from_name(word);
if (cap < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", word);
- prev = cur;
continue;
}
- sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
- prev = cur;
+ sum |= ((uint64_t) UINT64_C(1)) << (uint64_t) cap;
}
capability_bounding_set = invert ? ~sum : sum;
- if (*capability_bounding_set_drop && capability_bounding_set)
+ if (*capability_bounding_set_drop != 0 && capability_bounding_set != 0)
*capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set);
else
*capability_bounding_set_drop = ~capability_bounding_set;
@@ -1043,19 +1039,21 @@ int config_parse_bounding_set(const char *unit,
return 0;
}
-int config_parse_limit(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
struct rlimit **rl = data;
- unsigned long long u;
+ rlim_t v;
+ int r;
assert(filename);
assert(lvalue);
@@ -1065,15 +1063,22 @@ int config_parse_limit(const char *unit,
rl += ltype;
if (streq(rvalue, "infinity"))
- u = (unsigned long long) RLIM_INFINITY;
+ v = RLIM_INFINITY;
else {
- int r;
+ uint64_t u;
- r = safe_atollu(rvalue, &u);
+ /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
+ assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
+
+ r = safe_atou64(rvalue, &u);
+ if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
+ r = -ERANGE;
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
return 0;
}
+
+ v = (rlim_t) u;
}
if (!*rl) {
@@ -1082,23 +1087,25 @@ int config_parse_limit(const char *unit,
return log_oom();
}
- (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
+ (*rl)->rlim_cur = (*rl)->rlim_max = v;
return 0;
}
-int config_parse_bytes_limit(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_bytes_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
struct rlimit **rl = data;
- uint64_t bytes;
+ rlim_t bytes;
+ int r;
assert(filename);
assert(lvalue);
@@ -1108,15 +1115,120 @@ int config_parse_bytes_limit(const char *unit,
rl += ltype;
if (streq(rvalue, "infinity"))
- bytes = (uint64_t) RLIM_INFINITY;
+ bytes = RLIM_INFINITY;
else {
- int r;
+ uint64_t u;
+
+ r = parse_size(rvalue, 1024, &u);
+ if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
+ r = -ERANGE;
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ bytes = (rlim_t) u;
+ }
+
+ if (!*rl) {
+ *rl = new(struct rlimit, 1);
+ if (!*rl)
+ return log_oom();
+ }
+
+ (*rl)->rlim_cur = (*rl)->rlim_max = bytes;
+ return 0;
+}
+
+int config_parse_sec_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ struct rlimit **rl = data;
+ rlim_t seconds;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ rl += ltype;
+
+ if (streq(rvalue, "infinity"))
+ seconds = RLIM_INFINITY;
+ else {
+ usec_t t;
+
+ r = parse_sec(rvalue, &t);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (t == USEC_INFINITY)
+ seconds = RLIM_INFINITY;
+ else
+ seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
+ }
+
+ if (!*rl) {
+ *rl = new(struct rlimit, 1);
+ if (!*rl)
+ return log_oom();
+ }
+
+ (*rl)->rlim_cur = (*rl)->rlim_max = seconds;
+ return 0;
+}
- r = parse_size(rvalue, 1024, &bytes);
+
+int config_parse_usec_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ struct rlimit **rl = data;
+ rlim_t useconds;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ rl += ltype;
+
+ if (streq(rvalue, "infinity"))
+ useconds = RLIM_INFINITY;
+ else {
+ usec_t t;
+
+ r = parse_time(rvalue, &t, 1);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
return 0;
}
+
+ if (t == USEC_INFINITY)
+ useconds = RLIM_INFINITY;
+ else
+ useconds = (rlim_t) t;
}
if (!*rl) {
@@ -1125,7 +1237,7 @@ int config_parse_bytes_limit(const char *unit,
return log_oom();
}
- (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) bytes;
+ (*rl)->rlim_cur = (*rl)->rlim_max = useconds;
return 0;
}
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 029775bb46..0cf821289c 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -57,6 +57,8 @@ int config_parse_exec_secure_bits(const char *unit, const char *filename, unsign
int config_parse_bounding_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bytes_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_sec_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_usec_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_kill_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_mount_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/core/main.c b/src/core/main.c
index 950315e857..a86080642d 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -682,8 +682,14 @@ static int parse_config_file(void) {
const char *fn, *conf_dirs_nulstr;
- fn = arg_running_as == MANAGER_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf";
- conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? CONF_DIRS_NULSTR("systemd/system.conf") : CONF_DIRS_NULSTR("systemd/user.conf");
+ fn = arg_running_as == MANAGER_SYSTEM ?
+ PKGSYSCONFDIR "/system.conf" :
+ PKGSYSCONFDIR "/user.conf";
+
+ conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ?
+ CONF_PATHS_NULSTR("systemd/system.conf.d") :
+ CONF_PATHS_NULSTR("systemd/user.conf.d");
+
config_parse_many(fn, conf_dirs_nulstr, "Manager\0",
config_item_table_lookup, items, false, NULL);
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 6eb0ee9d9e..b2f5fbf6b4 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -1188,7 +1188,7 @@ static int parse_config(void) {
{}};
return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf",
- CONF_DIRS_NULSTR("systemd/journal-remote.conf"),
+ CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
"Remote\0", config_item_table_lookup, items,
false, NULL);
}
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index 42d14dc7c4..6302266ccb 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -542,7 +542,7 @@ static int parse_config(void) {
{}};
return config_parse_many(PKGSYSCONFDIR "/journal-upload.conf",
- CONF_DIRS_NULSTR("systemd/journal-upload.conf"),
+ CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"),
"Upload\0", config_item_table_lookup, items,
false, NULL);
}
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index 4c83e311db..f750ddfcbd 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -126,8 +126,8 @@ static int parse_config(void) {
{}
};
- return config_parse_many("/etc/systemd/coredump.conf",
- CONF_DIRS_NULSTR("systemd/coredump.conf"),
+ return config_parse_many(PKGSYSCONFDIR "/coredump.conf",
+ CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
"Coredump\0",
config_item_table_lookup, items,
false, NULL);
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 7a70dcbc57..36fe739073 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1296,10 +1296,22 @@ static int setup_signals(Server *s) {
if (r < 0)
return r;
+ /* Let's process SIGTERM late, so that we flush all queued
+ * messages to disk before we exit */
+ r = sd_event_source_set_priority(s->sigterm_event_source, SD_EVENT_PRIORITY_NORMAL+20);
+ if (r < 0)
+ return r;
+
+ /* When journald is invoked on the terminal (when debugging),
+ * it's useful if C-c is handled equivalent to SIGTERM. */
r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s);
if (r < 0)
return r;
+ r = sd_event_source_set_priority(s->sigint_event_source, SD_EVENT_PRIORITY_NORMAL+20);
+ if (r < 0)
+ return r;
+
return 0;
}
@@ -1360,8 +1372,8 @@ static int server_parse_proc_cmdline(Server *s) {
static int server_parse_config_file(Server *s) {
assert(s);
- return config_parse_many("/etc/systemd/journald.conf",
- CONF_DIRS_NULSTR("systemd/journald.conf"),
+ return config_parse_many(PKGSYSCONFDIR "/journald.conf",
+ CONF_PATHS_NULSTR("systemd/journald.conf.d"),
"Journal\0",
config_item_perf_lookup, journald_gperf_lookup,
false, s);
diff --git a/src/login/logind.c b/src/login/logind.c
index 83896ea627..be6bbe5b5c 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1102,8 +1102,8 @@ static int manager_run(Manager *m) {
static int manager_parse_config_file(Manager *m) {
assert(m);
- return config_parse_many("/etc/systemd/logind.conf",
- CONF_DIRS_NULSTR("systemd/logind.conf"),
+ return config_parse_many(PKGSYSCONFDIR "/logind.conf",
+ CONF_PATHS_NULSTR("systemd/logind.conf.d"),
"Login\0",
config_item_perf_lookup, logind_gperf_lookup,
false, m);
diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c
index 13784763f1..a7fdcb09cf 100644
--- a/src/modules-load/modules-load.c
+++ b/src/modules-load/modules-load.c
@@ -38,7 +38,7 @@
static char **arg_proc_cmdline_modules = NULL;
-static const char conf_file_dirs[] = CONF_DIRS_NULSTR("modules-load");
+static const char conf_file_dirs[] = CONF_PATHS_NULSTR("modules-load.d");
static void systemd_kmod_log(void *data, int priority, const char *file, int line,
const char *fn, const char *format, va_list args) {
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index de1bd26174..9207719551 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -150,8 +150,8 @@ int config_parse_support(
int manager_parse_config_file(Manager *m) {
assert(m);
- return config_parse_many("/etc/systemd/resolved.conf",
- CONF_DIRS_NULSTR("systemd/resolved.conf"),
+ return config_parse_many(PKGSYSCONFDIR "/resolved.conf",
+ CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
"Resolve\0",
config_item_perf_lookup, resolved_gperf_lookup,
false, m);
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index 102c5cc992..39b836d053 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -54,7 +54,7 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
};
config_parse_many(PKGSYSCONFDIR "/sleep.conf",
- CONF_DIRS_NULSTR("systemd/sleep.conf"),
+ CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
"Sleep\0", config_item_table_lookup, items,
false, NULL);
diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
index 152c98b348..25b5ff52ea 100644
--- a/src/sysctl/sysctl.c
+++ b/src/sysctl/sysctl.c
@@ -41,7 +41,7 @@
static char **arg_prefixes = NULL;
-static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysctl");
+static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d");
static int apply_all(Hashmap *sysctl_options) {
char *property, *value;
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 008b1bde24..675f94906b 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -72,7 +72,7 @@ typedef struct Item {
static char *arg_root = NULL;
-static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysusers");
+static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d");
static Hashmap *users = NULL, *groups = NULL;
static Hashmap *todo_uids = NULL, *todo_gids = NULL;
diff --git a/src/test/test-time.c b/src/test/test-time.c
index 3840fff061..820e4aaee2 100644
--- a/src/test/test-time.c
+++ b/src/test/test-time.c
@@ -57,6 +57,28 @@ static void test_parse_sec(void) {
assert_se(parse_sec(".3 infinity", &u) < 0);
}
+static void test_parse_time(void) {
+ usec_t u;
+
+ assert_se(parse_time("5", &u, 1) >= 0);
+ assert_se(u == 5);
+
+ assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0);
+ assert_se(u == 5 * USEC_PER_MSEC);
+
+ assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("5s", &u, 1) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+}
+
static void test_parse_nsec(void) {
nsec_t u;
@@ -161,6 +183,7 @@ static void test_get_timezones(void) {
int main(int argc, char *argv[]) {
test_parse_sec();
+ test_parse_time();
test_parse_nsec();
test_format_timespan(1);
test_format_timespan(USEC_PER_MSEC);
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index f9107e0d0d..3648ec9c58 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -681,6 +681,66 @@ static void test_config_parse_bounding_set(void) {
assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
}
+static void test_config_parse_rlimit(void) {
+ struct rlimit * rl[_RLIMIT_MAX] = {};
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
+
+ assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
+
+ assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
+}
+
int main(int argc, char *argv[]) {
int r;
@@ -690,6 +750,7 @@ int main(int argc, char *argv[]) {
r = test_unit_file_get_set();
test_config_parse_exec();
test_config_parse_bounding_set();
+ test_config_parse_rlimit();
test_load_env_file_1();
test_load_env_file_2();
test_load_env_file_3();
diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c
index 001a0f4d41..5881bc0c45 100644
--- a/src/timesync/timesyncd-conf.c
+++ b/src/timesync/timesyncd-conf.c
@@ -100,8 +100,8 @@ int config_parse_servers(
int manager_parse_config_file(Manager *m) {
assert(m);
- return config_parse_many("/etc/systemd/timesyncd.conf",
- CONF_DIRS_NULSTR("systemd/timesyncd.conf"),
+ return config_parse_many(PKGSYSCONFDIR "/timesyncd.conf",
+ CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
"Time\0",
config_item_perf_lookup, timesyncd_gperf_lookup,
false, m);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index ffae91a3ca..64f0c9396c 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -159,7 +159,7 @@ static char **arg_include_prefixes = NULL;
static char **arg_exclude_prefixes = NULL;
static char *arg_root = NULL;
-static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
+static const char conf_file_dirs[] = CONF_PATHS_NULSTR("tmpfiles.d");
#define MAX_DEPTH 256