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