Merge pull request #1835 from poettering/grabbag-of-stuff

Lots of small fixes
This commit is contained in:
Daniel Mack 2015-11-10 21:01:35 +01:00
commit e3c4a681db
31 changed files with 482 additions and 167 deletions

View File

@ -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

6
TODO
View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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);
/* 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. */
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) (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);

View File

@ -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;

View File

@ -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);

View File

@ -400,7 +400,7 @@ int detect_container(void) {
goto finish;
}
r = VIRTUALIZATION_NONE;
r = VIRTUALIZATION_CONTAINER_OTHER;
finish:
cached_found = r;

View File

@ -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;

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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,19 @@ 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, &bytes);
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) {
@ -1125,7 +1136,108 @@ 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 = 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;
}
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) {
*rl = new(struct rlimit, 1);
if (!*rl)
return log_oom();
}
(*rl)->rlim_cur = (*rl)->rlim_max = useconds;
return 0;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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