chiark / gitweb /
core: rework how we match mount units against each other
[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(
1777                 const char *unit,
1778                 const char *filename,
1779                 unsigned line,
1780                 const char *section,
1781                 const char *lvalue,
1782                 int ltype,
1783                 const char *rvalue,
1784                 void *data,
1785                 void *userdata) {
1786
1787         Unit *u = userdata;
1788         char *state;
1789         size_t l;
1790         char *w;
1791         int r;
1792
1793         assert(filename);
1794         assert(lvalue);
1795         assert(rvalue);
1796         assert(data);
1797
1798         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1799                 _cleanup_free_ char *n;
1800
1801                 n = strndup(w, l);
1802                 if (!n)
1803                         return log_oom();
1804
1805                 if (!utf8_is_valid(n)) {
1806                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1807                                    "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
1808                         continue;
1809                 }
1810
1811                 r = unit_require_mounts_for(u, n);
1812                 if (r < 0) {
1813                         log_syntax(unit, LOG_ERR, filename, line, r,
1814                                    "Failed to add required mount for, ignoring: %s", rvalue);
1815                         continue;
1816                 }
1817         }
1818
1819         return r;
1820 }
1821
1822 int config_parse_documentation(const char *unit,
1823                                const char *filename,
1824                                unsigned line,
1825                                const char *section,
1826                                const char *lvalue,
1827                                int ltype,
1828                                const char *rvalue,
1829                                void *data,
1830                                void *userdata) {
1831
1832         Unit *u = userdata;
1833         int r;
1834         char **a, **b;
1835
1836         assert(filename);
1837         assert(lvalue);
1838         assert(rvalue);
1839         assert(u);
1840
1841         if (isempty(rvalue)) {
1842                 /* Empty assignment resets the list */
1843                 strv_free(u->documentation);
1844                 u->documentation = NULL;
1845                 return 0;
1846         }
1847
1848         r = config_parse_unit_strv_printf(unit, filename, line, section, lvalue, ltype,
1849                                           rvalue, data, userdata);
1850         if (r < 0)
1851                 return r;
1852
1853         for (a = b = u->documentation; a && *a; a++) {
1854
1855                 if (is_valid_documentation_url(*a))
1856                         *(b++) = *a;
1857                 else {
1858                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1859                                    "Invalid URL, ignoring: %s", *a);
1860                         free(*a);
1861                 }
1862         }
1863         *b = NULL;
1864
1865         return r;
1866 }
1867
1868 static void syscall_set(uint32_t *p, int nr) {
1869         nr = SYSCALL_TO_INDEX(nr);
1870         p[nr >> 4] |= 1 << (nr & 31);
1871 }
1872
1873 static void syscall_unset(uint32_t *p, int nr) {
1874         nr = SYSCALL_TO_INDEX(nr);
1875         p[nr >> 4] &= ~(1 << (nr & 31));
1876 }
1877
1878 int config_parse_syscall_filter(const char *unit,
1879                                 const char *filename,
1880                                 unsigned line,
1881                                 const char *section,
1882                                 const char *lvalue,
1883                                 int ltype,
1884                                 const char *rvalue,
1885                                 void *data,
1886                                 void *userdata) {
1887
1888         ExecContext *c = data;
1889         Unit *u = userdata;
1890         bool invert = false;
1891         char *w;
1892         size_t l;
1893         char *state;
1894
1895         assert(filename);
1896         assert(lvalue);
1897         assert(rvalue);
1898         assert(u);
1899
1900         if (isempty(rvalue)) {
1901                 /* Empty assignment resets the list */
1902                 free(c->syscall_filter);
1903                 c->syscall_filter = NULL;
1904                 return 0;
1905         }
1906
1907         if (rvalue[0] == '~') {
1908                 invert = true;
1909                 rvalue++;
1910         }
1911
1912         if (!c->syscall_filter) {
1913                 size_t n;
1914
1915                 n = (syscall_max() + 31) >> 4;
1916                 c->syscall_filter = new(uint32_t, n);
1917                 if (!c->syscall_filter)
1918                         return log_oom();
1919
1920                 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
1921
1922                 /* Add these by default */
1923                 syscall_set(c->syscall_filter, __NR_execve);
1924                 syscall_set(c->syscall_filter, __NR_rt_sigreturn);
1925 #ifdef __NR_sigreturn
1926                 syscall_set(c->syscall_filter, __NR_sigreturn);
1927 #endif
1928                 syscall_set(c->syscall_filter, __NR_exit_group);
1929                 syscall_set(c->syscall_filter, __NR_exit);
1930         }
1931
1932         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1933                 int id;
1934                 _cleanup_free_ char *t = NULL;
1935
1936                 t = strndup(w, l);
1937                 if (!t)
1938                         return log_oom();
1939
1940                 id = syscall_from_name(t);
1941                 if (id < 0)  {
1942                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1943                                    "Failed to parse syscall, ignoring: %s", t);
1944                         continue;
1945                 }
1946
1947                 if (invert)
1948                         syscall_unset(c->syscall_filter, id);
1949                 else
1950                         syscall_set(c->syscall_filter, id);
1951         }
1952
1953         c->no_new_privileges = true;
1954
1955         return 0;
1956 }
1957
1958 int config_parse_unit_slice(
1959                 const char *unit,
1960                 const char *filename,
1961                 unsigned line,
1962                 const char *section,
1963                 const char *lvalue,
1964                 int ltype,
1965                 const char *rvalue,
1966                 void *data,
1967                 void *userdata) {
1968
1969         _cleanup_free_ char *k = NULL;
1970         Unit *u = userdata, *slice;
1971         int r;
1972
1973         assert(filename);
1974         assert(lvalue);
1975         assert(rvalue);
1976         assert(u);
1977
1978         r = unit_name_printf(u, rvalue, &k);
1979         if (r < 0)
1980                 log_syntax(unit, LOG_ERR, filename, line, -r,
1981                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
1982         if (!k) {
1983                 k = strdup(rvalue);
1984                 if (!k)
1985                         return log_oom();
1986         }
1987
1988         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
1989         if (r < 0) {
1990                 log_syntax(unit, LOG_ERR, filename, line, -r,
1991                            "Failed to load slice unit %s. Ignoring.", k);
1992                 return 0;
1993         }
1994
1995         if (slice->type != UNIT_SLICE) {
1996                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1997                            "Slice unit %s is not a slice. Ignoring.", k);
1998                 return 0;
1999         }
2000
2001         unit_ref_set(&u->slice, slice);
2002         return 0;
2003 }
2004
2005 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2006
2007 int config_parse_cpu_shares(
2008                 const char *unit,
2009                 const char *filename,
2010                 unsigned line,
2011                 const char *section,
2012                 const char *lvalue,
2013                 int ltype,
2014                 const char *rvalue,
2015                 void *data,
2016                 void *userdata) {
2017
2018         CGroupContext *c = data;
2019         unsigned long lu;
2020         int r;
2021
2022         assert(filename);
2023         assert(lvalue);
2024         assert(rvalue);
2025
2026         if (isempty(rvalue)) {
2027                 c->cpu_shares = 1024;
2028                 return 0;
2029         }
2030
2031         r = safe_atolu(rvalue, &lu);
2032         if (r < 0 || lu <= 0) {
2033                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2034                            "CPU shares '%s' invalid. Ignoring.", rvalue);
2035                 return 0;
2036         }
2037
2038         c->cpu_shares = lu;
2039         return 0;
2040 }
2041
2042 int config_parse_memory_limit(
2043                 const char *unit,
2044                 const char *filename,
2045                 unsigned line,
2046                 const char *section,
2047                 const char *lvalue,
2048                 int ltype,
2049                 const char *rvalue,
2050                 void *data,
2051                 void *userdata) {
2052
2053         CGroupContext *c = data;
2054         off_t bytes;
2055         int r;
2056
2057         if (isempty(rvalue)) {
2058                 c->memory_limit = (uint64_t) -1;
2059                 return 0;
2060         }
2061
2062         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2063
2064         r = parse_bytes(rvalue, &bytes);
2065         if (r < 0) {
2066                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2067                            "Memory limit '%s' invalid. Ignoring.", rvalue);
2068                 return 0;
2069         }
2070
2071         c->memory_limit = (uint64_t) bytes;
2072         return 0;
2073 }
2074
2075 int config_parse_device_allow(
2076                 const char *unit,
2077                 const char *filename,
2078                 unsigned line,
2079                 const char *section,
2080                 const char *lvalue,
2081                 int ltype,
2082                 const char *rvalue,
2083                 void *data,
2084                 void *userdata) {
2085
2086         _cleanup_free_ char *path = NULL;
2087         CGroupContext *c = data;
2088         CGroupDeviceAllow *a;
2089         const char *m;
2090         size_t n;
2091
2092         if (isempty(rvalue)) {
2093                 while (c->device_allow)
2094                         cgroup_context_free_device_allow(c, c->device_allow);
2095
2096                 return 0;
2097         }
2098
2099         n = strcspn(rvalue, WHITESPACE);
2100         path = strndup(rvalue, n);
2101         if (!path)
2102                 return log_oom();
2103
2104         if (!path_startswith(path, "/dev")) {
2105                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2106                            "Invalid device node path '%s'. Ignoring.", path);
2107                 return 0;
2108         }
2109
2110         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2111         if (isempty(m))
2112                 m = "rwm";
2113
2114         if (!in_charset(m, "rwm")) {
2115                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2116                            "Invalid device rights '%s'. Ignoring.", m);
2117                 return 0;
2118         }
2119
2120         a = new0(CGroupDeviceAllow, 1);
2121         if (!a)
2122                 return log_oom();
2123
2124         a->path = path;
2125         path = NULL;
2126         a->r = !!strchr(m, 'r');
2127         a->w = !!strchr(m, 'w');
2128         a->m = !!strchr(m, 'm');
2129
2130         LIST_PREPEND(CGroupDeviceAllow, device_allow, c->device_allow, a);
2131         return 0;
2132 }
2133
2134 int config_parse_blockio_weight(
2135                 const char *unit,
2136                 const char *filename,
2137                 unsigned line,
2138                 const char *section,
2139                 const char *lvalue,
2140                 int ltype,
2141                 const char *rvalue,
2142                 void *data,
2143                 void *userdata) {
2144
2145         CGroupContext *c = data;
2146         unsigned long lu;
2147         int r;
2148
2149         assert(filename);
2150         assert(lvalue);
2151         assert(rvalue);
2152
2153         if (isempty(rvalue)) {
2154                 c->blockio_weight = 1000;
2155                 return 0;
2156         }
2157
2158         r = safe_atolu(rvalue, &lu);
2159         if (r < 0 || lu < 10 || lu > 1000) {
2160                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2161                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2162                 return 0;
2163         }
2164
2165         c->blockio_weight = lu;
2166
2167         return 0;
2168 }
2169
2170 int config_parse_blockio_device_weight(
2171                 const char *unit,
2172                 const char *filename,
2173                 unsigned line,
2174                 const char *section,
2175                 const char *lvalue,
2176                 int ltype,
2177                 const char *rvalue,
2178                 void *data,
2179                 void *userdata) {
2180
2181         _cleanup_free_ char *path = NULL;
2182         CGroupBlockIODeviceWeight *w;
2183         CGroupContext *c = data;
2184         unsigned long lu;
2185         const char *weight;
2186         size_t n;
2187         int r;
2188
2189         assert(filename);
2190         assert(lvalue);
2191         assert(rvalue);
2192
2193         if (isempty(rvalue)) {
2194                 while (c->blockio_device_weights)
2195                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2196
2197                 return 0;
2198         }
2199
2200         n = strcspn(rvalue, WHITESPACE);
2201         weight = rvalue + n;
2202         if (!*weight) {
2203                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2204                            "Expected block device and device weight. Ignoring.");
2205                 return 0;
2206         }
2207
2208         path = strndup(rvalue, n);
2209         if (!path)
2210                 return log_oom();
2211
2212         if (!path_startswith(path, "/dev")) {
2213                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2214                            "Invalid device node path '%s'. Ignoring.", path);
2215                 return 0;
2216         }
2217
2218         weight += strspn(weight, WHITESPACE);
2219         r = safe_atolu(weight, &lu);
2220         if (r < 0 || lu < 10 || lu > 1000) {
2221                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2222                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2223                 return 0;
2224         }
2225
2226
2227         w = new0(CGroupBlockIODeviceWeight, 1);
2228         if (!w)
2229                 return log_oom();
2230
2231         w->path = path;
2232         path = NULL;
2233
2234         w->weight = lu;
2235
2236         LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
2237         return 0;
2238 }
2239
2240 int config_parse_blockio_bandwidth(
2241                 const char *unit,
2242                 const char *filename,
2243                 unsigned line,
2244                 const char *section,
2245                 const char *lvalue,
2246                 int ltype,
2247                 const char *rvalue,
2248                 void *data,
2249                 void *userdata) {
2250
2251         _cleanup_free_ char *path = NULL;
2252         CGroupBlockIODeviceBandwidth *b;
2253         CGroupContext *c = data;
2254         const char *bandwidth;
2255         off_t bytes;
2256         bool read;
2257         size_t n;
2258         int r;
2259
2260         assert(filename);
2261         assert(lvalue);
2262         assert(rvalue);
2263
2264         read = streq("BlockIOReadBandwidth", lvalue);
2265
2266         if (isempty(rvalue)) {
2267                 CGroupBlockIODeviceBandwidth *next;
2268
2269                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2270                         if (b->read == read)
2271                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2272
2273                 return 0;
2274         }
2275
2276         n = strcspn(rvalue, WHITESPACE);
2277         bandwidth = rvalue + n;
2278         bandwidth += strspn(bandwidth, WHITESPACE);
2279
2280         if (!*bandwidth) {
2281                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2282                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2283                 return 0;
2284         }
2285
2286         path = strndup(rvalue, n);
2287         if (!path)
2288                 return log_oom();
2289
2290         if (!path_startswith(path, "/dev")) {
2291                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2292                            "Invalid device node path '%s'. Ignoring.", path);
2293                 return 0;
2294         }
2295
2296         r = parse_bytes(bandwidth, &bytes);
2297         if (r < 0 || bytes <= 0) {
2298                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2299                            "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2300                 return 0;
2301         }
2302
2303         b = new0(CGroupBlockIODeviceBandwidth, 1);
2304         if (!b)
2305                 return log_oom();
2306
2307         b->path = path;
2308         path = NULL;
2309         b->bandwidth = (uint64_t) bytes;
2310         b->read = read;
2311
2312         LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
2313
2314         return 0;
2315 }
2316
2317 #define FOLLOW_MAX 8
2318
2319 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2320         unsigned c = 0;
2321         int fd, r;
2322         FILE *f;
2323         char *id = NULL;
2324
2325         assert(filename);
2326         assert(*filename);
2327         assert(_f);
2328         assert(names);
2329
2330         /* This will update the filename pointer if the loaded file is
2331          * reached by a symlink. The old string will be freed. */
2332
2333         for (;;) {
2334                 char *target, *name;
2335
2336                 if (c++ >= FOLLOW_MAX)
2337                         return -ELOOP;
2338
2339                 path_kill_slashes(*filename);
2340
2341                 /* Add the file name we are currently looking at to
2342                  * the names of this unit, but only if it is a valid
2343                  * unit name. */
2344                 name = path_get_file_name(*filename);
2345
2346                 if (unit_name_is_valid(name, true)) {
2347
2348                         id = set_get(names, name);
2349                         if (!id) {
2350                                 id = strdup(name);
2351                                 if (!id)
2352                                         return -ENOMEM;
2353
2354                                 r = set_consume(names, id);
2355                                 if (r < 0)
2356                                         return r;
2357                         }
2358                 }
2359
2360                 /* Try to open the file name, but don't if its a symlink */
2361                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2362                 if (fd >= 0)
2363                         break;
2364
2365                 if (errno != ELOOP)
2366                         return -errno;
2367
2368                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2369                 r = readlink_and_make_absolute(*filename, &target);
2370                 if (r < 0)
2371                         return r;
2372
2373                 free(*filename);
2374                 *filename = target;
2375         }
2376
2377         f = fdopen(fd, "re");
2378         if (!f) {
2379                 r = -errno;
2380                 close_nointr_nofail(fd);
2381                 return r;
2382         }
2383
2384         *_f = f;
2385         *_final = id;
2386         return 0;
2387 }
2388
2389 static int merge_by_names(Unit **u, Set *names, const char *id) {
2390         char *k;
2391         int r;
2392
2393         assert(u);
2394         assert(*u);
2395         assert(names);
2396
2397         /* Let's try to add in all symlink names we found */
2398         while ((k = set_steal_first(names))) {
2399
2400                 /* First try to merge in the other name into our
2401                  * unit */
2402                 r = unit_merge_by_name(*u, k);
2403                 if (r < 0) {
2404                         Unit *other;
2405
2406                         /* Hmm, we couldn't merge the other unit into
2407                          * ours? Then let's try it the other way
2408                          * round */
2409
2410                         other = manager_get_unit((*u)->manager, k);
2411                         free(k);
2412
2413                         if (other) {
2414                                 r = unit_merge(other, *u);
2415                                 if (r >= 0) {
2416                                         *u = other;
2417                                         return merge_by_names(u, names, NULL);
2418                                 }
2419                         }
2420
2421                         return r;
2422                 }
2423
2424                 if (id == k)
2425                         unit_choose_id(*u, id);
2426
2427                 free(k);
2428         }
2429
2430         return 0;
2431 }
2432
2433 static int load_from_path(Unit *u, const char *path) {
2434         int r;
2435         Set *symlink_names;
2436         FILE *f = NULL;
2437         char *filename = NULL, *id = NULL;
2438         Unit *merged;
2439         struct stat st;
2440
2441         assert(u);
2442         assert(path);
2443
2444         symlink_names = set_new(string_hash_func, string_compare_func);
2445         if (!symlink_names)
2446                 return -ENOMEM;
2447
2448         if (path_is_absolute(path)) {
2449
2450                 filename = strdup(path);
2451                 if (!filename) {
2452                         r = -ENOMEM;
2453                         goto finish;
2454                 }
2455
2456                 r = open_follow(&filename, &f, symlink_names, &id);
2457                 if (r < 0) {
2458                         free(filename);
2459                         filename = NULL;
2460
2461                         if (r != -ENOENT)
2462                                 goto finish;
2463                 }
2464
2465         } else  {
2466                 char **p;
2467
2468                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2469
2470                         /* Instead of opening the path right away, we manually
2471                          * follow all symlinks and add their name to our unit
2472                          * name set while doing so */
2473                         filename = path_make_absolute(path, *p);
2474                         if (!filename) {
2475                                 r = -ENOMEM;
2476                                 goto finish;
2477                         }
2478
2479                         if (u->manager->unit_path_cache &&
2480                             !set_get(u->manager->unit_path_cache, filename))
2481                                 r = -ENOENT;
2482                         else
2483                                 r = open_follow(&filename, &f, symlink_names, &id);
2484
2485                         if (r < 0) {
2486                                 free(filename);
2487                                 filename = NULL;
2488
2489                                 if (r != -ENOENT)
2490                                         goto finish;
2491
2492                                 /* Empty the symlink names for the next run */
2493                                 set_clear_free(symlink_names);
2494                                 continue;
2495                         }
2496
2497                         break;
2498                 }
2499         }
2500
2501         if (!filename) {
2502                 /* Hmm, no suitable file found? */
2503                 r = 0;
2504                 goto finish;
2505         }
2506
2507         merged = u;
2508         r = merge_by_names(&merged, symlink_names, id);
2509         if (r < 0)
2510                 goto finish;
2511
2512         if (merged != u) {
2513                 u->load_state = UNIT_MERGED;
2514                 r = 0;
2515                 goto finish;
2516         }
2517
2518         if (fstat(fileno(f), &st) < 0) {
2519                 r = -errno;
2520                 goto finish;
2521         }
2522
2523         if (null_or_empty(&st))
2524                 u->load_state = UNIT_MASKED;
2525         else {
2526                 u->load_state = UNIT_LOADED;
2527
2528                 /* Now, parse the file contents */
2529                 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
2530                                  config_item_perf_lookup,
2531                                  (void*) load_fragment_gperf_lookup, false, true, u);
2532                 if (r < 0)
2533                         goto finish;
2534         }
2535
2536         free(u->fragment_path);
2537         u->fragment_path = filename;
2538         filename = NULL;
2539
2540         u->fragment_mtime = timespec_load(&st.st_mtim);
2541
2542         if (u->source_path) {
2543                 if (stat(u->source_path, &st) >= 0)
2544                         u->source_mtime = timespec_load(&st.st_mtim);
2545                 else
2546                         u->source_mtime = 0;
2547         }
2548
2549         r = 0;
2550
2551 finish:
2552         set_free_free(symlink_names);
2553         free(filename);
2554
2555         if (f)
2556                 fclose(f);
2557
2558         return r;
2559 }
2560
2561 int unit_load_fragment(Unit *u) {
2562         int r;
2563         Iterator i;
2564         const char *t;
2565
2566         assert(u);
2567         assert(u->load_state == UNIT_STUB);
2568         assert(u->id);
2569
2570         /* First, try to find the unit under its id. We always look
2571          * for unit files in the default directories, to make it easy
2572          * to override things by placing things in /etc/systemd/system */
2573         r = load_from_path(u, u->id);
2574         if (r < 0)
2575                 return r;
2576
2577         /* Try to find an alias we can load this with */
2578         if (u->load_state == UNIT_STUB)
2579                 SET_FOREACH(t, u->names, i) {
2580
2581                         if (t == u->id)
2582                                 continue;
2583
2584                         r = load_from_path(u, t);
2585                         if (r < 0)
2586                                 return r;
2587
2588                         if (u->load_state != UNIT_STUB)
2589                                 break;
2590                 }
2591
2592         /* And now, try looking for it under the suggested (originally linked) path */
2593         if (u->load_state == UNIT_STUB && u->fragment_path) {
2594
2595                 r = load_from_path(u, u->fragment_path);
2596                 if (r < 0)
2597                         return r;
2598
2599                 if (u->load_state == UNIT_STUB) {
2600                         /* Hmm, this didn't work? Then let's get rid
2601                          * of the fragment path stored for us, so that
2602                          * we don't point to an invalid location. */
2603                         free(u->fragment_path);
2604                         u->fragment_path = NULL;
2605                 }
2606         }
2607
2608         /* Look for a template */
2609         if (u->load_state == UNIT_STUB && u->instance) {
2610                 char *k;
2611
2612                 k = unit_name_template(u->id);
2613                 if (!k)
2614                         return -ENOMEM;
2615
2616                 r = load_from_path(u, k);
2617                 free(k);
2618
2619                 if (r < 0)
2620                         return r;
2621
2622                 if (u->load_state == UNIT_STUB)
2623                         SET_FOREACH(t, u->names, i) {
2624
2625                                 if (t == u->id)
2626                                         continue;
2627
2628                                 k = unit_name_template(t);
2629                                 if (!k)
2630                                         return -ENOMEM;
2631
2632                                 r = load_from_path(u, k);
2633                                 free(k);
2634
2635                                 if (r < 0)
2636                                         return r;
2637
2638                                 if (u->load_state != UNIT_STUB)
2639                                         break;
2640                         }
2641         }
2642
2643         return 0;
2644 }
2645
2646 void unit_dump_config_items(FILE *f) {
2647         static const struct {
2648                 const ConfigParserCallback callback;
2649                 const char *rvalue;
2650         } table[] = {
2651                 { config_parse_int,                   "INTEGER" },
2652                 { config_parse_unsigned,              "UNSIGNED" },
2653                 { config_parse_bytes_size,            "SIZE" },
2654                 { config_parse_bool,                  "BOOLEAN" },
2655                 { config_parse_string,                "STRING" },
2656                 { config_parse_path,                  "PATH" },
2657                 { config_parse_unit_path_printf,      "PATH" },
2658                 { config_parse_strv,                  "STRING [...]" },
2659                 { config_parse_exec_nice,             "NICE" },
2660                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2661                 { config_parse_exec_io_class,         "IOCLASS" },
2662                 { config_parse_exec_io_priority,      "IOPRIORITY" },
2663                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2664                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
2665                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
2666                 { config_parse_mode,                  "MODE" },
2667                 { config_parse_unit_env_file,         "FILE" },
2668                 { config_parse_output,                "OUTPUT" },
2669                 { config_parse_input,                 "INPUT" },
2670                 { config_parse_facility,              "FACILITY" },
2671                 { config_parse_level,                 "LEVEL" },
2672                 { config_parse_exec_capabilities,     "CAPABILITIES" },
2673                 { config_parse_exec_secure_bits,      "SECUREBITS" },
2674                 { config_parse_bounding_set,          "BOUNDINGSET" },
2675                 { config_parse_limit,                 "LIMIT" },
2676                 { config_parse_unit_deps,             "UNIT [...]" },
2677                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
2678                 { config_parse_service_type,          "SERVICETYPE" },
2679                 { config_parse_service_restart,       "SERVICERESTART" },
2680 #ifdef HAVE_SYSV_COMPAT
2681                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
2682 #else
2683                 { config_parse_warn_compat,           "NOTSUPPORTED" },
2684 #endif
2685                 { config_parse_kill_mode,             "KILLMODE" },
2686                 { config_parse_kill_signal,           "SIGNAL" },
2687                 { config_parse_socket_listen,         "SOCKET [...]" },
2688                 { config_parse_socket_bind,           "SOCKETBIND" },
2689                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
2690                 { config_parse_sec,                   "SECONDS" },
2691                 { config_parse_nsec,                  "NANOSECONDS" },
2692                 { config_parse_path_strv,             "PATH [...]" },
2693                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2694                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
2695                 { config_parse_unit_string_printf,    "STRING" },
2696                 { config_parse_trigger_unit,          "UNIT" },
2697                 { config_parse_timer,                 "TIMER" },
2698                 { config_parse_path_spec,             "PATH" },
2699                 { config_parse_notify_access,         "ACCESS" },
2700                 { config_parse_ip_tos,                "TOS" },
2701                 { config_parse_unit_condition_path,   "CONDITION" },
2702                 { config_parse_unit_condition_string, "CONDITION" },
2703                 { config_parse_unit_condition_null,   "CONDITION" },
2704                 { config_parse_unit_slice,            "SLICE" },
2705                 { config_parse_documentation,         "URL" },
2706                 { config_parse_service_timeout,       "SECONDS" },
2707                 { config_parse_start_limit_action,    "ACTION" },
2708                 { config_parse_set_status,            "STATUS" },
2709                 { config_parse_service_sockets,       "SOCKETS" },
2710                 { config_parse_fsck_passno,           "PASSNO" },
2711                 { config_parse_environ,               "ENVIRON" },
2712                 { config_parse_syscall_filter,        "SYSCALL" },
2713                 { config_parse_cpu_shares,            "SHARES" },
2714                 { config_parse_memory_limit,          "LIMIT" },
2715                 { config_parse_device_allow,          "DEVICE" },
2716                 { config_parse_device_policy,         "POLICY" },
2717                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
2718                 { config_parse_blockio_weight,        "WEIGHT" },
2719                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
2720                 { config_parse_long,                  "LONG" },
2721                 { config_parse_socket_service,        "SERVICE" },
2722         };
2723
2724         const char *prev = NULL;
2725         const char *i;
2726
2727         assert(f);
2728
2729         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2730                 const char *rvalue = "OTHER", *lvalue;
2731                 unsigned j;
2732                 size_t prefix_len;
2733                 const char *dot;
2734                 const ConfigPerfItem *p;
2735
2736                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2737
2738                 dot = strchr(i, '.');
2739                 lvalue = dot ? dot + 1 : i;
2740                 prefix_len = dot-i;
2741
2742                 if (dot)
2743                         if (!prev || !strneq(prev, i, prefix_len+1)) {
2744                                 if (prev)
2745                                         fputc('\n', f);
2746
2747                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2748                         }
2749
2750                 for (j = 0; j < ELEMENTSOF(table); j++)
2751                         if (p->parse == table[j].callback) {
2752                                 rvalue = table[j].rvalue;
2753                                 break;
2754                         }
2755
2756                 fprintf(f, "%s=%s\n", lvalue, rvalue);
2757                 prev = i;
2758         }
2759 }