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