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));
294 if (unlink(p) < 0 && errno != ENOENT) {
301 rmdir_parents(p, config_path);
303 path_kill_slashes(p);
305 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
307 if (!set_get(remove_symlinks_to, p)) {
309 q = mark_symlink_for_removal(&remove_symlinks_to, p);
322 static int remove_marked_symlinks(
323 Set *remove_symlinks_to,
324 const char *config_path,
325 UnitFileChange **changes,
327 char** instance_whitelist) {
329 _cleanup_close_ int fd = -1;
335 if (set_size(remove_symlinks_to) <= 0)
338 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
346 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
352 /* This takes possession of cfd and closes it */
353 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
361 static int find_symlinks_fd(
365 const char *config_path,
366 bool *same_name_link) {
369 _cleanup_closedir_ DIR *d = NULL;
375 assert(same_name_link);
388 if (!de && errno != 0)
394 if (ignore_file(de->d_name))
397 dirent_ensure_type(d, de);
399 if (de->d_type == DT_DIR) {
401 _cleanup_free_ char *p = NULL;
403 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
413 p = path_make_absolute(de->d_name, path);
419 /* This will close nfd, regardless whether it succeeds or not */
420 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
426 } else if (de->d_type == DT_LNK) {
427 _cleanup_free_ char *p = NULL, *dest = NULL;
428 bool found_path, found_dest, b = false;
431 /* Acquire symlink name */
432 p = path_make_absolute(de->d_name, path);
436 /* Acquire symlink destination */
437 q = readlink_and_canonicalize(p, &dest);
447 /* Check if the symlink itself matches what we
449 if (path_is_absolute(name))
450 found_path = path_equal(p, name);
452 found_path = streq(de->d_name, name);
454 /* Check if what the symlink points to
455 * matches what we are looking for */
456 if (path_is_absolute(name))
457 found_dest = path_equal(dest, name);
459 found_dest = streq(basename(dest), name);
461 if (found_path && found_dest) {
462 _cleanup_free_ char *t = NULL;
464 /* Filter out same name links in the main
466 t = path_make_absolute(name, config_path);
470 b = path_equal(t, p);
474 *same_name_link = true;
475 else if (found_path || found_dest)
481 static int find_symlinks(
483 const char *config_path,
484 bool *same_name_link) {
490 assert(same_name_link);
492 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
499 /* This takes possession of fd and closes it */
500 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
503 static int find_symlinks_in_scope(
505 const char *root_dir,
507 UnitFileState *state) {
510 _cleanup_free_ char *path2 = NULL;
511 bool same_name_link_runtime = false, same_name_link = false;
514 assert(scope < _UNIT_FILE_SCOPE_MAX);
517 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
518 _cleanup_free_ char *path = NULL;
520 /* First look in runtime config path */
521 r = get_config_path(scope, true, root_dir, &path);
525 r = find_symlinks(name, path, &same_name_link_runtime);
529 *state = UNIT_FILE_ENABLED_RUNTIME;
534 /* Then look in the normal config path */
535 r = get_config_path(scope, false, root_dir, &path2);
539 r = find_symlinks(name, path2, &same_name_link);
543 *state = UNIT_FILE_ENABLED;
547 /* Hmm, we didn't find it, but maybe we found the same name
549 if (same_name_link_runtime) {
550 *state = UNIT_FILE_LINKED_RUNTIME;
552 } else if (same_name_link) {
553 *state = UNIT_FILE_LINKED;
563 const char *root_dir,
566 UnitFileChange **changes,
567 unsigned *n_changes) {
570 _cleanup_free_ char *prefix = NULL;
574 assert(scope < _UNIT_FILE_SCOPE_MAX);
576 r = get_config_path(scope, runtime, root_dir, &prefix);
580 STRV_FOREACH(i, files) {
581 _cleanup_free_ char *path = NULL;
583 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
589 path = path_make_absolute(*i, prefix);
595 if (symlink("/dev/null", path) >= 0) {
596 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
600 if (errno == EEXIST) {
602 if (null_or_empty_path(path) > 0)
608 if (symlink("/dev/null", path) >= 0) {
610 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
611 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
628 int unit_file_unmask(
631 const char *root_dir,
633 UnitFileChange **changes,
634 unsigned *n_changes) {
636 char **i, *config_path = NULL;
638 Set *remove_symlinks_to = NULL;
641 assert(scope < _UNIT_FILE_SCOPE_MAX);
643 r = get_config_path(scope, runtime, root_dir, &config_path);
647 STRV_FOREACH(i, files) {
650 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
656 path = path_make_absolute(*i, config_path);
662 q = null_or_empty_path(path);
664 if (unlink(path) >= 0) {
665 mark_symlink_for_removal(&remove_symlinks_to, path);
666 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
675 if (q != -ENOENT && r == 0)
683 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
687 set_free_free(remove_symlinks_to);
696 const char *root_dir,
699 UnitFileChange **changes,
700 unsigned *n_changes) {
702 _cleanup_lookup_paths_free_ LookupPaths paths = {};
704 _cleanup_free_ char *config_path = NULL;
708 assert(scope < _UNIT_FILE_SCOPE_MAX);
710 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
714 r = get_config_path(scope, runtime, root_dir, &config_path);
718 STRV_FOREACH(i, files) {
719 _cleanup_free_ char *path = NULL;
725 if (!path_is_absolute(*i) ||
726 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
732 if (lstat(*i, &st) < 0) {
738 if (!S_ISREG(st.st_mode)) {
743 q = in_search_path(*i, paths.unit_path);
750 path = path_make_absolute(fn, config_path);
754 if (symlink(*i, path) >= 0) {
755 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
759 if (errno == EEXIST) {
760 _cleanup_free_ char *dest = NULL;
762 q = readlink_and_make_absolute(path, &dest);
763 if (q < 0 && errno != ENOENT) {
769 if (q >= 0 && path_equal(dest, *i))
775 if (symlink(*i, path) >= 0) {
777 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
778 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
795 void unit_file_list_free(Hashmap *h) {
798 while ((i = hashmap_steal_first(h))) {
806 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
809 assert(changes || n_changes == 0);
814 for (i = 0; i < n_changes; i++) {
815 free(changes[i].path);
816 free(changes[i].source);
822 static void install_info_free(InstallInfo *i) {
827 strv_free(i->aliases);
828 strv_free(i->wanted_by);
829 strv_free(i->required_by);
833 static void install_info_hashmap_free(Hashmap *m) {
839 while ((i = hashmap_steal_first(m)))
840 install_info_free(i);
845 static void install_context_done(InstallContext *c) {
848 install_info_hashmap_free(c->will_install);
849 install_info_hashmap_free(c->have_installed);
851 c->will_install = c->have_installed = NULL;
854 static int install_info_add(
858 InstallInfo *i = NULL;
862 assert(name || path);
865 name = basename(path);
867 if (!unit_name_is_valid(name, TEMPLATE_VALID))
870 if (hashmap_get(c->have_installed, name) ||
871 hashmap_get(c->will_install, name))
874 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
878 i = new0(InstallInfo, 1);
882 i->name = strdup(name);
889 i->path = strdup(path);
896 r = hashmap_put(c->will_install, i->name, i);
904 install_info_free(i);
909 static int install_info_add_auto(
911 const char *name_or_path) {
914 assert(name_or_path);
916 if (path_is_absolute(name_or_path))
917 return install_info_add(c, NULL, name_or_path);
919 return install_info_add(c, name_or_path, NULL);
922 static int config_parse_also(const char *unit,
923 const char *filename,
926 unsigned section_line,
936 InstallContext *c = data;
942 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
943 _cleanup_free_ char *n;
950 r = install_info_add(c, n, NULL);
958 static int config_parse_user(const char *unit,
959 const char *filename,
962 unsigned section_line,
969 InstallInfo *i = data;
977 r = install_full_printf(i, rvalue, &printed);
987 static int unit_file_load(
991 bool allow_symlink) {
993 const ConfigTableItem items[] = {
994 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
995 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
996 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
997 { "Install", "Also", config_parse_also, 0, c },
998 { "Exec", "User", config_parse_user, 0, info },
999 { NULL, NULL, NULL, 0, NULL }
1003 _cleanup_fclose_ FILE *f = NULL;
1010 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1014 f = fdopen(fd, "re");
1020 r = config_parse(NULL, path, f, NULL,
1021 config_item_table_lookup, (void*) items, true, true, info);
1026 (int) strv_length(info->aliases) +
1027 (int) strv_length(info->wanted_by) +
1028 (int) strv_length(info->required_by);
1031 static int unit_file_search(
1035 const char *root_dir,
1036 bool allow_symlink) {
1046 char *full_path = NULL;
1048 if (!isempty(root_dir))
1049 full_path = strappenda(root_dir, info->path);
1051 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1056 STRV_FOREACH(p, paths->unit_path) {
1057 _cleanup_free_ char *path = NULL, *full_path = NULL;
1059 path = strjoin(*p, "/", info->name, NULL);
1063 if (!isempty(root_dir)) {
1064 full_path = strappend(root_dir, path);
1069 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1073 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1074 /* Unit file doesn't exist, however instance enablement was requested.
1075 * We will check if it is possible to load template unit file. */
1076 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1078 template = unit_name_template(info->name);
1082 /* We will reuse path variable since we don't need it anymore. */
1083 template_dir = path;
1084 *(strrchr(template_dir, '/') + 1) = '\0';
1086 path = strappend(template_dir, template);
1090 if (!isempty(root_dir)) {
1092 full_path = strappend(root_dir, path);
1097 /* Let's try to load template unit. */
1098 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
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 (int) strv_length(i->aliases) +
1136 (int) strv_length(i->wanted_by) +
1137 (int) 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))
1175 r = unlink(new_path);
1176 if (r < 0 && errno != ENOENT)
1179 if (symlink(old_path, new_path) >= 0) {
1180 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1181 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1188 static int install_info_symlink_alias(
1190 const char *config_path,
1192 UnitFileChange **changes,
1193 unsigned *n_changes) {
1199 assert(config_path);
1201 STRV_FOREACH(s, i->aliases) {
1202 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1204 q = install_full_printf(i, *s, &dst);
1208 alias_path = path_make_absolute(dst, config_path);
1212 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1220 static int install_info_symlink_wants(
1222 const char *config_path,
1224 UnitFileChange **changes,
1225 unsigned *n_changes) {
1231 assert(config_path);
1233 STRV_FOREACH(s, i->wanted_by) {
1234 _cleanup_free_ char *path = NULL, *dst = NULL;
1236 q = install_full_printf(i, *s, &dst);
1240 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1245 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1248 q = create_symlink(i->path, path, force, changes, n_changes);
1257 static int install_info_symlink_requires(
1259 const char *config_path,
1261 UnitFileChange **changes,
1262 unsigned *n_changes) {
1268 assert(config_path);
1270 STRV_FOREACH(s, i->required_by) {
1271 _cleanup_free_ char *path = NULL, *dst = NULL;
1273 q = install_full_printf(i, *s, &dst);
1277 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1282 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1285 q = create_symlink(i->path, path, force, changes, n_changes);
1294 static int install_info_symlink_link(
1297 const char *config_path,
1299 UnitFileChange **changes,
1300 unsigned *n_changes) {
1302 _cleanup_free_ char *path = NULL;
1307 assert(config_path);
1310 r = in_search_path(i->path, paths->unit_path);
1314 path = strjoin(config_path, "/", i->name, NULL);
1318 return create_symlink(i->path, path, force, changes, n_changes);
1321 static int install_info_apply(
1324 const char *config_path,
1326 UnitFileChange **changes,
1327 unsigned *n_changes) {
1333 assert(config_path);
1335 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1337 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1341 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1345 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1352 static int install_context_apply(
1355 const char *config_path,
1356 const char *root_dir,
1358 UnitFileChange **changes,
1359 unsigned *n_changes) {
1366 assert(config_path);
1368 while ((i = hashmap_first(c->will_install))) {
1370 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1374 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1376 q = unit_file_search(c, i, paths, root_dir, false);
1385 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1386 if (r >= 0 && q < 0)
1393 static int install_context_mark_for_removal(
1396 Set **remove_symlinks_to,
1397 const char *config_path,
1398 const char *root_dir) {
1405 assert(config_path);
1407 /* Marks all items for removal */
1409 while ((i = hashmap_first(c->will_install))) {
1411 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1415 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1417 q = unit_file_search(c, i, paths, root_dir, false);
1428 if (unit_name_is_instance(i->name)) {
1432 unit_file = basename(i->path);
1434 if (unit_name_is_instance(unit_file))
1435 /* unit file named as instance exists, thus all symlinks
1436 * pointing to it will be removed */
1437 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1439 /* does not exist, thus we will mark for removal symlinks
1440 * to template unit file */
1441 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1443 /* If i->path is not set, it means that we didn't actually find
1444 * the unit file. But we can still remove symlinks to the
1445 * nonexistent template. */
1446 unit_file = unit_name_template(i->name);
1450 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1454 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1456 if (r >= 0 && q < 0)
1463 int unit_file_enable(
1464 UnitFileScope scope,
1466 const char *root_dir,
1469 UnitFileChange **changes,
1470 unsigned *n_changes) {
1472 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1473 _cleanup_install_context_done_ InstallContext c = {};
1475 _cleanup_free_ char *config_path = NULL;
1479 assert(scope < _UNIT_FILE_SCOPE_MAX);
1481 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1485 r = get_config_path(scope, runtime, root_dir, &config_path);
1489 STRV_FOREACH(i, files) {
1490 r = install_info_add_auto(&c, *i);
1495 /* This will return the number of symlink rules that were
1496 supposed to be created, not the ones actually created. This is
1497 useful to determine whether the passed files had any
1498 installation data at all. */
1500 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1503 int unit_file_disable(
1504 UnitFileScope scope,
1506 const char *root_dir,
1508 UnitFileChange **changes,
1509 unsigned *n_changes) {
1511 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1512 _cleanup_install_context_done_ InstallContext c = {};
1514 _cleanup_free_ char *config_path = NULL;
1515 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1519 assert(scope < _UNIT_FILE_SCOPE_MAX);
1521 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1525 r = get_config_path(scope, runtime, root_dir, &config_path);
1529 STRV_FOREACH(i, files) {
1530 r = install_info_add_auto(&c, *i);
1535 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1537 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1544 int unit_file_reenable(
1545 UnitFileScope scope,
1547 const char *root_dir,
1550 UnitFileChange **changes,
1551 unsigned *n_changes) {
1554 r = unit_file_disable(scope, runtime, root_dir, files,
1555 changes, n_changes);
1559 return unit_file_enable(scope, runtime, root_dir, files, force,
1560 changes, n_changes);
1563 int unit_file_set_default(
1564 UnitFileScope scope,
1565 const char *root_dir,
1568 UnitFileChange **changes,
1569 unsigned *n_changes) {
1571 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1572 _cleanup_install_context_done_ InstallContext c = {};
1573 _cleanup_free_ char *config_path = NULL;
1576 InstallInfo *i = NULL;
1579 assert(scope < _UNIT_FILE_SCOPE_MAX);
1582 if (unit_name_to_type(file) != UNIT_TARGET)
1585 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1589 r = get_config_path(scope, false, root_dir, &config_path);
1593 r = install_info_add_auto(&c, file);
1597 assert_se(i = hashmap_first(c.will_install));
1599 r = unit_file_search(&c, i, &paths, root_dir, false);
1603 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1605 r = create_symlink(i->path, path, force, changes, n_changes);
1612 int unit_file_get_default(
1613 UnitFileScope scope,
1614 const char *root_dir,
1617 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1622 assert(scope < _UNIT_FILE_SCOPE_MAX);
1625 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1629 STRV_FOREACH(p, paths.unit_path) {
1630 _cleanup_free_ char *path = NULL, *tmp = NULL;
1633 if (isempty(root_dir))
1634 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1636 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1641 r = readlink_malloc(path, &tmp);
1644 else if (r == -EINVAL)
1646 n = strdup(SPECIAL_DEFAULT_TARGET);
1650 n = strdup(basename(tmp));
1662 UnitFileState unit_file_get_state(
1663 UnitFileScope scope,
1664 const char *root_dir,
1667 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1668 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1670 _cleanup_free_ char *path = NULL;
1674 assert(scope < _UNIT_FILE_SCOPE_MAX);
1677 if (root_dir && scope != UNIT_FILE_SYSTEM)
1680 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1683 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1687 STRV_FOREACH(i, paths.unit_path) {
1695 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1697 asprintf(&path, "%s/%s", *i, name);
1702 partial = path + strlen(root_dir) + 1;
1707 * Search for a unit file in our default paths, to
1708 * be sure, that there are no broken symlinks.
1710 if (lstat(path, &st) < 0) {
1712 if (errno != ENOENT)
1715 if (!unit_name_is_instance(name))
1718 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1721 r = null_or_empty_path(path);
1722 if (r < 0 && r != -ENOENT)
1725 state = path_startswith(*i, "/run") ?
1726 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1731 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1737 r = unit_file_can_install(&paths, root_dir, partial, true);
1738 if (r < 0 && errno != ENOENT)
1741 return UNIT_FILE_DISABLED;
1743 return UNIT_FILE_STATIC;
1746 return r < 0 ? r : state;
1749 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1750 _cleanup_strv_free_ char **files = NULL;
1755 assert(scope < _UNIT_FILE_SCOPE_MAX);
1758 if (scope == UNIT_FILE_SYSTEM)
1759 r = conf_files_list(&files, ".preset", root_dir,
1760 "/etc/systemd/system-preset",
1761 "/usr/local/lib/systemd/system-preset",
1762 "/usr/lib/systemd/system-preset",
1763 #ifdef HAVE_SPLIT_USR
1764 "/lib/systemd/system-preset",
1767 else if (scope == UNIT_FILE_GLOBAL)
1768 r = conf_files_list(&files, ".preset", root_dir,
1769 "/etc/systemd/user-preset",
1770 "/usr/local/lib/systemd/user-preset",
1771 "/usr/lib/systemd/user-preset",
1779 STRV_FOREACH(i, files) {
1780 _cleanup_free_ char *buf = NULL;
1781 _cleanup_fclose_ FILE *f;
1785 p = buf = strjoin(root_dir, "/", *i, NULL);
1791 if (errno == ENOENT)
1798 char line[LINE_MAX], *l;
1800 if (!fgets(line, sizeof(line), f))
1807 if (strchr(COMMENTS "\n", *l))
1810 if (first_word(l, "enable")) {
1812 l += strspn(l, WHITESPACE);
1814 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1815 log_debug("Preset file says enable %s.", name);
1819 } else if (first_word(l, "disable")) {
1821 l += strspn(l, WHITESPACE);
1823 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1824 log_debug("Preset file says disable %s.", name);
1829 log_debug("Couldn't parse line '%s'", l);
1833 /* Default is "enable" */
1834 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1838 int unit_file_preset(
1839 UnitFileScope scope,
1841 const char *root_dir,
1843 UnitFilePresetMode mode,
1845 UnitFileChange **changes,
1846 unsigned *n_changes) {
1848 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1849 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1850 _cleanup_free_ char *config_path = NULL;
1855 assert(scope < _UNIT_FILE_SCOPE_MAX);
1856 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1858 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1862 r = get_config_path(scope, runtime, root_dir, &config_path);
1866 STRV_FOREACH(i, files) {
1868 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1871 r = unit_file_query_preset(scope, root_dir, *i);
1875 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1876 r = install_info_add_auto(&plus, *i);
1877 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1878 r = install_info_add_auto(&minus, *i);
1887 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1888 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1890 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1892 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1897 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1898 /* Returns number of symlinks that where supposed to be installed. */
1899 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1907 int unit_file_preset_all(
1908 UnitFileScope scope,
1910 const char *root_dir,
1911 UnitFilePresetMode mode,
1913 UnitFileChange **changes,
1914 unsigned *n_changes) {
1916 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1917 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1918 _cleanup_free_ char *config_path = NULL;
1923 assert(scope < _UNIT_FILE_SCOPE_MAX);
1924 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1926 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1930 r = get_config_path(scope, runtime, root_dir, &config_path);
1934 STRV_FOREACH(i, paths.unit_path) {
1935 _cleanup_closedir_ DIR *d = NULL;
1936 _cleanup_free_ char *buf = NULL;
1937 const char *units_dir;
1939 if (!isempty(root_dir)) {
1940 buf = strjoin(root_dir, "/", *i, NULL);
1948 d = opendir(units_dir);
1950 if (errno == ENOENT)
1961 if (!de && errno != 0)
1967 if (ignore_file(de->d_name))
1970 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1973 dirent_ensure_type(d, de);
1975 if (de->d_type != DT_REG)
1978 r = unit_file_query_preset(scope, root_dir, de->d_name);
1982 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1983 r = install_info_add_auto(&plus, de->d_name);
1984 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1985 r = install_info_add_auto(&minus, de->d_name);
1995 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1996 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1998 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2000 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2005 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2006 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2014 static void unitfilelist_free(UnitFileList **f) {
2021 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2023 int unit_file_get_list(
2024 UnitFileScope scope,
2025 const char *root_dir,
2028 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2033 assert(scope < _UNIT_FILE_SCOPE_MAX);
2036 if (root_dir && scope != UNIT_FILE_SYSTEM)
2039 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2043 STRV_FOREACH(i, paths.unit_path) {
2044 _cleanup_closedir_ DIR *d = NULL;
2045 _cleanup_free_ char *buf = NULL;
2046 const char *units_dir;
2048 if (!isempty(root_dir)) {
2049 buf = strjoin(root_dir, "/", *i, NULL);
2057 d = opendir(units_dir);
2059 if (errno == ENOENT)
2066 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2071 if (!de && errno != 0)
2077 if (ignore_file(de->d_name))
2080 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2083 if (hashmap_get(h, de->d_name))
2086 dirent_ensure_type(d, de);
2088 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2091 f = new0(UnitFileList, 1);
2095 f->path = path_make_absolute(de->d_name, units_dir);
2099 r = null_or_empty_path(f->path);
2100 if (r < 0 && r != -ENOENT)
2104 path_startswith(*i, "/run") ?
2105 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2109 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2113 f->state = UNIT_FILE_ENABLED;
2117 r = unit_file_can_install(&paths, root_dir, f->path, true);
2118 if (r == -EINVAL || /* Invalid setting? */
2119 r == -EBADMSG || /* Invalid format? */
2120 r == -ENOENT /* Included file not found? */)
2121 f->state = UNIT_FILE_INVALID;
2125 f->state = UNIT_FILE_DISABLED;
2127 f->state = UNIT_FILE_STATIC;
2130 r = hashmap_put(h, basename(f->path), f);
2133 f = NULL; /* prevent cleanup */
2140 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2141 [UNIT_FILE_ENABLED] = "enabled",
2142 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2143 [UNIT_FILE_LINKED] = "linked",
2144 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2145 [UNIT_FILE_MASKED] = "masked",
2146 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2147 [UNIT_FILE_STATIC] = "static",
2148 [UNIT_FILE_DISABLED] = "disabled",
2149 [UNIT_FILE_INVALID] = "invalid",
2152 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2154 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2155 [UNIT_FILE_SYMLINK] = "symlink",
2156 [UNIT_FILE_UNLINK] = "unlink",
2159 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2161 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2162 [UNIT_FILE_PRESET_FULL] = "full",
2163 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2164 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2167 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);