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