1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty <of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "path-util.h"
33 #include "path-lookup.h"
35 #include "unit-name.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
44 Hashmap *will_install;
45 Hashmap *have_installed;
48 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
50 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
53 assert(scope < _UNIT_FILE_SCOPE_MAX);
57 return lookup_paths_init(paths,
58 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
59 scope == UNIT_FILE_USER,
63 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
68 assert(scope < _UNIT_FILE_SCOPE_MAX);
73 case UNIT_FILE_SYSTEM:
75 if (root_dir && runtime)
76 asprintf(&p, "%s/run/systemd/system", root_dir);
78 p = strdup("/run/systemd/system");
80 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
82 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
86 case UNIT_FILE_GLOBAL:
92 p = strdup("/run/systemd/user");
94 p = strdup(USER_CONFIG_UNIT_PATH);
99 if (root_dir || runtime)
102 r = user_config_home(&p);
104 return r < 0 ? r : -ENOENT;
109 assert_not_reached("Bad scope");
119 static int add_file_change(
120 UnitFileChange **changes,
122 UnitFileChangeType type,
124 const char *source) {
130 assert(!changes == !n_changes);
135 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
143 c[i].path = strdup(path);
148 c[i].source = strdup(source);
160 static int mark_symlink_for_removal(
161 Set **remove_symlinks_to,
169 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
177 path_kill_slashes(n);
179 r = set_consume(*remove_symlinks_to, n);
181 return r == -EEXIST ? 0 : r;
186 static int remove_marked_symlinks_fd(
187 Set *remove_symlinks_to,
190 const char *config_path,
192 UnitFileChange **changes,
197 _cleanup_closedir_ DIR *d = NULL;
199 assert(remove_symlinks_to);
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, basename(dest));
281 if (unit_name_is_instance(p))
282 found = found && strv_contains(files, basename(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(basename(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;
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 = basename(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,
925 unsigned section_line,
935 InstallContext *c = data;
941 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
942 _cleanup_free_ char *n;
949 r = install_info_add(c, n, NULL);
957 static int config_parse_user(const char *unit,
958 const char *filename,
961 unsigned section_line,
968 InstallInfo *i = data;
976 r = install_full_printf(i, rvalue, &printed);
986 static int unit_file_load(
990 bool allow_symlink) {
992 const ConfigTableItem items[] = {
993 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
994 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
995 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
996 { "Install", "Also", config_parse_also, 0, c },
997 { "Exec", "User", config_parse_user, 0, info },
998 { NULL, NULL, NULL, 0, NULL }
1002 _cleanup_fclose_ FILE *f = NULL;
1009 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1013 f = fdopen(fd, "re");
1015 close_nointr_nofail(fd);
1019 r = config_parse(NULL, path, f, NULL,
1020 config_item_table_lookup, (void*) items, true, true, info);
1025 strv_length(info->aliases) +
1026 strv_length(info->wanted_by) +
1027 strv_length(info->required_by);
1030 static int unit_file_search(
1034 const char *root_dir,
1035 bool allow_symlink) {
1045 return unit_file_load(c, info, info->path, allow_symlink);
1049 STRV_FOREACH(p, paths->unit_path) {
1052 if (isempty(root_dir))
1053 asprintf(&path, "%s/%s", *p, info->name);
1055 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1060 r = unit_file_load(c, info, path, allow_symlink);
1065 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1066 /* Unit file doesn't exist, however instance enablement was requested.
1067 * We will check if it is possible to load template unit file. */
1068 char *template = NULL,
1069 *template_path = NULL,
1070 *template_dir = NULL;
1072 template = unit_name_template(info->name);
1078 /* We will reuse path variable since we don't need it anymore. */
1079 template_dir = path;
1080 *(strrchr(path, '/') + 1) = '\0';
1082 template_path = strjoin(template_dir, template, NULL);
1083 if (!template_path) {
1089 /* Let's try to load template unit. */
1090 r = unit_file_load(c, info, template_path, allow_symlink);
1092 info->path = strdup(template_path);
1096 free(template_path);
1102 free(template_path);
1107 if (r != -ENOENT && r != -ELOOP)
1114 static int unit_file_can_install(
1116 const char *root_dir,
1118 bool allow_symlink) {
1120 _cleanup_install_context_done_ InstallContext c = {};
1127 r = install_info_add_auto(&c, name);
1131 assert_se(i = hashmap_first(c.will_install));
1133 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1137 strv_length(i->aliases) +
1138 strv_length(i->wanted_by) +
1139 strv_length(i->required_by);
1144 static int create_symlink(
1145 const char *old_path,
1146 const char *new_path,
1148 UnitFileChange **changes,
1149 unsigned *n_changes) {
1151 _cleanup_free_ char *dest = NULL;
1157 mkdir_parents_label(new_path, 0755);
1159 if (symlink(old_path, new_path) >= 0) {
1160 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1164 if (errno != EEXIST)
1167 r = readlink_and_make_absolute(new_path, &dest);
1171 if (path_equal(dest, old_path))
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, true)) {
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, true)) {
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) {
1303 _cleanup_free_ char *path = NULL;
1307 assert(config_path);
1310 r = in_search_path(i->path, paths->unit_path);
1314 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1317 r = 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);
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. */
1499 r = 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);
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);
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);
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, true))
1683 r = lookup_paths_init_from_scope(&paths, scope);
1687 STRV_FOREACH(i, paths.unit_path) {
1694 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1696 asprintf(&path, "%s/%s", *i, name);
1702 * Search for a unit file in our default paths, to
1703 * be sure, that there are no broken symlinks.
1705 if (lstat(path, &st) < 0) {
1707 if (errno != ENOENT)
1710 if (!unit_name_is_instance(name))
1713 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1716 r = null_or_empty_path(path);
1717 if (r < 0 && r != -ENOENT)
1720 state = path_startswith(*i, "/run") ?
1721 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1726 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1732 r = unit_file_can_install(&paths, root_dir, path, true);
1733 if (r < 0 && errno != ENOENT)
1736 return UNIT_FILE_DISABLED;
1738 return UNIT_FILE_STATIC;
1741 return r < 0 ? r : state;
1744 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1745 _cleanup_strv_free_ char **files = NULL;
1750 assert(scope < _UNIT_FILE_SCOPE_MAX);
1753 if (scope == UNIT_FILE_SYSTEM)
1754 r = conf_files_list(&files, ".preset", NULL,
1755 "/etc/systemd/system-preset",
1756 "/usr/local/lib/systemd/system-preset",
1757 "/usr/lib/systemd/system-preset",
1758 #ifdef HAVE_SPLIT_USR
1759 "/lib/systemd/system-preset",
1762 else if (scope == UNIT_FILE_GLOBAL)
1763 r = conf_files_list(&files, ".preset", NULL,
1764 "/etc/systemd/user-preset",
1765 "/usr/local/lib/systemd/user-preset",
1766 "/usr/lib/systemd/user-preset",
1774 STRV_FOREACH(i, files) {
1775 _cleanup_fclose_ FILE *f;
1777 f = fopen(*i, "re");
1779 if (errno == ENOENT)
1786 char line[LINE_MAX], *l;
1788 if (!fgets(line, sizeof(line), f))
1795 if (strchr(COMMENTS "\n", *l))
1798 if (first_word(l, "enable")) {
1800 l += strspn(l, WHITESPACE);
1802 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1805 } else if (first_word(l, "disable")) {
1807 l += strspn(l, WHITESPACE);
1809 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1813 log_debug("Couldn't parse line '%s'", l);
1817 /* Default is "enable" */
1821 int unit_file_preset(
1822 UnitFileScope scope,
1824 const char *root_dir,
1827 UnitFileChange **changes,
1828 unsigned *n_changes) {
1830 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1831 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1833 _cleanup_free_ char *config_path = NULL;
1834 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1838 assert(scope < _UNIT_FILE_SCOPE_MAX);
1840 r = lookup_paths_init_from_scope(&paths, scope);
1844 r = get_config_path(scope, runtime, root_dir, &config_path);
1848 STRV_FOREACH(i, files) {
1850 if (!unit_name_is_valid(*i, true))
1853 r = unit_file_query_preset(scope, *i);
1858 r = install_info_add_auto(&plus, *i);
1860 r = install_info_add_auto(&minus, *i);
1866 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1867 config_path, root_dir);
1869 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1870 changes, n_changes, files);
1874 /* Returns number of symlinks that where supposed to be installed. */
1875 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1876 changes, n_changes);
1883 static void unitfilelist_free(UnitFileList **f) {
1890 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1892 int unit_file_get_list(
1893 UnitFileScope scope,
1894 const char *root_dir,
1897 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1899 _cleanup_free_ char *buf = NULL;
1900 _cleanup_closedir_ DIR *d = NULL;
1904 assert(scope < _UNIT_FILE_SCOPE_MAX);
1907 if (root_dir && scope != UNIT_FILE_SYSTEM)
1910 r = lookup_paths_init_from_scope(&paths, scope);
1914 STRV_FOREACH(i, paths.unit_path) {
1915 const char *units_dir;
1921 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1931 d = opendir(units_dir);
1933 if (errno == ENOENT)
1941 union dirent_storage buffer;
1942 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1944 r = readdir_r(d, &buffer.de, &de);
1951 if (ignore_file(de->d_name))
1954 if (!unit_name_is_valid(de->d_name, true))
1957 if (hashmap_get(h, de->d_name))
1960 r = dirent_ensure_type(d, de);
1968 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1971 f = new0(UnitFileList, 1);
1975 f->path = path_make_absolute(de->d_name, units_dir);
1979 r = null_or_empty_path(f->path);
1980 if (r < 0 && r != -ENOENT)
1984 path_startswith(*i, "/run") ?
1985 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1989 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1993 f->state = UNIT_FILE_ENABLED;
1997 r = unit_file_can_install(&paths, root_dir, f->path, true);
1998 if (r == -EINVAL || /* Invalid setting? */
1999 r == -EBADMSG || /* Invalid format? */
2000 r == -ENOENT /* Included file not found? */)
2001 f->state = UNIT_FILE_INVALID;
2005 f->state = UNIT_FILE_DISABLED;
2007 f->state = UNIT_FILE_STATIC;
2010 r = hashmap_put(h, basename(f->path), f);
2013 f = NULL; /* prevent cleanup */
2020 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2021 [UNIT_FILE_ENABLED] = "enabled",
2022 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2023 [UNIT_FILE_LINKED] = "linked",
2024 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2025 [UNIT_FILE_MASKED] = "masked",
2026 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2027 [UNIT_FILE_STATIC] = "static",
2028 [UNIT_FILE_DISABLED] = "disabled",
2029 [UNIT_FILE_INVALID] = "invalid",
2032 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2034 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2035 [UNIT_FILE_SYMLINK] = "symlink",
2036 [UNIT_FILE_UNLINK] = "unlink",
2039 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);