chiark / gitweb /
unit: properly update references to units which are merged
[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(t->meta.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(t->meta.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
1390         assert(filename);
1391         assert(lvalue);
1392         assert(rvalue);
1393         assert(data);
1394
1395         dbus_error_init(&error);
1396
1397         if (!endswith(rvalue, ".service")) {
1398                 log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue);
1399                 return 0;
1400         }
1401
1402         if ((r = manager_load_unit(s->meta.manager, rvalue, NULL, &error, (Unit**) &s->service)) < 0) {
1403                 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1404                 dbus_error_free(&error);
1405                 return 0;
1406         }
1407
1408         return 0;
1409 }
1410
1411 int config_parse_service_sockets(
1412                 const char *filename,
1413                 unsigned line,
1414                 const char *section,
1415                 const char *lvalue,
1416                 int ltype,
1417                 const char *rvalue,
1418                 void *data,
1419                 void *userdata) {
1420
1421         Service *s = data;
1422         int r;
1423         char *state, *w;
1424         size_t l;
1425
1426         assert(filename);
1427         assert(lvalue);
1428         assert(rvalue);
1429         assert(data);
1430
1431         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1432                 char *t, *k;
1433
1434                 t = strndup(w, l);
1435                 if (!t)
1436                         return -ENOMEM;
1437
1438                 k = unit_name_printf(UNIT(s), t);
1439                 free(t);
1440
1441                 if (!k)
1442                         return -ENOMEM;
1443
1444                 if (!endswith(k, ".socket")) {
1445                         log_error("[%s:%u] Unit must be of type socket, ignoring: %s", filename, line, rvalue);
1446                         free(k);
1447                         continue;
1448                 }
1449
1450                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
1451                 if (r < 0)
1452                         log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s", filename, line, k, strerror(-r));
1453
1454                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
1455                 if (r < 0)
1456                         return r;
1457
1458                 free(k);
1459         }
1460
1461         return 0;
1462 }
1463
1464 int config_parse_unit_env_file(
1465                 const char *filename,
1466                 unsigned line,
1467                 const char *section,
1468                 const char *lvalue,
1469                 int ltype,
1470                 const char *rvalue,
1471                 void *data,
1472                 void *userdata) {
1473
1474         char ***env = data, **k;
1475         Unit *u = userdata;
1476         char *s;
1477
1478         assert(filename);
1479         assert(lvalue);
1480         assert(rvalue);
1481         assert(data);
1482
1483         s = unit_full_printf(u, rvalue);
1484         if (!s)
1485                 return -ENOMEM;
1486
1487         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1488                 log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s);
1489                 free(s);
1490                 return 0;
1491         }
1492
1493         k = strv_append(*env, s);
1494         free(s);
1495         if (!k)
1496                 return -ENOMEM;
1497
1498         strv_free(*env);
1499         *env = k;
1500
1501         return 0;
1502 }
1503
1504 int config_parse_ip_tos(
1505                 const char *filename,
1506                 unsigned line,
1507                 const char *section,
1508                 const char *lvalue,
1509                 int ltype,
1510                 const char *rvalue,
1511                 void *data,
1512                 void *userdata) {
1513
1514         int *ip_tos = data, x;
1515
1516         assert(filename);
1517         assert(lvalue);
1518         assert(rvalue);
1519         assert(data);
1520
1521         if ((x = ip_tos_from_string(rvalue)) < 0)
1522                 if (safe_atoi(rvalue, &x) < 0) {
1523                         log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
1524                         return 0;
1525                 }
1526
1527         *ip_tos = x;
1528         return 0;
1529 }
1530
1531 int config_parse_unit_condition_path(
1532                 const char *filename,
1533                 unsigned line,
1534                 const char *section,
1535                 const char *lvalue,
1536                 int ltype,
1537                 const char *rvalue,
1538                 void *data,
1539                 void *userdata) {
1540
1541         ConditionType cond = ltype;
1542         Unit *u = data;
1543         bool trigger, negate;
1544         Condition *c;
1545
1546         assert(filename);
1547         assert(lvalue);
1548         assert(rvalue);
1549         assert(data);
1550
1551         trigger = rvalue[0] == '|';
1552         if (trigger)
1553                 rvalue++;
1554
1555         negate = rvalue[0] == '!';
1556         if (negate)
1557                 rvalue++;
1558
1559         if (!path_is_absolute(rvalue)) {
1560                 log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, rvalue);
1561                 return 0;
1562         }
1563
1564         c = condition_new(cond, rvalue, trigger, negate);
1565         if (!c)
1566                 return -ENOMEM;
1567
1568         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
1569         return 0;
1570 }
1571
1572 int config_parse_unit_condition_string(
1573                 const char *filename,
1574                 unsigned line,
1575                 const char *section,
1576                 const char *lvalue,
1577                 int ltype,
1578                 const char *rvalue,
1579                 void *data,
1580                 void *userdata) {
1581
1582         ConditionType cond = ltype;
1583         Unit *u = data;
1584         bool trigger, negate;
1585         Condition *c;
1586
1587         assert(filename);
1588         assert(lvalue);
1589         assert(rvalue);
1590         assert(data);
1591
1592         if ((trigger = rvalue[0] == '|'))
1593                 rvalue++;
1594
1595         if ((negate = rvalue[0] == '!'))
1596                 rvalue++;
1597
1598         if (!(c = condition_new(cond, rvalue, trigger, negate)))
1599                 return -ENOMEM;
1600
1601         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
1602         return 0;
1603 }
1604
1605 int config_parse_unit_condition_null(
1606                 const char *filename,
1607                 unsigned line,
1608                 const char *section,
1609                 const char *lvalue,
1610                 int ltype,
1611                 const char *rvalue,
1612                 void *data,
1613                 void *userdata) {
1614
1615         Unit *u = data;
1616         Condition *c;
1617         bool trigger, negate;
1618         int b;
1619
1620         assert(filename);
1621         assert(lvalue);
1622         assert(rvalue);
1623         assert(data);
1624
1625         if ((trigger = rvalue[0] == '|'))
1626                 rvalue++;
1627
1628         if ((negate = rvalue[0] == '!'))
1629                 rvalue++;
1630
1631         if ((b = parse_boolean(rvalue)) < 0) {
1632                 log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue);
1633                 return 0;
1634         }
1635
1636         if (!b)
1637                 negate = !negate;
1638
1639         if (!(c = condition_new(CONDITION_NULL, NULL, trigger, negate)))
1640                 return -ENOMEM;
1641
1642         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
1643         return 0;
1644 }
1645
1646 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1647
1648 int config_parse_unit_cgroup_attr(
1649                 const char *filename,
1650                 unsigned line,
1651                 const char *section,
1652                 const char *lvalue,
1653                 int ltype,
1654                 const char *rvalue,
1655                 void *data,
1656                 void *userdata) {
1657
1658         Unit *u = data;
1659         char **l;
1660         int r;
1661
1662         assert(filename);
1663         assert(lvalue);
1664         assert(rvalue);
1665         assert(data);
1666
1667         l = strv_split_quoted(rvalue);
1668         if (!l)
1669                 return -ENOMEM;
1670
1671         if (strv_length(l) != 2) {
1672                 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1673                 strv_free(l);
1674                 return 0;
1675         }
1676
1677         r = unit_add_cgroup_attribute(u, NULL, l[0], l[1], NULL);
1678         strv_free(l);
1679
1680         if (r < 0) {
1681                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1682                 return 0;
1683         }
1684
1685         return 0;
1686 }
1687
1688 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) {
1689         Unit *u = data;
1690         int r;
1691         unsigned long ul;
1692         char *t;
1693
1694         assert(filename);
1695         assert(lvalue);
1696         assert(rvalue);
1697         assert(data);
1698
1699         if (safe_atolu(rvalue, &ul) < 0 || ul < 1) {
1700                 log_error("[%s:%u] Failed to parse CPU shares value, ignoring: %s", filename, line, rvalue);
1701                 return 0;
1702         }
1703
1704         if (asprintf(&t, "%lu", ul) < 0)
1705                 return -ENOMEM;
1706
1707         r = unit_add_cgroup_attribute(u, "cpu", "cpu.shares", t, NULL);
1708         free(t);
1709
1710         if (r < 0) {
1711                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1712                 return 0;
1713         }
1714
1715         return 0;
1716 }
1717
1718 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) {
1719         Unit *u = data;
1720         int r;
1721         off_t sz;
1722         char *t;
1723
1724         assert(filename);
1725         assert(lvalue);
1726         assert(rvalue);
1727         assert(data);
1728
1729         if (parse_bytes(rvalue, &sz) < 0 || sz <= 0) {
1730                 log_error("[%s:%u] Failed to parse memory limit value, ignoring: %s", filename, line, rvalue);
1731                 return 0;
1732         }
1733
1734         if (asprintf(&t, "%llu", (unsigned long long) sz) < 0)
1735                 return -ENOMEM;
1736
1737         r = unit_add_cgroup_attribute(u,
1738                                       "memory",
1739                                       streq(lvalue, "MemorySoftLimit") ? "memory.soft_limit_in_bytes" : "memory.limit_in_bytes",
1740                                       t, NULL);
1741         free(t);
1742
1743         if (r < 0) {
1744                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1745                 return 0;
1746         }
1747
1748         return 0;
1749 }
1750
1751 static int device_map(const char *controller, const char *name, const char *value, char **ret) {
1752         char **l;
1753
1754         assert(controller);
1755         assert(name);
1756         assert(value);
1757         assert(ret);
1758
1759         l = strv_split_quoted(value);
1760         if (!l)
1761                 return -ENOMEM;
1762
1763         assert(strv_length(l) >= 1);
1764
1765         if (streq(l[0], "*")) {
1766
1767                 if (asprintf(ret, "a *:*%s%s",
1768                              isempty(l[1]) ? "" : " ", strempty(l[1])) < 0) {
1769                         strv_free(l);
1770                         return -ENOMEM;
1771                 }
1772
1773         } else {
1774                 struct stat st;
1775
1776                 if (stat(l[0], &st) < 0) {
1777                         log_warning("Couldn't stat device %s", l[0]);
1778                         strv_free(l);
1779                         return -errno;
1780                 }
1781
1782                 if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
1783                         log_warning("%s is not a device.", l[0]);
1784                         strv_free(l);
1785                         return -ENODEV;
1786                 }
1787
1788                 if (asprintf(ret, "%c %u:%u%s%s",
1789                              S_ISCHR(st.st_mode) ? 'c' : 'b',
1790                              major(st.st_rdev), minor(st.st_rdev),
1791                              isempty(l[1]) ? "" : " ", strempty(l[1])) < 0) {
1792
1793                         strv_free(l);
1794                         return -ENOMEM;
1795                 }
1796         }
1797
1798         strv_free(l);
1799         return 0;
1800 }
1801
1802 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) {
1803         Unit *u = data;
1804         char **l;
1805         int r;
1806         unsigned k;
1807
1808         assert(filename);
1809         assert(lvalue);
1810         assert(rvalue);
1811         assert(data);
1812
1813         l = strv_split_quoted(rvalue);
1814         if (!l)
1815                 return -ENOMEM;
1816
1817         k = strv_length(l);
1818         if (k < 1 || k > 2) {
1819                 log_error("[%s:%u] Failed to parse device value, ignoring: %s", filename, line, rvalue);
1820                 strv_free(l);
1821                 return 0;
1822         }
1823
1824         if (!streq(l[0], "*") && !path_startswith(l[0], "/dev")) {
1825                 log_error("[%s:%u] Device node path not absolute, ignoring: %s", filename, line, rvalue);
1826                 strv_free(l);
1827                 return 0;
1828         }
1829
1830         if (!isempty(l[1]) && !in_charset(l[1], "rwm")) {
1831                 log_error("[%s:%u] Device access string invalid, ignoring: %s", filename, line, rvalue);
1832                 strv_free(l);
1833                 return 0;
1834         }
1835         strv_free(l);
1836
1837         r = unit_add_cgroup_attribute(u, "devices",
1838                                       streq(lvalue, "DeviceAllow") ? "devices.allow" : "devices.deny",
1839                                       rvalue, device_map);
1840
1841         if (r < 0) {
1842                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1843                 return 0;
1844         }
1845
1846         return 0;
1847 }
1848
1849 static int blkio_map(const char *controller, const char *name, const char *value, char **ret) {
1850         struct stat st;
1851         char **l;
1852         dev_t d;
1853
1854         assert(controller);
1855         assert(name);
1856         assert(value);
1857         assert(ret);
1858
1859         l = strv_split_quoted(value);
1860         if (!l)
1861                 return -ENOMEM;
1862
1863         assert(strv_length(l) == 2);
1864
1865         if (stat(l[0], &st) < 0) {
1866                 log_warning("Couldn't stat device %s", l[0]);
1867                 strv_free(l);
1868                 return -errno;
1869         }
1870
1871         if (S_ISBLK(st.st_mode))
1872                 d = st.st_rdev;
1873         else if (major(st.st_dev) != 0) {
1874                 /* If this is not a device node then find the block
1875                  * device this file is stored on */
1876                 d = st.st_dev;
1877
1878                 /* If this is a partition, try to get the originating
1879                  * block device */
1880                 block_get_whole_disk(d, &d);
1881         } else {
1882                 log_warning("%s is not a block device and file system block device cannot be determined or is not local.", l[0]);
1883                 strv_free(l);
1884                 return -ENODEV;
1885         }
1886
1887         if (asprintf(ret, "%u:%u %s", major(d), minor(d), l[1]) < 0) {
1888                 strv_free(l);
1889                 return -ENOMEM;
1890         }
1891
1892         strv_free(l);
1893         return 0;
1894 }
1895
1896 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) {
1897         Unit *u = data;
1898         int r;
1899         unsigned long ul;
1900         const char *device = NULL, *weight;
1901         unsigned k;
1902         char *t, **l;
1903
1904         assert(filename);
1905         assert(lvalue);
1906         assert(rvalue);
1907         assert(data);
1908
1909         l = strv_split_quoted(rvalue);
1910         if (!l)
1911                 return -ENOMEM;
1912
1913         k = strv_length(l);
1914         if (k < 1 || k > 2) {
1915                 log_error("[%s:%u] Failed to parse weight value, ignoring: %s", filename, line, rvalue);
1916                 strv_free(l);
1917                 return 0;
1918         }
1919
1920         if (k == 1)
1921                 weight = l[0];
1922         else {
1923                 device = l[0];
1924                 weight = l[1];
1925         }
1926
1927         if (device && !path_is_absolute(device)) {
1928                 log_error("[%s:%u] Failed to parse block device node value, ignoring: %s", filename, line, rvalue);
1929                 strv_free(l);
1930                 return 0;
1931         }
1932
1933         if (safe_atolu(weight, &ul) < 0 || ul < 10 || ul > 1000) {
1934                 log_error("[%s:%u] Failed to parse block IO weight value, ignoring: %s", filename, line, rvalue);
1935                 strv_free(l);
1936                 return 0;
1937         }
1938
1939         if (device)
1940                 r = asprintf(&t, "%s %lu", device, ul);
1941         else
1942                 r = asprintf(&t, "%lu", ul);
1943         strv_free(l);
1944
1945         if (r < 0)
1946                 return -ENOMEM;
1947
1948         if (device)
1949                 r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight_device", t, blkio_map);
1950         else
1951                 r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight", t, NULL);
1952         free(t);
1953
1954         if (r < 0) {
1955                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1956                 return 0;
1957         }
1958
1959         return 0;
1960 }
1961
1962 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) {
1963         Unit *u = data;
1964         int r;
1965         off_t bytes;
1966         unsigned k;
1967         char *t, **l;
1968
1969         assert(filename);
1970         assert(lvalue);
1971         assert(rvalue);
1972         assert(data);
1973
1974         l = strv_split_quoted(rvalue);
1975         if (!l)
1976                 return -ENOMEM;
1977
1978         k = strv_length(l);
1979         if (k != 2) {
1980                 log_error("[%s:%u] Failed to parse bandwidth value, ignoring: %s", filename, line, rvalue);
1981                 strv_free(l);
1982                 return 0;
1983         }
1984
1985         if (!path_is_absolute(l[0])) {
1986                 log_error("[%s:%u] Failed to parse block device node value, ignoring: %s", filename, line, rvalue);
1987                 strv_free(l);
1988                 return 0;
1989         }
1990
1991         if (parse_bytes(l[1], &bytes) < 0 || bytes <= 0) {
1992                 log_error("[%s:%u] Failed to parse block IO bandwith value, ignoring: %s", filename, line, rvalue);
1993                 strv_free(l);
1994                 return 0;
1995         }
1996
1997         r = asprintf(&t, "%s %llu", l[0], (unsigned long long) bytes);
1998         strv_free(l);
1999
2000         if (r < 0)
2001                 return -ENOMEM;
2002
2003         r = unit_add_cgroup_attribute(u, "blkio",
2004                                       streq(lvalue, "BlockIOReadBandwidth") ? "blkio.read_bps_device" : "blkio.write_bps_device",
2005                                       t, blkio_map);
2006         free(t);
2007
2008         if (r < 0) {
2009                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
2010                 return 0;
2011         }
2012
2013         return 0;
2014 }
2015
2016
2017 #define FOLLOW_MAX 8
2018
2019 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2020         unsigned c = 0;
2021         int fd, r;
2022         FILE *f;
2023         char *id = NULL;
2024
2025         assert(filename);
2026         assert(*filename);
2027         assert(_f);
2028         assert(names);
2029
2030         /* This will update the filename pointer if the loaded file is
2031          * reached by a symlink. The old string will be freed. */
2032
2033         for (;;) {
2034                 char *target, *name;
2035
2036                 if (c++ >= FOLLOW_MAX)
2037                         return -ELOOP;
2038
2039                 path_kill_slashes(*filename);
2040
2041                 /* Add the file name we are currently looking at to
2042                  * the names of this unit, but only if it is a valid
2043                  * unit name. */
2044                 name = file_name_from_path(*filename);
2045
2046                 if (unit_name_is_valid(name, true)) {
2047
2048                         id = set_get(names, name);
2049                         if (!id) {
2050                                 id = strdup(name);
2051                                 if (!id)
2052                                         return -ENOMEM;
2053
2054                                 r = set_put(names, id);
2055                                 if (r < 0) {
2056                                         free(id);
2057                                         return r;
2058                                 }
2059                         }
2060                 }
2061
2062                 /* Try to open the file name, but don't if its a symlink */
2063                 if ((fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW)) >= 0)
2064                         break;
2065
2066                 if (errno != ELOOP)
2067                         return -errno;
2068
2069                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2070                 if ((r = readlink_and_make_absolute(*filename, &target)) < 0)
2071                         return r;
2072
2073                 free(*filename);
2074                 *filename = target;
2075         }
2076
2077         if (!(f = fdopen(fd, "re"))) {
2078                 r = -errno;
2079                 close_nointr_nofail(fd);
2080                 return r;
2081         }
2082
2083         *_f = f;
2084         *_final = id;
2085         return 0;
2086 }
2087
2088 static int merge_by_names(Unit **u, Set *names, const char *id) {
2089         char *k;
2090         int r;
2091
2092         assert(u);
2093         assert(*u);
2094         assert(names);
2095
2096         /* Let's try to add in all symlink names we found */
2097         while ((k = set_steal_first(names))) {
2098
2099                 /* First try to merge in the other name into our
2100                  * unit */
2101                 if ((r = unit_merge_by_name(*u, k)) < 0) {
2102                         Unit *other;
2103
2104                         /* Hmm, we couldn't merge the other unit into
2105                          * ours? Then let's try it the other way
2106                          * round */
2107
2108                         other = manager_get_unit((*u)->meta.manager, k);
2109                         free(k);
2110
2111                         if (other)
2112                                 if ((r = unit_merge(other, *u)) >= 0) {
2113                                         *u = other;
2114                                         return merge_by_names(u, names, NULL);
2115                                 }
2116
2117                         return r;
2118                 }
2119
2120                 if (id == k)
2121                         unit_choose_id(*u, id);
2122
2123                 free(k);
2124         }
2125
2126         return 0;
2127 }
2128
2129 static int load_from_path(Unit *u, const char *path) {
2130         int r;
2131         Set *symlink_names;
2132         FILE *f = NULL;
2133         char *filename = NULL, *id = NULL;
2134         Unit *merged;
2135         struct stat st;
2136
2137         assert(u);
2138         assert(path);
2139
2140         symlink_names = set_new(string_hash_func, string_compare_func);
2141         if (!symlink_names)
2142                 return -ENOMEM;
2143
2144         if (path_is_absolute(path)) {
2145
2146                 if (!(filename = strdup(path))) {
2147                         r = -ENOMEM;
2148                         goto finish;
2149                 }
2150
2151                 if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
2152                         free(filename);
2153                         filename = NULL;
2154
2155                         if (r != -ENOENT)
2156                                 goto finish;
2157                 }
2158
2159         } else  {
2160                 char **p;
2161
2162                 STRV_FOREACH(p, u->meta.manager->lookup_paths.unit_path) {
2163
2164                         /* Instead of opening the path right away, we manually
2165                          * follow all symlinks and add their name to our unit
2166                          * name set while doing so */
2167                         if (!(filename = path_make_absolute(path, *p))) {
2168                                 r = -ENOMEM;
2169                                 goto finish;
2170                         }
2171
2172                         if (u->meta.manager->unit_path_cache &&
2173                             !set_get(u->meta.manager->unit_path_cache, filename))
2174                                 r = -ENOENT;
2175                         else
2176                                 r = open_follow(&filename, &f, symlink_names, &id);
2177
2178                         if (r < 0) {
2179                                 char *sn;
2180
2181                                 free(filename);
2182                                 filename = NULL;
2183
2184                                 if (r != -ENOENT)
2185                                         goto finish;
2186
2187                                 /* Empty the symlink names for the next run */
2188                                 while ((sn = set_steal_first(symlink_names)))
2189                                         free(sn);
2190
2191                                 continue;
2192                         }
2193
2194                         break;
2195                 }
2196         }
2197
2198         if (!filename) {
2199                 /* Hmm, no suitable file found? */
2200                 r = 0;
2201                 goto finish;
2202         }
2203
2204         merged = u;
2205         if ((r = merge_by_names(&merged, symlink_names, id)) < 0)
2206                 goto finish;
2207
2208         if (merged != u) {
2209                 u->meta.load_state = UNIT_MERGED;
2210                 r = 0;
2211                 goto finish;
2212         }
2213
2214         zero(st);
2215         if (fstat(fileno(f), &st) < 0) {
2216                 r = -errno;
2217                 goto finish;
2218         }
2219
2220         if (null_or_empty(&st))
2221                 u->meta.load_state = UNIT_MASKED;
2222         else {
2223                 /* Now, parse the file contents */
2224                 r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
2225                 if (r < 0)
2226                         goto finish;
2227
2228                 u->meta.load_state = UNIT_LOADED;
2229         }
2230
2231         free(u->meta.fragment_path);
2232         u->meta.fragment_path = filename;
2233         filename = NULL;
2234
2235         u->meta.fragment_mtime = timespec_load(&st.st_mtim);
2236
2237         r = 0;
2238
2239 finish:
2240         set_free_free(symlink_names);
2241         free(filename);
2242
2243         if (f)
2244                 fclose(f);
2245
2246         return r;
2247 }
2248
2249 int unit_load_fragment(Unit *u) {
2250         int r;
2251         Iterator i;
2252         const char *t;
2253
2254         assert(u);
2255         assert(u->meta.load_state == UNIT_STUB);
2256         assert(u->meta.id);
2257
2258         /* First, try to find the unit under its id. We always look
2259          * for unit files in the default directories, to make it easy
2260          * to override things by placing things in /etc/systemd/system */
2261         if ((r = load_from_path(u, u->meta.id)) < 0)
2262                 return r;
2263
2264         /* Try to find an alias we can load this with */
2265         if (u->meta.load_state == UNIT_STUB)
2266                 SET_FOREACH(t, u->meta.names, i) {
2267
2268                         if (t == u->meta.id)
2269                                 continue;
2270
2271                         if ((r = load_from_path(u, t)) < 0)
2272                                 return r;
2273
2274                         if (u->meta.load_state != UNIT_STUB)
2275                                 break;
2276                 }
2277
2278         /* And now, try looking for it under the suggested (originally linked) path */
2279         if (u->meta.load_state == UNIT_STUB && u->meta.fragment_path) {
2280
2281                 if ((r = load_from_path(u, u->meta.fragment_path)) < 0)
2282                         return r;
2283
2284                 if (u->meta.load_state == UNIT_STUB) {
2285                         /* Hmm, this didn't work? Then let's get rid
2286                          * of the fragment path stored for us, so that
2287                          * we don't point to an invalid location. */
2288                         free(u->meta.fragment_path);
2289                         u->meta.fragment_path = NULL;
2290                 }
2291         }
2292
2293         /* Look for a template */
2294         if (u->meta.load_state == UNIT_STUB && u->meta.instance) {
2295                 char *k;
2296
2297                 if (!(k = unit_name_template(u->meta.id)))
2298                         return -ENOMEM;
2299
2300                 r = load_from_path(u, k);
2301                 free(k);
2302
2303                 if (r < 0)
2304                         return r;
2305
2306                 if (u->meta.load_state == UNIT_STUB)
2307                         SET_FOREACH(t, u->meta.names, i) {
2308
2309                                 if (t == u->meta.id)
2310                                         continue;
2311
2312                                 if (!(k = unit_name_template(t)))
2313                                         return -ENOMEM;
2314
2315                                 r = load_from_path(u, k);
2316                                 free(k);
2317
2318                                 if (r < 0)
2319                                         return r;
2320
2321                                 if (u->meta.load_state != UNIT_STUB)
2322                                         break;
2323                         }
2324         }
2325
2326         return 0;
2327 }
2328
2329 void unit_dump_config_items(FILE *f) {
2330         static const struct {
2331                 const ConfigParserCallback callback;
2332                 const char *rvalue;
2333         } table[] = {
2334                 { config_parse_int,                   "INTEGER" },
2335                 { config_parse_unsigned,              "UNSIGNED" },
2336                 { config_parse_size,                  "SIZE" },
2337                 { config_parse_bool,                  "BOOLEAN" },
2338                 { config_parse_string,                "STRING" },
2339                 { config_parse_path,                  "PATH" },
2340                 { config_parse_unit_path_printf,      "PATH" },
2341                 { config_parse_strv,                  "STRING [...]" },
2342                 { config_parse_exec_nice,             "NICE" },
2343                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2344                 { config_parse_exec_io_class,         "IOCLASS" },
2345                 { config_parse_exec_io_priority,      "IOPRIORITY" },
2346                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2347                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
2348                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
2349                 { config_parse_mode,                  "MODE" },
2350                 { config_parse_unit_env_file,         "FILE" },
2351                 { config_parse_output,                "OUTPUT" },
2352                 { config_parse_input,                 "INPUT" },
2353                 { config_parse_facility,              "FACILITY" },
2354                 { config_parse_level,                 "LEVEL" },
2355                 { config_parse_exec_capabilities,     "CAPABILITIES" },
2356                 { config_parse_exec_secure_bits,      "SECUREBITS" },
2357                 { config_parse_exec_bounding_set,     "BOUNDINGSET" },
2358                 { config_parse_exec_timer_slack_nsec, "TIMERSLACK" },
2359                 { config_parse_limit,                 "LIMIT" },
2360                 { config_parse_unit_cgroup,           "CGROUP [...]" },
2361                 { config_parse_unit_deps,             "UNIT [...]" },
2362                 { config_parse_unit_names,            "UNIT [...]" },
2363                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
2364                 { config_parse_service_type,          "SERVICETYPE" },
2365                 { config_parse_service_restart,       "SERVICERESTART" },
2366 #ifdef HAVE_SYSV_COMPAT
2367                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
2368 #else
2369                 { config_parse_warn_compat,           "NOTSUPPORTED" },
2370 #endif
2371                 { config_parse_kill_mode,             "KILLMODE" },
2372                 { config_parse_kill_signal,           "SIGNAL" },
2373                 { config_parse_socket_listen,         "SOCKET [...]" },
2374                 { config_parse_socket_bind,           "SOCKETBIND" },
2375                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
2376                 { config_parse_usec,                  "SECONDS" },
2377                 { config_parse_path_strv,             "PATH [...]" },
2378                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
2379                 { config_parse_unit_string_printf,    "STRING" },
2380                 { config_parse_timer,                 "TIMER" },
2381                 { config_parse_timer_unit,            "NAME" },
2382                 { config_parse_path_spec,             "PATH" },
2383                 { config_parse_path_unit,             "UNIT" },
2384                 { config_parse_notify_access,         "ACCESS" },
2385                 { config_parse_ip_tos,                "TOS" },
2386                 { config_parse_unit_condition_path,   "CONDITION" },
2387                 { config_parse_unit_condition_string, "CONDITION" },
2388                 { config_parse_unit_condition_null,   "CONDITION" },
2389         };
2390
2391         const char *prev = NULL;
2392         const char *i;
2393
2394         assert(f);
2395
2396         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2397                 const char *rvalue = "OTHER", *lvalue;
2398                 unsigned j;
2399                 size_t prefix_len;
2400                 const char *dot;
2401                 const ConfigPerfItem *p;
2402
2403                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2404
2405                 dot = strchr(i, '.');
2406                 lvalue = dot ? dot + 1 : i;
2407                 prefix_len = dot-i;
2408
2409                 if (dot)
2410                         if (!prev || strncmp(prev, i, prefix_len+1) != 0) {
2411                                 if (prev)
2412                                         fputc('\n', f);
2413
2414                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2415                         }
2416
2417                 for (j = 0; j < ELEMENTSOF(table); j++)
2418                         if (p->parse == table[j].callback) {
2419                                 rvalue = table[j].rvalue;
2420                                 break;
2421                         }
2422
2423                 fprintf(f, "%s=%s\n", lvalue, rvalue);
2424                 prev = i;
2425         }
2426 }