]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
shared/install: add some more debug messages and comments
[thirdparty/systemd.git] / src / shared / install.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2011 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty <of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <fnmatch.h>
24 #include <limits.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #include "alloc-util.h"
33 #include "conf-files.h"
34 #include "conf-parser.h"
35 #include "dirent-util.h"
36 #include "extract-word.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "fs-util.h"
40 #include "hashmap.h"
41 #include "install-printf.h"
42 #include "install.h"
43 #include "log.h"
44 #include "macro.h"
45 #include "mkdir.h"
46 #include "path-lookup.h"
47 #include "path-util.h"
48 #include "rm-rf.h"
49 #include "set.h"
50 #include "special.h"
51 #include "stat-util.h"
52 #include "string-table.h"
53 #include "string-util.h"
54 #include "strv.h"
55 #include "unit-name.h"
56
57 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
58
59 typedef enum SearchFlags {
60 SEARCH_LOAD = 1,
61 SEARCH_FOLLOW_CONFIG_SYMLINKS = 2,
62 } SearchFlags;
63
64 typedef struct {
65 OrderedHashmap *will_process;
66 OrderedHashmap *have_processed;
67 } InstallContext;
68
69 typedef enum {
70 PRESET_UNKNOWN,
71 PRESET_ENABLE,
72 PRESET_DISABLE,
73 } PresetAction;
74
75 typedef struct {
76 char *pattern;
77 PresetAction action;
78 } PresetRule;
79
80 typedef struct {
81 PresetRule *rules;
82 size_t n_rules;
83 } Presets;
84
85 static inline void presets_freep(Presets *p) {
86 size_t i;
87
88 if (!p)
89 return;
90
91 for (i = 0; i < p->n_rules; i++)
92 free(p->rules[i].pattern);
93
94 free(p->rules);
95 p->n_rules = 0;
96 }
97
98 static int unit_file_lookup_state(UnitFileScope scope, const LookupPaths *paths, const char *name, UnitFileState *ret);
99
100 bool unit_type_may_alias(UnitType type) {
101 return IN_SET(type,
102 UNIT_SERVICE,
103 UNIT_SOCKET,
104 UNIT_TARGET,
105 UNIT_DEVICE,
106 UNIT_TIMER,
107 UNIT_PATH);
108 }
109
110 bool unit_type_may_template(UnitType type) {
111 return IN_SET(type,
112 UNIT_SERVICE,
113 UNIT_SOCKET,
114 UNIT_TARGET,
115 UNIT_TIMER,
116 UNIT_PATH);
117 }
118
119 static const char *unit_file_type_table[_UNIT_FILE_TYPE_MAX] = {
120 [UNIT_FILE_TYPE_REGULAR] = "regular",
121 [UNIT_FILE_TYPE_SYMLINK] = "symlink",
122 [UNIT_FILE_TYPE_MASKED] = "masked",
123 };
124
125 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type, UnitFileType);
126
127 static int in_search_path(const LookupPaths *p, const char *path) {
128 _cleanup_free_ char *parent = NULL;
129 char **i;
130
131 assert(path);
132
133 parent = dirname_malloc(path);
134 if (!parent)
135 return -ENOMEM;
136
137 STRV_FOREACH(i, p->search_path)
138 if (path_equal(parent, *i))
139 return true;
140
141 return false;
142 }
143
144 static const char* skip_root(const LookupPaths *p, const char *path) {
145 char *e;
146
147 assert(p);
148 assert(path);
149
150 if (!p->root_dir)
151 return path;
152
153 e = path_startswith(path, p->root_dir);
154 if (!e)
155 return NULL;
156
157 /* Make sure the returned path starts with a slash */
158 if (e[0] != '/') {
159 if (e == path || e[-1] != '/')
160 return NULL;
161
162 e--;
163 }
164
165 return e;
166 }
167
168 static int path_is_generator(const LookupPaths *p, const char *path) {
169 _cleanup_free_ char *parent = NULL;
170
171 assert(p);
172 assert(path);
173
174 parent = dirname_malloc(path);
175 if (!parent)
176 return -ENOMEM;
177
178 return path_equal_ptr(parent, p->generator) ||
179 path_equal_ptr(parent, p->generator_early) ||
180 path_equal_ptr(parent, p->generator_late);
181 }
182
183 static int path_is_transient(const LookupPaths *p, const char *path) {
184 _cleanup_free_ char *parent = NULL;
185
186 assert(p);
187 assert(path);
188
189 parent = dirname_malloc(path);
190 if (!parent)
191 return -ENOMEM;
192
193 return path_equal_ptr(parent, p->transient);
194 }
195
196 static int path_is_control(const LookupPaths *p, const char *path) {
197 _cleanup_free_ char *parent = NULL;
198
199 assert(p);
200 assert(path);
201
202 parent = dirname_malloc(path);
203 if (!parent)
204 return -ENOMEM;
205
206 return path_equal_ptr(parent, p->persistent_control) ||
207 path_equal_ptr(parent, p->runtime_control);
208 }
209
210 static int path_is_config(const LookupPaths *p, const char *path) {
211 _cleanup_free_ char *parent = NULL;
212
213 assert(p);
214 assert(path);
215
216 /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern
217 * configuration from transient or generated units */
218
219 parent = dirname_malloc(path);
220 if (!parent)
221 return -ENOMEM;
222
223 return path_equal_ptr(parent, p->persistent_config) ||
224 path_equal_ptr(parent, p->runtime_config);
225 }
226
227 static int path_is_runtime(const LookupPaths *p, const char *path) {
228 _cleanup_free_ char *parent = NULL;
229 const char *rpath;
230
231 assert(p);
232 assert(path);
233
234 /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime
235 * directories, as safety net. */
236
237 rpath = skip_root(p, path);
238 if (rpath && path_startswith(rpath, "/run"))
239 return true;
240
241 parent = dirname_malloc(path);
242 if (!parent)
243 return -ENOMEM;
244
245 return path_equal_ptr(parent, p->runtime_config) ||
246 path_equal_ptr(parent, p->generator) ||
247 path_equal_ptr(parent, p->generator_early) ||
248 path_equal_ptr(parent, p->generator_late) ||
249 path_equal_ptr(parent, p->transient) ||
250 path_equal_ptr(parent, p->runtime_control);
251 }
252
253 static int path_is_vendor(const LookupPaths *p, const char *path) {
254 const char *rpath;
255
256 assert(p);
257 assert(path);
258
259 rpath = skip_root(p, path);
260 if (!rpath)
261 return 0;
262
263 if (path_startswith(rpath, "/usr"))
264 return true;
265
266 #ifdef HAVE_SPLIT_USR
267 if (path_startswith(rpath, "/lib"))
268 return true;
269 #endif
270
271 return path_equal(rpath, SYSTEM_DATA_UNIT_PATH);
272 }
273
274 int unit_file_changes_add(
275 UnitFileChange **changes,
276 unsigned *n_changes,
277 UnitFileChangeType type,
278 const char *path,
279 const char *source) {
280
281 _cleanup_free_ char *p = NULL, *s = NULL;
282 UnitFileChange *c;
283
284 assert(path);
285 assert(!changes == !n_changes);
286
287 if (!changes)
288 return 0;
289
290 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
291 if (!c)
292 return -ENOMEM;
293 *changes = c;
294
295 p = strdup(path);
296 if (source)
297 s = strdup(source);
298
299 if (!p || (source && !s))
300 return -ENOMEM;
301
302 path_kill_slashes(p);
303 if (s)
304 path_kill_slashes(s);
305
306 c[*n_changes] = (UnitFileChange) { type, p, s };
307 p = s = NULL;
308 (*n_changes) ++;
309 return 0;
310 }
311
312 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
313 unsigned i;
314
315 assert(changes || n_changes == 0);
316
317 for (i = 0; i < n_changes; i++) {
318 free(changes[i].path);
319 free(changes[i].source);
320 }
321
322 free(changes);
323 }
324
325 void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet) {
326 unsigned i;
327 bool logged = false;
328
329 assert(changes || n_changes == 0);
330 /* If verb is not specified, errors are not allowed! */
331 assert(verb || r >= 0);
332
333 for (i = 0; i < n_changes; i++) {
334 assert(verb || changes[i].type >= 0);
335
336 switch(changes[i].type) {
337 case UNIT_FILE_SYMLINK:
338 if (!quiet)
339 log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source);
340 break;
341 case UNIT_FILE_UNLINK:
342 if (!quiet)
343 log_info("Removed %s.", changes[i].path);
344 break;
345 case UNIT_FILE_IS_MASKED:
346 if (!quiet)
347 log_info("Unit %s is masked, ignoring.", changes[i].path);
348 break;
349 case -EEXIST:
350 if (changes[i].source)
351 log_error_errno(changes[i].type,
352 "Failed to %s unit, file %s already exists and is a symlink to %s.",
353 verb, changes[i].path, changes[i].source);
354 else
355 log_error_errno(changes[i].type,
356 "Failed to %s unit, file %s already exists.",
357 verb, changes[i].path);
358 logged = true;
359 break;
360 case -ERFKILL:
361 log_error_errno(changes[i].type, "Failed to %s unit, unit %s is masked.",
362 verb, changes[i].path);
363 logged = true;
364 break;
365 case -EADDRNOTAVAIL:
366 log_error_errno(changes[i].type, "Failed to %s unit, unit %s is transient or generated.",
367 verb, changes[i].path);
368 logged = true;
369 break;
370 case -ELOOP:
371 log_error_errno(changes[i].type, "Failed to %s unit, refusing to operate on linked unit file %s",
372 verb, changes[i].path);
373 logged = true;
374 break;
375 default:
376 assert(changes[i].type < 0);
377 log_error_errno(changes[i].type, "Failed to %s unit, file %s: %m.",
378 verb, changes[i].path);
379 logged = true;
380 }
381 }
382
383 if (r < 0 && !logged)
384 log_error_errno(r, "Failed to %s: %m.", verb);
385 }
386
387
388
389 static int create_symlink(
390 const char *old_path,
391 const char *new_path,
392 bool force,
393 UnitFileChange **changes,
394 unsigned *n_changes) {
395
396 _cleanup_free_ char *dest = NULL;
397 int r;
398
399 assert(old_path);
400 assert(new_path);
401
402 /* Actually create a symlink, and remember that we did. Is
403 * smart enough to check if there's already a valid symlink in
404 * place. */
405
406 mkdir_parents_label(new_path, 0755);
407
408 if (symlink(old_path, new_path) >= 0) {
409 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
410 return 1;
411 }
412
413 if (errno != EEXIST) {
414 unit_file_changes_add(changes, n_changes, -errno, new_path, NULL);
415 return -errno;
416 }
417
418 r = readlink_malloc(new_path, &dest);
419 if (r < 0) {
420 /* translate EINVAL (non-symlink exists) to EEXIST */
421 if (r == -EINVAL)
422 r = -EEXIST;
423
424 unit_file_changes_add(changes, n_changes, r, new_path, NULL);
425 return r;
426 }
427
428 if (path_equal(dest, old_path))
429 return 0;
430
431 if (!force) {
432 unit_file_changes_add(changes, n_changes, -EEXIST, new_path, dest);
433 return -EEXIST;
434 }
435
436 r = symlink_atomic(old_path, new_path);
437 if (r < 0) {
438 unit_file_changes_add(changes, n_changes, r, new_path, NULL);
439 return r;
440 }
441
442 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
443 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
444
445 return 1;
446 }
447
448 static int mark_symlink_for_removal(
449 Set **remove_symlinks_to,
450 const char *p) {
451
452 char *n;
453 int r;
454
455 assert(p);
456
457 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
458 if (r < 0)
459 return r;
460
461 n = strdup(p);
462 if (!n)
463 return -ENOMEM;
464
465 path_kill_slashes(n);
466
467 r = set_consume(*remove_symlinks_to, n);
468 if (r == -EEXIST)
469 return 0;
470 if (r < 0)
471 return r;
472
473 return 1;
474 }
475
476 static int remove_marked_symlinks_fd(
477 Set *remove_symlinks_to,
478 int fd,
479 const char *path,
480 const char *config_path,
481 const LookupPaths *lp,
482 bool *restart,
483 UnitFileChange **changes,
484 unsigned *n_changes) {
485
486 _cleanup_closedir_ DIR *d = NULL;
487 struct dirent *de;
488 int r = 0;
489
490 assert(remove_symlinks_to);
491 assert(fd >= 0);
492 assert(path);
493 assert(config_path);
494 assert(lp);
495 assert(restart);
496
497 d = fdopendir(fd);
498 if (!d) {
499 safe_close(fd);
500 return -errno;
501 }
502
503 rewinddir(d);
504
505 FOREACH_DIRENT(de, d, return -errno) {
506
507 dirent_ensure_type(d, de);
508
509 if (de->d_type == DT_DIR) {
510 _cleanup_free_ char *p = NULL;
511 int nfd, q;
512
513 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
514 if (nfd < 0) {
515 if (errno == ENOENT)
516 continue;
517
518 if (r == 0)
519 r = -errno;
520 continue;
521 }
522
523 p = path_make_absolute(de->d_name, path);
524 if (!p) {
525 safe_close(nfd);
526 return -ENOMEM;
527 }
528
529 /* This will close nfd, regardless whether it succeeds or not */
530 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, restart, changes, n_changes);
531 if (q < 0 && r == 0)
532 r = q;
533
534 } else if (de->d_type == DT_LNK) {
535 _cleanup_free_ char *p = NULL, *dest = NULL;
536 const char *rp;
537 bool found;
538 int q;
539
540 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
541 continue;
542
543 p = path_make_absolute(de->d_name, path);
544 if (!p)
545 return -ENOMEM;
546 path_kill_slashes(p);
547
548 q = readlink_malloc(p, &dest);
549 if (q == -ENOENT)
550 continue;
551 if (q < 0) {
552 if (r == 0)
553 r = q;
554 continue;
555 }
556
557 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
558 * the same name as a file that is marked. */
559
560 found = set_contains(remove_symlinks_to, dest) ||
561 set_contains(remove_symlinks_to, basename(dest)) ||
562 set_contains(remove_symlinks_to, de->d_name);
563
564 if (!found)
565 continue;
566
567 if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) {
568 if (r == 0)
569 r = -errno;
570 unit_file_changes_add(changes, n_changes, -errno, p, NULL);
571 continue;
572 }
573
574 (void) rmdir_parents(p, config_path);
575
576 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
577
578 /* Now, remember the full path (but with the root prefix removed) of
579 * the symlink we just removed, and remove any symlinks to it, too. */
580
581 rp = skip_root(lp, p);
582 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p);
583 if (q < 0)
584 return q;
585 if (q > 0)
586 *restart = true;
587 }
588 }
589
590 return r;
591 }
592
593 static int remove_marked_symlinks(
594 Set *remove_symlinks_to,
595 const char *config_path,
596 const LookupPaths *lp,
597 UnitFileChange **changes,
598 unsigned *n_changes) {
599
600 _cleanup_close_ int fd = -1;
601 bool restart;
602 int r = 0;
603
604 assert(config_path);
605 assert(lp);
606
607 if (set_size(remove_symlinks_to) <= 0)
608 return 0;
609
610 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
611 if (fd < 0)
612 return -errno;
613
614 do {
615 int q, cfd;
616 restart = false;
617
618 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
619 if (cfd < 0)
620 return -errno;
621
622 /* This takes possession of cfd and closes it */
623 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, &restart, changes, n_changes);
624 if (r == 0)
625 r = q;
626 } while (restart);
627
628 return r;
629 }
630
631 static int find_symlinks_fd(
632 const char *root_dir,
633 const char *name,
634 int fd,
635 const char *path,
636 const char *config_path,
637 const LookupPaths *lp,
638 bool *same_name_link) {
639
640 _cleanup_closedir_ DIR *d = NULL;
641 struct dirent *de;
642 int r = 0;
643
644 assert(name);
645 assert(fd >= 0);
646 assert(path);
647 assert(config_path);
648 assert(lp);
649 assert(same_name_link);
650
651 d = fdopendir(fd);
652 if (!d) {
653 safe_close(fd);
654 return -errno;
655 }
656
657 FOREACH_DIRENT(de, d, return -errno) {
658
659 dirent_ensure_type(d, de);
660
661 if (de->d_type == DT_DIR) {
662 _cleanup_free_ char *p = NULL;
663 int nfd, q;
664
665 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
666 if (nfd < 0) {
667 if (errno == ENOENT)
668 continue;
669
670 if (r == 0)
671 r = -errno;
672 continue;
673 }
674
675 p = path_make_absolute(de->d_name, path);
676 if (!p) {
677 safe_close(nfd);
678 return -ENOMEM;
679 }
680
681 /* This will close nfd, regardless whether it succeeds or not */
682 q = find_symlinks_fd(root_dir, name, nfd, p, config_path, lp, same_name_link);
683 if (q > 0)
684 return 1;
685 if (r == 0)
686 r = q;
687
688 } else if (de->d_type == DT_LNK) {
689 _cleanup_free_ char *p = NULL, *dest = NULL;
690 bool found_path, found_dest, b = false;
691 int q;
692
693 /* Acquire symlink name */
694 p = path_make_absolute(de->d_name, path);
695 if (!p)
696 return -ENOMEM;
697
698 /* Acquire symlink destination */
699 q = readlink_malloc(p, &dest);
700 if (q == -ENOENT)
701 continue;
702 if (q < 0) {
703 if (r == 0)
704 r = q;
705 continue;
706 }
707
708 /* Make absolute */
709 if (!path_is_absolute(dest)) {
710 char *x;
711
712 x = prefix_root(root_dir, dest);
713 if (!x)
714 return -ENOMEM;
715
716 free(dest);
717 dest = x;
718 }
719
720 /* Check if the symlink itself matches what we
721 * are looking for */
722 if (path_is_absolute(name))
723 found_path = path_equal(p, name);
724 else
725 found_path = streq(de->d_name, name);
726
727 /* Check if what the symlink points to
728 * matches what we are looking for */
729 if (path_is_absolute(name))
730 found_dest = path_equal(dest, name);
731 else
732 found_dest = streq(basename(dest), name);
733
734 if (found_path && found_dest) {
735 _cleanup_free_ char *t = NULL;
736
737 /* Filter out same name links in the main
738 * config path */
739 t = path_make_absolute(name, config_path);
740 if (!t)
741 return -ENOMEM;
742
743 b = path_equal(t, p);
744 }
745
746 if (b)
747 *same_name_link = true;
748 else if (found_path || found_dest)
749 return 1;
750 }
751 }
752
753 return r;
754 }
755
756 static int find_symlinks(
757 const char *root_dir,
758 const char *name,
759 const char *config_path,
760 const LookupPaths *lp,
761 bool *same_name_link) {
762
763 int fd;
764
765 assert(name);
766 assert(config_path);
767 assert(same_name_link);
768
769 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
770 if (fd < 0) {
771 if (errno == ENOENT)
772 return 0;
773 return -errno;
774 }
775
776 /* This takes possession of fd and closes it */
777 return find_symlinks_fd(root_dir, name, fd, config_path, config_path, lp, same_name_link);
778 }
779
780 static int find_symlinks_in_scope(
781 UnitFileScope scope,
782 const LookupPaths *paths,
783 const char *name,
784 UnitFileState *state) {
785
786 bool same_name_link_runtime = false, same_name_link = false;
787 int r;
788
789 assert(scope >= 0);
790 assert(scope < _UNIT_FILE_SCOPE_MAX);
791 assert(paths);
792 assert(name);
793
794 /* First look in the persistent config path */
795 r = find_symlinks(paths->root_dir, name, paths->persistent_config, paths, &same_name_link);
796 if (r < 0)
797 return r;
798 if (r > 0) {
799 *state = UNIT_FILE_ENABLED;
800 return r;
801 }
802
803 /* Then look in runtime config path */
804 r = find_symlinks(paths->root_dir, name, paths->runtime_config, paths, &same_name_link_runtime);
805 if (r < 0)
806 return r;
807 if (r > 0) {
808 *state = UNIT_FILE_ENABLED_RUNTIME;
809 return r;
810 }
811
812 /* Hmm, we didn't find it, but maybe we found the same name
813 * link? */
814 if (same_name_link) {
815 *state = UNIT_FILE_LINKED;
816 return 1;
817 }
818 if (same_name_link_runtime) {
819 *state = UNIT_FILE_LINKED_RUNTIME;
820 return 1;
821 }
822
823 return 0;
824 }
825
826 static void install_info_free(UnitFileInstallInfo *i) {
827
828 if (!i)
829 return;
830
831 free(i->name);
832 free(i->path);
833 strv_free(i->aliases);
834 strv_free(i->wanted_by);
835 strv_free(i->required_by);
836 strv_free(i->also);
837 free(i->default_instance);
838 free(i->symlink_target);
839 free(i);
840 }
841
842 static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) {
843 UnitFileInstallInfo *i;
844
845 if (!m)
846 return NULL;
847
848 while ((i = ordered_hashmap_steal_first(m)))
849 install_info_free(i);
850
851 return ordered_hashmap_free(m);
852 }
853
854 static void install_context_done(InstallContext *c) {
855 assert(c);
856
857 c->will_process = install_info_hashmap_free(c->will_process);
858 c->have_processed = install_info_hashmap_free(c->have_processed);
859 }
860
861 static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) {
862 UnitFileInstallInfo *i;
863
864 i = ordered_hashmap_get(c->have_processed, name);
865 if (i)
866 return i;
867
868 return ordered_hashmap_get(c->will_process, name);
869 }
870
871 static int install_info_may_process(
872 UnitFileInstallInfo *i,
873 const LookupPaths *paths,
874 UnitFileChange **changes,
875 unsigned *n_changes) {
876 assert(i);
877 assert(paths);
878
879 /* Checks whether the loaded unit file is one we should process, or is masked, transient or generated and thus
880 * not subject to enable/disable operations. */
881
882 if (i->type == UNIT_FILE_TYPE_MASKED) {
883 unit_file_changes_add(changes, n_changes, -ERFKILL, i->path, NULL);
884 return -ERFKILL;
885 }
886 if (path_is_generator(paths, i->path) ||
887 path_is_transient(paths, i->path)) {
888 unit_file_changes_add(changes, n_changes, -EADDRNOTAVAIL, i->path, NULL);
889 return -EADDRNOTAVAIL;
890 }
891
892 return 0;
893 }
894
895 static int install_info_add(
896 InstallContext *c,
897 const char *name,
898 const char *path,
899 UnitFileInstallInfo **ret) {
900
901 UnitFileInstallInfo *i = NULL;
902 int r;
903
904 assert(c);
905 assert(name || path);
906
907 if (!name)
908 name = basename(path);
909
910 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
911 return -EINVAL;
912
913 i = install_info_find(c, name);
914 if (i) {
915 if (ret)
916 *ret = i;
917 return 0;
918 }
919
920 r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
921 if (r < 0)
922 return r;
923
924 i = new0(UnitFileInstallInfo, 1);
925 if (!i)
926 return -ENOMEM;
927 i->type = _UNIT_FILE_TYPE_INVALID;
928
929 i->name = strdup(name);
930 if (!i->name) {
931 r = -ENOMEM;
932 goto fail;
933 }
934
935 if (path) {
936 i->path = strdup(path);
937 if (!i->path) {
938 r = -ENOMEM;
939 goto fail;
940 }
941 }
942
943 r = ordered_hashmap_put(c->will_process, i->name, i);
944 if (r < 0)
945 goto fail;
946
947 if (ret)
948 *ret = i;
949
950 return 0;
951
952 fail:
953 install_info_free(i);
954 return r;
955 }
956
957 static int config_parse_alias(
958 const char *unit,
959 const char *filename,
960 unsigned line,
961 const char *section,
962 unsigned section_line,
963 const char *lvalue,
964 int ltype,
965 const char *rvalue,
966 void *data,
967 void *userdata) {
968
969 const char *name;
970 UnitType type;
971
972 assert(filename);
973 assert(lvalue);
974 assert(rvalue);
975
976 name = basename(filename);
977 type = unit_name_to_type(name);
978 if (!unit_type_may_alias(type))
979 return log_syntax(unit, LOG_WARNING, filename, line, 0,
980 "Aliases are not allowed for %s units, ignoring.",
981 unit_type_to_string(type));
982
983 return config_parse_strv(unit, filename, line, section, section_line,
984 lvalue, ltype, rvalue, data, userdata);
985 }
986
987 static int config_parse_also(
988 const char *unit,
989 const char *filename,
990 unsigned line,
991 const char *section,
992 unsigned section_line,
993 const char *lvalue,
994 int ltype,
995 const char *rvalue,
996 void *data,
997 void *userdata) {
998
999 UnitFileInstallInfo *i = userdata;
1000 InstallContext *c = data;
1001 int r;
1002
1003 assert(filename);
1004 assert(lvalue);
1005 assert(rvalue);
1006
1007 for (;;) {
1008 _cleanup_free_ char *word = NULL;
1009
1010 r = extract_first_word(&rvalue, &word, NULL, 0);
1011 if (r < 0)
1012 return r;
1013 if (r == 0)
1014 break;
1015
1016 r = install_info_add(c, word, NULL, NULL);
1017 if (r < 0)
1018 return r;
1019
1020 r = strv_push(&i->also, word);
1021 if (r < 0)
1022 return r;
1023
1024 word = NULL;
1025 }
1026
1027 return 0;
1028 }
1029
1030 static int config_parse_default_instance(
1031 const char *unit,
1032 const char *filename,
1033 unsigned line,
1034 const char *section,
1035 unsigned section_line,
1036 const char *lvalue,
1037 int ltype,
1038 const char *rvalue,
1039 void *data,
1040 void *userdata) {
1041
1042 UnitFileInstallInfo *i = data;
1043 const char *name;
1044 char *printed;
1045 int r;
1046
1047 assert(filename);
1048 assert(lvalue);
1049 assert(rvalue);
1050
1051 name = basename(filename);
1052 if (unit_name_is_valid(name, UNIT_NAME_INSTANCE))
1053 /* When enabling an instance, we might be using a template unit file,
1054 * but we should ignore DefaultInstance silently. */
1055 return 0;
1056 if (!unit_name_is_valid(name, UNIT_NAME_TEMPLATE))
1057 return log_syntax(unit, LOG_WARNING, filename, line, 0,
1058 "DefaultInstance only makes sense for template units, ignoring.");
1059
1060 r = install_full_printf(i, rvalue, &printed);
1061 if (r < 0)
1062 return r;
1063
1064 if (!unit_instance_is_valid(printed)) {
1065 free(printed);
1066 return -EINVAL;
1067 }
1068
1069 free(i->default_instance);
1070 i->default_instance = printed;
1071
1072 return 0;
1073 }
1074
1075 static int unit_file_load(
1076 InstallContext *c,
1077 UnitFileInstallInfo *info,
1078 const char *path,
1079 SearchFlags flags) {
1080
1081 const ConfigTableItem items[] = {
1082 { "Install", "Alias", config_parse_alias, 0, &info->aliases },
1083 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1084 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1085 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1086 { "Install", "Also", config_parse_also, 0, c },
1087 {}
1088 };
1089
1090 const char *name;
1091 UnitType type;
1092 _cleanup_fclose_ FILE *f = NULL;
1093 _cleanup_close_ int fd = -1;
1094 struct stat st;
1095 int r;
1096
1097 assert(c);
1098 assert(info);
1099 assert(path);
1100
1101 name = basename(path);
1102 type = unit_name_to_type(name);
1103 if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) &&
1104 !unit_type_may_template(type))
1105 return log_error_errno(EINVAL, "Unit type %s cannot be templated.", unit_type_to_string(type));
1106
1107 if (!(flags & SEARCH_LOAD)) {
1108 r = lstat(path, &st);
1109 if (r < 0)
1110 return -errno;
1111
1112 if (null_or_empty(&st))
1113 info->type = UNIT_FILE_TYPE_MASKED;
1114 else if (S_ISREG(st.st_mode))
1115 info->type = UNIT_FILE_TYPE_REGULAR;
1116 else if (S_ISLNK(st.st_mode))
1117 return -ELOOP;
1118 else if (S_ISDIR(st.st_mode))
1119 return -EISDIR;
1120 else
1121 return -ENOTTY;
1122
1123 return 0;
1124 }
1125
1126 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
1127 if (fd < 0)
1128 return -errno;
1129 if (fstat(fd, &st) < 0)
1130 return -errno;
1131 if (null_or_empty(&st)) {
1132 info->type = UNIT_FILE_TYPE_MASKED;
1133 return 0;
1134 }
1135 if (S_ISDIR(st.st_mode))
1136 return -EISDIR;
1137 if (!S_ISREG(st.st_mode))
1138 return -ENOTTY;
1139
1140 f = fdopen(fd, "re");
1141 if (!f)
1142 return -errno;
1143 fd = -1;
1144
1145 r = config_parse(NULL, path, f,
1146 NULL,
1147 config_item_table_lookup, items,
1148 true, true, false, info);
1149 if (r < 0)
1150 return r;
1151
1152 info->type = UNIT_FILE_TYPE_REGULAR;
1153
1154 return
1155 (int) strv_length(info->aliases) +
1156 (int) strv_length(info->wanted_by) +
1157 (int) strv_length(info->required_by);
1158 }
1159
1160 static int unit_file_load_or_readlink(
1161 InstallContext *c,
1162 UnitFileInstallInfo *info,
1163 const char *path,
1164 const char *root_dir,
1165 SearchFlags flags) {
1166
1167 _cleanup_free_ char *target = NULL;
1168 int r;
1169
1170 r = unit_file_load(c, info, path, flags);
1171 if (r != -ELOOP)
1172 return r;
1173
1174 /* This is a symlink, let's read it. */
1175
1176 r = readlink_malloc(path, &target);
1177 if (r < 0)
1178 return r;
1179
1180 if (path_equal(target, "/dev/null"))
1181 info->type = UNIT_FILE_TYPE_MASKED;
1182 else {
1183 const char *bn;
1184 UnitType a, b;
1185
1186 bn = basename(target);
1187
1188 if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
1189
1190 if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
1191 return -EINVAL;
1192
1193 } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1194
1195 if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
1196 return -EINVAL;
1197
1198 } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
1199
1200 if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
1201 return -EINVAL;
1202 } else
1203 return -EINVAL;
1204
1205 /* Enforce that the symlink destination does not
1206 * change the unit file type. */
1207
1208 a = unit_name_to_type(info->name);
1209 b = unit_name_to_type(bn);
1210 if (a < 0 || b < 0 || a != b)
1211 return -EINVAL;
1212
1213 if (path_is_absolute(target))
1214 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1215 info->symlink_target = prefix_root(root_dir, target);
1216 else
1217 /* This is a relative path, take it relative to the dir the symlink is located in. */
1218 info->symlink_target = file_in_same_dir(path, target);
1219 if (!info->symlink_target)
1220 return -ENOMEM;
1221
1222 info->type = UNIT_FILE_TYPE_SYMLINK;
1223 }
1224
1225 return 0;
1226 }
1227
1228 static int unit_file_search(
1229 InstallContext *c,
1230 UnitFileInstallInfo *info,
1231 const LookupPaths *paths,
1232 SearchFlags flags) {
1233
1234 _cleanup_free_ char *template = NULL;
1235 char **p;
1236 int r;
1237
1238 assert(c);
1239 assert(info);
1240 assert(paths);
1241
1242 /* Was this unit already loaded? */
1243 if (info->type != _UNIT_FILE_TYPE_INVALID)
1244 return 0;
1245
1246 if (info->path)
1247 return unit_file_load_or_readlink(c, info, info->path, paths->root_dir, flags);
1248
1249 assert(info->name);
1250
1251 STRV_FOREACH(p, paths->search_path) {
1252 _cleanup_free_ char *path = NULL;
1253
1254 path = strjoin(*p, "/", info->name, NULL);
1255 if (!path)
1256 return -ENOMEM;
1257
1258 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1259 if (r >= 0) {
1260 info->path = path;
1261 path = NULL;
1262 return r;
1263 } else if (r != -ENOENT)
1264 return r;
1265 }
1266
1267 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1268 /* Unit file doesn't exist, however instance
1269 * enablement was requested. We will check if it is
1270 * possible to load template unit file. */
1271
1272 r = unit_name_template(info->name, &template);
1273 if (r < 0)
1274 return r;
1275
1276 STRV_FOREACH(p, paths->search_path) {
1277 _cleanup_free_ char *path = NULL;
1278
1279 path = strjoin(*p, "/", template, NULL);
1280 if (!path)
1281 return -ENOMEM;
1282
1283 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1284 if (r >= 0) {
1285 info->path = path;
1286 path = NULL;
1287 return r;
1288 } else if (r != -ENOENT)
1289 return r;
1290 }
1291 }
1292
1293 log_debug("Cannot find unit %s%s%s.", info->name, template ? " or " : "", strempty(template));
1294 return -ENOENT;
1295 }
1296
1297 static int install_info_follow(
1298 InstallContext *c,
1299 UnitFileInstallInfo *i,
1300 const char *root_dir,
1301 SearchFlags flags) {
1302
1303 assert(c);
1304 assert(i);
1305
1306 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1307 return -EINVAL;
1308 if (!i->symlink_target)
1309 return -EINVAL;
1310
1311 /* If the basename doesn't match, the caller should add a
1312 * complete new entry for this. */
1313
1314 if (!streq(basename(i->symlink_target), i->name))
1315 return -EXDEV;
1316
1317 free(i->path);
1318 i->path = i->symlink_target;
1319 i->symlink_target = NULL;
1320 i->type = _UNIT_FILE_TYPE_INVALID;
1321
1322 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1323 }
1324
1325 /**
1326 * Search for the unit file. If the unit name is a symlink,
1327 * follow the symlink to the target, maybe more than once.
1328 * Propagate the instance name if present.
1329 */
1330 static int install_info_traverse(
1331 UnitFileScope scope,
1332 InstallContext *c,
1333 const LookupPaths *paths,
1334 UnitFileInstallInfo *start,
1335 SearchFlags flags,
1336 UnitFileInstallInfo **ret) {
1337
1338 UnitFileInstallInfo *i;
1339 unsigned k = 0;
1340 int r;
1341
1342 assert(paths);
1343 assert(start);
1344 assert(c);
1345
1346 r = unit_file_search(c, start, paths, flags);
1347 if (r < 0)
1348 return r;
1349
1350 i = start;
1351 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1352 /* Follow the symlink */
1353
1354 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1355 return -ELOOP;
1356
1357 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
1358 r = path_is_config(paths, i->path);
1359 if (r < 0)
1360 return r;
1361 if (r > 0)
1362 return -ELOOP;
1363 }
1364
1365 r = install_info_follow(c, i, paths->root_dir, flags);
1366 if (r == -EXDEV) {
1367 _cleanup_free_ char *buffer = NULL;
1368 const char *bn;
1369
1370 /* Target has a different name, create a new
1371 * install info object for that, and continue
1372 * with that. */
1373
1374 bn = basename(i->symlink_target);
1375
1376 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1377 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1378
1379 _cleanup_free_ char *instance = NULL;
1380
1381 r = unit_name_to_instance(i->name, &instance);
1382 if (r < 0)
1383 return r;
1384
1385 r = unit_name_replace_instance(bn, instance, &buffer);
1386 if (r < 0)
1387 return r;
1388
1389 bn = buffer;
1390 }
1391
1392 r = install_info_add(c, bn, NULL, &i);
1393 if (r < 0)
1394 return r;
1395
1396 /* Try again, with the new target we found. */
1397 r = unit_file_search(c, i, paths, flags);
1398 }
1399
1400 if (r < 0)
1401 return r;
1402 }
1403
1404 if (ret)
1405 *ret = i;
1406
1407 return 0;
1408 }
1409
1410 static int install_info_add_auto(
1411 InstallContext *c,
1412 const LookupPaths *paths,
1413 const char *name_or_path,
1414 UnitFileInstallInfo **ret) {
1415
1416 assert(c);
1417 assert(name_or_path);
1418
1419 if (path_is_absolute(name_or_path)) {
1420 const char *pp;
1421
1422 pp = prefix_roota(paths->root_dir, name_or_path);
1423
1424 return install_info_add(c, NULL, pp, ret);
1425 } else
1426 return install_info_add(c, name_or_path, NULL, ret);
1427 }
1428
1429 static int install_info_discover(
1430 UnitFileScope scope,
1431 InstallContext *c,
1432 const LookupPaths *paths,
1433 const char *name,
1434 SearchFlags flags,
1435 UnitFileInstallInfo **ret) {
1436
1437 UnitFileInstallInfo *i;
1438 int r;
1439
1440 assert(c);
1441 assert(paths);
1442 assert(name);
1443
1444 r = install_info_add_auto(c, paths, name, &i);
1445 if (r < 0)
1446 return r;
1447
1448 return install_info_traverse(scope, c, paths, i, flags, ret);
1449 }
1450
1451 static int install_info_symlink_alias(
1452 UnitFileInstallInfo *i,
1453 const LookupPaths *paths,
1454 const char *config_path,
1455 bool force,
1456 UnitFileChange **changes,
1457 unsigned *n_changes) {
1458
1459 char **s;
1460 int r = 0, q;
1461
1462 assert(i);
1463 assert(paths);
1464 assert(config_path);
1465
1466 STRV_FOREACH(s, i->aliases) {
1467 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1468 const char *rp;
1469
1470 q = install_full_printf(i, *s, &dst);
1471 if (q < 0)
1472 return q;
1473
1474 alias_path = path_make_absolute(dst, config_path);
1475 if (!alias_path)
1476 return -ENOMEM;
1477
1478 rp = skip_root(paths, i->path);
1479
1480 q = create_symlink(rp ?: i->path, alias_path, force, changes, n_changes);
1481 if (r == 0)
1482 r = q;
1483 }
1484
1485 return r;
1486 }
1487
1488 static int install_info_symlink_wants(
1489 UnitFileInstallInfo *i,
1490 const LookupPaths *paths,
1491 const char *config_path,
1492 char **list,
1493 const char *suffix,
1494 UnitFileChange **changes,
1495 unsigned *n_changes) {
1496
1497 _cleanup_free_ char *buf = NULL;
1498 const char *n;
1499 char **s;
1500 int r = 0, q;
1501
1502 assert(i);
1503 assert(paths);
1504 assert(config_path);
1505
1506 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
1507
1508 /* Don't install any symlink if there's no default
1509 * instance configured */
1510
1511 if (!i->default_instance)
1512 return 0;
1513
1514 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1515 if (r < 0)
1516 return r;
1517
1518 n = buf;
1519 } else
1520 n = i->name;
1521
1522 STRV_FOREACH(s, list) {
1523 _cleanup_free_ char *path = NULL, *dst = NULL;
1524 const char *rp;
1525
1526 q = install_full_printf(i, *s, &dst);
1527 if (q < 0)
1528 return q;
1529
1530 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1531 r = -EINVAL;
1532 continue;
1533 }
1534
1535 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1536 if (!path)
1537 return -ENOMEM;
1538
1539 rp = skip_root(paths, i->path);
1540
1541 q = create_symlink(rp ?: i->path, path, true, changes, n_changes);
1542 if (r == 0)
1543 r = q;
1544 }
1545
1546 return r;
1547 }
1548
1549 static int install_info_symlink_link(
1550 UnitFileInstallInfo *i,
1551 const LookupPaths *paths,
1552 const char *config_path,
1553 bool force,
1554 UnitFileChange **changes,
1555 unsigned *n_changes) {
1556
1557 _cleanup_free_ char *path = NULL;
1558 const char *rp;
1559 int r;
1560
1561 assert(i);
1562 assert(paths);
1563 assert(config_path);
1564 assert(i->path);
1565
1566 r = in_search_path(paths, i->path);
1567 if (r < 0)
1568 return r;
1569 if (r > 0)
1570 return 0;
1571
1572 path = strjoin(config_path, "/", i->name, NULL);
1573 if (!path)
1574 return -ENOMEM;
1575
1576 rp = skip_root(paths, i->path);
1577
1578 return create_symlink(rp ?: i->path, path, force, changes, n_changes);
1579 }
1580
1581 static int install_info_apply(
1582 UnitFileInstallInfo *i,
1583 const LookupPaths *paths,
1584 const char *config_path,
1585 bool force,
1586 UnitFileChange **changes,
1587 unsigned *n_changes) {
1588
1589 int r, q;
1590
1591 assert(i);
1592 assert(paths);
1593 assert(config_path);
1594
1595 if (i->type != UNIT_FILE_TYPE_REGULAR)
1596 return 0;
1597
1598 r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
1599
1600 q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
1601 if (r == 0)
1602 r = q;
1603
1604 q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
1605 if (r == 0)
1606 r = q;
1607
1608 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1609 /* Do not count links to the unit file towards the "carries_install_info" count */
1610 if (r == 0 && q < 0)
1611 r = q;
1612
1613 return r;
1614 }
1615
1616 static int install_context_apply(
1617 UnitFileScope scope,
1618 InstallContext *c,
1619 const LookupPaths *paths,
1620 const char *config_path,
1621 bool force,
1622 SearchFlags flags,
1623 UnitFileChange **changes,
1624 unsigned *n_changes) {
1625
1626 UnitFileInstallInfo *i;
1627 int r;
1628
1629 assert(c);
1630 assert(paths);
1631 assert(config_path);
1632
1633 if (ordered_hashmap_isempty(c->will_process))
1634 return 0;
1635
1636 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1637 if (r < 0)
1638 return r;
1639
1640 r = 0;
1641 while ((i = ordered_hashmap_first(c->will_process))) {
1642 int q;
1643
1644 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1645 if (q < 0)
1646 return q;
1647
1648 r = install_info_traverse(scope, c, paths, i, flags, NULL);
1649 if (r < 0)
1650 return r;
1651
1652 if (i->type != UNIT_FILE_TYPE_REGULAR)
1653 continue;
1654
1655 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1656 if (r >= 0) {
1657 if (q < 0)
1658 r = q;
1659 else
1660 r += q;
1661 }
1662 }
1663
1664 return r;
1665 }
1666
1667 static int install_context_mark_for_removal(
1668 UnitFileScope scope,
1669 InstallContext *c,
1670 const LookupPaths *paths,
1671 Set **remove_symlinks_to,
1672 const char *config_path) {
1673
1674 UnitFileInstallInfo *i;
1675 int r;
1676
1677 assert(c);
1678 assert(paths);
1679 assert(config_path);
1680
1681 /* Marks all items for removal */
1682
1683 if (ordered_hashmap_isempty(c->will_process))
1684 return 0;
1685
1686 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1687 if (r < 0)
1688 return r;
1689
1690 while ((i = ordered_hashmap_first(c->will_process))) {
1691
1692 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1693 if (r < 0)
1694 return r;
1695
1696 r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
1697 if (r < 0)
1698 return r;
1699
1700 if (i->type != UNIT_FILE_TYPE_REGULAR) {
1701 log_debug("Unit %s has type %s, ignoring.",
1702 i->name,
1703 unit_file_type_to_string(i->type) ?: "invalid");
1704 continue;
1705 }
1706
1707 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
1708 if (r < 0)
1709 return r;
1710 }
1711
1712 return 0;
1713 }
1714
1715 int unit_file_mask(
1716 UnitFileScope scope,
1717 bool runtime,
1718 const char *root_dir,
1719 char **files,
1720 bool force,
1721 UnitFileChange **changes,
1722 unsigned *n_changes) {
1723
1724 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1725 const char *config_path;
1726 char **i;
1727 int r;
1728
1729 assert(scope >= 0);
1730 assert(scope < _UNIT_FILE_SCOPE_MAX);
1731
1732 r = lookup_paths_init(&paths, scope, 0, root_dir);
1733 if (r < 0)
1734 return r;
1735
1736 config_path = runtime ? paths.runtime_config : paths.persistent_config;
1737
1738 STRV_FOREACH(i, files) {
1739 _cleanup_free_ char *path = NULL;
1740 int q;
1741
1742 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
1743 if (r == 0)
1744 r = -EINVAL;
1745 continue;
1746 }
1747
1748 path = path_make_absolute(*i, config_path);
1749 if (!path)
1750 return -ENOMEM;
1751
1752 q = create_symlink("/dev/null", path, force, changes, n_changes);
1753 if (q < 0 && r >= 0)
1754 r = q;
1755 }
1756
1757 return r;
1758 }
1759
1760 int unit_file_unmask(
1761 UnitFileScope scope,
1762 bool runtime,
1763 const char *root_dir,
1764 char **files,
1765 UnitFileChange **changes,
1766 unsigned *n_changes) {
1767
1768 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1769 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1770 _cleanup_free_ char **todo = NULL;
1771 size_t n_todo = 0, n_allocated = 0;
1772 const char *config_path;
1773 char **i;
1774 int r, q;
1775
1776 assert(scope >= 0);
1777 assert(scope < _UNIT_FILE_SCOPE_MAX);
1778
1779 r = lookup_paths_init(&paths, scope, 0, root_dir);
1780 if (r < 0)
1781 return r;
1782
1783 config_path = runtime ? paths.runtime_config : paths.persistent_config;
1784
1785 STRV_FOREACH(i, files) {
1786 _cleanup_free_ char *path = NULL;
1787
1788 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1789 return -EINVAL;
1790
1791 path = path_make_absolute(*i, config_path);
1792 if (!path)
1793 return -ENOMEM;
1794
1795 r = null_or_empty_path(path);
1796 if (r == -ENOENT)
1797 continue;
1798 if (r < 0)
1799 return r;
1800 if (r == 0)
1801 continue;
1802
1803 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1804 return -ENOMEM;
1805
1806 todo[n_todo++] = *i;
1807 }
1808
1809 strv_uniq(todo);
1810
1811 r = 0;
1812 STRV_FOREACH(i, todo) {
1813 _cleanup_free_ char *path = NULL;
1814 const char *rp;
1815
1816 path = path_make_absolute(*i, config_path);
1817 if (!path)
1818 return -ENOMEM;
1819
1820 if (unlink(path) < 0) {
1821 if (errno != ENOENT) {
1822 if (r >= 0)
1823 r = -errno;
1824 unit_file_changes_add(changes, n_changes, -errno, path, NULL);
1825 }
1826
1827 continue;
1828 }
1829
1830 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
1831
1832 rp = skip_root(&paths, path);
1833 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
1834 if (q < 0)
1835 return q;
1836 }
1837
1838 q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes);
1839 if (r >= 0)
1840 r = q;
1841
1842 return r;
1843 }
1844
1845 int unit_file_link(
1846 UnitFileScope scope,
1847 bool runtime,
1848 const char *root_dir,
1849 char **files,
1850 bool force,
1851 UnitFileChange **changes,
1852 unsigned *n_changes) {
1853
1854 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1855 _cleanup_free_ char **todo = NULL;
1856 size_t n_todo = 0, n_allocated = 0;
1857 const char *config_path;
1858 char **i;
1859 int r, q;
1860
1861 assert(scope >= 0);
1862 assert(scope < _UNIT_FILE_SCOPE_MAX);
1863
1864 r = lookup_paths_init(&paths, scope, 0, root_dir);
1865 if (r < 0)
1866 return r;
1867
1868 config_path = runtime ? paths.runtime_config : paths.persistent_config;
1869
1870 STRV_FOREACH(i, files) {
1871 _cleanup_free_ char *full = NULL;
1872 struct stat st;
1873 char *fn;
1874
1875 if (!path_is_absolute(*i))
1876 return -EINVAL;
1877
1878 fn = basename(*i);
1879 if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
1880 return -EINVAL;
1881
1882 full = prefix_root(paths.root_dir, *i);
1883 if (!full)
1884 return -ENOMEM;
1885
1886 if (lstat(full, &st) < 0)
1887 return -errno;
1888 if (S_ISLNK(st.st_mode))
1889 return -ELOOP;
1890 if (S_ISDIR(st.st_mode))
1891 return -EISDIR;
1892 if (!S_ISREG(st.st_mode))
1893 return -ENOTTY;
1894
1895 q = in_search_path(&paths, *i);
1896 if (q < 0)
1897 return q;
1898 if (q > 0)
1899 continue;
1900
1901 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1902 return -ENOMEM;
1903
1904 todo[n_todo++] = *i;
1905 }
1906
1907 strv_uniq(todo);
1908
1909 r = 0;
1910 STRV_FOREACH(i, todo) {
1911 _cleanup_free_ char *new_path = NULL;
1912 const char *old_path;
1913
1914 old_path = skip_root(&paths, *i);
1915 new_path = path_make_absolute(basename(*i), config_path);
1916 if (!new_path)
1917 return -ENOMEM;
1918
1919 q = create_symlink(old_path ?: *i, new_path, force, changes, n_changes);
1920 if (q < 0 && r >= 0)
1921 r = q;
1922 }
1923
1924 return r;
1925 }
1926
1927 static int path_shall_revert(const LookupPaths *paths, const char *path) {
1928 int r;
1929
1930 assert(paths);
1931 assert(path);
1932
1933 /* Checks whether the path is one where the drop-in directories shall be removed. */
1934
1935 r = path_is_config(paths, path);
1936 if (r != 0)
1937 return r;
1938
1939 r = path_is_control(paths, path);
1940 if (r != 0)
1941 return r;
1942
1943 return path_is_transient(paths, path);
1944 }
1945
1946 int unit_file_revert(
1947 UnitFileScope scope,
1948 const char *root_dir,
1949 char **files,
1950 UnitFileChange **changes,
1951 unsigned *n_changes) {
1952
1953 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1954 /* _cleanup_(install_context_done) InstallContext c = {}; */
1955 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1956 _cleanup_strv_free_ char **todo = NULL;
1957 size_t n_todo = 0, n_allocated = 0;
1958 char **i;
1959 int r, q;
1960
1961 /* Puts a unit file back into vendor state. This means:
1962 *
1963 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
1964 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
1965 *
1966 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
1967 * "config", but not in "transient" or "control" or even "generated").
1968 *
1969 * We remove all that in both the runtime and the persistent directories, if that applies.
1970 */
1971
1972 r = lookup_paths_init(&paths, scope, 0, root_dir);
1973 if (r < 0)
1974 return r;
1975
1976 STRV_FOREACH(i, files) {
1977 bool has_vendor = false;
1978 char **p;
1979
1980 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1981 return -EINVAL;
1982
1983 STRV_FOREACH(p, paths.search_path) {
1984 _cleanup_free_ char *path = NULL, *dropin = NULL;
1985 struct stat st;
1986
1987 path = path_make_absolute(*i, *p);
1988 if (!path)
1989 return -ENOMEM;
1990
1991 r = lstat(path, &st);
1992 if (r < 0) {
1993 if (errno != ENOENT)
1994 return -errno;
1995 } else if (S_ISREG(st.st_mode)) {
1996 /* Check if there's a vendor version */
1997 r = path_is_vendor(&paths, path);
1998 if (r < 0)
1999 return r;
2000 if (r > 0)
2001 has_vendor = true;
2002 }
2003
2004 dropin = strappend(path, ".d");
2005 if (!dropin)
2006 return -ENOMEM;
2007
2008 r = lstat(dropin, &st);
2009 if (r < 0) {
2010 if (errno != ENOENT)
2011 return -errno;
2012 } else if (S_ISDIR(st.st_mode)) {
2013 /* Remove the drop-ins */
2014 r = path_shall_revert(&paths, dropin);
2015 if (r < 0)
2016 return r;
2017 if (r > 0) {
2018 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2019 return -ENOMEM;
2020
2021 todo[n_todo++] = dropin;
2022 dropin = NULL;
2023 }
2024 }
2025 }
2026
2027 if (!has_vendor)
2028 continue;
2029
2030 /* OK, there's a vendor version, hence drop all configuration versions */
2031 STRV_FOREACH(p, paths.search_path) {
2032 _cleanup_free_ char *path = NULL;
2033 struct stat st;
2034
2035 path = path_make_absolute(*i, *p);
2036 if (!path)
2037 return -ENOMEM;
2038
2039 r = lstat(path, &st);
2040 if (r < 0) {
2041 if (errno != ENOENT)
2042 return -errno;
2043 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
2044 r = path_is_config(&paths, path);
2045 if (r < 0)
2046 return r;
2047 if (r > 0) {
2048 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2049 return -ENOMEM;
2050
2051 todo[n_todo++] = path;
2052 path = NULL;
2053 }
2054 }
2055 }
2056 }
2057
2058 strv_uniq(todo);
2059
2060 r = 0;
2061 STRV_FOREACH(i, todo) {
2062 _cleanup_strv_free_ char **fs = NULL;
2063 const char *rp;
2064 char **j;
2065
2066 (void) get_files_in_directory(*i, &fs);
2067
2068 q = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL);
2069 if (q < 0 && q != -ENOENT && r >= 0) {
2070 r = q;
2071 continue;
2072 }
2073
2074 STRV_FOREACH(j, fs) {
2075 _cleanup_free_ char *t = NULL;
2076
2077 t = strjoin(*i, "/", *j, NULL);
2078 if (!t)
2079 return -ENOMEM;
2080
2081 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, t, NULL);
2082 }
2083
2084 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, *i, NULL);
2085
2086 rp = skip_root(&paths, *i);
2087 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: *i);
2088 if (q < 0)
2089 return q;
2090 }
2091
2092 q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, changes, n_changes);
2093 if (r >= 0)
2094 r = q;
2095
2096 q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, changes, n_changes);
2097 if (r >= 0)
2098 r = q;
2099
2100 return r;
2101 }
2102
2103 int unit_file_add_dependency(
2104 UnitFileScope scope,
2105 bool runtime,
2106 const char *root_dir,
2107 char **files,
2108 const char *target,
2109 UnitDependency dep,
2110 bool force,
2111 UnitFileChange **changes,
2112 unsigned *n_changes) {
2113
2114 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2115 _cleanup_(install_context_done) InstallContext c = {};
2116 UnitFileInstallInfo *i, *target_info;
2117 const char *config_path;
2118 char **f;
2119 int r;
2120
2121 assert(scope >= 0);
2122 assert(scope < _UNIT_FILE_SCOPE_MAX);
2123 assert(target);
2124
2125 if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
2126 return -EINVAL;
2127
2128 if (!unit_name_is_valid(target, UNIT_NAME_ANY))
2129 return -EINVAL;
2130
2131 r = lookup_paths_init(&paths, scope, 0, root_dir);
2132 if (r < 0)
2133 return r;
2134
2135 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2136
2137 r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
2138 if (r < 0)
2139 return r;
2140 r = install_info_may_process(target_info, &paths, changes, n_changes);
2141 if (r < 0)
2142 return r;
2143
2144 assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
2145
2146 STRV_FOREACH(f, files) {
2147 char ***l;
2148
2149 r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2150 if (r < 0)
2151 return r;
2152 r = install_info_may_process(i, &paths, changes, n_changes);
2153 if (r < 0)
2154 return r;
2155
2156 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2157
2158 /* We didn't actually load anything from the unit
2159 * file, but instead just add in our new symlink to
2160 * create. */
2161
2162 if (dep == UNIT_WANTS)
2163 l = &i->wanted_by;
2164 else
2165 l = &i->required_by;
2166
2167 strv_free(*l);
2168 *l = strv_new(target_info->name, NULL);
2169 if (!*l)
2170 return -ENOMEM;
2171 }
2172
2173 return install_context_apply(scope, &c, &paths, config_path, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
2174 }
2175
2176 int unit_file_enable(
2177 UnitFileScope scope,
2178 bool runtime,
2179 const char *root_dir,
2180 char **files,
2181 bool force,
2182 UnitFileChange **changes,
2183 unsigned *n_changes) {
2184
2185 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2186 _cleanup_(install_context_done) InstallContext c = {};
2187 const char *config_path;
2188 UnitFileInstallInfo *i;
2189 char **f;
2190 int r;
2191
2192 assert(scope >= 0);
2193 assert(scope < _UNIT_FILE_SCOPE_MAX);
2194
2195 r = lookup_paths_init(&paths, scope, 0, root_dir);
2196 if (r < 0)
2197 return r;
2198
2199 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2200
2201 STRV_FOREACH(f, files) {
2202 r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD, &i);
2203 if (r < 0)
2204 return r;
2205 r = install_info_may_process(i, &paths, changes, n_changes);
2206 if (r < 0)
2207 return r;
2208
2209 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2210 }
2211
2212 /* This will return the number of symlink rules that were
2213 supposed to be created, not the ones actually created. This
2214 is useful to determine whether the passed files had any
2215 installation data at all. */
2216
2217 return install_context_apply(scope, &c, &paths, config_path, force, SEARCH_LOAD, changes, n_changes);
2218 }
2219
2220 int unit_file_disable(
2221 UnitFileScope scope,
2222 bool runtime,
2223 const char *root_dir,
2224 char **files,
2225 UnitFileChange **changes,
2226 unsigned *n_changes) {
2227
2228 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2229 _cleanup_(install_context_done) InstallContext c = {};
2230 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2231 const char *config_path;
2232 char **i;
2233 int r;
2234
2235 assert(scope >= 0);
2236 assert(scope < _UNIT_FILE_SCOPE_MAX);
2237
2238 r = lookup_paths_init(&paths, scope, 0, root_dir);
2239 if (r < 0)
2240 return r;
2241
2242 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2243
2244 STRV_FOREACH(i, files) {
2245 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2246 return -EINVAL;
2247
2248 r = install_info_add(&c, *i, NULL, NULL);
2249 if (r < 0)
2250 return r;
2251 }
2252
2253 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path);
2254 if (r < 0)
2255 return r;
2256
2257 return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes);
2258 }
2259
2260 int unit_file_reenable(
2261 UnitFileScope scope,
2262 bool runtime,
2263 const char *root_dir,
2264 char **files,
2265 bool force,
2266 UnitFileChange **changes,
2267 unsigned *n_changes) {
2268
2269 char **n;
2270 int r;
2271 size_t l, i;
2272
2273 /* First, we invoke the disable command with only the basename... */
2274 l = strv_length(files);
2275 n = newa(char*, l+1);
2276 for (i = 0; i < l; i++)
2277 n[i] = basename(files[i]);
2278 n[i] = NULL;
2279
2280 r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes);
2281 if (r < 0)
2282 return r;
2283
2284 /* But the enable command with the full name */
2285 return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes);
2286 }
2287
2288 int unit_file_set_default(
2289 UnitFileScope scope,
2290 const char *root_dir,
2291 const char *name,
2292 bool force,
2293 UnitFileChange **changes,
2294 unsigned *n_changes) {
2295
2296 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2297 _cleanup_(install_context_done) InstallContext c = {};
2298 UnitFileInstallInfo *i;
2299 const char *new_path, *old_path;
2300 int r;
2301
2302 assert(scope >= 0);
2303 assert(scope < _UNIT_FILE_SCOPE_MAX);
2304 assert(name);
2305
2306 if (unit_name_to_type(name) != UNIT_TARGET) /* this also validates the name */
2307 return -EINVAL;
2308 if (streq(name, SPECIAL_DEFAULT_TARGET))
2309 return -EINVAL;
2310
2311 r = lookup_paths_init(&paths, scope, 0, root_dir);
2312 if (r < 0)
2313 return r;
2314
2315 r = install_info_discover(scope, &c, &paths, name, 0, &i);
2316 if (r < 0)
2317 return r;
2318 r = install_info_may_process(i, &paths, changes, n_changes);
2319 if (r < 0)
2320 return r;
2321
2322 old_path = skip_root(&paths, i->path);
2323 new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET);
2324
2325 return create_symlink(old_path ?: i->path, new_path, force, changes, n_changes);
2326 }
2327
2328 int unit_file_get_default(
2329 UnitFileScope scope,
2330 const char *root_dir,
2331 char **name) {
2332
2333 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2334 _cleanup_(install_context_done) InstallContext c = {};
2335 UnitFileInstallInfo *i;
2336 char *n;
2337 int r;
2338
2339 assert(scope >= 0);
2340 assert(scope < _UNIT_FILE_SCOPE_MAX);
2341 assert(name);
2342
2343 r = lookup_paths_init(&paths, scope, 0, root_dir);
2344 if (r < 0)
2345 return r;
2346
2347 r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2348 if (r < 0)
2349 return r;
2350 r = install_info_may_process(i, &paths, NULL, 0);
2351 if (r < 0)
2352 return r;
2353
2354 n = strdup(i->name);
2355 if (!n)
2356 return -ENOMEM;
2357
2358 *name = n;
2359 return 0;
2360 }
2361
2362 static int unit_file_lookup_state(
2363 UnitFileScope scope,
2364 const LookupPaths *paths,
2365 const char *name,
2366 UnitFileState *ret) {
2367
2368 _cleanup_(install_context_done) InstallContext c = {};
2369 UnitFileInstallInfo *i;
2370 UnitFileState state;
2371 int r;
2372
2373 assert(paths);
2374 assert(name);
2375
2376 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2377 return -EINVAL;
2378
2379 r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2380 if (r < 0)
2381 return r;
2382
2383 /* Shortcut things, if the caller just wants to know if this unit exists. */
2384 if (!ret)
2385 return 0;
2386
2387 switch (i->type) {
2388
2389 case UNIT_FILE_TYPE_MASKED:
2390 r = path_is_runtime(paths, i->path);
2391 if (r < 0)
2392 return r;
2393
2394 state = r > 0 ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2395 break;
2396
2397 case UNIT_FILE_TYPE_REGULAR:
2398 r = path_is_generator(paths, i->path);
2399 if (r < 0)
2400 return r;
2401 if (r > 0) {
2402 state = UNIT_FILE_GENERATED;
2403 break;
2404 }
2405
2406 r = path_is_transient(paths, i->path);
2407 if (r < 0)
2408 return r;
2409 if (r > 0) {
2410 state = UNIT_FILE_TRANSIENT;
2411 break;
2412 }
2413
2414 r = find_symlinks_in_scope(scope, paths, i->name, &state);
2415 if (r < 0)
2416 return r;
2417 if (r == 0) {
2418 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i))
2419 state = UNIT_FILE_DISABLED;
2420 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i))
2421 state = UNIT_FILE_INDIRECT;
2422 else
2423 state = UNIT_FILE_STATIC;
2424 }
2425
2426 break;
2427
2428 default:
2429 assert_not_reached("Unexpect unit file type.");
2430 }
2431
2432 *ret = state;
2433 return 0;
2434 }
2435
2436 int unit_file_get_state(
2437 UnitFileScope scope,
2438 const char *root_dir,
2439 const char *name,
2440 UnitFileState *ret) {
2441
2442 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2443 int r;
2444
2445 assert(scope >= 0);
2446 assert(scope < _UNIT_FILE_SCOPE_MAX);
2447 assert(name);
2448
2449 r = lookup_paths_init(&paths, scope, 0, root_dir);
2450 if (r < 0)
2451 return r;
2452
2453 return unit_file_lookup_state(scope, &paths, name, ret);
2454 }
2455
2456 int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name) {
2457 _cleanup_(install_context_done) InstallContext c = {};
2458 int r;
2459
2460 assert(paths);
2461 assert(name);
2462
2463 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2464 return -EINVAL;
2465
2466 r = install_info_discover(scope, &c, paths, name, 0, NULL);
2467 if (r == -ENOENT)
2468 return 0;
2469 if (r < 0)
2470 return r;
2471
2472 return 1;
2473 }
2474
2475 static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
2476 _cleanup_(presets_freep) Presets ps = {};
2477 size_t n_allocated = 0;
2478 _cleanup_strv_free_ char **files = NULL;
2479 char **p;
2480 int r;
2481
2482 assert(scope >= 0);
2483 assert(scope < _UNIT_FILE_SCOPE_MAX);
2484 assert(presets);
2485
2486 if (scope == UNIT_FILE_SYSTEM)
2487 r = conf_files_list(&files, ".preset", root_dir,
2488 "/etc/systemd/system-preset",
2489 "/usr/local/lib/systemd/system-preset",
2490 "/usr/lib/systemd/system-preset",
2491 #ifdef HAVE_SPLIT_USR
2492 "/lib/systemd/system-preset",
2493 #endif
2494 NULL);
2495 else if (scope == UNIT_FILE_GLOBAL)
2496 r = conf_files_list(&files, ".preset", root_dir,
2497 "/etc/systemd/user-preset",
2498 "/usr/local/lib/systemd/user-preset",
2499 "/usr/lib/systemd/user-preset",
2500 NULL);
2501 else {
2502 *presets = (Presets){};
2503
2504 return 0;
2505 }
2506
2507 if (r < 0)
2508 return r;
2509
2510 STRV_FOREACH(p, files) {
2511 _cleanup_fclose_ FILE *f;
2512 char line[LINE_MAX];
2513 int n = 0;
2514
2515 f = fopen(*p, "re");
2516 if (!f) {
2517 if (errno == ENOENT)
2518 continue;
2519
2520 return -errno;
2521 }
2522
2523 FOREACH_LINE(line, f, return -errno) {
2524 PresetRule rule = {};
2525 const char *parameter;
2526 char *l;
2527
2528 l = strstrip(line);
2529 n++;
2530
2531 if (isempty(l))
2532 continue;
2533 if (strchr(COMMENTS, *l))
2534 continue;
2535
2536 parameter = first_word(l, "enable");
2537 if (parameter) {
2538 char *pattern;
2539
2540 pattern = strdup(parameter);
2541 if (!pattern)
2542 return -ENOMEM;
2543
2544 rule = (PresetRule) {
2545 .pattern = pattern,
2546 .action = PRESET_ENABLE,
2547 };
2548 }
2549
2550 parameter = first_word(l, "disable");
2551 if (parameter) {
2552 char *pattern;
2553
2554 pattern = strdup(parameter);
2555 if (!pattern)
2556 return -ENOMEM;
2557
2558 rule = (PresetRule) {
2559 .pattern = pattern,
2560 .action = PRESET_DISABLE,
2561 };
2562 }
2563
2564 if (rule.action) {
2565 if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1))
2566 return -ENOMEM;
2567
2568 ps.rules[ps.n_rules++] = rule;
2569 continue;
2570 }
2571
2572 log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
2573 }
2574 }
2575
2576 *presets = ps;
2577 ps = (Presets){};
2578
2579 return 0;
2580 }
2581
2582 static int query_presets(const char *name, const Presets presets) {
2583 PresetAction action = PRESET_UNKNOWN;
2584 size_t i;
2585
2586 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2587 return -EINVAL;
2588
2589 for (i = 0; i < presets.n_rules; i++)
2590 if (fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
2591 action = presets.rules[i].action;
2592 break;
2593 }
2594
2595 switch (action) {
2596 case PRESET_UNKNOWN:
2597 log_debug("Preset files don't specify rule for %s. Enabling.", name);
2598 return 1;
2599 case PRESET_ENABLE:
2600 log_debug("Preset files say enable %s.", name);
2601 return 1;
2602 case PRESET_DISABLE:
2603 log_debug("Preset files say disable %s.", name);
2604 return 0;
2605 default:
2606 assert_not_reached("invalid preset action");
2607 }
2608 }
2609
2610 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
2611 _cleanup_(presets_freep) Presets presets = {};
2612 int r;
2613
2614 r = read_presets(scope, root_dir, &presets);
2615 if (r < 0)
2616 return r;
2617
2618 return query_presets(name, presets);
2619 }
2620
2621 static int execute_preset(
2622 UnitFileScope scope,
2623 InstallContext *plus,
2624 InstallContext *minus,
2625 const LookupPaths *paths,
2626 const char *config_path,
2627 char **files,
2628 UnitFilePresetMode mode,
2629 bool force,
2630 UnitFileChange **changes,
2631 unsigned *n_changes) {
2632
2633 int r;
2634
2635 assert(plus);
2636 assert(minus);
2637 assert(paths);
2638 assert(config_path);
2639
2640 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2641 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2642
2643 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path);
2644 if (r < 0)
2645 return r;
2646
2647 r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, changes, n_changes);
2648 } else
2649 r = 0;
2650
2651 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2652 int q;
2653
2654 /* Returns number of symlinks that where supposed to be installed. */
2655 q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
2656 if (r >= 0) {
2657 if (q < 0)
2658 r = q;
2659 else
2660 r += q;
2661 }
2662 }
2663
2664 return r;
2665 }
2666
2667 static int preset_prepare_one(
2668 UnitFileScope scope,
2669 InstallContext *plus,
2670 InstallContext *minus,
2671 LookupPaths *paths,
2672 UnitFilePresetMode mode,
2673 const char *name,
2674 Presets presets,
2675 UnitFileChange **changes,
2676 unsigned *n_changes) {
2677
2678 UnitFileInstallInfo *i;
2679 int r;
2680
2681 if (install_info_find(plus, name) ||
2682 install_info_find(minus, name))
2683 return 0;
2684
2685 r = query_presets(name, presets);
2686 if (r < 0)
2687 return r;
2688
2689 if (r > 0) {
2690 r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2691 if (r < 0)
2692 return r;
2693
2694 r = install_info_may_process(i, paths, changes, n_changes);
2695 if (r < 0)
2696 return r;
2697 } else
2698 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2699
2700 return r;
2701 }
2702
2703 int unit_file_preset(
2704 UnitFileScope scope,
2705 bool runtime,
2706 const char *root_dir,
2707 char **files,
2708 UnitFilePresetMode mode,
2709 bool force,
2710 UnitFileChange **changes,
2711 unsigned *n_changes) {
2712
2713 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2714 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2715 _cleanup_(presets_freep) Presets presets = {};
2716 const char *config_path;
2717 char **i;
2718 int r;
2719
2720 assert(scope >= 0);
2721 assert(scope < _UNIT_FILE_SCOPE_MAX);
2722 assert(mode < _UNIT_FILE_PRESET_MAX);
2723
2724 r = lookup_paths_init(&paths, scope, 0, root_dir);
2725 if (r < 0)
2726 return r;
2727
2728 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2729
2730 r = read_presets(scope, root_dir, &presets);
2731 if (r < 0)
2732 return r;
2733
2734 STRV_FOREACH(i, files) {
2735 r = preset_prepare_one(scope, &plus, &minus, &paths, mode, *i, presets, changes, n_changes);
2736 if (r < 0)
2737 return r;
2738 }
2739
2740 return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, force, changes, n_changes);
2741 }
2742
2743 int unit_file_preset_all(
2744 UnitFileScope scope,
2745 bool runtime,
2746 const char *root_dir,
2747 UnitFilePresetMode mode,
2748 bool force,
2749 UnitFileChange **changes,
2750 unsigned *n_changes) {
2751
2752 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2753 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2754 _cleanup_(presets_freep) Presets presets = {};
2755 const char *config_path = NULL;
2756 char **i;
2757 int r;
2758
2759 assert(scope >= 0);
2760 assert(scope < _UNIT_FILE_SCOPE_MAX);
2761 assert(mode < _UNIT_FILE_PRESET_MAX);
2762
2763 r = lookup_paths_init(&paths, scope, 0, root_dir);
2764 if (r < 0)
2765 return r;
2766
2767 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2768
2769 r = read_presets(scope, root_dir, &presets);
2770 if (r < 0)
2771 return r;
2772
2773 STRV_FOREACH(i, paths.search_path) {
2774 _cleanup_closedir_ DIR *d = NULL;
2775 struct dirent *de;
2776
2777 d = opendir(*i);
2778 if (!d) {
2779 if (errno == ENOENT)
2780 continue;
2781
2782 return -errno;
2783 }
2784
2785 FOREACH_DIRENT(de, d, return -errno) {
2786
2787 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2788 continue;
2789
2790 dirent_ensure_type(d, de);
2791
2792 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2793 continue;
2794
2795 /* we don't pass changes[] in, because we want to handle errors on our own */
2796 r = preset_prepare_one(scope, &plus, &minus, &paths, mode, de->d_name, presets, NULL, 0);
2797 if (r == -ERFKILL)
2798 r = unit_file_changes_add(changes, n_changes,
2799 UNIT_FILE_IS_MASKED, de->d_name, NULL);
2800 if (r < 0)
2801 return r;
2802 }
2803 }
2804
2805 return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, force, changes, n_changes);
2806 }
2807
2808 static void unit_file_list_free_one(UnitFileList *f) {
2809 if (!f)
2810 return;
2811
2812 free(f->path);
2813 free(f);
2814 }
2815
2816 Hashmap* unit_file_list_free(Hashmap *h) {
2817 UnitFileList *i;
2818
2819 while ((i = hashmap_steal_first(h)))
2820 unit_file_list_free_one(i);
2821
2822 return hashmap_free(h);
2823 }
2824
2825 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2826
2827 int unit_file_get_list(
2828 UnitFileScope scope,
2829 const char *root_dir,
2830 Hashmap *h,
2831 char **states,
2832 char **patterns) {
2833
2834 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2835 char **i;
2836 int r;
2837
2838 assert(scope >= 0);
2839 assert(scope < _UNIT_FILE_SCOPE_MAX);
2840 assert(h);
2841
2842 r = lookup_paths_init(&paths, scope, 0, root_dir);
2843 if (r < 0)
2844 return r;
2845
2846 STRV_FOREACH(i, paths.search_path) {
2847 _cleanup_closedir_ DIR *d = NULL;
2848 struct dirent *de;
2849
2850 d = opendir(*i);
2851 if (!d) {
2852 if (errno == ENOENT)
2853 continue;
2854
2855 return -errno;
2856 }
2857
2858 FOREACH_DIRENT(de, d, return -errno) {
2859 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2860
2861 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2862 continue;
2863
2864 if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
2865 continue;
2866
2867 if (hashmap_get(h, de->d_name))
2868 continue;
2869
2870 dirent_ensure_type(d, de);
2871
2872 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2873 continue;
2874
2875 f = new0(UnitFileList, 1);
2876 if (!f)
2877 return -ENOMEM;
2878
2879 f->path = path_make_absolute(de->d_name, *i);
2880 if (!f->path)
2881 return -ENOMEM;
2882
2883 r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state);
2884 if (r < 0)
2885 f->state = UNIT_FILE_BAD;
2886
2887 if (!strv_isempty(states) &&
2888 !strv_contains(states, unit_file_state_to_string(f->state)))
2889 continue;
2890
2891 r = hashmap_put(h, basename(f->path), f);
2892 if (r < 0)
2893 return r;
2894
2895 f = NULL; /* prevent cleanup */
2896 }
2897 }
2898
2899 return 0;
2900 }
2901
2902 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2903 [UNIT_FILE_ENABLED] = "enabled",
2904 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2905 [UNIT_FILE_LINKED] = "linked",
2906 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2907 [UNIT_FILE_MASKED] = "masked",
2908 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2909 [UNIT_FILE_STATIC] = "static",
2910 [UNIT_FILE_DISABLED] = "disabled",
2911 [UNIT_FILE_INDIRECT] = "indirect",
2912 [UNIT_FILE_GENERATED] = "generated",
2913 [UNIT_FILE_TRANSIENT] = "transient",
2914 [UNIT_FILE_BAD] = "bad",
2915 };
2916
2917 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2918
2919 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2920 [UNIT_FILE_SYMLINK] = "symlink",
2921 [UNIT_FILE_UNLINK] = "unlink",
2922 [UNIT_FILE_IS_MASKED] = "masked",
2923 };
2924
2925 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2926
2927 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2928 [UNIT_FILE_PRESET_FULL] = "full",
2929 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2930 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2931 };
2932
2933 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);