#include <seccomp.h>
#endif
#include <sched.h>
-#include <string.h>
#include <sys/resource.h>
-#include <sys/stat.h>
#include "af-list.h"
#include "alloc-util.h"
#include "limits-util.h"
#include "load-fragment.h"
#include "log.h"
-#include "missing.h"
#include "mountpoint-util.h"
#include "nulstr-util.h"
#include "parse-util.h"
#endif
#include "securebits-util.h"
#include "signal-util.h"
+#include "socket-netlink.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "syslog-util.h"
+#include "time-util.h"
#include "unit-name.h"
#include "unit-printf.h"
#include "user-util.h"
-#include "time-util.h"
#include "web-util.h"
static int parse_socket_protocol(const char *s) {
void *userdata) {
_cleanup_free_ char *k = NULL;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
void *data,
void *userdata) {
- Unit *u = userdata;
+ const Unit *u = userdata;
_cleanup_free_ char *k = NULL;
int r;
void *userdata) {
_cleanup_free_ char *k = NULL;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
bool fatal = ltype;
void *userdata) {
char ***x = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
const char *p;
return 0;
}
+int config_parse_exec_coredump_filter(
+ 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) {
+
+ ExecContext *c = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ c->coredump_filter = 0;
+ c->coredump_filter_set = false;
+ return 0;
+ }
+
+ uint64_t f;
+ r = coredump_filter_mask_from_string(rvalue, &f);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse the CoredumpFilter=%s, ignoring: %m", rvalue);
+ return 0;
+ }
+
+ c->coredump_filter |= f;
+ c->oom_score_adjust_set = true;
+ return 0;
+}
+
int config_parse_exec(
const char *unit,
const char *filename,
void *userdata) {
ExecCommand **e = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
const char *p;
bool semicolon;
int r;
assert(e);
e += ltype;
- rvalue += strspn(rvalue, WHITESPACE);
if (isempty(rvalue)) {
/* An empty assignment resets the list */
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
const char *n;
ExecInput ei;
int r;
_cleanup_free_ char *unescaped = NULL, *resolved = NULL;
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
size_t sz;
void *p;
int r;
_cleanup_free_ char *resolved = NULL;
const char *n;
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
ExecOutput eo;
int r;
void *userdata) {
ExecContext *c = data;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- return parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
+ if (streq(rvalue, "numa")) {
+ c->cpu_affinity_from_numa = true;
+ cpu_set_reset(&c->cpu_set);
+
+ return 0;
+ }
+
+ r = parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
+ if (r >= 0)
+ c->cpu_affinity_from_numa = false;
+
+ return r;
}
int config_parse_capability_set(
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
bool ignore;
char *k;
int r;
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
bool ignore;
char *k;
int r;
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
bool ignore;
char *k;
int r;
_cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
_cleanup_free_ char *k = NULL;
- Unit *u = userdata;
+ const Unit *u = userdata;
Timer *t = data;
usec_t usec = 0;
TimerValue *v;
void *userdata) {
_cleanup_free_ char *k = NULL;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
return 0;
}
-int config_parse_service_timeout_abort(
+int config_parse_timeout_abort(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
- Service *s = userdata;
+ usec_t *ret = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(s);
+ assert(ret);
+
+ /* Note: apart from setting the arg, this returns an extra bit of information in the return value. */
- rvalue += strspn(rvalue, WHITESPACE);
if (isempty(rvalue)) {
- s->timeout_abort_set = false;
- return 0;
+ *ret = 0;
+ return 0; /* "not set" */
}
- r = parse_sec(rvalue, &s->timeout_abort_usec);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse TimeoutAbortSec= setting, ignoring: %s", rvalue);
- return 0;
- }
+ r = parse_sec(rvalue, ret);
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= setting, ignoring: %s", lvalue, rvalue);
+
+ return 1; /* "set" */
+}
- s->timeout_abort_set = true;
+int config_parse_service_timeout_abort(
+ 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) {
+
+ Service *s = userdata;
+ int r;
+
+ assert(s);
+
+ r = config_parse_timeout_abort(unit, filename, line, section, section_line, lvalue, ltype, rvalue,
+ &s->timeout_abort_usec, s);
+ if (r >= 0)
+ s->timeout_abort_set = r;
return 0;
}
_cleanup_free_ char *k = NULL;
char **user = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
return -ENOEXEC;
}
- if (!valid_user_group_name_or_id_compat(k)) {
+ if (!valid_user_group_name(k, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
return -ENOEXEC;
}
void *userdata) {
char ***users = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
const char *p = rvalue;
int r;
return -ENOEXEC;
}
- if (!valid_user_group_name_or_id_compat(k)) {
+ if (!valid_user_group_name(k, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
return -ENOEXEC;
}
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
bool missing_ok;
int r;
void *userdata) {
char ***env = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
_cleanup_free_ char *n = NULL;
int r;
void *data,
void *userdata) {
- Unit *u = userdata;
+ const Unit *u = userdata;
char ***env = data;
const char *p;
int r;
size_t nlen = 0, nbufsize = 0;
char*** passenv = data;
const char *p = rvalue;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
size_t nlen = 0, nbufsize = 0;
char*** unsetenv = data;
const char *p = rvalue;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
const char *p = rvalue;
int r;
}
}
+int config_parse_log_namespace(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *k = NULL;
+ ExecContext *c = data;
+ const Unit *u = userdata;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(c);
+
+ if (isempty(rvalue)) {
+ c->log_namespace = mfree(c->log_namespace);
+ return 0;
+ }
+
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
+ return 0;
+ }
+
+ if (!log_namespace_name_valid(k)) {
+ log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Specified log namespace name is not valid: %s", k);
+ return 0;
+ }
+
+ free_and_replace(c->log_namespace, k);
+ return 0;
+}
+
int config_parse_unit_condition_path(
const char *unit,
const char *filename,
Condition **list = data, *c;
ConditionType t = ltype;
bool trigger, negate;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
Condition **list = data, *c;
ConditionType t = ltype;
bool trigger, negate;
- Unit *u = userdata;
+ const Unit *u = userdata;
int r;
assert(filename);
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
bool invert = false;
const char *p;
int r;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *k = NULL;
- Unit *u = userdata, *slice = NULL;
+ Unit *u = userdata, *slice;
int r;
assert(filename);
return 0;
}
-int config_parse_cpuset_cpus(
+int config_parse_allowed_cpus(
const char *unit,
const char *filename,
unsigned line,
return 0;
}
-int config_parse_cpuset_mems(
+int config_parse_allowed_mems(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
- uint64_t *tasks_max = data, v;
- Unit *u = userdata;
+ const Unit *u = userdata;
+ TasksMax *tasks_max = data;
+ uint64_t v;
int r;
if (isempty(rvalue)) {
- *tasks_max = u ? u->manager->default_tasks_max : UINT64_MAX;
+ *tasks_max = u ? u->manager->default_tasks_max : TASKS_MAX_UNSET;
return 0;
}
if (streq(rvalue, "infinity")) {
- *tasks_max = CGROUP_LIMIT_MAX;
+ *tasks_max = TASKS_MAX_UNSET;
return 0;
}
r = parse_permille(rvalue);
- if (r < 0) {
+ if (r >= 0)
+ *tasks_max = (TasksMax) { r, 1000U }; /* r‰ */
+ else {
r = safe_atou64(rvalue, &v);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue);
return 0;
}
- } else
- v = system_tasks_max_scale(r, 1000U);
- if (v <= 0 || v >= UINT64_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue);
- return 0;
+ if (v <= 0 || v >= UINT64_MAX) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue);
+ return 0;
+ }
+
+ *tasks_max = (TasksMax) { v };
}
- *tasks_max = v;
return 0;
}
void *userdata) {
char***rt = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
const char *p;
int r;
void *data,
void *userdata) {
- Unit *u = userdata;
+ const Unit *u = userdata;
char*** sv = data;
const char *p = rvalue;
int r;
void *data,
void *userdata) {
- Unit *u = userdata;
+ const Unit *u = userdata;
ExecContext *c = data;
const char *p = rvalue;
int r;
void *userdata) {
ExecContext *c = data;
- Unit *u = userdata;
+ const Unit *u = userdata;
const char *p;
int r;
void *userdata) {
_cleanup_free_ char *k = NULL, *n = NULL;
- Unit *u = userdata;
+ const Unit *u = userdata;
char **s = data;
int r;
void *userdata) {
_cleanup_free_ char *resolved = NULL;
- Unit *u = userdata;
+ const Unit *u = userdata;
char ***paths = data;
int r;
return r;
if (null_or_empty(&st)) {
- u->load_state = UNIT_MASKED;
+ /* Unit file is masked */
+
+ u->load_state = u->perpetual ? UNIT_LOADED : UNIT_MASKED; /* don't allow perpetual units to ever be masked */
u->fragment_mtime = 0;
} else {
u->load_state = UNIT_LOADED;
{ config_parse_unsigned, "UNSIGNED" },
{ config_parse_iec_size, "SIZE" },
{ config_parse_iec_uint64, "SIZE" },
- { config_parse_si_size, "SIZE" },
+ { config_parse_si_uint64, "SIZE" },
{ config_parse_bool, "BOOLEAN" },
{ config_parse_string, "STRING" },
{ config_parse_path, "PATH" },
return 0;
}
-int config_parse_timeout_abort(
- const char* unit,
+int config_parse_swap_priority(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
void *data,
void *userdata) {
- usec_t *timeout_usec = data;
- int r;
+ Swap *s = userdata;
+ int r, priority;
+ assert(s);
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(timeout_usec);
+ assert(data);
- rvalue += strspn(rvalue, WHITESPACE);
if (isempty(rvalue)) {
- *timeout_usec = false;
+ s->parameters_fragment.priority = -1;
+ s->parameters_fragment.priority_set = false;
return 0;
}
- r = parse_sec(rvalue, timeout_usec);
+ r = safe_atoi(rvalue, &priority);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DefaultTimeoutAbortSec= setting, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap pririty '%s', ignoring.", rvalue);
+ return 0;
+ }
+
+ if (priority < -1) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Sorry, swap priorities smaller than -1 may only be assigned by the kernel itself, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (priority > 32767) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Swap priority out of range, ignoring: %s", rvalue);
return 0;
}
- *timeout_usec = true;
+ s->parameters_fragment.priority = priority;
+ s->parameters_fragment.priority_set = true;
return 0;
}