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