1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty <of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "path-util.h"
33 #include "path-lookup.h"
35 #include "unit-name.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
44 Hashmap *will_install;
45 Hashmap *have_installed;
48 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
50 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
53 assert(scope < _UNIT_FILE_SCOPE_MAX);
57 return lookup_paths_init(paths,
58 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
59 scope == UNIT_FILE_USER,
63 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
68 assert(scope < _UNIT_FILE_SCOPE_MAX);
73 case UNIT_FILE_SYSTEM:
75 if (root_dir && runtime)
76 asprintf(&p, "%s/run/systemd/system", root_dir);
78 p = strdup("/run/systemd/system");
80 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
82 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
86 case UNIT_FILE_GLOBAL:
92 p = strdup("/run/systemd/user");
94 p = strdup(USER_CONFIG_UNIT_PATH);
99 if (root_dir || runtime)
102 r = user_config_home(&p);
104 return r < 0 ? r : -ENOENT;
109 assert_not_reached("Bad scope");
119 static int add_file_change(
120 UnitFileChange **changes,
122 UnitFileChangeType type,
124 const char *source) {
130 assert(!changes == !n_changes);
135 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
143 c[i].path = strdup(path);
148 c[i].source = strdup(source);
160 static int mark_symlink_for_removal(
161 Set **remove_symlinks_to,
169 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
177 path_kill_slashes(n);
179 r = set_consume(*remove_symlinks_to, n);
181 return r == -EEXIST ? 0 : r;
186 static int remove_marked_symlinks_fd(
187 Set *remove_symlinks_to,
190 const char *config_path,
192 UnitFileChange **changes,
197 _cleanup_closedir_ DIR *d = NULL;
199 assert(remove_symlinks_to);
218 if (!de && errno != 0) {
226 if (ignore_file(de->d_name))
229 dirent_ensure_type(d, de);
231 if (de->d_type == DT_DIR) {
233 _cleanup_free_ char *p = NULL;
235 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
245 p = path_make_absolute(de->d_name, path);
251 /* This will close nfd, regardless whether it succeeds or not */
252 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
257 } else if (de->d_type == DT_LNK) {
258 _cleanup_free_ char *p = NULL, *dest = NULL;
262 p = path_make_absolute(de->d_name, path);
266 q = readlink_and_canonicalize(p, &dest);
277 set_get(remove_symlinks_to, dest) ||
278 set_get(remove_symlinks_to, basename(dest));
280 if (unit_name_is_instance(p))
281 found = found && strv_contains(files, basename(p));
285 if (unlink(p) < 0 && errno != ENOENT) {
290 rmdir_parents(p, config_path);
291 path_kill_slashes(p);
293 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
295 if (!set_get(remove_symlinks_to, p)) {
297 q = mark_symlink_for_removal(&remove_symlinks_to, p);
312 static int remove_marked_symlinks(
313 Set *remove_symlinks_to,
314 const char *config_path,
315 UnitFileChange **changes,
324 if (set_size(remove_symlinks_to) <= 0)
327 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
341 /* This takes possession of cfd and closes it */
342 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
352 static int find_symlinks_fd(
356 const char *config_path,
357 bool *same_name_link) {
360 _cleanup_closedir_ DIR *d = NULL;
366 assert(same_name_link);
379 if (!de && errno != 0)
385 if (ignore_file(de->d_name))
388 dirent_ensure_type(d, de);
390 if (de->d_type == DT_DIR) {
392 _cleanup_free_ char *p = NULL;
394 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
404 p = path_make_absolute(de->d_name, path);
410 /* This will close nfd, regardless whether it succeeds or not */
411 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
419 } else if (de->d_type == DT_LNK) {
420 _cleanup_free_ char *p = NULL, *dest = NULL;
421 bool found_path, found_dest, b = false;
424 /* Acquire symlink name */
425 p = path_make_absolute(de->d_name, path);
429 /* Acquire symlink destination */
430 q = readlink_and_canonicalize(p, &dest);
440 /* Check if the symlink itself matches what we
442 if (path_is_absolute(name))
443 found_path = path_equal(p, name);
445 found_path = streq(de->d_name, name);
447 /* Check if what the symlink points to
448 * matches what we are looking for */
449 if (path_is_absolute(name))
450 found_dest = path_equal(dest, name);
452 found_dest = streq(basename(dest), name);
454 if (found_path && found_dest) {
455 _cleanup_free_ char *t = NULL;
457 /* Filter out same name links in the main
459 t = path_make_absolute(name, config_path);
463 b = path_equal(t, p);
467 *same_name_link = true;
468 else if (found_path || found_dest)
474 static int find_symlinks(
476 const char *config_path,
477 bool *same_name_link) {
483 assert(same_name_link);
485 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
492 /* This takes possession of fd and closes it */
493 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
496 static int find_symlinks_in_scope(
498 const char *root_dir,
500 UnitFileState *state) {
503 _cleanup_free_ char *path2 = NULL;
504 bool same_name_link_runtime = false, same_name_link = false;
507 assert(scope < _UNIT_FILE_SCOPE_MAX);
510 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
511 _cleanup_free_ char *path = NULL;
513 /* First look in runtime config path */
514 r = get_config_path(scope, true, root_dir, &path);
518 r = find_symlinks(name, path, &same_name_link_runtime);
522 *state = UNIT_FILE_ENABLED_RUNTIME;
527 /* Then look in the normal config path */
528 r = get_config_path(scope, false, root_dir, &path2);
532 r = find_symlinks(name, path2, &same_name_link);
536 *state = UNIT_FILE_ENABLED;
540 /* Hmm, we didn't find it, but maybe we found the same name
542 if (same_name_link_runtime) {
543 *state = UNIT_FILE_LINKED_RUNTIME;
545 } else if (same_name_link) {
546 *state = UNIT_FILE_LINKED;
556 const char *root_dir,
559 UnitFileChange **changes,
560 unsigned *n_changes) {
563 _cleanup_free_ char *prefix;
567 assert(scope < _UNIT_FILE_SCOPE_MAX);
569 r = get_config_path(scope, runtime, root_dir, &prefix);
573 STRV_FOREACH(i, files) {
574 _cleanup_free_ char *path = NULL;
576 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
582 path = path_make_absolute(*i, prefix);
588 if (symlink("/dev/null", path) >= 0) {
589 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
594 if (errno == EEXIST) {
596 if (null_or_empty_path(path) > 0)
602 if (symlink("/dev/null", path) >= 0) {
604 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
605 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
622 int unit_file_unmask(
625 const char *root_dir,
627 UnitFileChange **changes,
628 unsigned *n_changes) {
630 char **i, *config_path = NULL;
632 Set *remove_symlinks_to = NULL;
635 assert(scope < _UNIT_FILE_SCOPE_MAX);
637 r = get_config_path(scope, runtime, root_dir, &config_path);
641 STRV_FOREACH(i, files) {
644 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
650 path = path_make_absolute(*i, config_path);
656 q = null_or_empty_path(path);
658 if (unlink(path) >= 0) {
659 mark_symlink_for_removal(&remove_symlinks_to, path);
660 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
669 if (q != -ENOENT && r == 0)
677 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
681 set_free_free(remove_symlinks_to);
690 const char *root_dir,
693 UnitFileChange **changes,
694 unsigned *n_changes) {
696 _cleanup_lookup_paths_free_ LookupPaths paths = {};
698 _cleanup_free_ char *config_path = NULL;
702 assert(scope < _UNIT_FILE_SCOPE_MAX);
704 r = lookup_paths_init_from_scope(&paths, scope);
708 r = get_config_path(scope, runtime, root_dir, &config_path);
712 STRV_FOREACH(i, files) {
713 _cleanup_free_ char *path = NULL;
719 if (!path_is_absolute(*i) ||
720 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
726 if (lstat(*i, &st) < 0) {
732 if (!S_ISREG(st.st_mode)) {
737 q = in_search_path(*i, paths.unit_path);
744 path = path_make_absolute(fn, config_path);
748 if (symlink(*i, path) >= 0) {
749 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
753 if (errno == EEXIST) {
754 _cleanup_free_ char *dest = NULL;
756 q = readlink_and_make_absolute(path, &dest);
758 if (q < 0 && errno != ENOENT) {
764 if (q >= 0 && path_equal(dest, *i))
770 if (symlink(*i, path) >= 0) {
772 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
773 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
790 void unit_file_list_free(Hashmap *h) {
793 while ((i = hashmap_steal_first(h))) {
801 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
804 assert(changes || n_changes == 0);
809 for (i = 0; i < n_changes; i++) {
810 free(changes[i].path);
811 free(changes[i].source);
817 static void install_info_free(InstallInfo *i) {
822 strv_free(i->aliases);
823 strv_free(i->wanted_by);
824 strv_free(i->required_by);
828 static void install_info_hashmap_free(Hashmap *m) {
834 while ((i = hashmap_steal_first(m)))
835 install_info_free(i);
840 static void install_context_done(InstallContext *c) {
843 install_info_hashmap_free(c->will_install);
844 install_info_hashmap_free(c->have_installed);
846 c->will_install = c->have_installed = NULL;
849 static int install_info_add(
853 InstallInfo *i = NULL;
857 assert(name || path);
860 name = basename(path);
862 if (!unit_name_is_valid(name, TEMPLATE_VALID))
865 if (hashmap_get(c->have_installed, name) ||
866 hashmap_get(c->will_install, name))
869 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
873 i = new0(InstallInfo, 1);
877 i->name = strdup(name);
884 i->path = strdup(path);
891 r = hashmap_put(c->will_install, i->name, i);
899 install_info_free(i);
904 static int install_info_add_auto(
906 const char *name_or_path) {
909 assert(name_or_path);
911 if (path_is_absolute(name_or_path))
912 return install_info_add(c, NULL, name_or_path);
914 return install_info_add(c, name_or_path, NULL);
917 static int config_parse_also(const char *unit,
918 const char *filename,
921 unsigned section_line,
931 InstallContext *c = data;
937 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
938 _cleanup_free_ char *n;
945 r = install_info_add(c, n, NULL);
953 static int config_parse_user(const char *unit,
954 const char *filename,
957 unsigned section_line,
964 InstallInfo *i = data;
972 r = install_full_printf(i, rvalue, &printed);
982 static int unit_file_load(
986 bool allow_symlink) {
988 const ConfigTableItem items[] = {
989 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
990 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
991 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
992 { "Install", "Also", config_parse_also, 0, c },
993 { "Exec", "User", config_parse_user, 0, info },
994 { NULL, NULL, NULL, 0, NULL }
998 _cleanup_fclose_ FILE *f = NULL;
1005 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1009 f = fdopen(fd, "re");
1015 r = config_parse(NULL, path, f, NULL,
1016 config_item_table_lookup, (void*) items, true, true, info);
1021 (int) strv_length(info->aliases) +
1022 (int) strv_length(info->wanted_by) +
1023 (int) strv_length(info->required_by);
1026 static int unit_file_search(
1030 const char *root_dir,
1031 bool allow_symlink) {
1041 return unit_file_load(c, info, info->path, allow_symlink);
1045 STRV_FOREACH(p, paths->unit_path) {
1048 if (isempty(root_dir))
1049 asprintf(&path, "%s/%s", *p, info->name);
1051 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1056 r = unit_file_load(c, info, path, allow_symlink);
1061 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1062 /* Unit file doesn't exist, however instance enablement was requested.
1063 * We will check if it is possible to load template unit file. */
1064 char *template = NULL,
1065 *template_path = NULL,
1066 *template_dir = NULL;
1068 template = unit_name_template(info->name);
1074 /* We will reuse path variable since we don't need it anymore. */
1075 template_dir = path;
1076 *(strrchr(path, '/') + 1) = '\0';
1078 template_path = strjoin(template_dir, template, NULL);
1079 if (!template_path) {
1085 /* Let's try to load template unit. */
1086 r = unit_file_load(c, info, template_path, allow_symlink);
1088 info->path = strdup(template_path);
1092 free(template_path);
1098 free(template_path);
1103 if (r != -ENOENT && r != -ELOOP)
1110 static int unit_file_can_install(
1112 const char *root_dir,
1114 bool allow_symlink) {
1116 _cleanup_install_context_done_ InstallContext c = {};
1123 r = install_info_add_auto(&c, name);
1127 assert_se(i = hashmap_first(c.will_install));
1129 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1133 (int) strv_length(i->aliases) +
1134 (int) strv_length(i->wanted_by) +
1135 (int) strv_length(i->required_by);
1140 static int create_symlink(
1141 const char *old_path,
1142 const char *new_path,
1144 UnitFileChange **changes,
1145 unsigned *n_changes) {
1147 _cleanup_free_ char *dest = NULL;
1153 mkdir_parents_label(new_path, 0755);
1155 if (symlink(old_path, new_path) >= 0) {
1156 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1160 if (errno != EEXIST)
1163 r = readlink_and_make_absolute(new_path, &dest);
1167 if (path_equal(dest, old_path))
1175 if (symlink(old_path, new_path) >= 0) {
1176 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1177 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1184 static int install_info_symlink_alias(
1186 const char *config_path,
1188 UnitFileChange **changes,
1189 unsigned *n_changes) {
1195 assert(config_path);
1197 STRV_FOREACH(s, i->aliases) {
1198 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1200 q = install_full_printf(i, *s, &dst);
1204 alias_path = path_make_absolute(dst, config_path);
1208 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1216 static int install_info_symlink_wants(
1218 const char *config_path,
1220 UnitFileChange **changes,
1221 unsigned *n_changes) {
1227 assert(config_path);
1229 STRV_FOREACH(s, i->wanted_by) {
1230 _cleanup_free_ char *path = NULL, *dst = NULL;
1232 q = install_full_printf(i, *s, &dst);
1236 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1241 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1244 q = create_symlink(i->path, path, force, changes, n_changes);
1253 static int install_info_symlink_requires(
1255 const char *config_path,
1257 UnitFileChange **changes,
1258 unsigned *n_changes) {
1264 assert(config_path);
1266 STRV_FOREACH(s, i->required_by) {
1267 _cleanup_free_ char *path = NULL, *dst = NULL;
1269 q = install_full_printf(i, *s, &dst);
1273 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1278 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1281 q = create_symlink(i->path, path, force, changes, n_changes);
1290 static int install_info_symlink_link(
1293 const char *config_path,
1295 UnitFileChange **changes,
1296 unsigned *n_changes) {
1299 _cleanup_free_ char *path = NULL;
1303 assert(config_path);
1306 r = in_search_path(i->path, paths->unit_path);
1310 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1313 r = create_symlink(i->path, path, force, changes, n_changes);
1317 static int install_info_apply(
1320 const char *config_path,
1322 UnitFileChange **changes,
1323 unsigned *n_changes) {
1329 assert(config_path);
1331 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1333 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1337 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1341 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1348 static int install_context_apply(
1351 const char *config_path,
1352 const char *root_dir,
1354 UnitFileChange **changes,
1355 unsigned *n_changes) {
1362 assert(config_path);
1364 while ((i = hashmap_first(c->will_install))) {
1366 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1370 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1372 q = unit_file_search(c, i, paths, root_dir, false);
1381 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1382 if (r >= 0 && q < 0)
1389 static int install_context_mark_for_removal(
1392 Set **remove_symlinks_to,
1393 const char *config_path,
1394 const char *root_dir) {
1401 assert(config_path);
1403 /* Marks all items for removal */
1405 while ((i = hashmap_first(c->will_install))) {
1407 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1411 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1413 q = unit_file_search(c, i, paths, root_dir, false);
1424 if (unit_name_is_instance(i->name)) {
1428 unit_file = basename(i->path);
1430 if (unit_name_is_instance(unit_file))
1431 /* unit file named as instance exists, thus all symlinks
1432 * pointing to it will be removed */
1433 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1435 /* does not exist, thus we will mark for removal symlinks
1436 * to template unit file */
1437 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1439 /* If i->path is not set, it means that we didn't actually find
1440 * the unit file. But we can still remove symlinks to the
1441 * nonexistent template. */
1442 unit_file = unit_name_template(i->name);
1446 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1450 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1452 if (r >= 0 && q < 0)
1459 int unit_file_enable(
1460 UnitFileScope scope,
1462 const char *root_dir,
1465 UnitFileChange **changes,
1466 unsigned *n_changes) {
1468 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1469 _cleanup_install_context_done_ InstallContext c = {};
1471 _cleanup_free_ char *config_path = NULL;
1475 assert(scope < _UNIT_FILE_SCOPE_MAX);
1477 r = lookup_paths_init_from_scope(&paths, scope);
1481 r = get_config_path(scope, runtime, root_dir, &config_path);
1485 STRV_FOREACH(i, files) {
1486 r = install_info_add_auto(&c, *i);
1491 /* This will return the number of symlink rules that were
1492 supposed to be created, not the ones actually created. This is
1493 useful to determine whether the passed files had any
1494 installation data at all. */
1495 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1499 int unit_file_disable(
1500 UnitFileScope scope,
1502 const char *root_dir,
1504 UnitFileChange **changes,
1505 unsigned *n_changes) {
1507 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1508 _cleanup_install_context_done_ InstallContext c = {};
1510 _cleanup_free_ char *config_path = NULL;
1511 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1515 assert(scope < _UNIT_FILE_SCOPE_MAX);
1517 r = lookup_paths_init_from_scope(&paths, scope);
1521 r = get_config_path(scope, runtime, root_dir, &config_path);
1525 STRV_FOREACH(i, files) {
1526 r = install_info_add_auto(&c, *i);
1531 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1533 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1540 int unit_file_reenable(
1541 UnitFileScope scope,
1543 const char *root_dir,
1546 UnitFileChange **changes,
1547 unsigned *n_changes) {
1550 r = unit_file_disable(scope, runtime, root_dir, files,
1551 changes, n_changes);
1555 return unit_file_enable(scope, runtime, root_dir, files, force,
1556 changes, n_changes);
1559 int unit_file_set_default(
1560 UnitFileScope scope,
1561 const char *root_dir,
1564 UnitFileChange **changes,
1565 unsigned *n_changes) {
1567 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1568 _cleanup_install_context_done_ InstallContext c = {};
1569 _cleanup_free_ char *config_path = NULL;
1572 InstallInfo *i = NULL;
1575 assert(scope < _UNIT_FILE_SCOPE_MAX);
1578 if (unit_name_to_type(file) != UNIT_TARGET)
1581 r = lookup_paths_init_from_scope(&paths, scope);
1585 r = get_config_path(scope, false, root_dir, &config_path);
1589 r = install_info_add_auto(&c, file);
1593 assert_se(i = hashmap_first(c.will_install));
1595 r = unit_file_search(&c, i, &paths, root_dir, false);
1599 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1601 r = create_symlink(i->path, path, force, changes, n_changes);
1608 int unit_file_get_default(
1609 UnitFileScope scope,
1610 const char *root_dir,
1613 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1618 assert(scope < _UNIT_FILE_SCOPE_MAX);
1621 r = lookup_paths_init_from_scope(&paths, scope);
1625 STRV_FOREACH(p, paths.unit_path) {
1626 _cleanup_free_ char *path = NULL, *tmp = NULL;
1629 if (isempty(root_dir))
1630 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1632 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1637 r = readlink_malloc(path, &tmp);
1640 else if (r == -EINVAL)
1642 n = strdup(SPECIAL_DEFAULT_TARGET);
1646 n = strdup(basename(tmp));
1658 UnitFileState unit_file_get_state(
1659 UnitFileScope scope,
1660 const char *root_dir,
1663 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1664 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1666 _cleanup_free_ char *path = NULL;
1670 assert(scope < _UNIT_FILE_SCOPE_MAX);
1673 if (root_dir && scope != UNIT_FILE_SYSTEM)
1676 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1679 r = lookup_paths_init_from_scope(&paths, scope);
1683 STRV_FOREACH(i, paths.unit_path) {
1690 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1692 asprintf(&path, "%s/%s", *i, name);
1698 * Search for a unit file in our default paths, to
1699 * be sure, that there are no broken symlinks.
1701 if (lstat(path, &st) < 0) {
1703 if (errno != ENOENT)
1706 if (!unit_name_is_instance(name))
1709 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1712 r = null_or_empty_path(path);
1713 if (r < 0 && r != -ENOENT)
1716 state = path_startswith(*i, "/run") ?
1717 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1722 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1728 r = unit_file_can_install(&paths, root_dir, path, true);
1729 if (r < 0 && errno != ENOENT)
1732 return UNIT_FILE_DISABLED;
1734 return UNIT_FILE_STATIC;
1737 return r < 0 ? r : state;
1740 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1741 _cleanup_strv_free_ char **files = NULL;
1746 assert(scope < _UNIT_FILE_SCOPE_MAX);
1749 if (scope == UNIT_FILE_SYSTEM)
1750 r = conf_files_list(&files, ".preset", NULL,
1751 "/etc/systemd/system-preset",
1752 "/usr/local/lib/systemd/system-preset",
1753 "/usr/lib/systemd/system-preset",
1754 #ifdef HAVE_SPLIT_USR
1755 "/lib/systemd/system-preset",
1758 else if (scope == UNIT_FILE_GLOBAL)
1759 r = conf_files_list(&files, ".preset", NULL,
1760 "/etc/systemd/user-preset",
1761 "/usr/local/lib/systemd/user-preset",
1762 "/usr/lib/systemd/user-preset",
1770 STRV_FOREACH(i, files) {
1771 _cleanup_fclose_ FILE *f;
1773 f = fopen(*i, "re");
1775 if (errno == ENOENT)
1782 char line[LINE_MAX], *l;
1784 if (!fgets(line, sizeof(line), f))
1791 if (strchr(COMMENTS "\n", *l))
1794 if (first_word(l, "enable")) {
1796 l += strspn(l, WHITESPACE);
1798 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1801 } else if (first_word(l, "disable")) {
1803 l += strspn(l, WHITESPACE);
1805 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1809 log_debug("Couldn't parse line '%s'", l);
1813 /* Default is "enable" */
1817 int unit_file_preset(
1818 UnitFileScope scope,
1820 const char *root_dir,
1823 UnitFileChange **changes,
1824 unsigned *n_changes) {
1826 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1827 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1829 _cleanup_free_ char *config_path = NULL;
1830 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1834 assert(scope < _UNIT_FILE_SCOPE_MAX);
1836 r = lookup_paths_init_from_scope(&paths, scope);
1840 r = get_config_path(scope, runtime, root_dir, &config_path);
1844 STRV_FOREACH(i, files) {
1846 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1849 r = unit_file_query_preset(scope, *i);
1854 r = install_info_add_auto(&plus, *i);
1856 r = install_info_add_auto(&minus, *i);
1862 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1863 config_path, root_dir);
1865 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1866 changes, n_changes, files);
1870 /* Returns number of symlinks that where supposed to be installed. */
1871 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1872 changes, n_changes);
1879 static void unitfilelist_free(UnitFileList **f) {
1886 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1888 int unit_file_get_list(
1889 UnitFileScope scope,
1890 const char *root_dir,
1893 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1895 _cleanup_free_ char *buf = NULL;
1896 _cleanup_closedir_ DIR *d = NULL;
1900 assert(scope < _UNIT_FILE_SCOPE_MAX);
1903 if (root_dir && scope != UNIT_FILE_SYSTEM)
1906 r = lookup_paths_init_from_scope(&paths, scope);
1910 STRV_FOREACH(i, paths.unit_path) {
1911 const char *units_dir;
1917 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1927 d = opendir(units_dir);
1929 if (errno == ENOENT)
1937 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1941 if (!de && errno != 0)
1947 if (ignore_file(de->d_name))
1950 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1953 if (hashmap_get(h, de->d_name))
1956 r = dirent_ensure_type(d, de);
1964 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1967 f = new0(UnitFileList, 1);
1971 f->path = path_make_absolute(de->d_name, units_dir);
1975 r = null_or_empty_path(f->path);
1976 if (r < 0 && r != -ENOENT)
1980 path_startswith(*i, "/run") ?
1981 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1985 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1989 f->state = UNIT_FILE_ENABLED;
1993 r = unit_file_can_install(&paths, root_dir, f->path, true);
1994 if (r == -EINVAL || /* Invalid setting? */
1995 r == -EBADMSG || /* Invalid format? */
1996 r == -ENOENT /* Included file not found? */)
1997 f->state = UNIT_FILE_INVALID;
2001 f->state = UNIT_FILE_DISABLED;
2003 f->state = UNIT_FILE_STATIC;
2006 r = hashmap_put(h, basename(f->path), f);
2009 f = NULL; /* prevent cleanup */
2016 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2017 [UNIT_FILE_ENABLED] = "enabled",
2018 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2019 [UNIT_FILE_LINKED] = "linked",
2020 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2021 [UNIT_FILE_MASKED] = "masked",
2022 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2023 [UNIT_FILE_STATIC] = "static",
2024 [UNIT_FILE_DISABLED] = "disabled",
2025 [UNIT_FILE_INVALID] = "invalid",
2028 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2030 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2031 [UNIT_FILE_SYMLINK] = "symlink",
2032 [UNIT_FILE_UNLINK] = "unlink",
2035 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);