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,
52 const char *root_dir) {
55 assert(scope < _UNIT_FILE_SCOPE_MAX);
59 return lookup_paths_init(paths,
60 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
61 scope == UNIT_FILE_USER,
66 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
71 assert(scope < _UNIT_FILE_SCOPE_MAX);
76 case UNIT_FILE_SYSTEM:
78 if (root_dir && runtime)
79 asprintf(&p, "%s/run/systemd/system", root_dir);
81 p = strdup("/run/systemd/system");
83 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
85 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
89 case UNIT_FILE_GLOBAL:
95 p = strdup("/run/systemd/user");
97 p = strdup(USER_CONFIG_UNIT_PATH);
102 if (root_dir || runtime)
105 r = user_config_home(&p);
107 return r < 0 ? r : -ENOENT;
112 assert_not_reached("Bad scope");
122 static int add_file_change(
123 UnitFileChange **changes,
125 UnitFileChangeType type,
127 const char *source) {
133 assert(!changes == !n_changes);
138 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
146 c[i].path = strdup(path);
151 c[i].source = strdup(source);
163 static int mark_symlink_for_removal(
164 Set **remove_symlinks_to,
172 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
180 path_kill_slashes(n);
182 r = set_consume(*remove_symlinks_to, n);
184 return r == -EEXIST ? 0 : r;
189 static int remove_marked_symlinks_fd(
190 Set *remove_symlinks_to,
193 const char *config_path,
195 UnitFileChange **changes,
200 _cleanup_closedir_ DIR *d = NULL;
202 assert(remove_symlinks_to);
221 if (!de && errno != 0) {
229 if (ignore_file(de->d_name))
232 dirent_ensure_type(d, de);
234 if (de->d_type == DT_DIR) {
236 _cleanup_free_ char *p = NULL;
238 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
248 p = path_make_absolute(de->d_name, path);
254 /* This will close nfd, regardless whether it succeeds or not */
255 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
260 } else if (de->d_type == DT_LNK) {
261 _cleanup_free_ char *p = NULL, *dest = NULL;
265 p = path_make_absolute(de->d_name, path);
269 q = readlink_and_canonicalize(p, &dest);
280 set_get(remove_symlinks_to, dest) ||
281 set_get(remove_symlinks_to, basename(dest));
283 if (unit_name_is_instance(p))
284 found = found && strv_contains(files, basename(p));
288 if (unlink(p) < 0 && errno != ENOENT) {
293 rmdir_parents(p, config_path);
294 path_kill_slashes(p);
296 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
298 if (!set_get(remove_symlinks_to, p)) {
300 q = mark_symlink_for_removal(&remove_symlinks_to, p);
315 static int remove_marked_symlinks(
316 Set *remove_symlinks_to,
317 const char *config_path,
318 UnitFileChange **changes,
327 if (set_size(remove_symlinks_to) <= 0)
330 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
338 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
344 /* This takes possession of cfd and closes it */
345 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
355 static int find_symlinks_fd(
359 const char *config_path,
360 bool *same_name_link) {
363 _cleanup_closedir_ DIR *d = NULL;
369 assert(same_name_link);
382 if (!de && errno != 0)
388 if (ignore_file(de->d_name))
391 dirent_ensure_type(d, de);
393 if (de->d_type == DT_DIR) {
395 _cleanup_free_ char *p = NULL;
397 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
407 p = path_make_absolute(de->d_name, path);
413 /* This will close nfd, regardless whether it succeeds or not */
414 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
422 } else if (de->d_type == DT_LNK) {
423 _cleanup_free_ char *p = NULL, *dest = NULL;
424 bool found_path, found_dest, b = false;
427 /* Acquire symlink name */
428 p = path_make_absolute(de->d_name, path);
432 /* Acquire symlink destination */
433 q = readlink_and_canonicalize(p, &dest);
443 /* Check if the symlink itself matches what we
445 if (path_is_absolute(name))
446 found_path = path_equal(p, name);
448 found_path = streq(de->d_name, name);
450 /* Check if what the symlink points to
451 * matches what we are looking for */
452 if (path_is_absolute(name))
453 found_dest = path_equal(dest, name);
455 found_dest = streq(basename(dest), name);
457 if (found_path && found_dest) {
458 _cleanup_free_ char *t = NULL;
460 /* Filter out same name links in the main
462 t = path_make_absolute(name, config_path);
466 b = path_equal(t, p);
470 *same_name_link = true;
471 else if (found_path || found_dest)
477 static int find_symlinks(
479 const char *config_path,
480 bool *same_name_link) {
486 assert(same_name_link);
488 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
495 /* This takes possession of fd and closes it */
496 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
499 static int find_symlinks_in_scope(
501 const char *root_dir,
503 UnitFileState *state) {
506 _cleanup_free_ char *path2 = NULL;
507 bool same_name_link_runtime = false, same_name_link = false;
510 assert(scope < _UNIT_FILE_SCOPE_MAX);
513 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
514 _cleanup_free_ char *path = NULL;
516 /* First look in runtime config path */
517 r = get_config_path(scope, true, root_dir, &path);
521 r = find_symlinks(name, path, &same_name_link_runtime);
525 *state = UNIT_FILE_ENABLED_RUNTIME;
530 /* Then look in the normal config path */
531 r = get_config_path(scope, false, root_dir, &path2);
535 r = find_symlinks(name, path2, &same_name_link);
539 *state = UNIT_FILE_ENABLED;
543 /* Hmm, we didn't find it, but maybe we found the same name
545 if (same_name_link_runtime) {
546 *state = UNIT_FILE_LINKED_RUNTIME;
548 } else if (same_name_link) {
549 *state = UNIT_FILE_LINKED;
559 const char *root_dir,
562 UnitFileChange **changes,
563 unsigned *n_changes) {
566 _cleanup_free_ char *prefix;
570 assert(scope < _UNIT_FILE_SCOPE_MAX);
572 r = get_config_path(scope, runtime, root_dir, &prefix);
576 STRV_FOREACH(i, files) {
577 _cleanup_free_ char *path = NULL;
579 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
585 path = path_make_absolute(*i, prefix);
591 if (symlink("/dev/null", path) >= 0) {
592 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
597 if (errno == EEXIST) {
599 if (null_or_empty_path(path) > 0)
605 if (symlink("/dev/null", path) >= 0) {
607 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
608 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
625 int unit_file_unmask(
628 const char *root_dir,
630 UnitFileChange **changes,
631 unsigned *n_changes) {
633 char **i, *config_path = NULL;
635 Set *remove_symlinks_to = NULL;
638 assert(scope < _UNIT_FILE_SCOPE_MAX);
640 r = get_config_path(scope, runtime, root_dir, &config_path);
644 STRV_FOREACH(i, files) {
647 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
653 path = path_make_absolute(*i, config_path);
659 q = null_or_empty_path(path);
661 if (unlink(path) >= 0) {
662 mark_symlink_for_removal(&remove_symlinks_to, path);
663 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
672 if (q != -ENOENT && r == 0)
680 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
684 set_free_free(remove_symlinks_to);
693 const char *root_dir,
696 UnitFileChange **changes,
697 unsigned *n_changes) {
699 _cleanup_lookup_paths_free_ LookupPaths paths = {};
701 _cleanup_free_ char *config_path = NULL;
705 assert(scope < _UNIT_FILE_SCOPE_MAX);
707 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
711 r = get_config_path(scope, runtime, root_dir, &config_path);
715 STRV_FOREACH(i, files) {
716 _cleanup_free_ char *path = NULL;
722 if (!path_is_absolute(*i) ||
723 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
729 if (lstat(*i, &st) < 0) {
735 if (!S_ISREG(st.st_mode)) {
740 q = in_search_path(*i, paths.unit_path);
747 path = path_make_absolute(fn, config_path);
751 if (symlink(*i, path) >= 0) {
752 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
756 if (errno == EEXIST) {
757 _cleanup_free_ char *dest = NULL;
759 q = readlink_and_make_absolute(path, &dest);
761 if (q < 0 && errno != ENOENT) {
767 if (q >= 0 && path_equal(dest, *i))
773 if (symlink(*i, path) >= 0) {
775 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
776 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
793 void unit_file_list_free(Hashmap *h) {
796 while ((i = hashmap_steal_first(h))) {
804 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
807 assert(changes || n_changes == 0);
812 for (i = 0; i < n_changes; i++) {
813 free(changes[i].path);
814 free(changes[i].source);
820 static void install_info_free(InstallInfo *i) {
825 strv_free(i->aliases);
826 strv_free(i->wanted_by);
827 strv_free(i->required_by);
831 static void install_info_hashmap_free(Hashmap *m) {
837 while ((i = hashmap_steal_first(m)))
838 install_info_free(i);
843 static void install_context_done(InstallContext *c) {
846 install_info_hashmap_free(c->will_install);
847 install_info_hashmap_free(c->have_installed);
849 c->will_install = c->have_installed = NULL;
852 static int install_info_add(
856 InstallInfo *i = NULL;
860 assert(name || path);
863 name = basename(path);
865 if (!unit_name_is_valid(name, TEMPLATE_VALID))
868 if (hashmap_get(c->have_installed, name) ||
869 hashmap_get(c->will_install, name))
872 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
876 i = new0(InstallInfo, 1);
880 i->name = strdup(name);
887 i->path = strdup(path);
894 r = hashmap_put(c->will_install, i->name, i);
902 install_info_free(i);
907 static int install_info_add_auto(
909 const char *name_or_path) {
912 assert(name_or_path);
914 if (path_is_absolute(name_or_path))
915 return install_info_add(c, NULL, name_or_path);
917 return install_info_add(c, name_or_path, NULL);
920 static int config_parse_also(const char *unit,
921 const char *filename,
924 unsigned section_line,
934 InstallContext *c = data;
940 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
941 _cleanup_free_ char *n;
948 r = install_info_add(c, n, NULL);
956 static int config_parse_user(const char *unit,
957 const char *filename,
960 unsigned section_line,
967 InstallInfo *i = data;
975 r = install_full_printf(i, rvalue, &printed);
985 static int unit_file_load(
989 bool allow_symlink) {
991 const ConfigTableItem items[] = {
992 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
993 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
994 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
995 { "Install", "Also", config_parse_also, 0, c },
996 { "Exec", "User", config_parse_user, 0, info },
997 { NULL, NULL, NULL, 0, NULL }
1001 _cleanup_fclose_ FILE *f = NULL;
1008 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1012 f = fdopen(fd, "re");
1018 r = config_parse(NULL, path, f, NULL,
1019 config_item_table_lookup, (void*) items, true, true, info);
1024 (int) strv_length(info->aliases) +
1025 (int) strv_length(info->wanted_by) +
1026 (int) strv_length(info->required_by);
1029 static int unit_file_search(
1033 const char *root_dir,
1034 bool allow_symlink) {
1044 char *full_path = NULL;
1046 if (!isempty(root_dir))
1047 full_path = strappenda(root_dir, info->path);
1049 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1054 STRV_FOREACH(p, paths->unit_path) {
1055 _cleanup_free_ char *path = NULL, *full_path = NULL;
1057 path = strjoin(*p, "/", info->name, NULL);
1061 if (!isempty(root_dir)) {
1062 full_path = strappend(root_dir, path);
1067 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1071 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1072 /* Unit file doesn't exist, however instance enablement was requested.
1073 * We will check if it is possible to load template unit file. */
1074 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1076 template = unit_name_template(info->name);
1080 /* We will reuse path variable since we don't need it anymore. */
1081 template_dir = path;
1082 *(strrchr(template_dir, '/') + 1) = '\0';
1084 path = strappend(template_dir, template);
1088 if (!isempty(root_dir)) {
1090 full_path = strappend(root_dir, path);
1095 /* Let's try to load template unit. */
1096 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
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))
1173 r = unlink(new_path);
1174 if (r < 0 && errno != ENOENT)
1177 if (symlink(old_path, new_path) >= 0) {
1178 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1179 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1186 static int install_info_symlink_alias(
1188 const char *config_path,
1190 UnitFileChange **changes,
1191 unsigned *n_changes) {
1197 assert(config_path);
1199 STRV_FOREACH(s, i->aliases) {
1200 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1202 q = install_full_printf(i, *s, &dst);
1206 alias_path = path_make_absolute(dst, config_path);
1210 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1218 static int install_info_symlink_wants(
1220 const char *config_path,
1222 UnitFileChange **changes,
1223 unsigned *n_changes) {
1229 assert(config_path);
1231 STRV_FOREACH(s, i->wanted_by) {
1232 _cleanup_free_ char *path = NULL, *dst = NULL;
1234 q = install_full_printf(i, *s, &dst);
1238 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1243 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1246 q = create_symlink(i->path, path, force, changes, n_changes);
1255 static int install_info_symlink_requires(
1257 const char *config_path,
1259 UnitFileChange **changes,
1260 unsigned *n_changes) {
1266 assert(config_path);
1268 STRV_FOREACH(s, i->required_by) {
1269 _cleanup_free_ char *path = NULL, *dst = NULL;
1271 q = install_full_printf(i, *s, &dst);
1275 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1280 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1283 q = create_symlink(i->path, path, force, changes, n_changes);
1292 static int install_info_symlink_link(
1295 const char *config_path,
1297 UnitFileChange **changes,
1298 unsigned *n_changes) {
1301 _cleanup_free_ char *path = NULL;
1305 assert(config_path);
1308 r = in_search_path(i->path, paths->unit_path);
1312 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1315 r = create_symlink(i->path, path, force, changes, n_changes);
1319 static int install_info_apply(
1322 const char *config_path,
1324 UnitFileChange **changes,
1325 unsigned *n_changes) {
1331 assert(config_path);
1333 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1335 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1339 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1343 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1350 static int install_context_apply(
1353 const char *config_path,
1354 const char *root_dir,
1356 UnitFileChange **changes,
1357 unsigned *n_changes) {
1364 assert(config_path);
1366 while ((i = hashmap_first(c->will_install))) {
1368 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1372 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1374 q = unit_file_search(c, i, paths, root_dir, false);
1383 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1384 if (r >= 0 && q < 0)
1391 static int install_context_mark_for_removal(
1394 Set **remove_symlinks_to,
1395 const char *config_path,
1396 const char *root_dir) {
1403 assert(config_path);
1405 /* Marks all items for removal */
1407 while ((i = hashmap_first(c->will_install))) {
1409 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1413 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1415 q = unit_file_search(c, i, paths, root_dir, false);
1426 if (unit_name_is_instance(i->name)) {
1430 unit_file = basename(i->path);
1432 if (unit_name_is_instance(unit_file))
1433 /* unit file named as instance exists, thus all symlinks
1434 * pointing to it will be removed */
1435 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1437 /* does not exist, thus we will mark for removal symlinks
1438 * to template unit file */
1439 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1441 /* If i->path is not set, it means that we didn't actually find
1442 * the unit file. But we can still remove symlinks to the
1443 * nonexistent template. */
1444 unit_file = unit_name_template(i->name);
1448 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1452 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1454 if (r >= 0 && q < 0)
1461 int unit_file_enable(
1462 UnitFileScope scope,
1464 const char *root_dir,
1467 UnitFileChange **changes,
1468 unsigned *n_changes) {
1470 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1471 _cleanup_install_context_done_ InstallContext c = {};
1473 _cleanup_free_ char *config_path = NULL;
1477 assert(scope < _UNIT_FILE_SCOPE_MAX);
1479 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1483 r = get_config_path(scope, runtime, root_dir, &config_path);
1487 STRV_FOREACH(i, files) {
1488 r = install_info_add_auto(&c, *i);
1493 /* This will return the number of symlink rules that were
1494 supposed to be created, not the ones actually created. This is
1495 useful to determine whether the passed files had any
1496 installation data at all. */
1498 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1501 int unit_file_disable(
1502 UnitFileScope scope,
1504 const char *root_dir,
1506 UnitFileChange **changes,
1507 unsigned *n_changes) {
1509 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1510 _cleanup_install_context_done_ InstallContext c = {};
1512 _cleanup_free_ char *config_path = NULL;
1513 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1517 assert(scope < _UNIT_FILE_SCOPE_MAX);
1519 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1523 r = get_config_path(scope, runtime, root_dir, &config_path);
1527 STRV_FOREACH(i, files) {
1528 r = install_info_add_auto(&c, *i);
1533 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1535 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1542 int unit_file_reenable(
1543 UnitFileScope scope,
1545 const char *root_dir,
1548 UnitFileChange **changes,
1549 unsigned *n_changes) {
1552 r = unit_file_disable(scope, runtime, root_dir, files,
1553 changes, n_changes);
1557 return unit_file_enable(scope, runtime, root_dir, files, force,
1558 changes, n_changes);
1561 int unit_file_set_default(
1562 UnitFileScope scope,
1563 const char *root_dir,
1566 UnitFileChange **changes,
1567 unsigned *n_changes) {
1569 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1570 _cleanup_install_context_done_ InstallContext c = {};
1571 _cleanup_free_ char *config_path = NULL;
1574 InstallInfo *i = NULL;
1577 assert(scope < _UNIT_FILE_SCOPE_MAX);
1580 if (unit_name_to_type(file) != UNIT_TARGET)
1583 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1587 r = get_config_path(scope, false, root_dir, &config_path);
1591 r = install_info_add_auto(&c, file);
1595 assert_se(i = hashmap_first(c.will_install));
1597 r = unit_file_search(&c, i, &paths, root_dir, false);
1601 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1603 r = create_symlink(i->path, path, force, changes, n_changes);
1610 int unit_file_get_default(
1611 UnitFileScope scope,
1612 const char *root_dir,
1615 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1620 assert(scope < _UNIT_FILE_SCOPE_MAX);
1623 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1627 STRV_FOREACH(p, paths.unit_path) {
1628 _cleanup_free_ char *path = NULL, *tmp = NULL;
1631 if (isempty(root_dir))
1632 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1634 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1639 r = readlink_malloc(path, &tmp);
1642 else if (r == -EINVAL)
1644 n = strdup(SPECIAL_DEFAULT_TARGET);
1648 n = strdup(basename(tmp));
1660 UnitFileState unit_file_get_state(
1661 UnitFileScope scope,
1662 const char *root_dir,
1665 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1666 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1668 _cleanup_free_ char *path = NULL;
1672 assert(scope < _UNIT_FILE_SCOPE_MAX);
1675 if (root_dir && scope != UNIT_FILE_SYSTEM)
1678 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1681 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1685 STRV_FOREACH(i, paths.unit_path) {
1693 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1695 asprintf(&path, "%s/%s", *i, name);
1700 partial = path + strlen(root_dir) + 1;
1705 * Search for a unit file in our default paths, to
1706 * be sure, that there are no broken symlinks.
1708 if (lstat(path, &st) < 0) {
1710 if (errno != ENOENT)
1713 if (!unit_name_is_instance(name))
1716 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1719 r = null_or_empty_path(path);
1720 if (r < 0 && r != -ENOENT)
1723 state = path_startswith(*i, "/run") ?
1724 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1729 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1735 r = unit_file_can_install(&paths, root_dir, partial, true);
1736 if (r < 0 && errno != ENOENT)
1739 return UNIT_FILE_DISABLED;
1741 return UNIT_FILE_STATIC;
1744 return r < 0 ? r : state;
1747 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1748 _cleanup_strv_free_ char **files = NULL;
1753 assert(scope < _UNIT_FILE_SCOPE_MAX);
1756 if (scope == UNIT_FILE_SYSTEM)
1757 r = conf_files_list(&files, ".preset", NULL,
1758 "/etc/systemd/system-preset",
1759 "/usr/local/lib/systemd/system-preset",
1760 "/usr/lib/systemd/system-preset",
1761 #ifdef HAVE_SPLIT_USR
1762 "/lib/systemd/system-preset",
1765 else if (scope == UNIT_FILE_GLOBAL)
1766 r = conf_files_list(&files, ".preset", NULL,
1767 "/etc/systemd/user-preset",
1768 "/usr/local/lib/systemd/user-preset",
1769 "/usr/lib/systemd/user-preset",
1777 STRV_FOREACH(i, files) {
1778 _cleanup_fclose_ FILE *f;
1780 f = fopen(*i, "re");
1782 if (errno == ENOENT)
1789 char line[LINE_MAX], *l;
1791 if (!fgets(line, sizeof(line), f))
1798 if (strchr(COMMENTS "\n", *l))
1801 if (first_word(l, "enable")) {
1803 l += strspn(l, WHITESPACE);
1805 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1808 } else if (first_word(l, "disable")) {
1810 l += strspn(l, WHITESPACE);
1812 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1816 log_debug("Couldn't parse line '%s'", l);
1820 /* Default is "enable" */
1824 int unit_file_preset(
1825 UnitFileScope scope,
1827 const char *root_dir,
1830 UnitFileChange **changes,
1831 unsigned *n_changes) {
1833 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1834 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1836 _cleanup_free_ char *config_path = NULL;
1837 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1841 assert(scope < _UNIT_FILE_SCOPE_MAX);
1843 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1847 r = get_config_path(scope, runtime, root_dir, &config_path);
1851 STRV_FOREACH(i, files) {
1853 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1856 r = unit_file_query_preset(scope, *i);
1861 r = install_info_add_auto(&plus, *i);
1863 r = install_info_add_auto(&minus, *i);
1869 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1870 config_path, root_dir);
1872 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1873 changes, n_changes, files);
1877 /* Returns number of symlinks that where supposed to be installed. */
1878 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1879 changes, n_changes);
1886 static void unitfilelist_free(UnitFileList **f) {
1893 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1895 int unit_file_get_list(
1896 UnitFileScope scope,
1897 const char *root_dir,
1900 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1902 _cleanup_free_ char *buf = NULL;
1903 _cleanup_closedir_ DIR *d = NULL;
1907 assert(scope < _UNIT_FILE_SCOPE_MAX);
1910 if (root_dir && scope != UNIT_FILE_SYSTEM)
1913 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1917 STRV_FOREACH(i, paths.unit_path) {
1918 const char *units_dir;
1924 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1934 d = opendir(units_dir);
1936 if (errno == ENOENT)
1944 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1948 if (!de && errno != 0)
1954 if (ignore_file(de->d_name))
1957 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1960 if (hashmap_get(h, de->d_name))
1963 r = dirent_ensure_type(d, de);
1971 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1974 f = new0(UnitFileList, 1);
1978 f->path = path_make_absolute(de->d_name, units_dir);
1982 r = null_or_empty_path(f->path);
1983 if (r < 0 && r != -ENOENT)
1987 path_startswith(*i, "/run") ?
1988 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1992 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1996 f->state = UNIT_FILE_ENABLED;
2000 r = unit_file_can_install(&paths, root_dir, f->path, true);
2001 if (r == -EINVAL || /* Invalid setting? */
2002 r == -EBADMSG || /* Invalid format? */
2003 r == -ENOENT /* Included file not found? */)
2004 f->state = UNIT_FILE_INVALID;
2008 f->state = UNIT_FILE_DISABLED;
2010 f->state = UNIT_FILE_STATIC;
2013 r = hashmap_put(h, basename(f->path), f);
2016 f = NULL; /* prevent cleanup */
2023 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2024 [UNIT_FILE_ENABLED] = "enabled",
2025 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2026 [UNIT_FILE_LINKED] = "linked",
2027 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2028 [UNIT_FILE_MASKED] = "masked",
2029 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2030 [UNIT_FILE_STATIC] = "static",
2031 [UNIT_FILE_DISABLED] = "disabled",
2032 [UNIT_FILE_INVALID] = "invalid",
2035 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2037 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2038 [UNIT_FILE_SYMLINK] = "symlink",
2039 [UNIT_FILE_UNLINK] = "unlink",
2042 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);