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