]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/load-fragment.c
Use enums to make it obvious what boolean params mean
[thirdparty/systemd.git] / src / core / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2012 Holger Hans Peter Freyther
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <linux/oom.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sched.h>
30 #include <sys/prctl.h>
31 #include <sys/mount.h>
32 #include <linux/fs.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36
37 #include "sd-messages.h"
38 #include "unit.h"
39 #include "strv.h"
40 #include "conf-parser.h"
41 #include "load-fragment.h"
42 #include "log.h"
43 #include "ioprio.h"
44 #include "securebits.h"
45 #include "missing.h"
46 #include "unit-name.h"
47 #include "unit-printf.h"
48 #include "utf8.h"
49 #include "path-util.h"
50 #include "syscall-list.h"
51 #include "env-util.h"
52 #include "cgroup.h"
53 #include "bus-util.h"
54 #include "bus-error.h"
55
56 #ifndef HAVE_SYSV_COMPAT
57 int config_parse_warn_compat(const char *unit,
58 const char *filename,
59 unsigned line,
60 const char *section,
61 unsigned section_line,
62 const char *lvalue,
63 int ltype,
64 const char *rvalue,
65 void *data,
66 void *userdata) {
67
68 log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
69 "Support for option %s= has been disabled at compile time and is ignored",
70 lvalue);
71 return 0;
72 }
73 #endif
74
75 int config_parse_unit_deps(const char* unit,
76 const char *filename,
77 unsigned line,
78 const char *section,
79 unsigned section_line,
80 const char *lvalue,
81 int ltype,
82 const char *rvalue,
83 void *data,
84 void *userdata) {
85
86 UnitDependency d = ltype;
87 Unit *u = userdata;
88 char *w;
89 size_t l;
90 char *state;
91
92 assert(filename);
93 assert(lvalue);
94 assert(rvalue);
95
96 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
97 _cleanup_free_ char *t = NULL, *k = NULL;
98 int r;
99
100 t = strndup(w, l);
101 if (!t)
102 return log_oom();
103
104 r = unit_name_printf(u, t, &k);
105 if (r < 0) {
106 log_syntax(unit, LOG_ERR, filename, line, -r,
107 "Failed to resolve specifiers, ignoring: %s", strerror(-r));
108 continue;
109 }
110
111 r = unit_add_dependency_by_name(u, d, k, NULL, true);
112 if (r < 0)
113 log_syntax(unit, LOG_ERR, filename, line, -r,
114 "Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
115 }
116
117 return 0;
118 }
119
120 int config_parse_unit_string_printf(const char *unit,
121 const char *filename,
122 unsigned line,
123 const char *section,
124 unsigned section_line,
125 const char *lvalue,
126 int ltype,
127 const char *rvalue,
128 void *data,
129 void *userdata) {
130
131 Unit *u = userdata;
132 _cleanup_free_ char *k = NULL;
133 int r;
134
135 assert(filename);
136 assert(lvalue);
137 assert(rvalue);
138 assert(u);
139
140 r = unit_full_printf(u, rvalue, &k);
141 if (r < 0)
142 log_syntax(unit, LOG_ERR, filename, line, -r,
143 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
144
145 return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
146 k ? k : rvalue, data, userdata);
147 }
148
149 int config_parse_unit_strv_printf(const char *unit,
150 const char *filename,
151 unsigned line,
152 const char *section,
153 unsigned section_line,
154 const char *lvalue,
155 int ltype,
156 const char *rvalue,
157 void *data,
158 void *userdata) {
159
160 Unit *u = userdata;
161 _cleanup_free_ char *k = NULL;
162 int r;
163
164 assert(filename);
165 assert(lvalue);
166 assert(rvalue);
167 assert(u);
168
169 r = unit_full_printf(u, rvalue, &k);
170 if (r < 0)
171 log_syntax(unit, LOG_ERR, filename, line, -r,
172 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
173
174 return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype,
175 k ? k : rvalue, data, userdata);
176 }
177
178 int config_parse_unit_path_printf(const char *unit,
179 const char *filename,
180 unsigned line,
181 const char *section,
182 unsigned section_line,
183 const char *lvalue,
184 int ltype,
185 const char *rvalue,
186 void *data,
187 void *userdata) {
188
189 Unit *u = userdata;
190 _cleanup_free_ char *k = NULL;
191 int r;
192
193 assert(filename);
194 assert(lvalue);
195 assert(rvalue);
196 assert(u);
197
198 r = unit_full_printf(u, rvalue, &k);
199 if (r < 0)
200 log_syntax(unit, LOG_ERR, filename, line, -r,
201 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
202
203 return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype,
204 k ? k : rvalue, data, userdata);
205 }
206
207 int config_parse_socket_listen(const char *unit,
208 const char *filename,
209 unsigned line,
210 const char *section,
211 unsigned section_line,
212 const char *lvalue,
213 int ltype,
214 const char *rvalue,
215 void *data,
216 void *userdata) {
217
218 SocketPort *p, *tail;
219 Socket *s;
220 int r;
221
222 assert(filename);
223 assert(lvalue);
224 assert(rvalue);
225 assert(data);
226
227 s = SOCKET(data);
228
229 if (isempty(rvalue)) {
230 /* An empty assignment removes all ports */
231 socket_free_ports(s);
232 return 0;
233 }
234
235 p = new0(SocketPort, 1);
236 if (!p)
237 return log_oom();
238
239 if (ltype != SOCKET_SOCKET) {
240
241 p->type = ltype;
242 r = unit_full_printf(UNIT(s), rvalue, &p->path);
243 if (r < 0) {
244 p->path = strdup(rvalue);
245 if (!p->path) {
246 free(p);
247 return log_oom();
248 } else
249 log_syntax(unit, LOG_ERR, filename, line, -r,
250 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
251 }
252
253 path_kill_slashes(p->path);
254
255 } else if (streq(lvalue, "ListenNetlink")) {
256 _cleanup_free_ char *k = NULL;
257
258 p->type = SOCKET_SOCKET;
259 r = unit_full_printf(UNIT(s), rvalue, &k);
260 if (r < 0)
261 log_syntax(unit, LOG_ERR, filename, line, -r,
262 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
263
264 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
265 if (r < 0) {
266 log_syntax(unit, LOG_ERR, filename, line, -r,
267 "Failed to parse address value, ignoring: %s", rvalue);
268 free(p);
269 return 0;
270 }
271
272 } else {
273 _cleanup_free_ char *k = NULL;
274
275 p->type = SOCKET_SOCKET;
276 r = unit_full_printf(UNIT(s), rvalue, &k);
277 if (r < 0)
278 log_syntax(unit, LOG_ERR, filename, line, -r,
279 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
280
281 r = socket_address_parse(&p->address, k ? k : rvalue);
282 if (r < 0) {
283 log_syntax(unit, LOG_ERR, filename, line, -r,
284 "Failed to parse address value, ignoring: %s", rvalue);
285 free(p);
286 return 0;
287 }
288
289 if (streq(lvalue, "ListenStream"))
290 p->address.type = SOCK_STREAM;
291 else if (streq(lvalue, "ListenDatagram"))
292 p->address.type = SOCK_DGRAM;
293 else {
294 assert(streq(lvalue, "ListenSequentialPacket"));
295 p->address.type = SOCK_SEQPACKET;
296 }
297
298 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
299 log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
300 "Address family not supported, ignoring: %s", rvalue);
301 free(p);
302 return 0;
303 }
304 }
305
306 p->fd = -1;
307 p->socket = s;
308
309 if (s->ports) {
310 LIST_FIND_TAIL(port, s->ports, tail);
311 LIST_INSERT_AFTER(port, s->ports, tail, p);
312 } else
313 LIST_PREPEND(port, s->ports, p);
314
315 return 0;
316 }
317
318 int config_parse_socket_bind(const char *unit,
319 const char *filename,
320 unsigned line,
321 const char *section,
322 unsigned section_line,
323 const char *lvalue,
324 int ltype,
325 const char *rvalue,
326 void *data,
327 void *userdata) {
328
329 Socket *s;
330 SocketAddressBindIPv6Only b;
331
332 assert(filename);
333 assert(lvalue);
334 assert(rvalue);
335 assert(data);
336
337 s = SOCKET(data);
338
339 b = socket_address_bind_ipv6_only_from_string(rvalue);
340 if (b < 0) {
341 int r;
342
343 r = parse_boolean(rvalue);
344 if (r < 0) {
345 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
346 "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
347 return 0;
348 }
349
350 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
351 } else
352 s->bind_ipv6_only = b;
353
354 return 0;
355 }
356
357 int config_parse_exec_nice(const char *unit,
358 const char *filename,
359 unsigned line,
360 const char *section,
361 unsigned section_line,
362 const char *lvalue,
363 int ltype,
364 const char *rvalue,
365 void *data,
366 void *userdata) {
367
368 ExecContext *c = data;
369 int priority, r;
370
371 assert(filename);
372 assert(lvalue);
373 assert(rvalue);
374 assert(data);
375
376 r = safe_atoi(rvalue, &priority);
377 if (r < 0) {
378 log_syntax(unit, LOG_ERR, filename, line, -r,
379 "Failed to parse nice priority, ignoring: %s. ", rvalue);
380 return 0;
381 }
382
383 if (priority < PRIO_MIN || priority >= PRIO_MAX) {
384 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
385 "Nice priority out of range, ignoring: %s", rvalue);
386 return 0;
387 }
388
389 c->nice = priority;
390 c->nice_set = true;
391
392 return 0;
393 }
394
395 int config_parse_exec_oom_score_adjust(const char* unit,
396 const char *filename,
397 unsigned line,
398 const char *section,
399 unsigned section_line,
400 const char *lvalue,
401 int ltype,
402 const char *rvalue,
403 void *data,
404 void *userdata) {
405
406 ExecContext *c = data;
407 int oa, r;
408
409 assert(filename);
410 assert(lvalue);
411 assert(rvalue);
412 assert(data);
413
414 r = safe_atoi(rvalue, &oa);
415 if (r < 0) {
416 log_syntax(unit, LOG_ERR, filename, line, -r,
417 "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
418 return 0;
419 }
420
421 if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
422 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
423 "OOM score adjust value out of range, ignoring: %s", rvalue);
424 return 0;
425 }
426
427 c->oom_score_adjust = oa;
428 c->oom_score_adjust_set = true;
429
430 return 0;
431 }
432
433 int config_parse_exec(const char *unit,
434 const char *filename,
435 unsigned line,
436 const char *section,
437 unsigned section_line,
438 const char *lvalue,
439 int ltype,
440 const char *rvalue,
441 void *data,
442 void *userdata) {
443
444 ExecCommand **e = data, *nce;
445 char *path, **n;
446 unsigned k;
447 int r;
448
449 assert(filename);
450 assert(lvalue);
451 assert(rvalue);
452 assert(e);
453
454 e += ltype;
455
456 if (isempty(rvalue)) {
457 /* An empty assignment resets the list */
458 exec_command_free_list(*e);
459 *e = NULL;
460 return 0;
461 }
462
463 /* We accept an absolute path as first argument, or
464 * alternatively an absolute prefixed with @ to allow
465 * overriding of argv[0]. */
466 for (;;) {
467 int i;
468 char *w;
469 size_t l;
470 char *state;
471 bool honour_argv0 = false, ignore = false;
472
473 path = NULL;
474 nce = NULL;
475 n = NULL;
476
477 rvalue += strspn(rvalue, WHITESPACE);
478
479 if (rvalue[0] == 0)
480 break;
481
482 for (i = 0; i < 2; i++) {
483 if (rvalue[0] == '-' && !ignore) {
484 ignore = true;
485 rvalue ++;
486 }
487
488 if (rvalue[0] == '@' && !honour_argv0) {
489 honour_argv0 = true;
490 rvalue ++;
491 }
492 }
493
494 if (*rvalue != '/') {
495 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
496 "Executable path is not absolute, ignoring: %s", rvalue);
497 return 0;
498 }
499
500 k = 0;
501 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
502 if (strneq(w, ";", MAX(l, 1U)))
503 break;
504
505 k++;
506 }
507
508 n = new(char*, k + !honour_argv0);
509 if (!n)
510 return log_oom();
511
512 k = 0;
513 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
514 if (strneq(w, ";", MAX(l, 1U)))
515 break;
516 else if (strneq(w, "\\;", MAX(l, 1U)))
517 w ++;
518
519 if (honour_argv0 && w == rvalue) {
520 assert(!path);
521
522 path = strndup(w, l);
523 if (!path) {
524 r = log_oom();
525 goto fail;
526 }
527
528 if (!utf8_is_valid(path)) {
529 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
530 "Path is not UTF-8 clean, ignoring assignment: %s",
531 rvalue);
532 r = 0;
533 goto fail;
534 }
535
536 } else {
537 char *c;
538
539 c = n[k++] = cunescape_length(w, l);
540 if (!c) {
541 r = log_oom();
542 goto fail;
543 }
544
545 if (!utf8_is_valid(c)) {
546 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
547 "Path is not UTF-8 clean, ignoring assignment: %s",
548 rvalue);
549 r = 0;
550 goto fail;
551 }
552 }
553 }
554
555 n[k] = NULL;
556
557 if (!n[0]) {
558 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
559 "Invalid command line, ignoring: %s", rvalue);
560 r = 0;
561 goto fail;
562 }
563
564 if (!path) {
565 path = strdup(n[0]);
566 if (!path) {
567 r = log_oom();
568 goto fail;
569 }
570 }
571
572 assert(path_is_absolute(path));
573
574 nce = new0(ExecCommand, 1);
575 if (!nce) {
576 r = log_oom();
577 goto fail;
578 }
579
580 nce->argv = n;
581 nce->path = path;
582 nce->ignore = ignore;
583
584 path_kill_slashes(nce->path);
585
586 exec_command_append_list(e, nce);
587
588 rvalue = state;
589 }
590
591 return 0;
592
593 fail:
594 n[k] = NULL;
595 strv_free(n);
596 free(path);
597 free(nce);
598
599 return r;
600 }
601
602 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
603 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
604
605 int config_parse_socket_bindtodevice(const char* unit,
606 const char *filename,
607 unsigned line,
608 const char *section,
609 unsigned section_line,
610 const char *lvalue,
611 int ltype,
612 const char *rvalue,
613 void *data,
614 void *userdata) {
615
616 Socket *s = data;
617 char *n;
618
619 assert(filename);
620 assert(lvalue);
621 assert(rvalue);
622 assert(data);
623
624 if (rvalue[0] && !streq(rvalue, "*")) {
625 n = strdup(rvalue);
626 if (!n)
627 return log_oom();
628 } else
629 n = NULL;
630
631 free(s->bind_to_device);
632 s->bind_to_device = n;
633
634 return 0;
635 }
636
637 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
638 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
639
640 int config_parse_exec_io_class(const char *unit,
641 const char *filename,
642 unsigned line,
643 const char *section,
644 unsigned section_line,
645 const char *lvalue,
646 int ltype,
647 const char *rvalue,
648 void *data,
649 void *userdata) {
650
651 ExecContext *c = data;
652 int x;
653
654 assert(filename);
655 assert(lvalue);
656 assert(rvalue);
657 assert(data);
658
659 x = ioprio_class_from_string(rvalue);
660 if (x < 0) {
661 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
662 "Failed to parse IO scheduling class, ignoring: %s", rvalue);
663 return 0;
664 }
665
666 c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
667 c->ioprio_set = true;
668
669 return 0;
670 }
671
672 int config_parse_exec_io_priority(const char *unit,
673 const char *filename,
674 unsigned line,
675 const char *section,
676 unsigned section_line,
677 const char *lvalue,
678 int ltype,
679 const char *rvalue,
680 void *data,
681 void *userdata) {
682
683 ExecContext *c = data;
684 int i, r;
685
686 assert(filename);
687 assert(lvalue);
688 assert(rvalue);
689 assert(data);
690
691 r = safe_atoi(rvalue, &i);
692 if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
693 log_syntax(unit, LOG_ERR, filename, line, -r,
694 "Failed to parse IO priority, ignoring: %s", rvalue);
695 return 0;
696 }
697
698 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
699 c->ioprio_set = true;
700
701 return 0;
702 }
703
704 int config_parse_exec_cpu_sched_policy(const char *unit,
705 const char *filename,
706 unsigned line,
707 const char *section,
708 unsigned section_line,
709 const char *lvalue,
710 int ltype,
711 const char *rvalue,
712 void *data,
713 void *userdata) {
714
715
716 ExecContext *c = data;
717 int x;
718
719 assert(filename);
720 assert(lvalue);
721 assert(rvalue);
722 assert(data);
723
724 x = sched_policy_from_string(rvalue);
725 if (x < 0) {
726 log_syntax(unit, LOG_ERR, filename, line, -x,
727 "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
728 return 0;
729 }
730
731 c->cpu_sched_policy = x;
732 /* Moving to or from real-time policy? We need to adjust the priority */
733 c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
734 c->cpu_sched_set = true;
735
736 return 0;
737 }
738
739 int config_parse_exec_cpu_sched_prio(const char *unit,
740 const char *filename,
741 unsigned line,
742 const char *section,
743 unsigned section_line,
744 const char *lvalue,
745 int ltype,
746 const char *rvalue,
747 void *data,
748 void *userdata) {
749
750 ExecContext *c = data;
751 int i, min, max, r;
752
753 assert(filename);
754 assert(lvalue);
755 assert(rvalue);
756 assert(data);
757
758 r = safe_atoi(rvalue, &i);
759 if (r < 0) {
760 log_syntax(unit, LOG_ERR, filename, line, -r,
761 "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
762 return 0;
763 }
764
765 /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
766 min = sched_get_priority_min(c->cpu_sched_policy);
767 max = sched_get_priority_max(c->cpu_sched_policy);
768
769 if (i < min || i > max) {
770 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
771 "CPU scheduling priority is out of range, ignoring: %s", rvalue);
772 return 0;
773 }
774
775 c->cpu_sched_priority = i;
776 c->cpu_sched_set = true;
777
778 return 0;
779 }
780
781 int config_parse_exec_cpu_affinity(const char *unit,
782 const char *filename,
783 unsigned line,
784 const char *section,
785 unsigned section_line,
786 const char *lvalue,
787 int ltype,
788 const char *rvalue,
789 void *data,
790 void *userdata) {
791
792 ExecContext *c = data;
793 char *w;
794 size_t l;
795 char *state;
796
797 assert(filename);
798 assert(lvalue);
799 assert(rvalue);
800 assert(data);
801
802 if (isempty(rvalue)) {
803 /* An empty assignment resets the CPU list */
804 if (c->cpuset)
805 CPU_FREE(c->cpuset);
806 c->cpuset = NULL;
807 return 0;
808 }
809
810 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
811 _cleanup_free_ char *t = NULL;
812 int r;
813 unsigned cpu;
814
815 t = strndup(w, l);
816 if (!t)
817 return log_oom();
818
819 r = safe_atou(t, &cpu);
820
821 if (!c->cpuset) {
822 c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
823 if (!c->cpuset)
824 return log_oom();
825 }
826
827 if (r < 0 || cpu >= c->cpuset_ncpus) {
828 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
829 "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
830 return 0;
831 }
832
833 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
834 }
835
836 return 0;
837 }
838
839 int config_parse_exec_capabilities(const char *unit,
840 const char *filename,
841 unsigned line,
842 const char *section,
843 unsigned section_line,
844 const char *lvalue,
845 int ltype,
846 const char *rvalue,
847 void *data,
848 void *userdata) {
849
850 ExecContext *c = data;
851 cap_t cap;
852
853 assert(filename);
854 assert(lvalue);
855 assert(rvalue);
856 assert(data);
857
858 cap = cap_from_text(rvalue);
859 if (!cap) {
860 log_syntax(unit, LOG_ERR, filename, line, errno,
861 "Failed to parse capabilities, ignoring: %s", rvalue);
862 return 0;
863 }
864
865 if (c->capabilities)
866 cap_free(c->capabilities);
867 c->capabilities = cap;
868
869 return 0;
870 }
871
872 int config_parse_exec_secure_bits(const char *unit,
873 const char *filename,
874 unsigned line,
875 const char *section,
876 unsigned section_line,
877 const char *lvalue,
878 int ltype,
879 const char *rvalue,
880 void *data,
881 void *userdata) {
882
883 ExecContext *c = data;
884 char *w;
885 size_t l;
886 char *state;
887
888 assert(filename);
889 assert(lvalue);
890 assert(rvalue);
891 assert(data);
892
893 if (isempty(rvalue)) {
894 /* An empty assignment resets the field */
895 c->secure_bits = 0;
896 return 0;
897 }
898
899 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
900 if (first_word(w, "keep-caps"))
901 c->secure_bits |= 1<<SECURE_KEEP_CAPS;
902 else if (first_word(w, "keep-caps-locked"))
903 c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
904 else if (first_word(w, "no-setuid-fixup"))
905 c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
906 else if (first_word(w, "no-setuid-fixup-locked"))
907 c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
908 else if (first_word(w, "noroot"))
909 c->secure_bits |= 1<<SECURE_NOROOT;
910 else if (first_word(w, "noroot-locked"))
911 c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
912 else {
913 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
914 "Failed to parse secure bits, ignoring: %s", rvalue);
915 return 0;
916 }
917 }
918
919 return 0;
920 }
921
922 int config_parse_bounding_set(const char *unit,
923 const char *filename,
924 unsigned line,
925 const char *section,
926 unsigned section_line,
927 const char *lvalue,
928 int ltype,
929 const char *rvalue,
930 void *data,
931 void *userdata) {
932
933 uint64_t *capability_bounding_set_drop = data;
934 char *w;
935 size_t l;
936 char *state;
937 bool invert = false;
938 uint64_t sum = 0;
939
940 assert(filename);
941 assert(lvalue);
942 assert(rvalue);
943 assert(data);
944
945 if (rvalue[0] == '~') {
946 invert = true;
947 rvalue++;
948 }
949
950 /* Note that we store this inverted internally, since the
951 * kernel wants it like this. But we actually expose it
952 * non-inverted everywhere to have a fully normalized
953 * interface. */
954
955 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
956 _cleanup_free_ char *t = NULL;
957 int r;
958 cap_value_t cap;
959
960 t = strndup(w, l);
961 if (!t)
962 return log_oom();
963
964 r = cap_from_name(t, &cap);
965 if (r < 0) {
966 log_syntax(unit, LOG_ERR, filename, line, errno,
967 "Failed to parse capability in bounding set, ignoring: %s", t);
968 continue;
969 }
970
971 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
972 }
973
974 if (invert)
975 *capability_bounding_set_drop |= sum;
976 else
977 *capability_bounding_set_drop |= ~sum;
978
979 return 0;
980 }
981
982 int config_parse_limit(const char *unit,
983 const char *filename,
984 unsigned line,
985 const char *section,
986 unsigned section_line,
987 const char *lvalue,
988 int ltype,
989 const char *rvalue,
990 void *data,
991 void *userdata) {
992
993 struct rlimit **rl = data;
994 unsigned long long u;
995
996 assert(filename);
997 assert(lvalue);
998 assert(rvalue);
999 assert(data);
1000
1001 rl += ltype;
1002
1003 if (streq(rvalue, "infinity"))
1004 u = (unsigned long long) RLIM_INFINITY;
1005 else {
1006 int r;
1007
1008 r = safe_atollu(rvalue, &u);
1009 if (r < 0) {
1010 log_syntax(unit, LOG_ERR, filename, line, -r,
1011 "Failed to parse resource value, ignoring: %s", rvalue);
1012 return 0;
1013 }
1014 }
1015
1016 if (!*rl) {
1017 *rl = new(struct rlimit, 1);
1018 if (!*rl)
1019 return log_oom();
1020 }
1021
1022 (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
1023 return 0;
1024 }
1025
1026 #ifdef HAVE_SYSV_COMPAT
1027 int config_parse_sysv_priority(const char *unit,
1028 const char *filename,
1029 unsigned line,
1030 const char *section,
1031 unsigned section_line,
1032 const char *lvalue,
1033 int ltype,
1034 const char *rvalue,
1035 void *data,
1036 void *userdata) {
1037
1038 int *priority = data;
1039 int i, r;
1040
1041 assert(filename);
1042 assert(lvalue);
1043 assert(rvalue);
1044 assert(data);
1045
1046 r = safe_atoi(rvalue, &i);
1047 if (r < 0 || i < 0) {
1048 log_syntax(unit, LOG_ERR, filename, line, -r,
1049 "Failed to parse SysV start priority, ignoring: %s", rvalue);
1050 return 0;
1051 }
1052
1053 *priority = (int) i;
1054 return 0;
1055 }
1056 #endif
1057
1058 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1059
1060 int config_parse_kill_signal(const char *unit,
1061 const char *filename,
1062 unsigned line,
1063 const char *section,
1064 unsigned section_line,
1065 const char *lvalue,
1066 int ltype,
1067 const char *rvalue,
1068 void *data,
1069 void *userdata) {
1070
1071 int *sig = data;
1072 int r;
1073
1074 assert(filename);
1075 assert(lvalue);
1076 assert(rvalue);
1077 assert(sig);
1078
1079 r = signal_from_string_try_harder(rvalue);
1080 if (r <= 0) {
1081 log_syntax(unit, LOG_ERR, filename, line, -r,
1082 "Failed to parse kill signal, ignoring: %s", rvalue);
1083 return 0;
1084 }
1085
1086 *sig = r;
1087 return 0;
1088 }
1089
1090 int config_parse_exec_mount_flags(const char *unit,
1091 const char *filename,
1092 unsigned line,
1093 const char *section,
1094 unsigned section_line,
1095 const char *lvalue,
1096 int ltype,
1097 const char *rvalue,
1098 void *data,
1099 void *userdata) {
1100
1101 ExecContext *c = data;
1102 char *w;
1103 size_t l;
1104 char *state;
1105 unsigned long flags = 0;
1106
1107 assert(filename);
1108 assert(lvalue);
1109 assert(rvalue);
1110 assert(data);
1111
1112 FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1113 _cleanup_free_ char *t;
1114
1115 t = strndup(w, l);
1116 if (!t)
1117 return log_oom();
1118
1119 if (streq(t, "shared"))
1120 flags |= MS_SHARED;
1121 else if (streq(t, "slave"))
1122 flags |= MS_SLAVE;
1123 else if (streq(w, "private"))
1124 flags |= MS_PRIVATE;
1125 else {
1126 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1127 "Failed to parse mount flag %s, ignoring: %s",
1128 t, rvalue);
1129 return 0;
1130 }
1131 }
1132
1133 c->mount_flags = flags;
1134 return 0;
1135 }
1136
1137 int config_parse_timer(const char *unit,
1138 const char *filename,
1139 unsigned line,
1140 const char *section,
1141 unsigned section_line,
1142 const char *lvalue,
1143 int ltype,
1144 const char *rvalue,
1145 void *data,
1146 void *userdata) {
1147
1148 Timer *t = data;
1149 usec_t u = 0;
1150 TimerValue *v;
1151 TimerBase b;
1152 CalendarSpec *c = NULL;
1153 clockid_t id;
1154
1155 assert(filename);
1156 assert(lvalue);
1157 assert(rvalue);
1158 assert(data);
1159
1160 if (isempty(rvalue)) {
1161 /* Empty assignment resets list */
1162 timer_free_values(t);
1163 return 0;
1164 }
1165
1166 b = timer_base_from_string(lvalue);
1167 if (b < 0) {
1168 log_syntax(unit, LOG_ERR, filename, line, -b,
1169 "Failed to parse timer base, ignoring: %s", lvalue);
1170 return 0;
1171 }
1172
1173 if (b == TIMER_CALENDAR) {
1174 if (calendar_spec_from_string(rvalue, &c) < 0) {
1175 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1176 "Failed to parse calendar specification, ignoring: %s",
1177 rvalue);
1178 return 0;
1179 }
1180
1181 id = CLOCK_REALTIME;
1182 } else {
1183 if (parse_sec(rvalue, &u) < 0) {
1184 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1185 "Failed to parse timer value, ignoring: %s",
1186 rvalue);
1187 return 0;
1188 }
1189
1190 id = CLOCK_MONOTONIC;
1191 }
1192
1193 v = new0(TimerValue, 1);
1194 if (!v)
1195 return log_oom();
1196
1197 v->base = b;
1198 v->clock_id = id;
1199 v->value = u;
1200 v->calendar_spec = c;
1201
1202 LIST_PREPEND(value, t->values, v);
1203
1204 return 0;
1205 }
1206
1207 int config_parse_trigger_unit(
1208 const char *unit,
1209 const char *filename,
1210 unsigned line,
1211 const char *section,
1212 unsigned section_line,
1213 const char *lvalue,
1214 int ltype,
1215 const char *rvalue,
1216 void *data,
1217 void *userdata) {
1218
1219 _cleanup_free_ char *p = NULL;
1220 Unit *u = data;
1221 UnitType type;
1222 int r;
1223
1224 assert(filename);
1225 assert(lvalue);
1226 assert(rvalue);
1227 assert(data);
1228
1229 if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1230 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1231 "Multiple units to trigger specified, ignoring: %s", rvalue);
1232 return 0;
1233 }
1234
1235 r = unit_name_printf(u, rvalue, &p);
1236 if (r < 0)
1237 log_syntax(unit, LOG_ERR, filename, line, -r,
1238 "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1239
1240 type = unit_name_to_type(p ?: rvalue);
1241 if (type < 0) {
1242 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1243 "Unit type not valid, ignoring: %s", rvalue);
1244 return 0;
1245 }
1246
1247 if (type == u->type) {
1248 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1249 "Trigger cannot be of same type, ignoring: %s", rvalue);
1250 return 0;
1251 }
1252
1253 r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1254 if (r < 0) {
1255 log_syntax(unit, LOG_ERR, filename, line, -r,
1256 "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1257 return 0;
1258 }
1259
1260 return 0;
1261 }
1262
1263 int config_parse_path_spec(const char *unit,
1264 const char *filename,
1265 unsigned line,
1266 const char *section,
1267 unsigned section_line,
1268 const char *lvalue,
1269 int ltype,
1270 const char *rvalue,
1271 void *data,
1272 void *userdata) {
1273
1274 Path *p = data;
1275 PathSpec *s;
1276 PathType b;
1277 _cleanup_free_ char *k = NULL;
1278 int r;
1279
1280 assert(filename);
1281 assert(lvalue);
1282 assert(rvalue);
1283 assert(data);
1284
1285 if (isempty(rvalue)) {
1286 /* Empty assignment clears list */
1287 path_free_specs(p);
1288 return 0;
1289 }
1290
1291 b = path_type_from_string(lvalue);
1292 if (b < 0) {
1293 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1294 "Failed to parse path type, ignoring: %s", lvalue);
1295 return 0;
1296 }
1297
1298 r = unit_full_printf(UNIT(p), rvalue, &k);
1299 if (r < 0) {
1300 k = strdup(rvalue);
1301 if (!k)
1302 return log_oom();
1303 else
1304 log_syntax(unit, LOG_ERR, filename, line, -r,
1305 "Failed to resolve unit specifiers on %s. Ignoring.",
1306 rvalue);
1307 }
1308
1309 if (!path_is_absolute(k)) {
1310 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1311 "Path is not absolute, ignoring: %s", k);
1312 return 0;
1313 }
1314
1315 s = new0(PathSpec, 1);
1316 if (!s)
1317 return log_oom();
1318
1319 s->unit = UNIT(p);
1320 s->path = path_kill_slashes(k);
1321 k = NULL;
1322 s->type = b;
1323 s->inotify_fd = -1;
1324
1325 LIST_PREPEND(spec, p->specs, s);
1326
1327 return 0;
1328 }
1329
1330 int config_parse_socket_service(const char *unit,
1331 const char *filename,
1332 unsigned line,
1333 const char *section,
1334 unsigned section_line,
1335 const char *lvalue,
1336 int ltype,
1337 const char *rvalue,
1338 void *data,
1339 void *userdata) {
1340
1341 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1342 Socket *s = data;
1343 int r;
1344 Unit *x;
1345 _cleanup_free_ char *p = NULL;
1346
1347 assert(filename);
1348 assert(lvalue);
1349 assert(rvalue);
1350 assert(data);
1351
1352 r = unit_name_printf(UNIT(s), rvalue, &p);
1353 if (r < 0) {
1354 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1355 return 0;
1356 }
1357
1358 if (!endswith(p, ".service")) {
1359 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1360 return 0;
1361 }
1362
1363 r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1364 if (r < 0) {
1365 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1366 return 0;
1367 }
1368
1369 unit_ref_set(&s->service, x);
1370
1371 return 0;
1372 }
1373
1374 int config_parse_service_sockets(const char *unit,
1375 const char *filename,
1376 unsigned line,
1377 const char *section,
1378 unsigned section_line,
1379 const char *lvalue,
1380 int ltype,
1381 const char *rvalue,
1382 void *data,
1383 void *userdata) {
1384
1385 Service *s = data;
1386 int r;
1387 char *state, *w;
1388 size_t l;
1389
1390 assert(filename);
1391 assert(lvalue);
1392 assert(rvalue);
1393 assert(data);
1394
1395 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1396 _cleanup_free_ char *t = NULL, *k = NULL;
1397
1398 t = strndup(w, l);
1399 if (!t)
1400 return log_oom();
1401
1402 r = unit_name_printf(UNIT(s), t, &k);
1403 if (r < 0)
1404 log_syntax(unit, LOG_ERR, filename, line, -r,
1405 "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1406
1407 if (!endswith(k ?: t, ".socket")) {
1408 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1409 "Unit must be of type socket, ignoring: %s", k ?: t);
1410 continue;
1411 }
1412
1413 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1414 if (r < 0)
1415 log_syntax(unit, LOG_ERR, filename, line, -r,
1416 "Failed to add dependency on %s, ignoring: %s",
1417 k ?: t, strerror(-r));
1418
1419 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1420 if (r < 0)
1421 return r;
1422 }
1423
1424 return 0;
1425 }
1426
1427 int config_parse_service_timeout(const char *unit,
1428 const char *filename,
1429 unsigned line,
1430 const char *section,
1431 unsigned section_line,
1432 const char *lvalue,
1433 int ltype,
1434 const char *rvalue,
1435 void *data,
1436 void *userdata) {
1437
1438 Service *s = userdata;
1439 int r;
1440
1441 assert(filename);
1442 assert(lvalue);
1443 assert(rvalue);
1444 assert(s);
1445
1446 r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1447 rvalue, data, userdata);
1448 if (r < 0)
1449 return r;
1450
1451 if (streq(lvalue, "TimeoutSec")) {
1452 s->start_timeout_defined = true;
1453 s->timeout_stop_usec = s->timeout_start_usec;
1454 } else if (streq(lvalue, "TimeoutStartSec"))
1455 s->start_timeout_defined = true;
1456
1457 return 0;
1458 }
1459
1460 int config_parse_busname_service(
1461 const char *unit,
1462 const char *filename,
1463 unsigned line,
1464 const char *section,
1465 unsigned section_line,
1466 const char *lvalue,
1467 int ltype,
1468 const char *rvalue,
1469 void *data,
1470 void *userdata) {
1471
1472 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1473 BusName *n = data;
1474 int r;
1475 Unit *x;
1476 _cleanup_free_ char *p = NULL;
1477
1478 assert(filename);
1479 assert(lvalue);
1480 assert(rvalue);
1481 assert(data);
1482
1483 r = unit_name_printf(UNIT(n), rvalue, &p);
1484 if (r < 0) {
1485 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1486 return 0;
1487 }
1488
1489 if (!endswith(p, ".service")) {
1490 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1491 return 0;
1492 }
1493
1494 r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1495 if (r < 0) {
1496 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1497 return 0;
1498 }
1499
1500 unit_ref_set(&n->service, x);
1501
1502 return 0;
1503 }
1504
1505 int config_parse_unit_env_file(const char *unit,
1506 const char *filename,
1507 unsigned line,
1508 const char *section,
1509 unsigned section_line,
1510 const char *lvalue,
1511 int ltype,
1512 const char *rvalue,
1513 void *data,
1514 void *userdata) {
1515
1516 char ***env = data;
1517 Unit *u = userdata;
1518 _cleanup_free_ char *n = NULL;
1519 const char *s;
1520 int r;
1521
1522 assert(filename);
1523 assert(lvalue);
1524 assert(rvalue);
1525 assert(data);
1526
1527 if (isempty(rvalue)) {
1528 /* Empty assignment frees the list */
1529 strv_free(*env);
1530 *env = NULL;
1531 return 0;
1532 }
1533
1534 r = unit_full_printf(u, rvalue, &n);
1535 if (r < 0)
1536 log_syntax(unit, LOG_ERR, filename, line, r,
1537 "Failed to resolve specifiers, ignoring: %s", rvalue);
1538
1539 s = n ?: rvalue;
1540 if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1541 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1542 "Path '%s' is not absolute, ignoring.", s);
1543 return 0;
1544 }
1545
1546 r = strv_extend(env, s);
1547 if (r < 0)
1548 return log_oom();
1549
1550 return 0;
1551 }
1552
1553 int config_parse_environ(const char *unit,
1554 const char *filename,
1555 unsigned line,
1556 const char *section,
1557 unsigned section_line,
1558 const char *lvalue,
1559 int ltype,
1560 const char *rvalue,
1561 void *data,
1562 void *userdata) {
1563
1564 Unit *u = userdata;
1565 char*** env = data, *w, *state;
1566 size_t l;
1567 _cleanup_free_ char *k = NULL;
1568 int r;
1569
1570 assert(filename);
1571 assert(lvalue);
1572 assert(rvalue);
1573 assert(data);
1574
1575 if (isempty(rvalue)) {
1576 /* Empty assignment resets the list */
1577 strv_free(*env);
1578 *env = NULL;
1579 return 0;
1580 }
1581
1582 if (u) {
1583 r = unit_full_printf(u, rvalue, &k);
1584 if (r < 0)
1585 log_syntax(unit, LOG_ERR, filename, line, -r,
1586 "Failed to resolve specifiers, ignoring: %s", rvalue);
1587 }
1588
1589 if (!k)
1590 k = strdup(rvalue);
1591 if (!k)
1592 return log_oom();
1593
1594 FOREACH_WORD_QUOTED(w, l, k, state) {
1595 _cleanup_free_ char *n;
1596 char **x;
1597
1598 n = cunescape_length(w, l);
1599 if (!n)
1600 return log_oom();
1601
1602 if (!env_assignment_is_valid(n)) {
1603 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1604 "Invalid environment assignment, ignoring: %s", rvalue);
1605 continue;
1606 }
1607
1608 x = strv_env_set(*env, n);
1609 if (!x)
1610 return log_oom();
1611
1612 strv_free(*env);
1613 *env = x;
1614 }
1615
1616 return 0;
1617 }
1618
1619 int config_parse_ip_tos(const char *unit,
1620 const char *filename,
1621 unsigned line,
1622 const char *section,
1623 unsigned section_line,
1624 const char *lvalue,
1625 int ltype,
1626 const char *rvalue,
1627 void *data,
1628 void *userdata) {
1629
1630 int *ip_tos = data, x;
1631
1632 assert(filename);
1633 assert(lvalue);
1634 assert(rvalue);
1635 assert(data);
1636
1637 x = ip_tos_from_string(rvalue);
1638 if (x < 0) {
1639 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1640 "Failed to parse IP TOS value, ignoring: %s", rvalue);
1641 return 0;
1642 }
1643
1644 *ip_tos = x;
1645 return 0;
1646 }
1647
1648 int config_parse_unit_condition_path(const char *unit,
1649 const char *filename,
1650 unsigned line,
1651 const char *section,
1652 unsigned section_line,
1653 const char *lvalue,
1654 int ltype,
1655 const char *rvalue,
1656 void *data,
1657 void *userdata) {
1658
1659 ConditionType cond = ltype;
1660 Unit *u = data;
1661 bool trigger, negate;
1662 Condition *c;
1663 _cleanup_free_ char *p = NULL;
1664 int r;
1665
1666 assert(filename);
1667 assert(lvalue);
1668 assert(rvalue);
1669 assert(data);
1670
1671 if (isempty(rvalue)) {
1672 /* Empty assignment resets the list */
1673 condition_free_list(u->conditions);
1674 u->conditions = NULL;
1675 return 0;
1676 }
1677
1678 trigger = rvalue[0] == '|';
1679 if (trigger)
1680 rvalue++;
1681
1682 negate = rvalue[0] == '!';
1683 if (negate)
1684 rvalue++;
1685
1686 r = unit_full_printf(u, rvalue, &p);
1687 if (r < 0)
1688 log_syntax(unit, LOG_ERR, filename, line, -r,
1689 "Failed to resolve specifiers, ignoring: %s", rvalue);
1690 if (!p) {
1691 p = strdup(rvalue);
1692 if (!p)
1693 return log_oom();
1694 }
1695
1696 if (!path_is_absolute(p)) {
1697 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1698 "Path in condition not absolute, ignoring: %s", p);
1699 return 0;
1700 }
1701
1702 c = condition_new(cond, p, trigger, negate);
1703 if (!c)
1704 return log_oom();
1705
1706 LIST_PREPEND(conditions, u->conditions, c);
1707 return 0;
1708 }
1709
1710 int config_parse_unit_condition_string(const char *unit,
1711 const char *filename,
1712 unsigned line,
1713 const char *section,
1714 unsigned section_line,
1715 const char *lvalue,
1716 int ltype,
1717 const char *rvalue,
1718 void *data,
1719 void *userdata) {
1720
1721 ConditionType cond = ltype;
1722 Unit *u = data;
1723 bool trigger, negate;
1724 Condition *c;
1725 _cleanup_free_ char *s = NULL;
1726 int r;
1727
1728 assert(filename);
1729 assert(lvalue);
1730 assert(rvalue);
1731 assert(data);
1732
1733 if (isempty(rvalue)) {
1734 /* Empty assignment resets the list */
1735 condition_free_list(u->conditions);
1736 u->conditions = NULL;
1737 return 0;
1738 }
1739
1740 trigger = rvalue[0] == '|';
1741 if (trigger)
1742 rvalue++;
1743
1744 negate = rvalue[0] == '!';
1745 if (negate)
1746 rvalue++;
1747
1748 r = unit_full_printf(u, rvalue, &s);
1749 if (r < 0)
1750 log_syntax(unit, LOG_ERR, filename, line, -r,
1751 "Failed to resolve specifiers, ignoring: %s", rvalue);
1752 if (!s) {
1753 s = strdup(rvalue);
1754 if (!s)
1755 return log_oom();
1756 }
1757
1758 c = condition_new(cond, s, trigger, negate);
1759 if (!c)
1760 return log_oom();
1761
1762 LIST_PREPEND(conditions, u->conditions, c);
1763 return 0;
1764 }
1765
1766 int config_parse_unit_condition_null(const char *unit,
1767 const char *filename,
1768 unsigned line,
1769 const char *section,
1770 unsigned section_line,
1771 const char *lvalue,
1772 int ltype,
1773 const char *rvalue,
1774 void *data,
1775 void *userdata) {
1776
1777 Unit *u = data;
1778 Condition *c;
1779 bool trigger, negate;
1780 int b;
1781
1782 assert(filename);
1783 assert(lvalue);
1784 assert(rvalue);
1785 assert(data);
1786
1787 if (isempty(rvalue)) {
1788 /* Empty assignment resets the list */
1789 condition_free_list(u->conditions);
1790 u->conditions = NULL;
1791 return 0;
1792 }
1793
1794 trigger = rvalue[0] == '|';
1795 if (trigger)
1796 rvalue++;
1797
1798 negate = rvalue[0] == '!';
1799 if (negate)
1800 rvalue++;
1801
1802 b = parse_boolean(rvalue);
1803 if (b < 0) {
1804 log_syntax(unit, LOG_ERR, filename, line, -b,
1805 "Failed to parse boolean value in condition, ignoring: %s",
1806 rvalue);
1807 return 0;
1808 }
1809
1810 if (!b)
1811 negate = !negate;
1812
1813 c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1814 if (!c)
1815 return log_oom();
1816
1817 LIST_PREPEND(conditions, u->conditions, c);
1818 return 0;
1819 }
1820
1821 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1822 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
1823
1824 int config_parse_unit_requires_mounts_for(
1825 const char *unit,
1826 const char *filename,
1827 unsigned line,
1828 const char *section,
1829 unsigned section_line,
1830 const char *lvalue,
1831 int ltype,
1832 const char *rvalue,
1833 void *data,
1834 void *userdata) {
1835
1836 Unit *u = userdata;
1837 char *state;
1838 size_t l;
1839 char *w;
1840
1841 assert(filename);
1842 assert(lvalue);
1843 assert(rvalue);
1844 assert(data);
1845
1846 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1847 int r;
1848 _cleanup_free_ char *n;
1849
1850 n = strndup(w, l);
1851 if (!n)
1852 return log_oom();
1853
1854 if (!utf8_is_valid(n)) {
1855 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1856 "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
1857 continue;
1858 }
1859
1860 r = unit_require_mounts_for(u, n);
1861 if (r < 0) {
1862 log_syntax(unit, LOG_ERR, filename, line, r,
1863 "Failed to add required mount for, ignoring: %s", rvalue);
1864 continue;
1865 }
1866 }
1867
1868 return 0;
1869 }
1870
1871 int config_parse_documentation(const char *unit,
1872 const char *filename,
1873 unsigned line,
1874 const char *section,
1875 unsigned section_line,
1876 const char *lvalue,
1877 int ltype,
1878 const char *rvalue,
1879 void *data,
1880 void *userdata) {
1881
1882 Unit *u = userdata;
1883 int r;
1884 char **a, **b;
1885
1886 assert(filename);
1887 assert(lvalue);
1888 assert(rvalue);
1889 assert(u);
1890
1891 if (isempty(rvalue)) {
1892 /* Empty assignment resets the list */
1893 strv_free(u->documentation);
1894 u->documentation = NULL;
1895 return 0;
1896 }
1897
1898 r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
1899 rvalue, data, userdata);
1900 if (r < 0)
1901 return r;
1902
1903 for (a = b = u->documentation; a && *a; a++) {
1904
1905 if (is_valid_documentation_url(*a))
1906 *(b++) = *a;
1907 else {
1908 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1909 "Invalid URL, ignoring: %s", *a);
1910 free(*a);
1911 }
1912 }
1913 if (b)
1914 *b = NULL;
1915
1916 return r;
1917 }
1918
1919 static void syscall_set(uint32_t *p, int nr) {
1920 nr = SYSCALL_TO_INDEX(nr);
1921 p[nr >> 4] |= 1 << (nr & 31);
1922 }
1923
1924 static void syscall_unset(uint32_t *p, int nr) {
1925 nr = SYSCALL_TO_INDEX(nr);
1926 p[nr >> 4] &= ~(1 << (nr & 31));
1927 }
1928
1929 int config_parse_syscall_filter(const char *unit,
1930 const char *filename,
1931 unsigned line,
1932 const char *section,
1933 unsigned section_line,
1934 const char *lvalue,
1935 int ltype,
1936 const char *rvalue,
1937 void *data,
1938 void *userdata) {
1939
1940 ExecContext *c = data;
1941 Unit *u = userdata;
1942 bool invert = false;
1943 char *w;
1944 size_t l;
1945 char *state;
1946
1947 assert(filename);
1948 assert(lvalue);
1949 assert(rvalue);
1950 assert(u);
1951
1952 if (isempty(rvalue)) {
1953 /* Empty assignment resets the list */
1954 free(c->syscall_filter);
1955 c->syscall_filter = NULL;
1956 return 0;
1957 }
1958
1959 if (rvalue[0] == '~') {
1960 invert = true;
1961 rvalue++;
1962 }
1963
1964 if (!c->syscall_filter) {
1965 size_t n;
1966
1967 n = (syscall_max() + 31) >> 4;
1968 c->syscall_filter = new(uint32_t, n);
1969 if (!c->syscall_filter)
1970 return log_oom();
1971
1972 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
1973
1974 /* Add these by default */
1975 syscall_set(c->syscall_filter, __NR_execve);
1976 syscall_set(c->syscall_filter, __NR_rt_sigreturn);
1977 #ifdef __NR_sigreturn
1978 syscall_set(c->syscall_filter, __NR_sigreturn);
1979 #endif
1980 syscall_set(c->syscall_filter, __NR_exit_group);
1981 syscall_set(c->syscall_filter, __NR_exit);
1982 }
1983
1984 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1985 int id;
1986 _cleanup_free_ char *t = NULL;
1987
1988 t = strndup(w, l);
1989 if (!t)
1990 return log_oom();
1991
1992 id = syscall_from_name(t);
1993 if (id < 0) {
1994 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1995 "Failed to parse syscall, ignoring: %s", t);
1996 continue;
1997 }
1998
1999 if (invert)
2000 syscall_unset(c->syscall_filter, id);
2001 else
2002 syscall_set(c->syscall_filter, id);
2003 }
2004
2005 c->no_new_privileges = true;
2006
2007 return 0;
2008 }
2009
2010 int config_parse_unit_slice(
2011 const char *unit,
2012 const char *filename,
2013 unsigned line,
2014 const char *section,
2015 unsigned section_line,
2016 const char *lvalue,
2017 int ltype,
2018 const char *rvalue,
2019 void *data,
2020 void *userdata) {
2021
2022 _cleanup_free_ char *k = NULL;
2023 Unit *u = userdata, *slice;
2024 int r;
2025
2026 assert(filename);
2027 assert(lvalue);
2028 assert(rvalue);
2029 assert(u);
2030
2031 r = unit_name_printf(u, rvalue, &k);
2032 if (r < 0)
2033 log_syntax(unit, LOG_ERR, filename, line, -r,
2034 "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2035 if (!k) {
2036 k = strdup(rvalue);
2037 if (!k)
2038 return log_oom();
2039 }
2040
2041 r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2042 if (r < 0) {
2043 log_syntax(unit, LOG_ERR, filename, line, -r,
2044 "Failed to load slice unit %s. Ignoring.", k);
2045 return 0;
2046 }
2047
2048 if (slice->type != UNIT_SLICE) {
2049 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2050 "Slice unit %s is not a slice. Ignoring.", k);
2051 return 0;
2052 }
2053
2054 unit_ref_set(&u->slice, slice);
2055 return 0;
2056 }
2057
2058 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2059
2060 int config_parse_cpu_shares(
2061 const char *unit,
2062 const char *filename,
2063 unsigned line,
2064 const char *section,
2065 unsigned section_line,
2066 const char *lvalue,
2067 int ltype,
2068 const char *rvalue,
2069 void *data,
2070 void *userdata) {
2071
2072 CGroupContext *c = data;
2073 unsigned long lu;
2074 int r;
2075
2076 assert(filename);
2077 assert(lvalue);
2078 assert(rvalue);
2079
2080 if (isempty(rvalue)) {
2081 c->cpu_shares = 1024;
2082 return 0;
2083 }
2084
2085 r = safe_atolu(rvalue, &lu);
2086 if (r < 0 || lu <= 0) {
2087 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2088 "CPU shares '%s' invalid. Ignoring.", rvalue);
2089 return 0;
2090 }
2091
2092 c->cpu_shares = lu;
2093 return 0;
2094 }
2095
2096 int config_parse_memory_limit(
2097 const char *unit,
2098 const char *filename,
2099 unsigned line,
2100 const char *section,
2101 unsigned section_line,
2102 const char *lvalue,
2103 int ltype,
2104 const char *rvalue,
2105 void *data,
2106 void *userdata) {
2107
2108 CGroupContext *c = data;
2109 off_t bytes;
2110 int r;
2111
2112 if (isempty(rvalue)) {
2113 c->memory_limit = (uint64_t) -1;
2114 return 0;
2115 }
2116
2117 assert_cc(sizeof(uint64_t) == sizeof(off_t));
2118
2119 r = parse_bytes(rvalue, &bytes);
2120 if (r < 0) {
2121 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2122 "Memory limit '%s' invalid. Ignoring.", rvalue);
2123 return 0;
2124 }
2125
2126 c->memory_limit = (uint64_t) bytes;
2127 return 0;
2128 }
2129
2130 int config_parse_device_allow(
2131 const char *unit,
2132 const char *filename,
2133 unsigned line,
2134 const char *section,
2135 unsigned section_line,
2136 const char *lvalue,
2137 int ltype,
2138 const char *rvalue,
2139 void *data,
2140 void *userdata) {
2141
2142 _cleanup_free_ char *path = NULL;
2143 CGroupContext *c = data;
2144 CGroupDeviceAllow *a;
2145 const char *m;
2146 size_t n;
2147
2148 if (isempty(rvalue)) {
2149 while (c->device_allow)
2150 cgroup_context_free_device_allow(c, c->device_allow);
2151
2152 return 0;
2153 }
2154
2155 n = strcspn(rvalue, WHITESPACE);
2156 path = strndup(rvalue, n);
2157 if (!path)
2158 return log_oom();
2159
2160 if (!path_startswith(path, "/dev")) {
2161 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2162 "Invalid device node path '%s'. Ignoring.", path);
2163 return 0;
2164 }
2165
2166 m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2167 if (isempty(m))
2168 m = "rwm";
2169
2170 if (!in_charset(m, "rwm")) {
2171 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2172 "Invalid device rights '%s'. Ignoring.", m);
2173 return 0;
2174 }
2175
2176 a = new0(CGroupDeviceAllow, 1);
2177 if (!a)
2178 return log_oom();
2179
2180 a->path = path;
2181 path = NULL;
2182 a->r = !!strchr(m, 'r');
2183 a->w = !!strchr(m, 'w');
2184 a->m = !!strchr(m, 'm');
2185
2186 LIST_PREPEND(device_allow, c->device_allow, a);
2187 return 0;
2188 }
2189
2190 int config_parse_blockio_weight(
2191 const char *unit,
2192 const char *filename,
2193 unsigned line,
2194 const char *section,
2195 unsigned section_line,
2196 const char *lvalue,
2197 int ltype,
2198 const char *rvalue,
2199 void *data,
2200 void *userdata) {
2201
2202 CGroupContext *c = data;
2203 unsigned long lu;
2204 int r;
2205
2206 assert(filename);
2207 assert(lvalue);
2208 assert(rvalue);
2209
2210 if (isempty(rvalue)) {
2211 c->blockio_weight = 1000;
2212 return 0;
2213 }
2214
2215 r = safe_atolu(rvalue, &lu);
2216 if (r < 0 || lu < 10 || lu > 1000) {
2217 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2218 "Block IO weight '%s' invalid. Ignoring.", rvalue);
2219 return 0;
2220 }
2221
2222 c->blockio_weight = lu;
2223
2224 return 0;
2225 }
2226
2227 int config_parse_blockio_device_weight(
2228 const char *unit,
2229 const char *filename,
2230 unsigned line,
2231 const char *section,
2232 unsigned section_line,
2233 const char *lvalue,
2234 int ltype,
2235 const char *rvalue,
2236 void *data,
2237 void *userdata) {
2238
2239 _cleanup_free_ char *path = NULL;
2240 CGroupBlockIODeviceWeight *w;
2241 CGroupContext *c = data;
2242 unsigned long lu;
2243 const char *weight;
2244 size_t n;
2245 int r;
2246
2247 assert(filename);
2248 assert(lvalue);
2249 assert(rvalue);
2250
2251 if (isempty(rvalue)) {
2252 while (c->blockio_device_weights)
2253 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2254
2255 return 0;
2256 }
2257
2258 n = strcspn(rvalue, WHITESPACE);
2259 weight = rvalue + n;
2260 if (!*weight) {
2261 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2262 "Expected block device and device weight. Ignoring.");
2263 return 0;
2264 }
2265
2266 path = strndup(rvalue, n);
2267 if (!path)
2268 return log_oom();
2269
2270 if (!path_startswith(path, "/dev")) {
2271 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2272 "Invalid device node path '%s'. Ignoring.", path);
2273 return 0;
2274 }
2275
2276 weight += strspn(weight, WHITESPACE);
2277 r = safe_atolu(weight, &lu);
2278 if (r < 0 || lu < 10 || lu > 1000) {
2279 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2280 "Block IO weight '%s' invalid. Ignoring.", rvalue);
2281 return 0;
2282 }
2283
2284
2285 w = new0(CGroupBlockIODeviceWeight, 1);
2286 if (!w)
2287 return log_oom();
2288
2289 w->path = path;
2290 path = NULL;
2291
2292 w->weight = lu;
2293
2294 LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2295 return 0;
2296 }
2297
2298 int config_parse_blockio_bandwidth(
2299 const char *unit,
2300 const char *filename,
2301 unsigned line,
2302 const char *section,
2303 unsigned section_line,
2304 const char *lvalue,
2305 int ltype,
2306 const char *rvalue,
2307 void *data,
2308 void *userdata) {
2309
2310 _cleanup_free_ char *path = NULL;
2311 CGroupBlockIODeviceBandwidth *b;
2312 CGroupContext *c = data;
2313 const char *bandwidth;
2314 off_t bytes;
2315 bool read;
2316 size_t n;
2317 int r;
2318
2319 assert(filename);
2320 assert(lvalue);
2321 assert(rvalue);
2322
2323 read = streq("BlockIOReadBandwidth", lvalue);
2324
2325 if (isempty(rvalue)) {
2326 CGroupBlockIODeviceBandwidth *next;
2327
2328 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2329 if (b->read == read)
2330 cgroup_context_free_blockio_device_bandwidth(c, b);
2331
2332 return 0;
2333 }
2334
2335 n = strcspn(rvalue, WHITESPACE);
2336 bandwidth = rvalue + n;
2337 bandwidth += strspn(bandwidth, WHITESPACE);
2338
2339 if (!*bandwidth) {
2340 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2341 "Expected space separated pair of device node and bandwidth. Ignoring.");
2342 return 0;
2343 }
2344
2345 path = strndup(rvalue, n);
2346 if (!path)
2347 return log_oom();
2348
2349 if (!path_startswith(path, "/dev")) {
2350 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2351 "Invalid device node path '%s'. Ignoring.", path);
2352 return 0;
2353 }
2354
2355 r = parse_bytes(bandwidth, &bytes);
2356 if (r < 0 || bytes <= 0) {
2357 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2358 "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2359 return 0;
2360 }
2361
2362 b = new0(CGroupBlockIODeviceBandwidth, 1);
2363 if (!b)
2364 return log_oom();
2365
2366 b->path = path;
2367 path = NULL;
2368 b->bandwidth = (uint64_t) bytes;
2369 b->read = read;
2370
2371 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2372
2373 return 0;
2374 }
2375
2376 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
2377
2378 int config_parse_job_mode_isolate(
2379 const char *unit,
2380 const char *filename,
2381 unsigned line,
2382 const char *section,
2383 unsigned section_line,
2384 const char *lvalue,
2385 int ltype,
2386 const char *rvalue,
2387 void *data,
2388 void *userdata) {
2389
2390 JobMode *m = data;
2391 int r;
2392
2393 assert(filename);
2394 assert(lvalue);
2395 assert(rvalue);
2396
2397 r = parse_boolean(rvalue);
2398 if (r < 0) {
2399 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse boolean, ignoring: %s", rvalue);
2400 return 0;
2401 }
2402
2403 *m = r ? JOB_ISOLATE : JOB_REPLACE;
2404 return 0;
2405 }
2406
2407 #define FOLLOW_MAX 8
2408
2409 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2410 unsigned c = 0;
2411 int fd, r;
2412 FILE *f;
2413 char *id = NULL;
2414
2415 assert(filename);
2416 assert(*filename);
2417 assert(_f);
2418 assert(names);
2419
2420 /* This will update the filename pointer if the loaded file is
2421 * reached by a symlink. The old string will be freed. */
2422
2423 for (;;) {
2424 char *target, *name;
2425
2426 if (c++ >= FOLLOW_MAX)
2427 return -ELOOP;
2428
2429 path_kill_slashes(*filename);
2430
2431 /* Add the file name we are currently looking at to
2432 * the names of this unit, but only if it is a valid
2433 * unit name. */
2434 name = basename(*filename);
2435
2436 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
2437
2438 id = set_get(names, name);
2439 if (!id) {
2440 id = strdup(name);
2441 if (!id)
2442 return -ENOMEM;
2443
2444 r = set_consume(names, id);
2445 if (r < 0)
2446 return r;
2447 }
2448 }
2449
2450 /* Try to open the file name, but don't if its a symlink */
2451 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2452 if (fd >= 0)
2453 break;
2454
2455 if (errno != ELOOP)
2456 return -errno;
2457
2458 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2459 r = readlink_and_make_absolute(*filename, &target);
2460 if (r < 0)
2461 return r;
2462
2463 free(*filename);
2464 *filename = target;
2465 }
2466
2467 f = fdopen(fd, "re");
2468 if (!f) {
2469 r = -errno;
2470 close_nointr_nofail(fd);
2471 return r;
2472 }
2473
2474 *_f = f;
2475 *_final = id;
2476 return 0;
2477 }
2478
2479 static int merge_by_names(Unit **u, Set *names, const char *id) {
2480 char *k;
2481 int r;
2482
2483 assert(u);
2484 assert(*u);
2485 assert(names);
2486
2487 /* Let's try to add in all symlink names we found */
2488 while ((k = set_steal_first(names))) {
2489
2490 /* First try to merge in the other name into our
2491 * unit */
2492 r = unit_merge_by_name(*u, k);
2493 if (r < 0) {
2494 Unit *other;
2495
2496 /* Hmm, we couldn't merge the other unit into
2497 * ours? Then let's try it the other way
2498 * round */
2499
2500 other = manager_get_unit((*u)->manager, k);
2501 free(k);
2502
2503 if (other) {
2504 r = unit_merge(other, *u);
2505 if (r >= 0) {
2506 *u = other;
2507 return merge_by_names(u, names, NULL);
2508 }
2509 }
2510
2511 return r;
2512 }
2513
2514 if (id == k)
2515 unit_choose_id(*u, id);
2516
2517 free(k);
2518 }
2519
2520 return 0;
2521 }
2522
2523 static int load_from_path(Unit *u, const char *path) {
2524 int r;
2525 _cleanup_set_free_free_ Set *symlink_names = NULL;
2526 _cleanup_fclose_ FILE *f = NULL;
2527 _cleanup_free_ char *filename = NULL;
2528 char *id = NULL;
2529 Unit *merged;
2530 struct stat st;
2531
2532 assert(u);
2533 assert(path);
2534
2535 symlink_names = set_new(string_hash_func, string_compare_func);
2536 if (!symlink_names)
2537 return -ENOMEM;
2538
2539 if (path_is_absolute(path)) {
2540
2541 filename = strdup(path);
2542 if (!filename)
2543 return -ENOMEM;
2544
2545 r = open_follow(&filename, &f, symlink_names, &id);
2546 if (r < 0) {
2547 free(filename);
2548 filename = NULL;
2549
2550 if (r != -ENOENT)
2551 return r;
2552 }
2553
2554 } else {
2555 char **p;
2556
2557 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2558
2559 /* Instead of opening the path right away, we manually
2560 * follow all symlinks and add their name to our unit
2561 * name set while doing so */
2562 filename = path_make_absolute(path, *p);
2563 if (!filename)
2564 return -ENOMEM;
2565
2566 if (u->manager->unit_path_cache &&
2567 !set_get(u->manager->unit_path_cache, filename))
2568 r = -ENOENT;
2569 else
2570 r = open_follow(&filename, &f, symlink_names, &id);
2571
2572 if (r < 0) {
2573 free(filename);
2574 filename = NULL;
2575
2576 if (r != -ENOENT)
2577 return r;
2578
2579 /* Empty the symlink names for the next run */
2580 set_clear_free(symlink_names);
2581 continue;
2582 }
2583
2584 break;
2585 }
2586 }
2587
2588 if (!filename)
2589 /* Hmm, no suitable file found? */
2590 return 0;
2591
2592 merged = u;
2593 r = merge_by_names(&merged, symlink_names, id);
2594 if (r < 0)
2595 return r;
2596
2597 if (merged != u) {
2598 u->load_state = UNIT_MERGED;
2599 return 0;
2600 }
2601
2602 if (fstat(fileno(f), &st) < 0)
2603 return -errno;
2604
2605 if (null_or_empty(&st))
2606 u->load_state = UNIT_MASKED;
2607 else {
2608 u->load_state = UNIT_LOADED;
2609
2610 /* Now, parse the file contents */
2611 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
2612 config_item_perf_lookup,
2613 (void*) load_fragment_gperf_lookup, false, true, u);
2614 if (r < 0)
2615 return r;
2616 }
2617
2618 free(u->fragment_path);
2619 u->fragment_path = filename;
2620 filename = NULL;
2621
2622 u->fragment_mtime = timespec_load(&st.st_mtim);
2623
2624 if (u->source_path) {
2625 if (stat(u->source_path, &st) >= 0)
2626 u->source_mtime = timespec_load(&st.st_mtim);
2627 else
2628 u->source_mtime = 0;
2629 }
2630
2631 return 0;
2632 }
2633
2634 int unit_load_fragment(Unit *u) {
2635 int r;
2636 Iterator i;
2637 const char *t;
2638
2639 assert(u);
2640 assert(u->load_state == UNIT_STUB);
2641 assert(u->id);
2642
2643 /* First, try to find the unit under its id. We always look
2644 * for unit files in the default directories, to make it easy
2645 * to override things by placing things in /etc/systemd/system */
2646 r = load_from_path(u, u->id);
2647 if (r < 0)
2648 return r;
2649
2650 /* Try to find an alias we can load this with */
2651 if (u->load_state == UNIT_STUB)
2652 SET_FOREACH(t, u->names, i) {
2653
2654 if (t == u->id)
2655 continue;
2656
2657 r = load_from_path(u, t);
2658 if (r < 0)
2659 return r;
2660
2661 if (u->load_state != UNIT_STUB)
2662 break;
2663 }
2664
2665 /* And now, try looking for it under the suggested (originally linked) path */
2666 if (u->load_state == UNIT_STUB && u->fragment_path) {
2667
2668 r = load_from_path(u, u->fragment_path);
2669 if (r < 0)
2670 return r;
2671
2672 if (u->load_state == UNIT_STUB) {
2673 /* Hmm, this didn't work? Then let's get rid
2674 * of the fragment path stored for us, so that
2675 * we don't point to an invalid location. */
2676 free(u->fragment_path);
2677 u->fragment_path = NULL;
2678 }
2679 }
2680
2681 /* Look for a template */
2682 if (u->load_state == UNIT_STUB && u->instance) {
2683 _cleanup_free_ char *k;
2684
2685 k = unit_name_template(u->id);
2686 if (!k)
2687 return -ENOMEM;
2688
2689 r = load_from_path(u, k);
2690 if (r < 0)
2691 return r;
2692
2693 if (u->load_state == UNIT_STUB)
2694 SET_FOREACH(t, u->names, i) {
2695 _cleanup_free_ char *z = NULL;
2696
2697 if (t == u->id)
2698 continue;
2699
2700 z = unit_name_template(t);
2701 if (!z)
2702 return -ENOMEM;
2703
2704 r = load_from_path(u, z);
2705 if (r < 0)
2706 return r;
2707
2708 if (u->load_state != UNIT_STUB)
2709 break;
2710 }
2711 }
2712
2713 return 0;
2714 }
2715
2716 void unit_dump_config_items(FILE *f) {
2717 static const struct {
2718 const ConfigParserCallback callback;
2719 const char *rvalue;
2720 } table[] = {
2721 { config_parse_int, "INTEGER" },
2722 { config_parse_unsigned, "UNSIGNED" },
2723 { config_parse_bytes_size, "SIZE" },
2724 { config_parse_bool, "BOOLEAN" },
2725 { config_parse_string, "STRING" },
2726 { config_parse_path, "PATH" },
2727 { config_parse_unit_path_printf, "PATH" },
2728 { config_parse_strv, "STRING [...]" },
2729 { config_parse_exec_nice, "NICE" },
2730 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2731 { config_parse_exec_io_class, "IOCLASS" },
2732 { config_parse_exec_io_priority, "IOPRIORITY" },
2733 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2734 { config_parse_exec_cpu_sched_prio, "CPUSCHEDPRIO" },
2735 { config_parse_exec_cpu_affinity, "CPUAFFINITY" },
2736 { config_parse_mode, "MODE" },
2737 { config_parse_unit_env_file, "FILE" },
2738 { config_parse_output, "OUTPUT" },
2739 { config_parse_input, "INPUT" },
2740 { config_parse_facility, "FACILITY" },
2741 { config_parse_level, "LEVEL" },
2742 { config_parse_exec_capabilities, "CAPABILITIES" },
2743 { config_parse_exec_secure_bits, "SECUREBITS" },
2744 { config_parse_bounding_set, "BOUNDINGSET" },
2745 { config_parse_limit, "LIMIT" },
2746 { config_parse_unit_deps, "UNIT [...]" },
2747 { config_parse_exec, "PATH [ARGUMENT [...]]" },
2748 { config_parse_service_type, "SERVICETYPE" },
2749 { config_parse_service_restart, "SERVICERESTART" },
2750 #ifdef HAVE_SYSV_COMPAT
2751 { config_parse_sysv_priority, "SYSVPRIORITY" },
2752 #else
2753 { config_parse_warn_compat, "NOTSUPPORTED" },
2754 #endif
2755 { config_parse_kill_mode, "KILLMODE" },
2756 { config_parse_kill_signal, "SIGNAL" },
2757 { config_parse_socket_listen, "SOCKET [...]" },
2758 { config_parse_socket_bind, "SOCKETBIND" },
2759 { config_parse_socket_bindtodevice, "NETWORKINTERFACE" },
2760 { config_parse_sec, "SECONDS" },
2761 { config_parse_nsec, "NANOSECONDS" },
2762 { config_parse_path_strv, "PATH [...]" },
2763 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2764 { config_parse_exec_mount_flags, "MOUNTFLAG [...]" },
2765 { config_parse_unit_string_printf, "STRING" },
2766 { config_parse_trigger_unit, "UNIT" },
2767 { config_parse_timer, "TIMER" },
2768 { config_parse_path_spec, "PATH" },
2769 { config_parse_notify_access, "ACCESS" },
2770 { config_parse_ip_tos, "TOS" },
2771 { config_parse_unit_condition_path, "CONDITION" },
2772 { config_parse_unit_condition_string, "CONDITION" },
2773 { config_parse_unit_condition_null, "CONDITION" },
2774 { config_parse_unit_slice, "SLICE" },
2775 { config_parse_documentation, "URL" },
2776 { config_parse_service_timeout, "SECONDS" },
2777 { config_parse_start_limit_action, "ACTION" },
2778 { config_parse_set_status, "STATUS" },
2779 { config_parse_service_sockets, "SOCKETS" },
2780 { config_parse_environ, "ENVIRON" },
2781 { config_parse_syscall_filter, "SYSCALL" },
2782 { config_parse_cpu_shares, "SHARES" },
2783 { config_parse_memory_limit, "LIMIT" },
2784 { config_parse_device_allow, "DEVICE" },
2785 { config_parse_device_policy, "POLICY" },
2786 { config_parse_blockio_bandwidth, "BANDWIDTH" },
2787 { config_parse_blockio_weight, "WEIGHT" },
2788 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
2789 { config_parse_long, "LONG" },
2790 { config_parse_socket_service, "SERVICE" },
2791 };
2792
2793 const char *prev = NULL;
2794 const char *i;
2795
2796 assert(f);
2797
2798 NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2799 const char *rvalue = "OTHER", *lvalue;
2800 unsigned j;
2801 size_t prefix_len;
2802 const char *dot;
2803 const ConfigPerfItem *p;
2804
2805 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2806
2807 dot = strchr(i, '.');
2808 lvalue = dot ? dot + 1 : i;
2809 prefix_len = dot-i;
2810
2811 if (dot)
2812 if (!prev || !strneq(prev, i, prefix_len+1)) {
2813 if (prev)
2814 fputc('\n', f);
2815
2816 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2817 }
2818
2819 for (j = 0; j < ELEMENTSOF(table); j++)
2820 if (p->parse == table[j].callback) {
2821 rvalue = table[j].rvalue;
2822 break;
2823 }
2824
2825 fprintf(f, "%s=%s\n", lvalue, rvalue);
2826 prev = i;
2827 }
2828 }