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