]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/load-fragment.c
Merge pull request #15376 from poettering/homed-btrfs-subvol-luks
[thirdparty/systemd.git] / src / core / load-fragment.c
index f991b7f5e87e091f425ffaa30bc17ba54cfa8759..b16c62a5c7c62d2adb10623c0759cc6ef6159893 100644 (file)
@@ -11,9 +11,7 @@
 #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"
 #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) {
@@ -592,6 +592,45 @@ int config_parse_exec_oom_score_adjust(
         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,
@@ -616,7 +655,6 @@ int config_parse_exec(
         assert(e);
 
         e += ltype;
-        rvalue += strspn(rvalue, WHITESPACE);
 
         if (isempty(rvalue)) {
                 /* An empty assignment resets the list */
@@ -1331,13 +1369,25 @@ int config_parse_exec_cpu_affinity(const char *unit,
                                    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(
@@ -1933,7 +1983,7 @@ int config_parse_service_timeout(
         return 0;
 }
 
-int config_parse_service_timeout_abort(
+int config_parse_timeout_abort(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -1945,27 +1995,49 @@ int config_parse_service_timeout_abort(
                 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;
 }
 
@@ -2035,7 +2107,7 @@ int config_parse_user_group_compat(
                 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;
         }
@@ -2089,7 +2161,7 @@ int config_parse_user_group_strv_compat(
                         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;
                 }
@@ -2499,6 +2571,48 @@ int config_parse_log_extra_fields(
         }
 }
 
+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,
@@ -3148,7 +3262,7 @@ int config_parse_cpu_quota(
         return 0;
 }
 
-int config_parse_cpuset_cpus(
+int config_parse_allowed_cpus(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -3167,7 +3281,7 @@ int config_parse_cpuset_cpus(
         return 0;
 }
 
-int config_parse_cpuset_mems(
+int config_parse_allowed_mems(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -3265,36 +3379,39 @@ int config_parse_tasks_max(
                 void *data,
                 void *userdata) {
 
-        uint64_t *tasks_max = data, v;
         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;
 }
 
@@ -4680,7 +4797,9 @@ int unit_load_fragment(Unit *u) {
                         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;
@@ -4746,7 +4865,7 @@ void unit_dump_config_items(FILE *f) {
                 { 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" },
@@ -4981,8 +5100,8 @@ int config_parse_crash_chvt(
         return 0;
 }
 
-int config_parse_timeout_abort(
-                const charunit,
+int config_parse_swap_priority(
+                const char *unit,
                 const char *filename,
                 unsigned line,
                 const char *section,
@@ -4993,26 +5112,38 @@ int config_parse_timeout_abort(
                 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;
 }