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