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,
197 char** instance_whitelist) {
199 _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, instance_whitelist);
259 } else if (de->d_type == DT_LNK) {
260 _cleanup_free_ char *p = NULL, *dest = NULL;
264 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
267 if (unit_name_is_instance(de->d_name) &&
268 instance_whitelist &&
269 !strv_contains(instance_whitelist, de->d_name))
272 p = path_make_absolute(de->d_name, path);
276 q = readlink_and_canonicalize(p, &dest);
287 set_get(remove_symlinks_to, dest) ||
288 set_get(remove_symlinks_to, basename(dest));
292 if (unlink(p) < 0 && errno != ENOENT) {
299 rmdir_parents(p, config_path);
301 path_kill_slashes(p);
303 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
305 if (!set_get(remove_symlinks_to, p)) {
307 q = mark_symlink_for_removal(&remove_symlinks_to, p);
321 static int remove_marked_symlinks(
322 Set *remove_symlinks_to,
323 const char *config_path,
324 UnitFileChange **changes,
326 char** instance_whitelist) {
328 _cleanup_close_ int fd = -1;
334 if (set_size(remove_symlinks_to) <= 0)
337 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
345 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
351 /* This takes possession of cfd and closes it */
352 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
360 static int find_symlinks_fd(
364 const char *config_path,
365 bool *same_name_link) {
368 _cleanup_closedir_ DIR *d = NULL;
374 assert(same_name_link);
387 if (!de && errno != 0)
393 if (ignore_file(de->d_name))
396 dirent_ensure_type(d, de);
398 if (de->d_type == DT_DIR) {
400 _cleanup_free_ char *p = NULL;
402 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
412 p = path_make_absolute(de->d_name, path);
418 /* This will close nfd, regardless whether it succeeds or not */
419 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
427 } else if (de->d_type == DT_LNK) {
428 _cleanup_free_ char *p = NULL, *dest = NULL;
429 bool found_path, found_dest, b = false;
432 /* Acquire symlink name */
433 p = path_make_absolute(de->d_name, path);
437 /* Acquire symlink destination */
438 q = readlink_and_canonicalize(p, &dest);
448 /* Check if the symlink itself matches what we
450 if (path_is_absolute(name))
451 found_path = path_equal(p, name);
453 found_path = streq(de->d_name, name);
455 /* Check if what the symlink points to
456 * matches what we are looking for */
457 if (path_is_absolute(name))
458 found_dest = path_equal(dest, name);
460 found_dest = streq(basename(dest), name);
462 if (found_path && found_dest) {
463 _cleanup_free_ char *t = NULL;
465 /* Filter out same name links in the main
467 t = path_make_absolute(name, config_path);
471 b = path_equal(t, p);
475 *same_name_link = true;
476 else if (found_path || found_dest)
482 static int find_symlinks(
484 const char *config_path,
485 bool *same_name_link) {
491 assert(same_name_link);
493 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
500 /* This takes possession of fd and closes it */
501 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
504 static int find_symlinks_in_scope(
506 const char *root_dir,
508 UnitFileState *state) {
511 _cleanup_free_ char *path2 = NULL;
512 bool same_name_link_runtime = false, same_name_link = false;
515 assert(scope < _UNIT_FILE_SCOPE_MAX);
518 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
519 _cleanup_free_ char *path = NULL;
521 /* First look in runtime config path */
522 r = get_config_path(scope, true, root_dir, &path);
526 r = find_symlinks(name, path, &same_name_link_runtime);
530 *state = UNIT_FILE_ENABLED_RUNTIME;
535 /* Then look in the normal config path */
536 r = get_config_path(scope, false, root_dir, &path2);
540 r = find_symlinks(name, path2, &same_name_link);
544 *state = UNIT_FILE_ENABLED;
548 /* Hmm, we didn't find it, but maybe we found the same name
550 if (same_name_link_runtime) {
551 *state = UNIT_FILE_LINKED_RUNTIME;
553 } else if (same_name_link) {
554 *state = UNIT_FILE_LINKED;
564 const char *root_dir,
567 UnitFileChange **changes,
568 unsigned *n_changes) {
571 _cleanup_free_ char *prefix = NULL;
575 assert(scope < _UNIT_FILE_SCOPE_MAX);
577 r = get_config_path(scope, runtime, root_dir, &prefix);
581 STRV_FOREACH(i, files) {
582 _cleanup_free_ char *path = NULL;
584 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
590 path = path_make_absolute(*i, prefix);
596 if (symlink("/dev/null", path) >= 0) {
597 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
602 if (errno == EEXIST) {
604 if (null_or_empty_path(path) > 0)
610 if (symlink("/dev/null", path) >= 0) {
612 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
613 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
630 int unit_file_unmask(
633 const char *root_dir,
635 UnitFileChange **changes,
636 unsigned *n_changes) {
638 char **i, *config_path = NULL;
640 Set *remove_symlinks_to = NULL;
643 assert(scope < _UNIT_FILE_SCOPE_MAX);
645 r = get_config_path(scope, runtime, root_dir, &config_path);
649 STRV_FOREACH(i, files) {
652 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
658 path = path_make_absolute(*i, config_path);
664 q = null_or_empty_path(path);
666 if (unlink(path) >= 0) {
667 mark_symlink_for_removal(&remove_symlinks_to, path);
668 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
677 if (q != -ENOENT && r == 0)
685 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
689 set_free_free(remove_symlinks_to);
698 const char *root_dir,
701 UnitFileChange **changes,
702 unsigned *n_changes) {
704 _cleanup_lookup_paths_free_ LookupPaths paths = {};
706 _cleanup_free_ char *config_path = NULL;
710 assert(scope < _UNIT_FILE_SCOPE_MAX);
712 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
716 r = get_config_path(scope, runtime, root_dir, &config_path);
720 STRV_FOREACH(i, files) {
721 _cleanup_free_ char *path = NULL;
727 if (!path_is_absolute(*i) ||
728 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
734 if (lstat(*i, &st) < 0) {
740 if (!S_ISREG(st.st_mode)) {
745 q = in_search_path(*i, paths.unit_path);
752 path = path_make_absolute(fn, config_path);
756 if (symlink(*i, path) >= 0) {
757 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
761 if (errno == EEXIST) {
762 _cleanup_free_ char *dest = NULL;
764 q = readlink_and_make_absolute(path, &dest);
766 if (q < 0 && errno != ENOENT) {
772 if (q >= 0 && path_equal(dest, *i))
778 if (symlink(*i, path) >= 0) {
780 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
781 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
798 void unit_file_list_free(Hashmap *h) {
801 while ((i = hashmap_steal_first(h))) {
809 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
812 assert(changes || n_changes == 0);
817 for (i = 0; i < n_changes; i++) {
818 free(changes[i].path);
819 free(changes[i].source);
825 static void install_info_free(InstallInfo *i) {
830 strv_free(i->aliases);
831 strv_free(i->wanted_by);
832 strv_free(i->required_by);
836 static void install_info_hashmap_free(Hashmap *m) {
842 while ((i = hashmap_steal_first(m)))
843 install_info_free(i);
848 static void install_context_done(InstallContext *c) {
851 install_info_hashmap_free(c->will_install);
852 install_info_hashmap_free(c->have_installed);
854 c->will_install = c->have_installed = NULL;
857 static int install_info_add(
861 InstallInfo *i = NULL;
865 assert(name || path);
868 name = basename(path);
870 if (!unit_name_is_valid(name, TEMPLATE_VALID))
873 if (hashmap_get(c->have_installed, name) ||
874 hashmap_get(c->will_install, name))
877 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
881 i = new0(InstallInfo, 1);
885 i->name = strdup(name);
892 i->path = strdup(path);
899 r = hashmap_put(c->will_install, i->name, i);
907 install_info_free(i);
912 static int install_info_add_auto(
914 const char *name_or_path) {
917 assert(name_or_path);
919 if (path_is_absolute(name_or_path))
920 return install_info_add(c, NULL, name_or_path);
922 return install_info_add(c, name_or_path, NULL);
925 static int config_parse_also(const char *unit,
926 const char *filename,
929 unsigned section_line,
939 InstallContext *c = data;
945 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
946 _cleanup_free_ char *n;
953 r = install_info_add(c, n, NULL);
961 static int config_parse_user(const char *unit,
962 const char *filename,
965 unsigned section_line,
972 InstallInfo *i = data;
980 r = install_full_printf(i, rvalue, &printed);
990 static int unit_file_load(
994 bool allow_symlink) {
996 const ConfigTableItem items[] = {
997 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
998 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
999 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1000 { "Install", "Also", config_parse_also, 0, c },
1001 { "Exec", "User", config_parse_user, 0, info },
1002 { NULL, NULL, NULL, 0, NULL }
1006 _cleanup_fclose_ FILE *f = NULL;
1013 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1017 f = fdopen(fd, "re");
1023 r = config_parse(NULL, path, f, NULL,
1024 config_item_table_lookup, (void*) items, true, true, info);
1029 (int) strv_length(info->aliases) +
1030 (int) strv_length(info->wanted_by) +
1031 (int) strv_length(info->required_by);
1034 static int unit_file_search(
1038 const char *root_dir,
1039 bool allow_symlink) {
1049 char *full_path = NULL;
1051 if (!isempty(root_dir))
1052 full_path = strappenda(root_dir, info->path);
1054 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1059 STRV_FOREACH(p, paths->unit_path) {
1060 _cleanup_free_ char *path = NULL, *full_path = NULL;
1062 path = strjoin(*p, "/", info->name, NULL);
1066 if (!isempty(root_dir)) {
1067 full_path = strappend(root_dir, path);
1072 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1076 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1077 /* Unit file doesn't exist, however instance enablement was requested.
1078 * We will check if it is possible to load template unit file. */
1079 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1081 template = unit_name_template(info->name);
1085 /* We will reuse path variable since we don't need it anymore. */
1086 template_dir = path;
1087 *(strrchr(template_dir, '/') + 1) = '\0';
1089 path = strappend(template_dir, template);
1093 if (!isempty(root_dir)) {
1095 full_path = strappend(root_dir, path);
1100 /* Let's try to load template unit. */
1101 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1108 if (r != -ENOENT && r != -ELOOP)
1115 static int unit_file_can_install(
1117 const char *root_dir,
1119 bool allow_symlink) {
1121 _cleanup_install_context_done_ InstallContext c = {};
1128 r = install_info_add_auto(&c, name);
1132 assert_se(i = hashmap_first(c.will_install));
1134 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1138 (int) strv_length(i->aliases) +
1139 (int) strv_length(i->wanted_by) +
1140 (int) strv_length(i->required_by);
1145 static int create_symlink(
1146 const char *old_path,
1147 const char *new_path,
1149 UnitFileChange **changes,
1150 unsigned *n_changes) {
1152 _cleanup_free_ char *dest = NULL;
1158 mkdir_parents_label(new_path, 0755);
1160 if (symlink(old_path, new_path) >= 0) {
1161 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1165 if (errno != EEXIST)
1168 r = readlink_and_make_absolute(new_path, &dest);
1172 if (path_equal(dest, old_path))
1178 r = unlink(new_path);
1179 if (r < 0 && errno != ENOENT)
1182 if (symlink(old_path, new_path) >= 0) {
1183 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1184 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1191 static int install_info_symlink_alias(
1193 const char *config_path,
1195 UnitFileChange **changes,
1196 unsigned *n_changes) {
1202 assert(config_path);
1204 STRV_FOREACH(s, i->aliases) {
1205 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1207 q = install_full_printf(i, *s, &dst);
1211 alias_path = path_make_absolute(dst, config_path);
1215 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1223 static int install_info_symlink_wants(
1225 const char *config_path,
1227 UnitFileChange **changes,
1228 unsigned *n_changes) {
1234 assert(config_path);
1236 STRV_FOREACH(s, i->wanted_by) {
1237 _cleanup_free_ char *path = NULL, *dst = NULL;
1239 q = install_full_printf(i, *s, &dst);
1243 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1248 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1251 q = create_symlink(i->path, path, force, changes, n_changes);
1260 static int install_info_symlink_requires(
1262 const char *config_path,
1264 UnitFileChange **changes,
1265 unsigned *n_changes) {
1271 assert(config_path);
1273 STRV_FOREACH(s, i->required_by) {
1274 _cleanup_free_ char *path = NULL, *dst = NULL;
1276 q = install_full_printf(i, *s, &dst);
1280 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1285 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1288 q = create_symlink(i->path, path, force, changes, n_changes);
1297 static int install_info_symlink_link(
1300 const char *config_path,
1302 UnitFileChange **changes,
1303 unsigned *n_changes) {
1306 _cleanup_free_ char *path = NULL;
1310 assert(config_path);
1313 r = in_search_path(i->path, paths->unit_path);
1317 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1320 r = create_symlink(i->path, path, force, changes, n_changes);
1324 static int install_info_apply(
1327 const char *config_path,
1329 UnitFileChange **changes,
1330 unsigned *n_changes) {
1336 assert(config_path);
1338 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1340 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1344 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1348 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1355 static int install_context_apply(
1358 const char *config_path,
1359 const char *root_dir,
1361 UnitFileChange **changes,
1362 unsigned *n_changes) {
1369 assert(config_path);
1371 while ((i = hashmap_first(c->will_install))) {
1373 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1377 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1379 q = unit_file_search(c, i, paths, root_dir, false);
1388 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1389 if (r >= 0 && q < 0)
1396 static int install_context_mark_for_removal(
1399 Set **remove_symlinks_to,
1400 const char *config_path,
1401 const char *root_dir) {
1408 assert(config_path);
1410 /* Marks all items for removal */
1412 while ((i = hashmap_first(c->will_install))) {
1414 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1418 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1420 q = unit_file_search(c, i, paths, root_dir, false);
1431 if (unit_name_is_instance(i->name)) {
1435 unit_file = basename(i->path);
1437 if (unit_name_is_instance(unit_file))
1438 /* unit file named as instance exists, thus all symlinks
1439 * pointing to it will be removed */
1440 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1442 /* does not exist, thus we will mark for removal symlinks
1443 * to template unit file */
1444 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1446 /* If i->path is not set, it means that we didn't actually find
1447 * the unit file. But we can still remove symlinks to the
1448 * nonexistent template. */
1449 unit_file = unit_name_template(i->name);
1453 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1457 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1459 if (r >= 0 && q < 0)
1466 int unit_file_enable(
1467 UnitFileScope scope,
1469 const char *root_dir,
1472 UnitFileChange **changes,
1473 unsigned *n_changes) {
1475 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1476 _cleanup_install_context_done_ InstallContext c = {};
1478 _cleanup_free_ char *config_path = NULL;
1482 assert(scope < _UNIT_FILE_SCOPE_MAX);
1484 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1488 r = get_config_path(scope, runtime, root_dir, &config_path);
1492 STRV_FOREACH(i, files) {
1493 r = install_info_add_auto(&c, *i);
1498 /* This will return the number of symlink rules that were
1499 supposed to be created, not the ones actually created. This is
1500 useful to determine whether the passed files had any
1501 installation data at all. */
1503 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1506 int unit_file_disable(
1507 UnitFileScope scope,
1509 const char *root_dir,
1511 UnitFileChange **changes,
1512 unsigned *n_changes) {
1514 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1515 _cleanup_install_context_done_ InstallContext c = {};
1517 _cleanup_free_ char *config_path = NULL;
1518 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1522 assert(scope < _UNIT_FILE_SCOPE_MAX);
1524 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1528 r = get_config_path(scope, runtime, root_dir, &config_path);
1532 STRV_FOREACH(i, files) {
1533 r = install_info_add_auto(&c, *i);
1538 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1540 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1547 int unit_file_reenable(
1548 UnitFileScope scope,
1550 const char *root_dir,
1553 UnitFileChange **changes,
1554 unsigned *n_changes) {
1557 r = unit_file_disable(scope, runtime, root_dir, files,
1558 changes, n_changes);
1562 return unit_file_enable(scope, runtime, root_dir, files, force,
1563 changes, n_changes);
1566 int unit_file_set_default(
1567 UnitFileScope scope,
1568 const char *root_dir,
1571 UnitFileChange **changes,
1572 unsigned *n_changes) {
1574 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1575 _cleanup_install_context_done_ InstallContext c = {};
1576 _cleanup_free_ char *config_path = NULL;
1579 InstallInfo *i = NULL;
1582 assert(scope < _UNIT_FILE_SCOPE_MAX);
1585 if (unit_name_to_type(file) != UNIT_TARGET)
1588 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1592 r = get_config_path(scope, false, root_dir, &config_path);
1596 r = install_info_add_auto(&c, file);
1600 assert_se(i = hashmap_first(c.will_install));
1602 r = unit_file_search(&c, i, &paths, root_dir, false);
1606 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1608 r = create_symlink(i->path, path, force, changes, n_changes);
1615 int unit_file_get_default(
1616 UnitFileScope scope,
1617 const char *root_dir,
1620 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1625 assert(scope < _UNIT_FILE_SCOPE_MAX);
1628 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1632 STRV_FOREACH(p, paths.unit_path) {
1633 _cleanup_free_ char *path = NULL, *tmp = NULL;
1636 if (isempty(root_dir))
1637 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1639 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1644 r = readlink_malloc(path, &tmp);
1647 else if (r == -EINVAL)
1649 n = strdup(SPECIAL_DEFAULT_TARGET);
1653 n = strdup(basename(tmp));
1665 UnitFileState unit_file_get_state(
1666 UnitFileScope scope,
1667 const char *root_dir,
1670 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1671 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1673 _cleanup_free_ char *path = NULL;
1677 assert(scope < _UNIT_FILE_SCOPE_MAX);
1680 if (root_dir && scope != UNIT_FILE_SYSTEM)
1683 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1686 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1690 STRV_FOREACH(i, paths.unit_path) {
1698 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1700 asprintf(&path, "%s/%s", *i, name);
1705 partial = path + strlen(root_dir) + 1;
1710 * Search for a unit file in our default paths, to
1711 * be sure, that there are no broken symlinks.
1713 if (lstat(path, &st) < 0) {
1715 if (errno != ENOENT)
1718 if (!unit_name_is_instance(name))
1721 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1724 r = null_or_empty_path(path);
1725 if (r < 0 && r != -ENOENT)
1728 state = path_startswith(*i, "/run") ?
1729 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1734 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1740 r = unit_file_can_install(&paths, root_dir, partial, true);
1741 if (r < 0 && errno != ENOENT)
1744 return UNIT_FILE_DISABLED;
1746 return UNIT_FILE_STATIC;
1749 return r < 0 ? r : state;
1752 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1753 _cleanup_strv_free_ char **files = NULL;
1758 assert(scope < _UNIT_FILE_SCOPE_MAX);
1761 if (scope == UNIT_FILE_SYSTEM)
1762 r = conf_files_list(&files, ".preset", NULL,
1763 "/etc/systemd/system-preset",
1764 "/usr/local/lib/systemd/system-preset",
1765 "/usr/lib/systemd/system-preset",
1766 #ifdef HAVE_SPLIT_USR
1767 "/lib/systemd/system-preset",
1770 else if (scope == UNIT_FILE_GLOBAL)
1771 r = conf_files_list(&files, ".preset", NULL,
1772 "/etc/systemd/user-preset",
1773 "/usr/local/lib/systemd/user-preset",
1774 "/usr/lib/systemd/user-preset",
1782 STRV_FOREACH(i, files) {
1783 _cleanup_fclose_ FILE *f;
1785 f = fopen(*i, "re");
1787 if (errno == ENOENT)
1794 char line[LINE_MAX], *l;
1796 if (!fgets(line, sizeof(line), f))
1803 if (strchr(COMMENTS "\n", *l))
1806 if (first_word(l, "enable")) {
1808 l += strspn(l, WHITESPACE);
1810 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1813 } else if (first_word(l, "disable")) {
1815 l += strspn(l, WHITESPACE);
1817 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1821 log_debug("Couldn't parse line '%s'", l);
1825 /* Default is "enable" */
1829 int unit_file_preset(
1830 UnitFileScope scope,
1832 const char *root_dir,
1834 UnitFilePresetMode mode,
1836 UnitFileChange **changes,
1837 unsigned *n_changes) {
1839 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1840 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1841 _cleanup_free_ char *config_path = NULL;
1846 assert(scope < _UNIT_FILE_SCOPE_MAX);
1847 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1849 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1853 r = get_config_path(scope, runtime, root_dir, &config_path);
1857 STRV_FOREACH(i, files) {
1859 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1862 r = unit_file_query_preset(scope, *i);
1866 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1867 r = install_info_add_auto(&plus, *i);
1868 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1869 r = install_info_add_auto(&minus, *i);
1878 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1879 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1881 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1883 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1888 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1889 /* Returns number of symlinks that where supposed to be installed. */
1890 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1898 int unit_file_preset_all(
1899 UnitFileScope scope,
1901 const char *root_dir,
1902 UnitFilePresetMode mode,
1904 UnitFileChange **changes,
1905 unsigned *n_changes) {
1907 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1908 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1909 _cleanup_free_ char *config_path = NULL;
1914 assert(scope < _UNIT_FILE_SCOPE_MAX);
1915 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1917 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1921 r = get_config_path(scope, runtime, root_dir, &config_path);
1925 STRV_FOREACH(i, paths.unit_path) {
1926 _cleanup_closedir_ DIR *d = NULL;
1927 _cleanup_free_ char *buf = NULL;
1928 const char *units_dir;
1930 if (!isempty(root_dir)) {
1931 buf = strjoin(root_dir, "/", *i, NULL);
1939 d = opendir(units_dir);
1941 if (errno == ENOENT)
1952 if (!de && errno != 0)
1958 if (ignore_file(de->d_name))
1961 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1964 dirent_ensure_type(d, de);
1966 if (de->d_type != DT_REG)
1969 r = unit_file_query_preset(scope, de->d_name);
1973 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1974 r = install_info_add_auto(&plus, de->d_name);
1975 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1976 r = install_info_add_auto(&minus, de->d_name);
1986 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1987 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1989 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1991 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
1996 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1997 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2005 static void unitfilelist_free(UnitFileList **f) {
2012 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2014 int unit_file_get_list(
2015 UnitFileScope scope,
2016 const char *root_dir,
2019 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2024 assert(scope < _UNIT_FILE_SCOPE_MAX);
2027 if (root_dir && scope != UNIT_FILE_SYSTEM)
2030 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2034 STRV_FOREACH(i, paths.unit_path) {
2035 _cleanup_closedir_ DIR *d = NULL;
2036 _cleanup_free_ char *buf = NULL;
2037 const char *units_dir;
2039 if (!isempty(root_dir)) {
2040 buf = strjoin(root_dir, "/", *i, NULL);
2048 d = opendir(units_dir);
2050 if (errno == ENOENT)
2057 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2062 if (!de && errno != 0)
2068 if (ignore_file(de->d_name))
2071 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2074 if (hashmap_get(h, de->d_name))
2077 dirent_ensure_type(d, de);
2079 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2082 f = new0(UnitFileList, 1);
2086 f->path = path_make_absolute(de->d_name, units_dir);
2090 r = null_or_empty_path(f->path);
2091 if (r < 0 && r != -ENOENT)
2095 path_startswith(*i, "/run") ?
2096 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2100 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2104 f->state = UNIT_FILE_ENABLED;
2108 r = unit_file_can_install(&paths, root_dir, f->path, true);
2109 if (r == -EINVAL || /* Invalid setting? */
2110 r == -EBADMSG || /* Invalid format? */
2111 r == -ENOENT /* Included file not found? */)
2112 f->state = UNIT_FILE_INVALID;
2116 f->state = UNIT_FILE_DISABLED;
2118 f->state = UNIT_FILE_STATIC;
2121 r = hashmap_put(h, basename(f->path), f);
2124 f = NULL; /* prevent cleanup */
2131 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2132 [UNIT_FILE_ENABLED] = "enabled",
2133 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2134 [UNIT_FILE_LINKED] = "linked",
2135 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2136 [UNIT_FILE_MASKED] = "masked",
2137 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2138 [UNIT_FILE_STATIC] = "static",
2139 [UNIT_FILE_DISABLED] = "disabled",
2140 [UNIT_FILE_INVALID] = "invalid",
2143 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2145 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2146 [UNIT_FILE_SYMLINK] = "symlink",
2147 [UNIT_FILE_UNLINK] = "unlink",
2150 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2152 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2153 [UNIT_FILE_PRESET_FULL] = "full",
2154 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2155 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2158 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);