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"
43 Hashmap *will_install;
44 Hashmap *have_installed;
47 #define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free)
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);
207 close_nointr_nofail(fd);
215 union dirent_storage buf;
218 k = readdir_r(d, &buf.de, &de);
227 if (ignore_file(de->d_name))
230 dirent_ensure_type(d, de);
232 if (de->d_type == DT_DIR) {
234 _cleanup_free_ char *p = NULL;
236 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
246 p = path_make_absolute(de->d_name, path);
248 close_nointr_nofail(nfd);
252 /* This will close nfd, regardless whether it succeeds or not */
253 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
258 } else if (de->d_type == DT_LNK) {
259 _cleanup_free_ char *p = NULL, *dest = NULL;
263 p = path_make_absolute(de->d_name, path);
267 q = readlink_and_canonicalize(p, &dest);
278 set_get(remove_symlinks_to, dest) ||
279 set_get(remove_symlinks_to, path_get_file_name(dest));
281 if (unit_name_is_instance(p))
282 found = found && strv_contains(files, path_get_file_name(p));
286 if (unlink(p) < 0 && errno != ENOENT) {
291 rmdir_parents(p, config_path);
292 path_kill_slashes(p);
294 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
296 if (!set_get(remove_symlinks_to, p)) {
298 q = mark_symlink_for_removal(&remove_symlinks_to, p);
313 static int remove_marked_symlinks(
314 Set *remove_symlinks_to,
315 const char *config_path,
316 UnitFileChange **changes,
325 if (set_size(remove_symlinks_to) <= 0)
328 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
342 /* This takes possession of cfd and closes it */
343 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
348 close_nointr_nofail(fd);
353 static int find_symlinks_fd(
357 const char *config_path,
358 bool *same_name_link) {
361 _cleanup_closedir_ DIR *d = NULL;
367 assert(same_name_link);
371 close_nointr_nofail(fd);
378 union dirent_storage buf;
380 k = readdir_r(d, &buf.de, &de);
387 if (ignore_file(de->d_name))
390 dirent_ensure_type(d, de);
392 if (de->d_type == DT_DIR) {
394 _cleanup_free_ char *p = NULL;
396 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
406 p = path_make_absolute(de->d_name, path);
408 close_nointr_nofail(nfd);
412 /* This will close nfd, regardless whether it succeeds or not */
413 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
421 } else if (de->d_type == DT_LNK) {
422 _cleanup_free_ char *p = NULL, *dest = NULL;
423 bool found_path, found_dest, b = false;
426 /* Acquire symlink name */
427 p = path_make_absolute(de->d_name, path);
431 /* Acquire symlink destination */
432 q = readlink_and_canonicalize(p, &dest);
442 /* Check if the symlink itself matches what we
444 if (path_is_absolute(name))
445 found_path = path_equal(p, name);
447 found_path = streq(de->d_name, name);
449 /* Check if what the symlink points to
450 * matches what we are looking for */
451 if (path_is_absolute(name))
452 found_dest = path_equal(dest, name);
454 found_dest = streq(path_get_file_name(dest), name);
456 if (found_path && found_dest) {
457 _cleanup_free_ char *t = NULL;
459 /* Filter out same name links in the main
461 t = path_make_absolute(name, config_path);
465 b = path_equal(t, p);
469 *same_name_link = true;
470 else if (found_path || found_dest)
478 static int find_symlinks(
480 const char *config_path,
481 bool *same_name_link) {
487 assert(same_name_link);
489 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
496 /* This takes possession of fd and closes it */
497 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
500 static int find_symlinks_in_scope(
502 const char *root_dir,
504 UnitFileState *state) {
507 _cleanup_free_ char *path2 = NULL;
508 bool same_name_link_runtime = false, same_name_link = false;
511 assert(scope < _UNIT_FILE_SCOPE_MAX);
514 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
515 _cleanup_free_ char *path = NULL;
517 /* First look in runtime config path */
518 r = get_config_path(scope, true, root_dir, &path);
522 r = find_symlinks(name, path, &same_name_link_runtime);
526 *state = UNIT_FILE_ENABLED_RUNTIME;
531 /* Then look in the normal config path */
532 r = get_config_path(scope, false, root_dir, &path2);
536 r = find_symlinks(name, path2, &same_name_link);
540 *state = UNIT_FILE_ENABLED;
544 /* Hmm, we didn't find it, but maybe we found the same name
546 if (same_name_link_runtime) {
547 *state = UNIT_FILE_LINKED_RUNTIME;
549 } else if (same_name_link) {
550 *state = UNIT_FILE_LINKED;
560 const char *root_dir,
563 UnitFileChange **changes,
564 unsigned *n_changes) {
567 _cleanup_free_ char *prefix;
571 assert(scope < _UNIT_FILE_SCOPE_MAX);
573 r = get_config_path(scope, runtime, root_dir, &prefix);
577 STRV_FOREACH(i, files) {
578 _cleanup_free_ char *path = NULL;
580 if (!unit_name_is_valid(*i, true)) {
586 path = path_make_absolute(*i, prefix);
592 if (symlink("/dev/null", path) >= 0) {
593 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
598 if (errno == EEXIST) {
600 if (null_or_empty_path(path) > 0)
606 if (symlink("/dev/null", path) >= 0) {
608 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
609 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
626 int unit_file_unmask(
629 const char *root_dir,
631 UnitFileChange **changes,
632 unsigned *n_changes) {
634 char **i, *config_path = NULL;
636 Set *remove_symlinks_to = NULL;
639 assert(scope < _UNIT_FILE_SCOPE_MAX);
641 r = get_config_path(scope, runtime, root_dir, &config_path);
645 STRV_FOREACH(i, files) {
648 if (!unit_name_is_valid(*i, true)) {
654 path = path_make_absolute(*i, config_path);
660 q = null_or_empty_path(path);
662 if (unlink(path) >= 0) {
663 mark_symlink_for_removal(&remove_symlinks_to, path);
664 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
673 if (q != -ENOENT && r == 0)
681 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
685 set_free_free(remove_symlinks_to);
694 const char *root_dir,
697 UnitFileChange **changes,
698 unsigned *n_changes) {
700 _cleanup_lookup_paths_free_ LookupPaths paths = {};
702 _cleanup_free_ char *config_path = NULL;
706 assert(scope < _UNIT_FILE_SCOPE_MAX);
708 r = lookup_paths_init_from_scope(&paths, scope);
712 r = get_config_path(scope, runtime, root_dir, &config_path);
716 STRV_FOREACH(i, files) {
717 _cleanup_free_ char *path = NULL;
721 fn = path_get_file_name(*i);
723 if (!path_is_absolute(*i) ||
724 !unit_name_is_valid(fn, true)) {
730 if (lstat(*i, &st) < 0) {
736 if (!S_ISREG(st.st_mode)) {
741 q = in_search_path(*i, paths.unit_path);
748 path = path_make_absolute(fn, config_path);
752 if (symlink(*i, path) >= 0) {
753 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
757 if (errno == EEXIST) {
758 _cleanup_free_ char *dest = NULL;
760 q = readlink_and_make_absolute(path, &dest);
762 if (q < 0 && errno != ENOENT) {
768 if (q >= 0 && path_equal(dest, *i))
774 if (symlink(*i, path) >= 0) {
776 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
777 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
794 void unit_file_list_free(Hashmap *h) {
797 while ((i = hashmap_steal_first(h))) {
805 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
808 assert(changes || n_changes == 0);
813 for (i = 0; i < n_changes; i++) {
814 free(changes[i].path);
815 free(changes[i].source);
821 static void install_info_free(InstallInfo *i) {
826 strv_free(i->aliases);
827 strv_free(i->wanted_by);
828 strv_free(i->required_by);
832 static void install_info_hashmap_free(Hashmap *m) {
838 while ((i = hashmap_steal_first(m)))
839 install_info_free(i);
844 static void install_context_done(InstallContext *c) {
847 install_info_hashmap_free(c->will_install);
848 install_info_hashmap_free(c->have_installed);
850 c->will_install = c->have_installed = NULL;
853 static int install_info_add(
857 InstallInfo *i = NULL;
861 assert(name || path);
864 name = path_get_file_name(path);
866 if (!unit_name_is_valid(name, true))
869 if (hashmap_get(c->have_installed, name) ||
870 hashmap_get(c->will_install, name))
873 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
877 i = new0(InstallInfo, 1);
881 i->name = strdup(name);
888 i->path = strdup(path);
895 r = hashmap_put(c->will_install, i->name, i);
903 install_info_free(i);
908 static int install_info_add_auto(
910 const char *name_or_path) {
913 assert(name_or_path);
915 if (path_is_absolute(name_or_path))
916 return install_info_add(c, NULL, name_or_path);
918 return install_info_add(c, name_or_path, NULL);
921 static int config_parse_also(const char *unit,
922 const char *filename,
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,
966 InstallInfo *i = data;
974 r = install_full_printf(i, rvalue, &printed);
984 static int unit_file_load(
988 bool allow_symlink) {
990 const ConfigTableItem items[] = {
991 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
992 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
993 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
994 { "Install", "Also", config_parse_also, 0, c },
995 { "Exec", "User", config_parse_user, 0, info },
996 { NULL, NULL, NULL, 0, NULL }
1000 _cleanup_fclose_ FILE *f = NULL;
1007 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1011 f = fdopen(fd, "re");
1013 close_nointr_nofail(fd);
1017 r = config_parse(NULL, path, f, NULL,
1018 config_item_table_lookup, (void*) items, true, true, info);
1023 strv_length(info->aliases) +
1024 strv_length(info->wanted_by) +
1025 strv_length(info->required_by);
1028 static int unit_file_search(
1032 const char *root_dir,
1033 bool allow_symlink) {
1043 return unit_file_load(c, info, info->path, allow_symlink);
1047 STRV_FOREACH(p, paths->unit_path) {
1050 if (isempty(root_dir))
1051 asprintf(&path, "%s/%s", *p, info->name);
1053 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1058 r = unit_file_load(c, info, path, allow_symlink);
1063 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1064 /* Unit file doesn't exist, however instance enablement was requested.
1065 * We will check if it is possible to load template unit file. */
1066 char *template = NULL,
1067 *template_path = NULL,
1068 *template_dir = NULL;
1070 template = unit_name_template(info->name);
1076 /* We will reuse path variable since we don't need it anymore. */
1077 template_dir = path;
1078 *(strrchr(path, '/') + 1) = '\0';
1080 template_path = strjoin(template_dir, template, NULL);
1081 if (!template_path) {
1087 /* Let's try to load template unit. */
1088 r = unit_file_load(c, info, template_path, allow_symlink);
1090 info->path = strdup(template_path);
1094 free(template_path);
1100 free(template_path);
1105 if (r != -ENOENT && r != -ELOOP)
1112 static int unit_file_can_install(
1114 const char *root_dir,
1116 bool allow_symlink) {
1118 _cleanup_install_context_done_ InstallContext c = {};
1125 r = install_info_add_auto(&c, name);
1129 assert_se(i = hashmap_first(c.will_install));
1131 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1135 strv_length(i->aliases) +
1136 strv_length(i->wanted_by) +
1137 strv_length(i->required_by);
1142 static int create_symlink(
1143 const char *old_path,
1144 const char *new_path,
1146 UnitFileChange **changes,
1147 unsigned *n_changes) {
1149 _cleanup_free_ char *dest = NULL;
1155 mkdir_parents_label(new_path, 0755);
1157 if (symlink(old_path, new_path) >= 0) {
1158 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1162 if (errno != EEXIST)
1165 r = readlink_and_make_absolute(new_path, &dest);
1169 if (path_equal(dest, old_path))
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, true)) {
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, true)) {
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 = path_get_file_name(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);
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. */
1497 r = 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);
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,
1565 UnitFileChange **changes,
1566 unsigned *n_changes) {
1568 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1569 _cleanup_install_context_done_ InstallContext c = {};
1570 _cleanup_free_ char *config_path = NULL;
1573 InstallInfo *i = NULL;
1576 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 i = (InstallInfo*)hashmap_first(c.will_install);
1595 r = unit_file_search(&c, i, &paths, root_dir, false);
1599 path = strappenda(config_path, "/default.target");
1600 r = create_symlink(i->path, path, true, changes, n_changes);
1607 int unit_file_get_default(
1608 UnitFileScope scope,
1609 const char *root_dir,
1612 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1616 r = lookup_paths_init_from_scope(&paths, scope);
1620 STRV_FOREACH(p, paths.unit_path) {
1621 _cleanup_free_ char *path = NULL, *tmp = NULL;
1623 if (isempty(root_dir))
1624 path = strappend(*p, "/default.target");
1626 path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1631 r = readlink_malloc(path, &tmp);
1637 *name = strdup(path_get_file_name(tmp));
1647 UnitFileState unit_file_get_state(
1648 UnitFileScope scope,
1649 const char *root_dir,
1652 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1653 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1655 _cleanup_free_ char *path = NULL;
1659 assert(scope < _UNIT_FILE_SCOPE_MAX);
1662 if (root_dir && scope != UNIT_FILE_SYSTEM)
1665 if (!unit_name_is_valid(name, true))
1668 r = lookup_paths_init_from_scope(&paths, scope);
1672 STRV_FOREACH(i, paths.unit_path) {
1679 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1681 asprintf(&path, "%s/%s", *i, name);
1687 * Search for a unit file in our default paths, to
1688 * be sure, that there are no broken symlinks.
1690 if (lstat(path, &st) < 0) {
1692 if (errno != ENOENT)
1695 if (!unit_name_is_instance(name))
1698 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1701 r = null_or_empty_path(path);
1702 if (r < 0 && r != -ENOENT)
1705 state = path_startswith(*i, "/run") ?
1706 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1711 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1717 r = unit_file_can_install(&paths, root_dir, path, true);
1718 if (r < 0 && errno != ENOENT)
1721 return UNIT_FILE_DISABLED;
1723 return UNIT_FILE_STATIC;
1726 return r < 0 ? r : state;
1729 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1730 _cleanup_strv_free_ char **files = NULL;
1735 assert(scope < _UNIT_FILE_SCOPE_MAX);
1738 if (scope == UNIT_FILE_SYSTEM)
1739 r = conf_files_list(&files, ".preset", NULL,
1740 "/etc/systemd/system-preset",
1741 "/usr/local/lib/systemd/system-preset",
1742 "/usr/lib/systemd/system-preset",
1743 #ifdef HAVE_SPLIT_USR
1744 "/lib/systemd/system-preset",
1747 else if (scope == UNIT_FILE_GLOBAL)
1748 r = conf_files_list(&files, ".preset", NULL,
1749 "/etc/systemd/user-preset",
1750 "/usr/local/lib/systemd/user-preset",
1751 "/usr/lib/systemd/user-preset",
1759 STRV_FOREACH(i, files) {
1760 _cleanup_fclose_ FILE *f;
1762 f = fopen(*i, "re");
1764 if (errno == ENOENT)
1771 char line[LINE_MAX], *l;
1773 if (!fgets(line, sizeof(line), f))
1780 if (strchr(COMMENTS "\n", *l))
1783 if (first_word(l, "enable")) {
1785 l += strspn(l, WHITESPACE);
1787 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1790 } else if (first_word(l, "disable")) {
1792 l += strspn(l, WHITESPACE);
1794 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1798 log_debug("Couldn't parse line '%s'", l);
1802 /* Default is "enable" */
1806 int unit_file_preset(
1807 UnitFileScope scope,
1809 const char *root_dir,
1812 UnitFileChange **changes,
1813 unsigned *n_changes) {
1815 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1816 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1818 _cleanup_free_ char *config_path = NULL;
1819 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1823 assert(scope < _UNIT_FILE_SCOPE_MAX);
1825 r = lookup_paths_init_from_scope(&paths, scope);
1829 r = get_config_path(scope, runtime, root_dir, &config_path);
1833 STRV_FOREACH(i, files) {
1835 if (!unit_name_is_valid(*i, true))
1838 r = unit_file_query_preset(scope, *i);
1843 r = install_info_add_auto(&plus, *i);
1845 r = install_info_add_auto(&minus, *i);
1851 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1852 config_path, root_dir);
1854 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1855 changes, n_changes, files);
1859 /* Returns number of symlinks that where supposed to be installed. */
1860 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1861 changes, n_changes);
1868 static void unitfilelist_free(UnitFileList **f) {
1875 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1877 int unit_file_get_list(
1878 UnitFileScope scope,
1879 const char *root_dir,
1882 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1884 _cleanup_free_ char *buf = NULL;
1885 _cleanup_closedir_ DIR *d = NULL;
1889 assert(scope < _UNIT_FILE_SCOPE_MAX);
1892 if (root_dir && scope != UNIT_FILE_SYSTEM)
1895 r = lookup_paths_init_from_scope(&paths, scope);
1899 STRV_FOREACH(i, paths.unit_path) {
1900 const char *units_dir;
1906 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1916 d = opendir(units_dir);
1918 if (errno == ENOENT)
1926 union dirent_storage buffer;
1927 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1929 r = readdir_r(d, &buffer.de, &de);
1936 if (ignore_file(de->d_name))
1939 if (!unit_name_is_valid(de->d_name, true))
1942 if (hashmap_get(h, de->d_name))
1945 r = dirent_ensure_type(d, de);
1953 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1956 f = new0(UnitFileList, 1);
1960 f->path = path_make_absolute(de->d_name, units_dir);
1964 r = null_or_empty_path(f->path);
1965 if (r < 0 && r != -ENOENT)
1969 path_startswith(*i, "/run") ?
1970 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1974 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1978 f->state = UNIT_FILE_ENABLED;
1982 r = unit_file_can_install(&paths, root_dir, f->path, true);
1983 if (r == -EINVAL || /* Invalid setting? */
1984 r == -EBADMSG || /* Invalid format? */
1985 r == -ENOENT /* Included file not found? */)
1986 f->state = UNIT_FILE_INVALID;
1990 f->state = UNIT_FILE_DISABLED;
1992 f->state = UNIT_FILE_STATIC;
1995 r = hashmap_put(h, path_get_file_name(f->path), f);
1998 f = NULL; /* prevent cleanup */
2005 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2006 [UNIT_FILE_ENABLED] = "enabled",
2007 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2008 [UNIT_FILE_LINKED] = "linked",
2009 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2010 [UNIT_FILE_MASKED] = "masked",
2011 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2012 [UNIT_FILE_STATIC] = "static",
2013 [UNIT_FILE_DISABLED] = "disabled",
2014 [UNIT_FILE_INVALID] = "invalid",
2017 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2019 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2020 [UNIT_FILE_SYMLINK] = "symlink",
2021 [UNIT_FILE_UNLINK] = "unlink",
2024 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);