]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
Merge pull request #4391 from keszybz/treewide-macros
[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 static int install_info_add(
939 InstallContext *c,
940 const char *name,
941 const char *path,
942 UnitFileInstallInfo **ret) {
943
944 UnitFileInstallInfo *i = NULL;
945 int r;
946
947 assert(c);
948 assert(name || path);
949
950 if (!name)
951 name = basename(path);
952
953 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
954 return -EINVAL;
955
956 i = install_info_find(c, name);
957 if (i) {
958 if (ret)
959 *ret = i;
960 return 0;
961 }
962
963 r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
964 if (r < 0)
965 return r;
966
967 i = new0(UnitFileInstallInfo, 1);
968 if (!i)
969 return -ENOMEM;
970 i->type = _UNIT_FILE_TYPE_INVALID;
971
972 i->name = strdup(name);
973 if (!i->name) {
974 r = -ENOMEM;
975 goto fail;
976 }
977
978 if (path) {
979 i->path = strdup(path);
980 if (!i->path) {
981 r = -ENOMEM;
982 goto fail;
983 }
984 }
985
986 r = ordered_hashmap_put(c->will_process, i->name, i);
987 if (r < 0)
988 goto fail;
989
990 if (ret)
991 *ret = i;
992
993 return 0;
994
995 fail:
996 install_info_free(i);
997 return r;
998 }
999
1000 static int config_parse_alias(
1001 const char *unit,
1002 const char *filename,
1003 unsigned line,
1004 const char *section,
1005 unsigned section_line,
1006 const char *lvalue,
1007 int ltype,
1008 const char *rvalue,
1009 void *data,
1010 void *userdata) {
1011
1012 const char *name;
1013 UnitType type;
1014
1015 assert(filename);
1016 assert(lvalue);
1017 assert(rvalue);
1018
1019 name = basename(filename);
1020 type = unit_name_to_type(name);
1021 if (!unit_type_may_alias(type))
1022 return log_syntax(unit, LOG_WARNING, filename, line, 0,
1023 "Alias= is not allowed for %s units, ignoring.",
1024 unit_type_to_string(type));
1025
1026 return config_parse_strv(unit, filename, line, section, section_line,
1027 lvalue, ltype, rvalue, data, userdata);
1028 }
1029
1030 static int config_parse_also(
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 = userdata;
1043 InstallContext *c = data;
1044 int r;
1045
1046 assert(filename);
1047 assert(lvalue);
1048 assert(rvalue);
1049
1050 for (;;) {
1051 _cleanup_free_ char *word = NULL;
1052
1053 r = extract_first_word(&rvalue, &word, NULL, 0);
1054 if (r < 0)
1055 return r;
1056 if (r == 0)
1057 break;
1058
1059 r = install_info_add(c, word, NULL, NULL);
1060 if (r < 0)
1061 return r;
1062
1063 r = strv_push(&i->also, word);
1064 if (r < 0)
1065 return r;
1066
1067 word = NULL;
1068 }
1069
1070 return 0;
1071 }
1072
1073 static int config_parse_default_instance(
1074 const char *unit,
1075 const char *filename,
1076 unsigned line,
1077 const char *section,
1078 unsigned section_line,
1079 const char *lvalue,
1080 int ltype,
1081 const char *rvalue,
1082 void *data,
1083 void *userdata) {
1084
1085 UnitFileInstallInfo *i = data;
1086 const char *name;
1087 _cleanup_free_ char *printed = NULL;
1088 int r;
1089
1090 assert(filename);
1091 assert(lvalue);
1092 assert(rvalue);
1093
1094 name = basename(filename);
1095 if (unit_name_is_valid(name, UNIT_NAME_INSTANCE))
1096 /* When enabling an instance, we might be using a template unit file,
1097 * but we should ignore DefaultInstance silently. */
1098 return 0;
1099 if (!unit_name_is_valid(name, UNIT_NAME_TEMPLATE))
1100 return log_syntax(unit, LOG_WARNING, filename, line, 0,
1101 "DefaultInstance= only makes sense for template units, ignoring.");
1102
1103 r = install_full_printf(i, rvalue, &printed);
1104 if (r < 0)
1105 return r;
1106
1107 if (!unit_instance_is_valid(printed))
1108 return -EINVAL;
1109
1110 return free_and_replace(i->default_instance, printed);
1111 }
1112
1113 static int unit_file_load(
1114 InstallContext *c,
1115 UnitFileInstallInfo *info,
1116 const char *path,
1117 SearchFlags flags) {
1118
1119 const ConfigTableItem items[] = {
1120 { "Install", "Alias", config_parse_alias, 0, &info->aliases },
1121 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1122 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1123 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1124 { "Install", "Also", config_parse_also, 0, c },
1125 {}
1126 };
1127
1128 const char *name;
1129 UnitType type;
1130 _cleanup_fclose_ FILE *f = NULL;
1131 _cleanup_close_ int fd = -1;
1132 struct stat st;
1133 int r;
1134
1135 assert(info);
1136 assert(path);
1137
1138 name = basename(path);
1139 type = unit_name_to_type(name);
1140 if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) &&
1141 !unit_type_may_template(type))
1142 return log_error_errno(EINVAL, "Unit type %s cannot be templated.", unit_type_to_string(type));
1143
1144 if (!(flags & SEARCH_LOAD)) {
1145 r = lstat(path, &st);
1146 if (r < 0)
1147 return -errno;
1148
1149 if (null_or_empty(&st))
1150 info->type = UNIT_FILE_TYPE_MASKED;
1151 else if (S_ISREG(st.st_mode))
1152 info->type = UNIT_FILE_TYPE_REGULAR;
1153 else if (S_ISLNK(st.st_mode))
1154 return -ELOOP;
1155 else if (S_ISDIR(st.st_mode))
1156 return -EISDIR;
1157 else
1158 return -ENOTTY;
1159
1160 return 0;
1161 }
1162
1163 /* c is only needed if we actually load the file */
1164 assert(c);
1165
1166 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
1167 if (fd < 0)
1168 return -errno;
1169 if (fstat(fd, &st) < 0)
1170 return -errno;
1171 if (null_or_empty(&st)) {
1172 info->type = UNIT_FILE_TYPE_MASKED;
1173 return 0;
1174 }
1175 if (S_ISDIR(st.st_mode))
1176 return -EISDIR;
1177 if (!S_ISREG(st.st_mode))
1178 return -ENOTTY;
1179
1180 f = fdopen(fd, "re");
1181 if (!f)
1182 return -errno;
1183 fd = -1;
1184
1185 r = config_parse(NULL, path, f,
1186 NULL,
1187 config_item_table_lookup, items,
1188 true, true, false, info);
1189 if (r < 0)
1190 return r;
1191
1192 info->type = UNIT_FILE_TYPE_REGULAR;
1193
1194 return
1195 (int) strv_length(info->aliases) +
1196 (int) strv_length(info->wanted_by) +
1197 (int) strv_length(info->required_by);
1198 }
1199
1200 static int unit_file_load_or_readlink(
1201 InstallContext *c,
1202 UnitFileInstallInfo *info,
1203 const char *path,
1204 const char *root_dir,
1205 SearchFlags flags) {
1206
1207 _cleanup_free_ char *target = NULL;
1208 int r;
1209
1210 r = unit_file_load(c, info, path, flags);
1211 if (r != -ELOOP)
1212 return r;
1213
1214 /* This is a symlink, let's read it. */
1215
1216 r = readlink_malloc(path, &target);
1217 if (r < 0)
1218 return r;
1219
1220 if (path_equal(target, "/dev/null"))
1221 info->type = UNIT_FILE_TYPE_MASKED;
1222 else {
1223 const char *bn;
1224 UnitType a, b;
1225
1226 bn = basename(target);
1227
1228 if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
1229
1230 if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
1231 return -EINVAL;
1232
1233 } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1234
1235 if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
1236 return -EINVAL;
1237
1238 } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
1239
1240 if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
1241 return -EINVAL;
1242 } else
1243 return -EINVAL;
1244
1245 /* Enforce that the symlink destination does not
1246 * change the unit file type. */
1247
1248 a = unit_name_to_type(info->name);
1249 b = unit_name_to_type(bn);
1250 if (a < 0 || b < 0 || a != b)
1251 return -EINVAL;
1252
1253 if (path_is_absolute(target))
1254 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1255 info->symlink_target = prefix_root(root_dir, target);
1256 else
1257 /* This is a relative path, take it relative to the dir the symlink is located in. */
1258 info->symlink_target = file_in_same_dir(path, target);
1259 if (!info->symlink_target)
1260 return -ENOMEM;
1261
1262 info->type = UNIT_FILE_TYPE_SYMLINK;
1263 }
1264
1265 return 0;
1266 }
1267
1268 static int unit_file_search(
1269 InstallContext *c,
1270 UnitFileInstallInfo *info,
1271 const LookupPaths *paths,
1272 SearchFlags flags) {
1273
1274 _cleanup_free_ char *template = NULL;
1275 char **p;
1276 int r;
1277
1278 assert(info);
1279 assert(paths);
1280
1281 /* Was this unit already loaded? */
1282 if (info->type != _UNIT_FILE_TYPE_INVALID)
1283 return 0;
1284
1285 if (info->path)
1286 return unit_file_load_or_readlink(c, info, info->path, paths->root_dir, flags);
1287
1288 assert(info->name);
1289
1290 STRV_FOREACH(p, paths->search_path) {
1291 _cleanup_free_ char *path = NULL;
1292
1293 path = strjoin(*p, "/", info->name, NULL);
1294 if (!path)
1295 return -ENOMEM;
1296
1297 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1298 if (r >= 0) {
1299 info->path = path;
1300 path = NULL;
1301 return r;
1302 } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
1303 return r;
1304 }
1305
1306 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1307 /* Unit file doesn't exist, however instance
1308 * enablement was requested. We will check if it is
1309 * possible to load template unit file. */
1310
1311 r = unit_name_template(info->name, &template);
1312 if (r < 0)
1313 return r;
1314
1315 STRV_FOREACH(p, paths->search_path) {
1316 _cleanup_free_ char *path = NULL;
1317
1318 path = strjoin(*p, "/", template, NULL);
1319 if (!path)
1320 return -ENOMEM;
1321
1322 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1323 if (r >= 0) {
1324 info->path = path;
1325 path = NULL;
1326 return r;
1327 } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
1328 return r;
1329 }
1330 }
1331
1332 log_debug("Cannot find unit %s%s%s.", info->name, template ? " or " : "", strempty(template));
1333 return -ENOENT;
1334 }
1335
1336 static int install_info_follow(
1337 InstallContext *c,
1338 UnitFileInstallInfo *i,
1339 const char *root_dir,
1340 SearchFlags flags) {
1341
1342 assert(c);
1343 assert(i);
1344
1345 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1346 return -EINVAL;
1347 if (!i->symlink_target)
1348 return -EINVAL;
1349
1350 /* If the basename doesn't match, the caller should add a
1351 * complete new entry for this. */
1352
1353 if (!streq(basename(i->symlink_target), i->name))
1354 return -EXDEV;
1355
1356 free_and_replace(i->path, i->symlink_target);
1357 i->type = _UNIT_FILE_TYPE_INVALID;
1358
1359 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1360 }
1361
1362 /**
1363 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1364 * target, maybe more than once. Propagate the instance name if present.
1365 */
1366 static int install_info_traverse(
1367 UnitFileScope scope,
1368 InstallContext *c,
1369 const LookupPaths *paths,
1370 UnitFileInstallInfo *start,
1371 SearchFlags flags,
1372 UnitFileInstallInfo **ret) {
1373
1374 UnitFileInstallInfo *i;
1375 unsigned k = 0;
1376 int r;
1377
1378 assert(paths);
1379 assert(start);
1380 assert(c);
1381
1382 r = unit_file_search(c, start, paths, flags);
1383 if (r < 0)
1384 return r;
1385
1386 i = start;
1387 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1388 /* Follow the symlink */
1389
1390 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1391 return -ELOOP;
1392
1393 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
1394 r = path_is_config(paths, i->path);
1395 if (r < 0)
1396 return r;
1397 if (r > 0)
1398 return -ELOOP;
1399 }
1400
1401 r = install_info_follow(c, i, paths->root_dir, flags);
1402 if (r == -EXDEV) {
1403 _cleanup_free_ char *buffer = NULL;
1404 const char *bn;
1405
1406 /* Target has a different name, create a new
1407 * install info object for that, and continue
1408 * with that. */
1409
1410 bn = basename(i->symlink_target);
1411
1412 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1413 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1414
1415 _cleanup_free_ char *instance = NULL;
1416
1417 r = unit_name_to_instance(i->name, &instance);
1418 if (r < 0)
1419 return r;
1420
1421 r = unit_name_replace_instance(bn, instance, &buffer);
1422 if (r < 0)
1423 return r;
1424
1425 bn = buffer;
1426 }
1427
1428 r = install_info_add(c, bn, NULL, &i);
1429 if (r < 0)
1430 return r;
1431
1432 /* Try again, with the new target we found. */
1433 r = unit_file_search(c, i, paths, flags);
1434 if (r == -ENOENT)
1435 /* Translate error code to highlight this specific case */
1436 return -ENOLINK;
1437 }
1438
1439 if (r < 0)
1440 return r;
1441 }
1442
1443 if (ret)
1444 *ret = i;
1445
1446 return 0;
1447 }
1448
1449 /**
1450 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1451 * or the name (otherwise). root_dir is prepended to the path.
1452 */
1453 static int install_info_add_auto(
1454 InstallContext *c,
1455 const LookupPaths *paths,
1456 const char *name_or_path,
1457 UnitFileInstallInfo **ret) {
1458
1459 assert(c);
1460 assert(name_or_path);
1461
1462 if (path_is_absolute(name_or_path)) {
1463 const char *pp;
1464
1465 pp = prefix_roota(paths->root_dir, name_or_path);
1466
1467 return install_info_add(c, NULL, pp, ret);
1468 } else
1469 return install_info_add(c, name_or_path, NULL, ret);
1470 }
1471
1472 static int install_info_discover(
1473 UnitFileScope scope,
1474 InstallContext *c,
1475 const LookupPaths *paths,
1476 const char *name,
1477 SearchFlags flags,
1478 UnitFileInstallInfo **ret) {
1479
1480 UnitFileInstallInfo *i;
1481 int r;
1482
1483 assert(c);
1484 assert(paths);
1485 assert(name);
1486
1487 r = install_info_add_auto(c, paths, name, &i);
1488 if (r < 0)
1489 return r;
1490
1491 return install_info_traverse(scope, c, paths, i, flags, ret);
1492 }
1493
1494 static int install_info_symlink_alias(
1495 UnitFileInstallInfo *i,
1496 const LookupPaths *paths,
1497 const char *config_path,
1498 bool force,
1499 UnitFileChange **changes,
1500 unsigned *n_changes) {
1501
1502 char **s;
1503 int r = 0, q;
1504
1505 assert(i);
1506 assert(paths);
1507 assert(config_path);
1508
1509 STRV_FOREACH(s, i->aliases) {
1510 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1511
1512 q = install_full_printf(i, *s, &dst);
1513 if (q < 0)
1514 return q;
1515
1516 alias_path = path_make_absolute(dst, config_path);
1517 if (!alias_path)
1518 return -ENOMEM;
1519
1520 q = create_symlink(paths, i->path, alias_path, force, changes, n_changes);
1521 if (r == 0)
1522 r = q;
1523 }
1524
1525 return r;
1526 }
1527
1528 static int install_info_symlink_wants(
1529 UnitFileInstallInfo *i,
1530 const LookupPaths *paths,
1531 const char *config_path,
1532 char **list,
1533 const char *suffix,
1534 UnitFileChange **changes,
1535 unsigned *n_changes) {
1536
1537 _cleanup_free_ char *buf = NULL;
1538 const char *n;
1539 char **s;
1540 int r = 0, q;
1541
1542 assert(i);
1543 assert(paths);
1544 assert(config_path);
1545
1546 if (strv_isempty(list))
1547 return 0;
1548
1549 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
1550 UnitFileInstallInfo instance = {
1551 .type = _UNIT_FILE_TYPE_INVALID,
1552 };
1553 _cleanup_free_ char *path = NULL;
1554
1555 /* Don't install any symlink if there's no default
1556 * instance configured */
1557
1558 if (!i->default_instance)
1559 return 0;
1560
1561 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1562 if (r < 0)
1563 return r;
1564
1565 instance.name = buf;
1566 r = unit_file_search(NULL, &instance, paths, SEARCH_FOLLOW_CONFIG_SYMLINKS);
1567 if (r < 0)
1568 return r;
1569
1570 path = instance.path;
1571 instance.path = NULL;
1572
1573 if (instance.type == UNIT_FILE_TYPE_MASKED) {
1574 unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL);
1575 return -ERFKILL;
1576 }
1577
1578 n = buf;
1579 } else
1580 n = i->name;
1581
1582 STRV_FOREACH(s, list) {
1583 _cleanup_free_ char *path = NULL, *dst = NULL;
1584
1585 q = install_full_printf(i, *s, &dst);
1586 if (q < 0)
1587 return q;
1588
1589 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1590 r = -EINVAL;
1591 continue;
1592 }
1593
1594 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1595 if (!path)
1596 return -ENOMEM;
1597
1598 q = create_symlink(paths, i->path, path, true, changes, n_changes);
1599 if (r == 0)
1600 r = q;
1601 }
1602
1603 return r;
1604 }
1605
1606 static int install_info_symlink_link(
1607 UnitFileInstallInfo *i,
1608 const LookupPaths *paths,
1609 const char *config_path,
1610 bool force,
1611 UnitFileChange **changes,
1612 unsigned *n_changes) {
1613
1614 _cleanup_free_ char *path = NULL;
1615 int r;
1616
1617 assert(i);
1618 assert(paths);
1619 assert(config_path);
1620 assert(i->path);
1621
1622 r = in_search_path(paths, i->path);
1623 if (r < 0)
1624 return r;
1625 if (r > 0)
1626 return 0;
1627
1628 path = strjoin(config_path, "/", i->name, NULL);
1629 if (!path)
1630 return -ENOMEM;
1631
1632 return create_symlink(paths, i->path, path, force, changes, n_changes);
1633 }
1634
1635 static int install_info_apply(
1636 UnitFileInstallInfo *i,
1637 const LookupPaths *paths,
1638 const char *config_path,
1639 bool force,
1640 UnitFileChange **changes,
1641 unsigned *n_changes) {
1642
1643 int r, q;
1644
1645 assert(i);
1646 assert(paths);
1647 assert(config_path);
1648
1649 if (i->type != UNIT_FILE_TYPE_REGULAR)
1650 return 0;
1651
1652 r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
1653
1654 q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
1655 if (r == 0)
1656 r = q;
1657
1658 q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
1659 if (r == 0)
1660 r = q;
1661
1662 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1663 /* Do not count links to the unit file towards the "carries_install_info" count */
1664 if (r == 0 && q < 0)
1665 r = q;
1666
1667 return r;
1668 }
1669
1670 static int install_context_apply(
1671 UnitFileScope scope,
1672 InstallContext *c,
1673 const LookupPaths *paths,
1674 const char *config_path,
1675 bool force,
1676 SearchFlags flags,
1677 UnitFileChange **changes,
1678 unsigned *n_changes) {
1679
1680 UnitFileInstallInfo *i;
1681 int r;
1682
1683 assert(c);
1684 assert(paths);
1685 assert(config_path);
1686
1687 if (ordered_hashmap_isempty(c->will_process))
1688 return 0;
1689
1690 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1691 if (r < 0)
1692 return r;
1693
1694 r = 0;
1695 while ((i = ordered_hashmap_first(c->will_process))) {
1696 int q;
1697
1698 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1699 if (q < 0)
1700 return q;
1701
1702 r = install_info_traverse(scope, c, paths, i, flags, NULL);
1703 if (r < 0)
1704 return r;
1705
1706 /* We can attempt to process a masked unit when a different unit
1707 * that we were processing specifies it in Also=. */
1708 if (i->type == UNIT_FILE_TYPE_MASKED) {
1709 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL);
1710 if (r >= 0)
1711 /* Assume that something *could* have been enabled here,
1712 * avoid "empty [Install] section" warning. */
1713 r += 1;
1714 continue;
1715 }
1716
1717 if (i->type != UNIT_FILE_TYPE_REGULAR)
1718 continue;
1719
1720 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1721 if (r >= 0) {
1722 if (q < 0)
1723 r = q;
1724 else
1725 r += q;
1726 }
1727 }
1728
1729 return r;
1730 }
1731
1732 static int install_context_mark_for_removal(
1733 UnitFileScope scope,
1734 InstallContext *c,
1735 const LookupPaths *paths,
1736 Set **remove_symlinks_to,
1737 const char *config_path) {
1738
1739 UnitFileInstallInfo *i;
1740 int r;
1741
1742 assert(c);
1743 assert(paths);
1744 assert(config_path);
1745
1746 /* Marks all items for removal */
1747
1748 if (ordered_hashmap_isempty(c->will_process))
1749 return 0;
1750
1751 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1752 if (r < 0)
1753 return r;
1754
1755 while ((i = ordered_hashmap_first(c->will_process))) {
1756
1757 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1758 if (r < 0)
1759 return r;
1760
1761 r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
1762 if (r == -ENOLINK)
1763 return 0;
1764 else if (r < 0)
1765 return r;
1766
1767 if (i->type != UNIT_FILE_TYPE_REGULAR) {
1768 log_debug("Unit %s has type %s, ignoring.",
1769 i->name,
1770 unit_file_type_to_string(i->type) ?: "invalid");
1771 continue;
1772 }
1773
1774 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
1775 if (r < 0)
1776 return r;
1777 }
1778
1779 return 0;
1780 }
1781
1782 int unit_file_mask(
1783 UnitFileScope scope,
1784 bool runtime,
1785 const char *root_dir,
1786 char **files,
1787 bool force,
1788 UnitFileChange **changes,
1789 unsigned *n_changes) {
1790
1791 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1792 const char *config_path;
1793 char **i;
1794 int r;
1795
1796 assert(scope >= 0);
1797 assert(scope < _UNIT_FILE_SCOPE_MAX);
1798
1799 r = lookup_paths_init(&paths, scope, 0, root_dir);
1800 if (r < 0)
1801 return r;
1802
1803 config_path = runtime ? paths.runtime_config : paths.persistent_config;
1804
1805 STRV_FOREACH(i, files) {
1806 _cleanup_free_ char *path = NULL;
1807 int q;
1808
1809 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
1810 if (r == 0)
1811 r = -EINVAL;
1812 continue;
1813 }
1814
1815 path = path_make_absolute(*i, config_path);
1816 if (!path)
1817 return -ENOMEM;
1818
1819 q = create_symlink(&paths, "/dev/null", path, force, changes, n_changes);
1820 if (q < 0 && r >= 0)
1821 r = q;
1822 }
1823
1824 return r;
1825 }
1826
1827 int unit_file_unmask(
1828 UnitFileScope scope,
1829 bool runtime,
1830 const char *root_dir,
1831 char **files,
1832 UnitFileChange **changes,
1833 unsigned *n_changes) {
1834
1835 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1836 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1837 _cleanup_free_ char **todo = NULL;
1838 size_t n_todo = 0, n_allocated = 0;
1839 const char *config_path;
1840 char **i;
1841 int r, q;
1842
1843 assert(scope >= 0);
1844 assert(scope < _UNIT_FILE_SCOPE_MAX);
1845
1846 r = lookup_paths_init(&paths, scope, 0, root_dir);
1847 if (r < 0)
1848 return r;
1849
1850 config_path = runtime ? paths.runtime_config : paths.persistent_config;
1851
1852 STRV_FOREACH(i, files) {
1853 _cleanup_free_ char *path = NULL;
1854
1855 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1856 return -EINVAL;
1857
1858 path = path_make_absolute(*i, config_path);
1859 if (!path)
1860 return -ENOMEM;
1861
1862 r = null_or_empty_path(path);
1863 if (r == -ENOENT)
1864 continue;
1865 if (r < 0)
1866 return r;
1867 if (r == 0)
1868 continue;
1869
1870 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1871 return -ENOMEM;
1872
1873 todo[n_todo++] = *i;
1874 }
1875
1876 strv_uniq(todo);
1877
1878 r = 0;
1879 STRV_FOREACH(i, todo) {
1880 _cleanup_free_ char *path = NULL;
1881 const char *rp;
1882
1883 path = path_make_absolute(*i, config_path);
1884 if (!path)
1885 return -ENOMEM;
1886
1887 if (unlink(path) < 0) {
1888 if (errno != ENOENT) {
1889 if (r >= 0)
1890 r = -errno;
1891 unit_file_changes_add(changes, n_changes, -errno, path, NULL);
1892 }
1893
1894 continue;
1895 }
1896
1897 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
1898
1899 rp = skip_root(&paths, path);
1900 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
1901 if (q < 0)
1902 return q;
1903 }
1904
1905 q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes);
1906 if (r >= 0)
1907 r = q;
1908
1909 return r;
1910 }
1911
1912 int unit_file_link(
1913 UnitFileScope scope,
1914 bool runtime,
1915 const char *root_dir,
1916 char **files,
1917 bool force,
1918 UnitFileChange **changes,
1919 unsigned *n_changes) {
1920
1921 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1922 _cleanup_free_ char **todo = NULL;
1923 size_t n_todo = 0, n_allocated = 0;
1924 const char *config_path;
1925 char **i;
1926 int r, q;
1927
1928 assert(scope >= 0);
1929 assert(scope < _UNIT_FILE_SCOPE_MAX);
1930
1931 r = lookup_paths_init(&paths, scope, 0, root_dir);
1932 if (r < 0)
1933 return r;
1934
1935 config_path = runtime ? paths.runtime_config : paths.persistent_config;
1936
1937 STRV_FOREACH(i, files) {
1938 _cleanup_free_ char *full = NULL;
1939 struct stat st;
1940 char *fn;
1941
1942 if (!path_is_absolute(*i))
1943 return -EINVAL;
1944
1945 fn = basename(*i);
1946 if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
1947 return -EINVAL;
1948
1949 full = prefix_root(paths.root_dir, *i);
1950 if (!full)
1951 return -ENOMEM;
1952
1953 if (lstat(full, &st) < 0)
1954 return -errno;
1955 if (S_ISLNK(st.st_mode))
1956 return -ELOOP;
1957 if (S_ISDIR(st.st_mode))
1958 return -EISDIR;
1959 if (!S_ISREG(st.st_mode))
1960 return -ENOTTY;
1961
1962 q = in_search_path(&paths, *i);
1963 if (q < 0)
1964 return q;
1965 if (q > 0)
1966 continue;
1967
1968 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1969 return -ENOMEM;
1970
1971 todo[n_todo++] = *i;
1972 }
1973
1974 strv_uniq(todo);
1975
1976 r = 0;
1977 STRV_FOREACH(i, todo) {
1978 _cleanup_free_ char *new_path = NULL;
1979
1980 new_path = path_make_absolute(basename(*i), config_path);
1981 if (!new_path)
1982 return -ENOMEM;
1983
1984 q = create_symlink(&paths, *i, new_path, force, changes, n_changes);
1985 if (q < 0 && r >= 0)
1986 r = q;
1987 }
1988
1989 return r;
1990 }
1991
1992 static int path_shall_revert(const LookupPaths *paths, const char *path) {
1993 int r;
1994
1995 assert(paths);
1996 assert(path);
1997
1998 /* Checks whether the path is one where the drop-in directories shall be removed. */
1999
2000 r = path_is_config(paths, path);
2001 if (r != 0)
2002 return r;
2003
2004 r = path_is_control(paths, path);
2005 if (r != 0)
2006 return r;
2007
2008 return path_is_transient(paths, path);
2009 }
2010
2011 int unit_file_revert(
2012 UnitFileScope scope,
2013 const char *root_dir,
2014 char **files,
2015 UnitFileChange **changes,
2016 unsigned *n_changes) {
2017
2018 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2019 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2020 _cleanup_strv_free_ char **todo = NULL;
2021 size_t n_todo = 0, n_allocated = 0;
2022 char **i;
2023 int r, q;
2024
2025 /* Puts a unit file back into vendor state. This means:
2026 *
2027 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2028 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2029 *
2030 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2031 * "config", but not in "transient" or "control" or even "generated").
2032 *
2033 * We remove all that in both the runtime and the persistent directories, if that applies.
2034 */
2035
2036 r = lookup_paths_init(&paths, scope, 0, root_dir);
2037 if (r < 0)
2038 return r;
2039
2040 STRV_FOREACH(i, files) {
2041 bool has_vendor = false;
2042 char **p;
2043
2044 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2045 return -EINVAL;
2046
2047 STRV_FOREACH(p, paths.search_path) {
2048 _cleanup_free_ char *path = NULL, *dropin = NULL;
2049 struct stat st;
2050
2051 path = path_make_absolute(*i, *p);
2052 if (!path)
2053 return -ENOMEM;
2054
2055 r = lstat(path, &st);
2056 if (r < 0) {
2057 if (errno != ENOENT)
2058 return -errno;
2059 } else if (S_ISREG(st.st_mode)) {
2060 /* Check if there's a vendor version */
2061 r = path_is_vendor(&paths, path);
2062 if (r < 0)
2063 return r;
2064 if (r > 0)
2065 has_vendor = true;
2066 }
2067
2068 dropin = strappend(path, ".d");
2069 if (!dropin)
2070 return -ENOMEM;
2071
2072 r = lstat(dropin, &st);
2073 if (r < 0) {
2074 if (errno != ENOENT)
2075 return -errno;
2076 } else if (S_ISDIR(st.st_mode)) {
2077 /* Remove the drop-ins */
2078 r = path_shall_revert(&paths, dropin);
2079 if (r < 0)
2080 return r;
2081 if (r > 0) {
2082 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2083 return -ENOMEM;
2084
2085 todo[n_todo++] = dropin;
2086 dropin = NULL;
2087 }
2088 }
2089 }
2090
2091 if (!has_vendor)
2092 continue;
2093
2094 /* OK, there's a vendor version, hence drop all configuration versions */
2095 STRV_FOREACH(p, paths.search_path) {
2096 _cleanup_free_ char *path = NULL;
2097 struct stat st;
2098
2099 path = path_make_absolute(*i, *p);
2100 if (!path)
2101 return -ENOMEM;
2102
2103 r = lstat(path, &st);
2104 if (r < 0) {
2105 if (errno != ENOENT)
2106 return -errno;
2107 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
2108 r = path_is_config(&paths, path);
2109 if (r < 0)
2110 return r;
2111 if (r > 0) {
2112 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2113 return -ENOMEM;
2114
2115 todo[n_todo++] = path;
2116 path = NULL;
2117 }
2118 }
2119 }
2120 }
2121
2122 strv_uniq(todo);
2123
2124 r = 0;
2125 STRV_FOREACH(i, todo) {
2126 _cleanup_strv_free_ char **fs = NULL;
2127 const char *rp;
2128 char **j;
2129
2130 (void) get_files_in_directory(*i, &fs);
2131
2132 q = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL);
2133 if (q < 0 && q != -ENOENT && r >= 0) {
2134 r = q;
2135 continue;
2136 }
2137
2138 STRV_FOREACH(j, fs) {
2139 _cleanup_free_ char *t = NULL;
2140
2141 t = strjoin(*i, "/", *j, NULL);
2142 if (!t)
2143 return -ENOMEM;
2144
2145 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, t, NULL);
2146 }
2147
2148 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, *i, NULL);
2149
2150 rp = skip_root(&paths, *i);
2151 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: *i);
2152 if (q < 0)
2153 return q;
2154 }
2155
2156 q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, changes, n_changes);
2157 if (r >= 0)
2158 r = q;
2159
2160 q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, changes, n_changes);
2161 if (r >= 0)
2162 r = q;
2163
2164 return r;
2165 }
2166
2167 int unit_file_add_dependency(
2168 UnitFileScope scope,
2169 bool runtime,
2170 const char *root_dir,
2171 char **files,
2172 const char *target,
2173 UnitDependency dep,
2174 bool force,
2175 UnitFileChange **changes,
2176 unsigned *n_changes) {
2177
2178 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2179 _cleanup_(install_context_done) InstallContext c = {};
2180 UnitFileInstallInfo *i, *target_info;
2181 const char *config_path;
2182 char **f;
2183 int r;
2184
2185 assert(scope >= 0);
2186 assert(scope < _UNIT_FILE_SCOPE_MAX);
2187 assert(target);
2188
2189 if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
2190 return -EINVAL;
2191
2192 if (!unit_name_is_valid(target, UNIT_NAME_ANY))
2193 return -EINVAL;
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 r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
2202 if (r < 0)
2203 return r;
2204 r = install_info_may_process(target_info, &paths, changes, n_changes);
2205 if (r < 0)
2206 return r;
2207
2208 assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
2209
2210 STRV_FOREACH(f, files) {
2211 char ***l;
2212
2213 r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2214 if (r < 0)
2215 return r;
2216 r = install_info_may_process(i, &paths, changes, n_changes);
2217 if (r < 0)
2218 return r;
2219
2220 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2221
2222 /* We didn't actually load anything from the unit
2223 * file, but instead just add in our new symlink to
2224 * create. */
2225
2226 if (dep == UNIT_WANTS)
2227 l = &i->wanted_by;
2228 else
2229 l = &i->required_by;
2230
2231 strv_free(*l);
2232 *l = strv_new(target_info->name, NULL);
2233 if (!*l)
2234 return -ENOMEM;
2235 }
2236
2237 return install_context_apply(scope, &c, &paths, config_path, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
2238 }
2239
2240 int unit_file_enable(
2241 UnitFileScope scope,
2242 bool runtime,
2243 const char *root_dir,
2244 char **files,
2245 bool force,
2246 UnitFileChange **changes,
2247 unsigned *n_changes) {
2248
2249 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2250 _cleanup_(install_context_done) InstallContext c = {};
2251 const char *config_path;
2252 UnitFileInstallInfo *i;
2253 char **f;
2254 int r;
2255
2256 assert(scope >= 0);
2257 assert(scope < _UNIT_FILE_SCOPE_MAX);
2258
2259 r = lookup_paths_init(&paths, scope, 0, root_dir);
2260 if (r < 0)
2261 return r;
2262
2263 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2264
2265 STRV_FOREACH(f, files) {
2266 r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2267 if (r < 0)
2268 return r;
2269 r = install_info_may_process(i, &paths, changes, n_changes);
2270 if (r < 0)
2271 return r;
2272
2273 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2274 }
2275
2276 /* This will return the number of symlink rules that were
2277 supposed to be created, not the ones actually created. This
2278 is useful to determine whether the passed files had any
2279 installation data at all. */
2280
2281 return install_context_apply(scope, &c, &paths, config_path, force, SEARCH_LOAD, changes, n_changes);
2282 }
2283
2284 int unit_file_disable(
2285 UnitFileScope scope,
2286 bool runtime,
2287 const char *root_dir,
2288 char **files,
2289 UnitFileChange **changes,
2290 unsigned *n_changes) {
2291
2292 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2293 _cleanup_(install_context_done) InstallContext c = {};
2294 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2295 const char *config_path;
2296 char **i;
2297 int r;
2298
2299 assert(scope >= 0);
2300 assert(scope < _UNIT_FILE_SCOPE_MAX);
2301
2302 r = lookup_paths_init(&paths, scope, 0, root_dir);
2303 if (r < 0)
2304 return r;
2305
2306 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2307
2308 STRV_FOREACH(i, files) {
2309 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2310 return -EINVAL;
2311
2312 r = install_info_add(&c, *i, NULL, NULL);
2313 if (r < 0)
2314 return r;
2315 }
2316
2317 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path);
2318 if (r < 0)
2319 return r;
2320
2321 return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes);
2322 }
2323
2324 int unit_file_reenable(
2325 UnitFileScope scope,
2326 bool runtime,
2327 const char *root_dir,
2328 char **files,
2329 bool force,
2330 UnitFileChange **changes,
2331 unsigned *n_changes) {
2332
2333 char **n;
2334 int r;
2335 size_t l, i;
2336
2337 /* First, we invoke the disable command with only the basename... */
2338 l = strv_length(files);
2339 n = newa(char*, l+1);
2340 for (i = 0; i < l; i++)
2341 n[i] = basename(files[i]);
2342 n[i] = NULL;
2343
2344 r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes);
2345 if (r < 0)
2346 return r;
2347
2348 /* But the enable command with the full name */
2349 return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes);
2350 }
2351
2352 int unit_file_set_default(
2353 UnitFileScope scope,
2354 const char *root_dir,
2355 const char *name,
2356 bool force,
2357 UnitFileChange **changes,
2358 unsigned *n_changes) {
2359
2360 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2361 _cleanup_(install_context_done) InstallContext c = {};
2362 UnitFileInstallInfo *i;
2363 const char *new_path;
2364 int r;
2365
2366 assert(scope >= 0);
2367 assert(scope < _UNIT_FILE_SCOPE_MAX);
2368 assert(name);
2369
2370 if (unit_name_to_type(name) != UNIT_TARGET) /* this also validates the name */
2371 return -EINVAL;
2372 if (streq(name, SPECIAL_DEFAULT_TARGET))
2373 return -EINVAL;
2374
2375 r = lookup_paths_init(&paths, scope, 0, root_dir);
2376 if (r < 0)
2377 return r;
2378
2379 r = install_info_discover(scope, &c, &paths, name, 0, &i);
2380 if (r < 0)
2381 return r;
2382 r = install_info_may_process(i, &paths, changes, n_changes);
2383 if (r < 0)
2384 return r;
2385
2386 new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET);
2387 return create_symlink(&paths, i->path, new_path, force, changes, n_changes);
2388 }
2389
2390 int unit_file_get_default(
2391 UnitFileScope scope,
2392 const char *root_dir,
2393 char **name) {
2394
2395 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2396 _cleanup_(install_context_done) InstallContext c = {};
2397 UnitFileInstallInfo *i;
2398 char *n;
2399 int r;
2400
2401 assert(scope >= 0);
2402 assert(scope < _UNIT_FILE_SCOPE_MAX);
2403 assert(name);
2404
2405 r = lookup_paths_init(&paths, scope, 0, root_dir);
2406 if (r < 0)
2407 return r;
2408
2409 r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2410 if (r < 0)
2411 return r;
2412 r = install_info_may_process(i, &paths, NULL, 0);
2413 if (r < 0)
2414 return r;
2415
2416 n = strdup(i->name);
2417 if (!n)
2418 return -ENOMEM;
2419
2420 *name = n;
2421 return 0;
2422 }
2423
2424 static int unit_file_lookup_state(
2425 UnitFileScope scope,
2426 const LookupPaths *paths,
2427 const char *name,
2428 UnitFileState *ret) {
2429
2430 _cleanup_(install_context_done) InstallContext c = {};
2431 UnitFileInstallInfo *i;
2432 UnitFileState state;
2433 int r;
2434
2435 assert(paths);
2436 assert(name);
2437
2438 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2439 return -EINVAL;
2440
2441 r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2442 if (r < 0)
2443 return r;
2444
2445 /* Shortcut things, if the caller just wants to know if this unit exists. */
2446 if (!ret)
2447 return 0;
2448
2449 switch (i->type) {
2450
2451 case UNIT_FILE_TYPE_MASKED:
2452 r = path_is_runtime(paths, i->path);
2453 if (r < 0)
2454 return r;
2455
2456 state = r > 0 ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2457 break;
2458
2459 case UNIT_FILE_TYPE_REGULAR:
2460 r = path_is_generator(paths, i->path);
2461 if (r < 0)
2462 return r;
2463 if (r > 0) {
2464 state = UNIT_FILE_GENERATED;
2465 break;
2466 }
2467
2468 r = path_is_transient(paths, i->path);
2469 if (r < 0)
2470 return r;
2471 if (r > 0) {
2472 state = UNIT_FILE_TRANSIENT;
2473 break;
2474 }
2475
2476 r = find_symlinks_in_scope(scope, paths, i->name, &state);
2477 if (r < 0)
2478 return r;
2479 if (r == 0) {
2480 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i))
2481 state = UNIT_FILE_DISABLED;
2482 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i))
2483 state = UNIT_FILE_INDIRECT;
2484 else
2485 state = UNIT_FILE_STATIC;
2486 }
2487
2488 break;
2489
2490 default:
2491 assert_not_reached("Unexpect unit file type.");
2492 }
2493
2494 *ret = state;
2495 return 0;
2496 }
2497
2498 int unit_file_get_state(
2499 UnitFileScope scope,
2500 const char *root_dir,
2501 const char *name,
2502 UnitFileState *ret) {
2503
2504 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2505 int r;
2506
2507 assert(scope >= 0);
2508 assert(scope < _UNIT_FILE_SCOPE_MAX);
2509 assert(name);
2510
2511 r = lookup_paths_init(&paths, scope, 0, root_dir);
2512 if (r < 0)
2513 return r;
2514
2515 return unit_file_lookup_state(scope, &paths, name, ret);
2516 }
2517
2518 int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name) {
2519 _cleanup_(install_context_done) InstallContext c = {};
2520 int r;
2521
2522 assert(paths);
2523 assert(name);
2524
2525 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2526 return -EINVAL;
2527
2528 r = install_info_discover(scope, &c, paths, name, 0, NULL);
2529 if (r == -ENOENT)
2530 return 0;
2531 if (r < 0)
2532 return r;
2533
2534 return 1;
2535 }
2536
2537 static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
2538 _cleanup_(presets_freep) Presets ps = {};
2539 size_t n_allocated = 0;
2540 _cleanup_strv_free_ char **files = NULL;
2541 char **p;
2542 int r;
2543
2544 assert(scope >= 0);
2545 assert(scope < _UNIT_FILE_SCOPE_MAX);
2546 assert(presets);
2547
2548 if (scope == UNIT_FILE_SYSTEM)
2549 r = conf_files_list(&files, ".preset", root_dir,
2550 "/etc/systemd/system-preset",
2551 "/usr/local/lib/systemd/system-preset",
2552 "/usr/lib/systemd/system-preset",
2553 #ifdef HAVE_SPLIT_USR
2554 "/lib/systemd/system-preset",
2555 #endif
2556 NULL);
2557 else if (scope == UNIT_FILE_GLOBAL)
2558 r = conf_files_list(&files, ".preset", root_dir,
2559 "/etc/systemd/user-preset",
2560 "/usr/local/lib/systemd/user-preset",
2561 "/usr/lib/systemd/user-preset",
2562 NULL);
2563 else {
2564 *presets = (Presets){};
2565
2566 return 0;
2567 }
2568
2569 if (r < 0)
2570 return r;
2571
2572 STRV_FOREACH(p, files) {
2573 _cleanup_fclose_ FILE *f;
2574 char line[LINE_MAX];
2575 int n = 0;
2576
2577 f = fopen(*p, "re");
2578 if (!f) {
2579 if (errno == ENOENT)
2580 continue;
2581
2582 return -errno;
2583 }
2584
2585 FOREACH_LINE(line, f, return -errno) {
2586 PresetRule rule = {};
2587 const char *parameter;
2588 char *l;
2589
2590 l = strstrip(line);
2591 n++;
2592
2593 if (isempty(l))
2594 continue;
2595 if (strchr(COMMENTS, *l))
2596 continue;
2597
2598 parameter = first_word(l, "enable");
2599 if (parameter) {
2600 char *pattern;
2601
2602 pattern = strdup(parameter);
2603 if (!pattern)
2604 return -ENOMEM;
2605
2606 rule = (PresetRule) {
2607 .pattern = pattern,
2608 .action = PRESET_ENABLE,
2609 };
2610 }
2611
2612 parameter = first_word(l, "disable");
2613 if (parameter) {
2614 char *pattern;
2615
2616 pattern = strdup(parameter);
2617 if (!pattern)
2618 return -ENOMEM;
2619
2620 rule = (PresetRule) {
2621 .pattern = pattern,
2622 .action = PRESET_DISABLE,
2623 };
2624 }
2625
2626 if (rule.action) {
2627 if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1))
2628 return -ENOMEM;
2629
2630 ps.rules[ps.n_rules++] = rule;
2631 continue;
2632 }
2633
2634 log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
2635 }
2636 }
2637
2638 *presets = ps;
2639 ps = (Presets){};
2640
2641 return 0;
2642 }
2643
2644 static int query_presets(const char *name, const Presets presets) {
2645 PresetAction action = PRESET_UNKNOWN;
2646 size_t i;
2647
2648 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2649 return -EINVAL;
2650
2651 for (i = 0; i < presets.n_rules; i++)
2652 if (fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
2653 action = presets.rules[i].action;
2654 break;
2655 }
2656
2657 switch (action) {
2658 case PRESET_UNKNOWN:
2659 log_debug("Preset files don't specify rule for %s. Enabling.", name);
2660 return 1;
2661 case PRESET_ENABLE:
2662 log_debug("Preset files say enable %s.", name);
2663 return 1;
2664 case PRESET_DISABLE:
2665 log_debug("Preset files say disable %s.", name);
2666 return 0;
2667 default:
2668 assert_not_reached("invalid preset action");
2669 }
2670 }
2671
2672 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
2673 _cleanup_(presets_freep) Presets presets = {};
2674 int r;
2675
2676 r = read_presets(scope, root_dir, &presets);
2677 if (r < 0)
2678 return r;
2679
2680 return query_presets(name, presets);
2681 }
2682
2683 static int execute_preset(
2684 UnitFileScope scope,
2685 InstallContext *plus,
2686 InstallContext *minus,
2687 const LookupPaths *paths,
2688 const char *config_path,
2689 char **files,
2690 UnitFilePresetMode mode,
2691 bool force,
2692 UnitFileChange **changes,
2693 unsigned *n_changes) {
2694
2695 int r;
2696
2697 assert(plus);
2698 assert(minus);
2699 assert(paths);
2700 assert(config_path);
2701
2702 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2703 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2704
2705 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path);
2706 if (r < 0)
2707 return r;
2708
2709 r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, changes, n_changes);
2710 } else
2711 r = 0;
2712
2713 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2714 int q;
2715
2716 /* Returns number of symlinks that where supposed to be installed. */
2717 q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
2718 if (r >= 0) {
2719 if (q < 0)
2720 r = q;
2721 else
2722 r += q;
2723 }
2724 }
2725
2726 return r;
2727 }
2728
2729 static int preset_prepare_one(
2730 UnitFileScope scope,
2731 InstallContext *plus,
2732 InstallContext *minus,
2733 LookupPaths *paths,
2734 const char *name,
2735 Presets presets,
2736 UnitFileChange **changes,
2737 unsigned *n_changes) {
2738
2739 _cleanup_(install_context_done) InstallContext tmp = {};
2740 UnitFileInstallInfo *i;
2741 int r;
2742
2743 if (install_info_find(plus, name) || install_info_find(minus, name))
2744 return 0;
2745
2746 r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2747 if (r < 0)
2748 return r;
2749 if (!streq(name, i->name)) {
2750 log_debug("Skipping %s because is an alias for %s", name, i->name);
2751 return 0;
2752 }
2753
2754 r = query_presets(name, presets);
2755 if (r < 0)
2756 return r;
2757
2758 if (r > 0) {
2759 r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2760 if (r < 0)
2761 return r;
2762
2763 r = install_info_may_process(i, paths, changes, n_changes);
2764 if (r < 0)
2765 return r;
2766 } else
2767 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2768
2769 return r;
2770 }
2771
2772 int unit_file_preset(
2773 UnitFileScope scope,
2774 bool runtime,
2775 const char *root_dir,
2776 char **files,
2777 UnitFilePresetMode mode,
2778 bool force,
2779 UnitFileChange **changes,
2780 unsigned *n_changes) {
2781
2782 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2783 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2784 _cleanup_(presets_freep) Presets presets = {};
2785 const char *config_path;
2786 char **i;
2787 int r;
2788
2789 assert(scope >= 0);
2790 assert(scope < _UNIT_FILE_SCOPE_MAX);
2791 assert(mode < _UNIT_FILE_PRESET_MAX);
2792
2793 r = lookup_paths_init(&paths, scope, 0, root_dir);
2794 if (r < 0)
2795 return r;
2796
2797 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2798
2799 r = read_presets(scope, root_dir, &presets);
2800 if (r < 0)
2801 return r;
2802
2803 STRV_FOREACH(i, files) {
2804 r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
2805 if (r < 0)
2806 return r;
2807 }
2808
2809 return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, force, changes, n_changes);
2810 }
2811
2812 int unit_file_preset_all(
2813 UnitFileScope scope,
2814 bool runtime,
2815 const char *root_dir,
2816 UnitFilePresetMode mode,
2817 bool force,
2818 UnitFileChange **changes,
2819 unsigned *n_changes) {
2820
2821 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2822 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2823 _cleanup_(presets_freep) Presets presets = {};
2824 const char *config_path = NULL;
2825 char **i;
2826 int r;
2827
2828 assert(scope >= 0);
2829 assert(scope < _UNIT_FILE_SCOPE_MAX);
2830 assert(mode < _UNIT_FILE_PRESET_MAX);
2831
2832 r = lookup_paths_init(&paths, scope, 0, root_dir);
2833 if (r < 0)
2834 return r;
2835
2836 config_path = runtime ? paths.runtime_config : paths.persistent_config;
2837
2838 r = read_presets(scope, root_dir, &presets);
2839 if (r < 0)
2840 return r;
2841
2842 STRV_FOREACH(i, paths.search_path) {
2843 _cleanup_closedir_ DIR *d = NULL;
2844 struct dirent *de;
2845
2846 d = opendir(*i);
2847 if (!d) {
2848 if (errno == ENOENT)
2849 continue;
2850
2851 return -errno;
2852 }
2853
2854 FOREACH_DIRENT(de, d, return -errno) {
2855
2856 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2857 continue;
2858
2859 dirent_ensure_type(d, de);
2860
2861 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2862 continue;
2863
2864 /* we don't pass changes[] in, because we want to handle errors on our own */
2865 r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
2866 if (r == -ERFKILL)
2867 r = unit_file_changes_add(changes, n_changes,
2868 UNIT_FILE_IS_MASKED, de->d_name, NULL);
2869 else if (r == -ENOLINK)
2870 r = unit_file_changes_add(changes, n_changes,
2871 UNIT_FILE_IS_DANGLING, de->d_name, NULL);
2872 if (r < 0)
2873 return r;
2874 }
2875 }
2876
2877 return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, force, changes, n_changes);
2878 }
2879
2880 static void unit_file_list_free_one(UnitFileList *f) {
2881 if (!f)
2882 return;
2883
2884 free(f->path);
2885 free(f);
2886 }
2887
2888 Hashmap* unit_file_list_free(Hashmap *h) {
2889 UnitFileList *i;
2890
2891 while ((i = hashmap_steal_first(h)))
2892 unit_file_list_free_one(i);
2893
2894 return hashmap_free(h);
2895 }
2896
2897 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2898
2899 int unit_file_get_list(
2900 UnitFileScope scope,
2901 const char *root_dir,
2902 Hashmap *h,
2903 char **states,
2904 char **patterns) {
2905
2906 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2907 char **i;
2908 int r;
2909
2910 assert(scope >= 0);
2911 assert(scope < _UNIT_FILE_SCOPE_MAX);
2912 assert(h);
2913
2914 r = lookup_paths_init(&paths, scope, 0, root_dir);
2915 if (r < 0)
2916 return r;
2917
2918 STRV_FOREACH(i, paths.search_path) {
2919 _cleanup_closedir_ DIR *d = NULL;
2920 struct dirent *de;
2921
2922 d = opendir(*i);
2923 if (!d) {
2924 if (errno == ENOENT)
2925 continue;
2926 if (IN_SET(errno, ENOTDIR, EACCES)) {
2927 log_debug("Failed to open \"%s\": %m", *i);
2928 continue;
2929 }
2930
2931 return -errno;
2932 }
2933
2934 FOREACH_DIRENT(de, d, return -errno) {
2935 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2936
2937 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2938 continue;
2939
2940 if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
2941 continue;
2942
2943 if (hashmap_get(h, de->d_name))
2944 continue;
2945
2946 dirent_ensure_type(d, de);
2947
2948 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2949 continue;
2950
2951 f = new0(UnitFileList, 1);
2952 if (!f)
2953 return -ENOMEM;
2954
2955 f->path = path_make_absolute(de->d_name, *i);
2956 if (!f->path)
2957 return -ENOMEM;
2958
2959 r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state);
2960 if (r < 0)
2961 f->state = UNIT_FILE_BAD;
2962
2963 if (!strv_isempty(states) &&
2964 !strv_contains(states, unit_file_state_to_string(f->state)))
2965 continue;
2966
2967 r = hashmap_put(h, basename(f->path), f);
2968 if (r < 0)
2969 return r;
2970
2971 f = NULL; /* prevent cleanup */
2972 }
2973 }
2974
2975 return 0;
2976 }
2977
2978 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2979 [UNIT_FILE_ENABLED] = "enabled",
2980 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2981 [UNIT_FILE_LINKED] = "linked",
2982 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2983 [UNIT_FILE_MASKED] = "masked",
2984 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2985 [UNIT_FILE_STATIC] = "static",
2986 [UNIT_FILE_DISABLED] = "disabled",
2987 [UNIT_FILE_INDIRECT] = "indirect",
2988 [UNIT_FILE_GENERATED] = "generated",
2989 [UNIT_FILE_TRANSIENT] = "transient",
2990 [UNIT_FILE_BAD] = "bad",
2991 };
2992
2993 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2994
2995 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2996 [UNIT_FILE_SYMLINK] = "symlink",
2997 [UNIT_FILE_UNLINK] = "unlink",
2998 [UNIT_FILE_IS_MASKED] = "masked",
2999 [UNIT_FILE_IS_DANGLING] = "dangling",
3000 };
3001
3002 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
3003
3004 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
3005 [UNIT_FILE_PRESET_FULL] = "full",
3006 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
3007 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
3008 };
3009
3010 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);