X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fload-fragment.c;h=cf92f0df734f3eee57ee54d3bca050f6549c4e2a;hp=65a2a39248ba3e0fa979b569e07fa41522402e00;hb=8e7076caae32a560a11c1643b53fc4f12db4a6b1;hpb=cbb21cca098f9063b0ff5548b2c73ab517f55ea5 diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 65a2a3924..cf92f0df7 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -34,6 +34,8 @@ #include #include +#include + #include "unit.h" #include "strv.h" #include "conf-parser.h" @@ -44,37 +46,40 @@ #include "missing.h" #include "unit-name.h" #include "unit-printf.h" -#include "bus-errors.h" +#include "dbus-common.h" #include "utf8.h" #include "path-util.h" #include "syscall-list.h" #include "env-util.h" +#include "cgroup.h" #ifndef HAVE_SYSV_COMPAT -int config_parse_warn_compat( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - log_debug("[%s:%u] Support for option %s= has been disabled at compile time and is ignored", filename, line, lvalue); +int config_parse_warn_compat(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + log_syntax(unit, LOG_DEBUG, filename, line, EINVAL, + "Support for option %s= has been disabled at compile time and is ignored", + lvalue); return 0; } #endif -int config_parse_unit_deps( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_deps(const char* unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { UnitDependency d = ltype; Unit *u = userdata; @@ -87,7 +92,7 @@ int config_parse_unit_deps( assert(rvalue); FOREACH_WORD_QUOTED(w, l, rvalue, state) { - char _cleanup_free_ *t = NULL, *k = NULL; + _cleanup_free_ char *t = NULL, *k = NULL; int r; t = strndup(w, l); @@ -100,22 +105,22 @@ int config_parse_unit_deps( r = unit_add_dependency_by_name(u, d, k, NULL, true); if (r < 0) - log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s", - filename, line, k, strerror(-r)); + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to add dependency on %s, ignoring: %s", k, strerror(-r)); } return 0; } -int config_parse_unit_string_printf( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_string_printf(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = userdata; _cleanup_free_ char *k = NULL; @@ -127,21 +132,22 @@ int config_parse_unit_string_printf( k = unit_full_printf(u, rvalue); if (!k) - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); - return config_parse_string(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata); + return config_parse_string(unit, filename, line, section, lvalue, ltype, + k ? k : rvalue, data, userdata); } -int config_parse_unit_strv_printf( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_strv_printf(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = userdata; _cleanup_free_ char *k = NULL; @@ -153,21 +159,22 @@ int config_parse_unit_strv_printf( k = unit_full_printf(u, rvalue); if (!k) - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); - return config_parse_strv(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata); + return config_parse_strv(unit, filename, line, section, lvalue, ltype, + k ? k : rvalue, data, userdata); } -int config_parse_unit_path_printf( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_path_printf(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = userdata; _cleanup_free_ char *k = NULL; @@ -179,21 +186,22 @@ int config_parse_unit_path_printf( k = unit_full_printf(u, rvalue); if (!k) - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); - return config_parse_path(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata); + return config_parse_path(unit, filename, line, section, lvalue, ltype, + k ? k : rvalue, data, userdata); } -int config_parse_socket_listen( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_socket_listen(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { SocketPort *p, *tail; Socket *s; @@ -225,8 +233,8 @@ int config_parse_socket_listen( free(p); return log_oom(); } else - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); } path_kill_slashes(p->path); @@ -238,12 +246,13 @@ int config_parse_socket_listen( p->type = SOCKET_SOCKET; k = unit_full_printf(UNIT(s), rvalue); if (!k) - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); r = socket_address_parse_netlink(&p->address, k ? k : rvalue); if (r < 0) { - log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse address value, ignoring: %s", rvalue); free(p); return 0; } @@ -255,12 +264,13 @@ int config_parse_socket_listen( p->type = SOCKET_SOCKET; k = unit_full_printf(UNIT(s), rvalue); if (!k) - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); r = socket_address_parse(&p->address, k ? k : rvalue); if (r < 0) { - log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse address value, ignoring: %s", rvalue); free(p); return 0; } @@ -275,7 +285,8 @@ int config_parse_socket_listen( } if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) { - log_error("[%s:%u] Address family not supported, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, ENOTSUP, + "Address family not supported, ignoring: %s", rvalue); free(p); return 0; } @@ -292,15 +303,15 @@ int config_parse_socket_listen( return 0; } -int config_parse_socket_bind( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_socket_bind(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Socket *s; SocketAddressBindIPv6Only b; @@ -318,7 +329,8 @@ int config_parse_socket_bind( r = parse_boolean(rvalue); if (r < 0) { - log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse bind IPv6 only value, ignoring: %s", rvalue); return 0; } @@ -329,31 +341,34 @@ int config_parse_socket_bind( return 0; } -int config_parse_exec_nice( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_nice(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; - int priority; + int priority, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (safe_atoi(rvalue, &priority) < 0) { - log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue); + r = safe_atoi(rvalue, &priority); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse nice priority, ignoring: %s. ", rvalue); return 0; } if (priority < PRIO_MIN || priority >= PRIO_MAX) { - log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, ERANGE, + "Nice priority out of range, ignoring: %s", rvalue); return 0; } @@ -363,31 +378,34 @@ int config_parse_exec_nice( return 0; } -int config_parse_exec_oom_score_adjust( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_oom_score_adjust(const char* unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; - int oa; + int oa, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (safe_atoi(rvalue, &oa) < 0) { - log_error("[%s:%u] Failed to parse the OOM score adjust value, ignoring: %s", filename, line, rvalue); + r = safe_atoi(rvalue, &oa); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse the OOM score adjust value, ignoring: %s", rvalue); return 0; } if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) { - log_error("[%s:%u] OOM score adjust value out of range, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, ERANGE, + "OOM score adjust value out of range, ignoring: %s", rvalue); return 0; } @@ -397,15 +415,15 @@ int config_parse_exec_oom_score_adjust( return 0; } -int config_parse_exec( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecCommand **e = data, *nce; char *path, **n; @@ -458,8 +476,8 @@ int config_parse_exec( } if (*rvalue != '/') { - log_error("[%s:%u] Executable path is not absolute, ignoring: %s", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Executable path is not absolute, ignoring: %s", rvalue); return 0; } @@ -492,7 +510,9 @@ int config_parse_exec( } if (!utf8_is_valid(path)) { - log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Path is not UTF-8 clean, ignoring assignment: %s", + rvalue); r = 0; goto fail; } @@ -507,7 +527,9 @@ int config_parse_exec( } if (!utf8_is_valid(c)) { - log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Path is not UTF-8 clean, ignoring assignment: %s", + rvalue); r = 0; goto fail; } @@ -517,7 +539,8 @@ int config_parse_exec( n[k] = NULL; if (!n[0]) { - log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid command line, ignoring: %s", rvalue); r = 0; goto fail; } @@ -563,15 +586,15 @@ fail: DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type"); DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier"); -int config_parse_socket_bindtodevice( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_socket_bindtodevice(const char* unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Socket *s = data; char *n; @@ -597,15 +620,15 @@ int config_parse_socket_bindtodevice( DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier"); DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier"); -int config_parse_exec_io_class( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_io_class(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; int x; @@ -617,7 +640,8 @@ int config_parse_exec_io_class( x = ioprio_class_from_string(rvalue); if (x < 0) { - log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse IO scheduling class, ignoring: %s", rvalue); return 0; } @@ -627,26 +651,28 @@ int config_parse_exec_io_class( return 0; } -int config_parse_exec_io_priority( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_io_priority(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; - int i; + int i, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) { - log_error("[%s:%u] Failed to parse io priority, ignoring: %s", filename, line, rvalue); + r = safe_atoi(rvalue, &i); + if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse IO priority, ignoring: %s", rvalue); return 0; } @@ -656,15 +682,15 @@ int config_parse_exec_io_priority( return 0; } -int config_parse_exec_cpu_sched_policy( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_cpu_sched_policy(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; @@ -677,7 +703,8 @@ int config_parse_exec_cpu_sched_policy( x = sched_policy_from_string(rvalue); if (x < 0) { - log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, -x, + "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); return 0; } @@ -689,26 +716,28 @@ int config_parse_exec_cpu_sched_policy( return 0; } -int config_parse_exec_cpu_sched_prio( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_cpu_sched_prio(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; - int i, min, max; + int i, min, max, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (safe_atoi(rvalue, &i) < 0) { - log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue); + r = safe_atoi(rvalue, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); return 0; } @@ -717,7 +746,8 @@ int config_parse_exec_cpu_sched_prio( max = sched_get_priority_max(c->cpu_sched_policy); if (i < min || i > max) { - log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, ERANGE, + "CPU scheduling priority is out of range, ignoring: %s", rvalue); return 0; } @@ -727,15 +757,15 @@ int config_parse_exec_cpu_sched_prio( return 0; } -int config_parse_exec_cpu_affinity( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_cpu_affinity(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; char *w; @@ -756,7 +786,7 @@ int config_parse_exec_cpu_affinity( } FOREACH_WORD_QUOTED(w, l, rvalue, state) { - char _cleanup_free_ *t = NULL; + _cleanup_free_ char *t = NULL; int r; unsigned cpu; @@ -773,8 +803,8 @@ int config_parse_exec_cpu_affinity( } if (r < 0 || cpu >= c->cpuset_ncpus) { - log_error("[%s:%u] Failed to parse CPU affinity %s, ignoring: %s", - filename, line, t, rvalue); + log_syntax(unit, LOG_ERR, filename, line, ERANGE, + "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue); return 0; } @@ -784,15 +814,15 @@ int config_parse_exec_cpu_affinity( return 0; } -int config_parse_exec_capabilities( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_capabilities(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; cap_t cap; @@ -804,10 +834,8 @@ int config_parse_exec_capabilities( cap = cap_from_text(rvalue); if (!cap) { - if (errno == ENOMEM) - return log_oom(); - - log_error("[%s:%u] Failed to parse capabilities, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, errno, + "Failed to parse capabilities, ignoring: %s", rvalue); return 0; } @@ -818,15 +846,15 @@ int config_parse_exec_capabilities( return 0; } -int config_parse_exec_secure_bits( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_secure_bits(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; char *w; @@ -858,8 +886,8 @@ int config_parse_exec_secure_bits( else if (first_word(w, "noroot-locked")) c->secure_bits |= 1<cgroup_bondings, false); - u->cgroup_bondings = NULL; - return 0; - } - - FOREACH_WORD_QUOTED(w, l, rvalue, state) { - char _cleanup_free_ *t = NULL, *k = NULL, *ku = NULL; - int r; - - t = strndup(w, l); - if (!t) - return log_oom(); - - k = unit_full_printf(u, t); - if (!k) - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, t); - - ku = cunescape(k ? k : t); - if (!ku) - return log_oom(); - - r = unit_add_cgroup_from_text(u, ku, true, NULL); - if (r < 0) { - log_error("[%s:%u] Failed to parse cgroup value %s, ignoring: %s", - filename, line, k, rvalue); - return 0; - } - } - - return 0; -} - #ifdef HAVE_SYSV_COMPAT -int config_parse_sysv_priority( - const char *filename, - unsigned line, - const char *section, - 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, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { int *priority = data; - int i; + int i, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (safe_atoi(rvalue, &i) < 0 || i < 0) { - log_error("[%s:%u] Failed to parse SysV start priority, ignoring: %s", filename, line, rvalue); + r = safe_atoi(rvalue, &i); + if (r < 0 || i < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse SysV start priority, ignoring: %s", rvalue); return 0; } @@ -1042,26 +1028,28 @@ int config_parse_sysv_priority( } #endif -int config_parse_fsck_passno( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_fsck_passno(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { int *passno = data; - int i; + int i, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (safe_atoi(rvalue, &i) || i < 0) { - log_error("[%s:%u] Failed to parse fsck pass number, ignoring: %s", filename, line, rvalue); + r = safe_atoi(rvalue, &i); + if (r || i < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse fsck pass number, ignoring: %s", rvalue); return 0; } @@ -1071,15 +1059,15 @@ int config_parse_fsck_passno( DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode"); -int config_parse_kill_signal( - const char *filename, - unsigned line, - const char *section, - 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, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { int *sig = data; int r; @@ -1091,7 +1079,8 @@ int config_parse_kill_signal( r = signal_from_string_try_harder(rvalue); if (r <= 0) { - log_error("[%s:%u] Failed to parse kill signal, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to parse kill signal, ignoring: %s", rvalue); return 0; } @@ -1099,15 +1088,15 @@ int config_parse_kill_signal( return 0; } -int config_parse_exec_mount_flags( - const char *filename, - unsigned line, - const char *section, - 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, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; char *w; @@ -1121,7 +1110,7 @@ int config_parse_exec_mount_flags( assert(data); FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) { - char _cleanup_free_ *t; + _cleanup_free_ char *t; t = strndup(w, l); if (!t) @@ -1134,8 +1123,9 @@ int config_parse_exec_mount_flags( else if (streq(w, "private")) flags |= MS_PRIVATE; else { - log_error("[%s:%u] Failed to parse mount flag %s, ignoring: %s", - filename, line, t, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse mount flag %s, ignoring: %s", + t, rvalue); return 0; } } @@ -1144,15 +1134,15 @@ int config_parse_exec_mount_flags( return 0; } -int config_parse_timer( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_timer(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Timer *t = data; usec_t u = 0; @@ -1174,20 +1164,25 @@ int config_parse_timer( b = timer_base_from_string(lvalue); if (b < 0) { - log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue); + log_syntax(unit, LOG_ERR, filename, line, -b, + "Failed to parse timer base, ignoring: %s", lvalue); return 0; } if (b == TIMER_CALENDAR) { if (calendar_spec_from_string(rvalue, &c) < 0) { - log_error("[%s:%u] Failed to parse calendar specification, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse calendar specification, ignoring: %s", + rvalue); return 0; } id = CLOCK_REALTIME; } else { - if (parse_usec(rvalue, &u) < 0) { - log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue); + if (parse_sec(rvalue, &u) < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse timer value, ignoring: %s", + rvalue); return 0; } @@ -1208,7 +1203,8 @@ int config_parse_timer( return 0; } -int config_parse_timer_unit( +int config_parse_trigger_unit( + const char *unit, const char *filename, unsigned line, const char *section, @@ -1218,54 +1214,63 @@ int config_parse_timer_unit( void *data, void *userdata) { - Timer *t = data; - int r; - DBusError error; - Unit *u; _cleanup_free_ char *p = NULL; - + Unit *u = data; + UnitType type; + int r; + assert(filename); assert(lvalue); assert(rvalue); assert(data); - dbus_error_init(&error); + if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Multiple units to trigger specified, ignoring: %s", rvalue); + return 0; + } - p = unit_name_printf(UNIT(t), rvalue); + p = unit_name_printf(u, rvalue); if (!p) return log_oom(); - if (endswith(p, ".timer")) { - log_error("[%s:%u] Unit cannot be of type timer, ignoring: %s", filename, line, rvalue); + type = unit_name_to_type(p); + if (type < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Unit type not valid, ignoring: %s", rvalue); return 0; } - r = manager_load_unit(UNIT(t)->manager, p, NULL, NULL, &u); - if (r < 0) { - log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r)); - dbus_error_free(&error); + if (type == u->type) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Trigger cannot be of same type, ignoring: %s", rvalue); return 0; } - unit_ref_set(&t->unit, u); + r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to add trigger on %s, ignoring: %s", p, strerror(-r)); + return 0; + } return 0; } -int config_parse_path_spec( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_path_spec(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Path *p = data; PathSpec *s; PathType b; - char *k; + _cleanup_free_ char *k = NULL; assert(filename); assert(lvalue); @@ -1280,7 +1285,8 @@ int config_parse_path_spec( b = path_type_from_string(lvalue); if (b < 0) { - log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse path type, ignoring: %s", lvalue); return 0; } @@ -1290,23 +1296,23 @@ int config_parse_path_spec( if (!k) return log_oom(); else - log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.", - filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", + rvalue); } if (!path_is_absolute(k)) { - log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k); - free(k); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Path is not absolute, ignoring: %s", k); return 0; } s = new0(PathSpec, 1); - if (!s) { - free(k); + if (!s) return log_oom(); - } s->path = path_kill_slashes(k); + k = NULL; s->type = b; s->inotify_fd = -1; @@ -1315,59 +1321,15 @@ int config_parse_path_spec( return 0; } -int config_parse_path_unit( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Path *t = data; - int r; - DBusError error; - Unit *u; - _cleanup_free_ char *p = NULL; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - dbus_error_init(&error); - - p = unit_name_printf(UNIT(t), rvalue); - if (!p) - return log_oom(); - - if (endswith(p, ".path")) { - log_error("[%s:%u] Unit cannot be of type path, ignoring: %s", filename, line, p); - return 0; - } - - r = manager_load_unit(UNIT(t)->manager, p, NULL, &error, &u); - if (r < 0) { - log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, p, bus_error(&error, r)); - dbus_error_free(&error); - return 0; - } - - unit_ref_set(&t->unit, u); - - return 0; -} - -int config_parse_socket_service( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_socket_service(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Socket *s = data; int r; @@ -1387,13 +1349,16 @@ int config_parse_socket_service( return log_oom(); if (!endswith(p, ".service")) { - log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Unit must be of type service, ignoring: %s", rvalue); return 0; } r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x); if (r < 0) { - log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r)); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to load unit %s, ignoring: %s", + rvalue, bus_error(&error, r)); dbus_error_free(&error); return 0; } @@ -1403,15 +1368,15 @@ int config_parse_socket_service( return 0; } -int config_parse_service_sockets( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_service_sockets(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Service *s = data; int r; @@ -1424,7 +1389,7 @@ int config_parse_service_sockets( assert(data); FOREACH_WORD_QUOTED(w, l, rvalue, state) { - char _cleanup_free_ *t = NULL, *k = NULL; + _cleanup_free_ char *t = NULL, *k = NULL; t = strndup(w, l); if (!t) @@ -1435,15 +1400,16 @@ int config_parse_service_sockets( return log_oom(); if (!endswith(k, ".socket")) { - log_error("[%s:%u] Unit must be of type socket, ignoring: %s", - filename, line, k); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Unit must be of type socket, ignoring: %s", k); continue; } r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true); if (r < 0) - log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s", - filename, line, k, strerror(-r)); + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to add dependency on %s, ignoring: %s", + k, strerror(-r)); r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true); if (r < 0) @@ -1453,15 +1419,15 @@ int config_parse_service_sockets( return 0; } -int config_parse_service_timeout( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_service_timeout(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Service *s = userdata; int r; @@ -1471,7 +1437,8 @@ int config_parse_service_timeout( assert(rvalue); assert(s); - r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata); + r = config_parse_sec(unit, filename, line, section, lvalue, ltype, + rvalue, data, userdata); if (r < 0) return r; @@ -1484,15 +1451,15 @@ int config_parse_service_timeout( return 0; } -int config_parse_unit_env_file( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_env_file(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { char ***env = data; Unit *u = userdata; @@ -1516,7 +1483,8 @@ int config_parse_unit_env_file( return log_oom(); if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) { - log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Path '%s' is not absolute, ignoring.", s); return 0; } @@ -1527,15 +1495,15 @@ int config_parse_unit_env_file( return 0; } -int config_parse_environ( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_environ(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = userdata; char*** env = data, *w, *state; @@ -1545,7 +1513,7 @@ int config_parse_environ( assert(filename); assert(lvalue); assert(rvalue); - assert(u); + assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ @@ -1554,7 +1522,11 @@ int config_parse_environ( return 0; } - k = unit_full_printf(u, rvalue); + if (u) + k = unit_full_printf(u, rvalue); + else + k = strdup(rvalue); + if (!k) return log_oom(); @@ -1567,7 +1539,8 @@ int config_parse_environ( return log_oom(); if (!env_assignment_is_valid(n)) { - log_error("[%s:%u] Invalid environment assignment, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid environment assignment, ignoring: %s", rvalue); continue; } @@ -1582,15 +1555,15 @@ int config_parse_environ( return 0; } -int config_parse_ip_tos( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_ip_tos(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { int *ip_tos = data, x; @@ -1601,7 +1574,8 @@ int config_parse_ip_tos( x = ip_tos_from_string(rvalue); if (x < 0) { - log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse IP TOS value, ignoring: %s", rvalue); return 0; } @@ -1609,15 +1583,15 @@ int config_parse_ip_tos( return 0; } -int config_parse_unit_condition_path( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_condition_path(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ConditionType cond = ltype; Unit *u = data; @@ -1650,7 +1624,8 @@ int config_parse_unit_condition_path( return log_oom(); if (!path_is_absolute(p)) { - log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Path in condition not absolute, ignoring: %s", p); return 0; } @@ -1662,15 +1637,15 @@ int config_parse_unit_condition_path( return 0; } -int config_parse_unit_condition_string( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_condition_string(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ConditionType cond = ltype; Unit *u = data; @@ -1710,15 +1685,15 @@ int config_parse_unit_condition_string( return 0; } -int config_parse_unit_condition_null( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_condition_null(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = data; Condition *c; @@ -1747,7 +1722,9 @@ int config_parse_unit_condition_null( b = parse_boolean(rvalue); if (b < 0) { - log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue); + log_syntax(unit, LOG_ERR, filename, line, -b, + "Failed to parse boolean value in condition, ignoring: %s", + rvalue); return 0; } @@ -1765,107 +1742,15 @@ int config_parse_unit_condition_null( DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier"); -int config_parse_unit_cgroup_attr( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Unit *u = data; - size_t a, b; - _cleanup_free_ char *n = NULL, *v = NULL; - const CGroupSemantics *s; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - /* Empty assignment clears the list */ - cgroup_attribute_free_list(u->cgroup_attributes); - u->cgroup_attributes = NULL; - return 0; - } - - a = strcspn(rvalue, WHITESPACE); - b = strspn(rvalue + a, WHITESPACE); - if (a <= 0 || b <= 0) { - log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue); - return 0; - } - - n = strndup(rvalue, a); - if (!n) - return log_oom(); - - r = cgroup_semantics_find(NULL, n, rvalue + a + b, &v, &s); - if (r < 0) { - log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue); - return 0; - } - - r = unit_add_cgroup_attribute(u, s, NULL, n, v ? v : rvalue + a + b, NULL); - if (r < 0) { - log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue); - return 0; - } - - return 0; -} - -int config_parse_unit_cgroup_attr_pretty( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Unit *u = data; - _cleanup_free_ char *v = NULL; - const CGroupSemantics *s; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = cgroup_semantics_find(NULL, lvalue, rvalue, &v, &s); - if (r < 0) { - log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue); - return 0; - } else if (r == 0) { - log_error("[%s:%u] Unknown or unsupported cgroup attribute %s, ignoring: %s", filename, line, lvalue, rvalue); - return 0; - } - - r = unit_add_cgroup_attribute(u, s, NULL, NULL, v, NULL); - if (r < 0) { - log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue); - return 0; - } - - return 0; -} - -int config_parse_unit_requires_mounts_for( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_unit_requires_mounts_for(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = userdata; int r; @@ -1878,7 +1763,8 @@ int config_parse_unit_requires_mounts_for( empty_before = !u->requires_mounts_for; - r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata); + r = config_parse_path_strv(unit, filename, line, section, lvalue, ltype, + rvalue, data, userdata); /* Make it easy to find units with requires_mounts set */ if (empty_before && u->requires_mounts_for) @@ -1887,15 +1773,15 @@ int config_parse_unit_requires_mounts_for( return r; } -int config_parse_documentation( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_documentation(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { Unit *u = userdata; int r; @@ -1913,7 +1799,8 @@ int config_parse_documentation( return 0; } - r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata); + r = config_parse_unit_strv_printf(unit, filename, line, section, lvalue, ltype, + rvalue, data, userdata); if (r < 0) return r; @@ -1922,7 +1809,8 @@ int config_parse_documentation( if (is_valid_documentation_url(*a)) *(b++) = *a; else { - log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid URL, ignoring: %s", *a); free(*a); } } @@ -1941,15 +1829,15 @@ static void syscall_unset(uint32_t *p, int nr) { p[nr >> 4] &= ~(1 << (nr & 31)); } -int config_parse_syscall_filter( - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_syscall_filter(const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { ExecContext *c = data; Unit *u = userdata; @@ -1997,7 +1885,7 @@ int config_parse_syscall_filter( FOREACH_WORD_QUOTED(w, l, rvalue, state) { int id; - char _cleanup_free_ *t = NULL; + _cleanup_free_ char *t = NULL; t = strndup(w, l); if (!t) @@ -2005,8 +1893,8 @@ int config_parse_syscall_filter( id = syscall_from_name(t); if (id < 0) { - log_error("[%s:%u] Failed to parse syscall, ignoring: %s", - filename, line, t); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to parse syscall, ignoring: %s", t); continue; } @@ -2021,6 +1909,356 @@ int config_parse_syscall_filter( return 0; } +int config_parse_unit_slice( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *k = NULL; + Unit *u = userdata, *slice; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + k = unit_name_printf(u, rvalue); + if (!k) + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); + + r = manager_load_unit(u->manager, k ? k : rvalue, NULL, NULL, &slice); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Failed to load slice unit %s. Ignoring.", k ? k : rvalue); + return 0; + } + + if (slice->type != UNIT_SLICE) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Slice unit %s is not a slice. Ignoring.", k ? k : rvalue); + return 0; + } + + unit_ref_set(&u->slice, slice); + return 0; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy"); + +int config_parse_cpu_shares( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + unsigned long lu; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + c->cpu_shares = 1024; + return 0; + } + + r = safe_atolu(rvalue, &lu); + if (r < 0 || lu <= 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "CPU shares '%s' invalid. Ignoring.", rvalue); + return 0; + } + + c->cpu_shares = lu; + return 0; +} + +int config_parse_memory_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + uint64_t *limit; + off_t bytes; + int r; + + limit = streq(lvalue, "MemoryLimit") ? &c->memory_limit : &c->memory_soft_limit; + + if (isempty(rvalue)) { + *limit = (uint64_t) -1; + return 0; + } + + assert_cc(sizeof(uint64_t) == sizeof(off_t)); + + r = parse_bytes(rvalue, &bytes); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Memory limit '%s' invalid. Ignoring.", rvalue); + return 0; + } + + *limit = (uint64_t) bytes; + return 0; +} + +int config_parse_device_allow( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL; + CGroupContext *c = data; + CGroupDeviceAllow *a; + const char *m; + size_t n; + + if (isempty(rvalue)) { + while (c->device_allow) + cgroup_context_free_device_allow(c, c->device_allow); + + return 0; + } + + n = strcspn(rvalue, WHITESPACE); + path = strndup(rvalue, n); + if (!path) + return log_oom(); + + if (!path_startswith(path, "/dev")) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid device node path '%s'. Ignoring.", path); + return 0; + } + + m = rvalue + n + strspn(rvalue + n, WHITESPACE); + if (isempty(m)) + m = "rwm"; + + if (!in_charset(m, "rwm")) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid device rights '%s'. Ignoring.", m); + return 0; + } + + a = new0(CGroupDeviceAllow, 1); + if (!a) + return log_oom(); + + a->path = path; + path = NULL; + a->r = !!strchr(m, 'r'); + a->w = !!strchr(m, 'w'); + a->m = !!strchr(m, 'm'); + + LIST_PREPEND(CGroupDeviceAllow, device_allow, c->device_allow, a); + return 0; +} + +int config_parse_blockio_weight( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + unsigned long lu; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + c->blockio_weight = 1000; + return 0; + } + + r = safe_atolu(rvalue, &lu); + if (r < 0 || lu < 10 || lu > 1000) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Block IO weight '%s' invalid. Ignoring.", rvalue); + return 0; + } + + c->blockio_weight = lu; + + return 0; +} + +int config_parse_blockio_device_weight( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL; + CGroupBlockIODeviceWeight *w; + CGroupContext *c = data; + unsigned long lu; + const char *weight; + size_t n; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + while (c->blockio_device_weights) + cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); + + return 0; + } + + n = strcspn(rvalue, WHITESPACE); + weight = rvalue + n; + if (!*weight) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Expected block device and device weight. Ignoring."); + return 0; + } + + path = strndup(rvalue, n); + if (!path) + return log_oom(); + + if (!path_startswith(path, "/dev")) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid device node path '%s'. Ignoring.", path); + return 0; + } + + weight += strspn(weight, WHITESPACE); + r = safe_atolu(weight, &lu); + if (r < 0 || lu < 10 || lu > 1000) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Block IO weight '%s' invalid. Ignoring.", rvalue); + return 0; + } + + + w = new0(CGroupBlockIODeviceWeight, 1); + if (!w) + return log_oom(); + + w->path = path; + path = NULL; + + w->weight = lu; + + LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w); + return 0; +} + +int config_parse_blockio_bandwidth( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL; + CGroupBlockIODeviceBandwidth *b; + CGroupContext *c = data; + const char *bandwidth; + off_t bytes; + size_t n; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + while (c->blockio_device_bandwidths) + cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths); + + return 0; + } + + n = strcspn(rvalue, WHITESPACE); + bandwidth = rvalue + n; + bandwidth += strspn(bandwidth, WHITESPACE); + + if (!*bandwidth) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Expected space separated pair of device node and bandwidth. Ignoring."); + return 0; + } + + path = strndup(rvalue, n); + if (!path) + return log_oom(); + + if (!path_startswith(path, "/dev")) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid device node path '%s'. Ignoring.", path); + return 0; + } + + r = parse_bytes(bandwidth, &bytes); + if (r < 0 || bytes <= 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue); + return 0; + } + + b = new0(CGroupBlockIODeviceBandwidth, 1); + if (!b) + return log_oom(); + + b->path = path; + path = NULL; + b->bandwidth = (uint64_t) bytes; + + LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b); + + return 0; +} + #define FOLLOW_MAX 8 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { @@ -2058,11 +2296,9 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { if (!id) return -ENOMEM; - r = set_put(names, id); - if (r < 0) { - free(id); + r = set_consume(names, id); + if (r < 0) return r; - } } } @@ -2232,12 +2468,14 @@ static int load_from_path(Unit *u, const char *path) { if (null_or_empty(&st)) u->load_state = UNIT_MASKED; else { + u->load_state = UNIT_LOADED; + /* Now, parse the file contents */ - r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u); + r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections, + config_item_perf_lookup, + (void*) load_fragment_gperf_lookup, false, true, u); if (r < 0) goto finish; - - u->load_state = UNIT_LOADED; } free(u->fragment_path); @@ -2380,7 +2618,6 @@ void unit_dump_config_items(FILE *f) { { config_parse_exec_secure_bits, "SECUREBITS" }, { config_parse_bounding_set, "BOUNDINGSET" }, { config_parse_limit, "LIMIT" }, - { config_parse_unit_cgroup, "CGROUP [...]" }, { config_parse_unit_deps, "UNIT [...]" }, { config_parse_exec, "PATH [ARGUMENT [...]]" }, { config_parse_service_type, "SERVICETYPE" }, @@ -2395,21 +2632,21 @@ void unit_dump_config_items(FILE *f) { { config_parse_socket_listen, "SOCKET [...]" }, { config_parse_socket_bind, "SOCKETBIND" }, { config_parse_socket_bindtodevice, "NETWORKINTERFACE" }, - { config_parse_usec, "SECONDS" }, + { config_parse_sec, "SECONDS" }, { config_parse_nsec, "NANOSECONDS" }, { config_parse_path_strv, "PATH [...]" }, { config_parse_unit_requires_mounts_for, "PATH [...]" }, { config_parse_exec_mount_flags, "MOUNTFLAG [...]" }, { config_parse_unit_string_printf, "STRING" }, + { config_parse_trigger_unit, "UNIT" }, { config_parse_timer, "TIMER" }, - { config_parse_timer_unit, "NAME" }, { config_parse_path_spec, "PATH" }, - { config_parse_path_unit, "UNIT" }, { config_parse_notify_access, "ACCESS" }, { config_parse_ip_tos, "TOS" }, { config_parse_unit_condition_path, "CONDITION" }, { config_parse_unit_condition_string, "CONDITION" }, { config_parse_unit_condition_null, "CONDITION" }, + { config_parse_unit_slice, "SLICE" }, }; const char *prev = NULL;