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