]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
core: add new .slice unit type for partitioning systems
[thirdparty/systemd.git] / src / shared / install.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fnmatch.h>
27
28 #include "util.h"
29 #include "mkdir.h"
30 #include "hashmap.h"
31 #include "set.h"
32 #include "path-util.h"
33 #include "path-lookup.h"
34 #include "strv.h"
35 #include "unit-name.h"
36 #include "install.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
41
42 typedef struct {
43 Hashmap *will_install;
44 Hashmap *have_installed;
45 } InstallContext;
46
47 #define _cleanup_lookup_paths_free_ \
48 __attribute__((cleanup(lookup_paths_free)))
49 #define _cleanup_install_context_done_ \
50 __attribute__((cleanup(install_context_done)))
51
52 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
53 assert(paths);
54 assert(scope >= 0);
55 assert(scope < _UNIT_FILE_SCOPE_MAX);
56
57 zero(*paths);
58
59 return lookup_paths_init(paths,
60 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
61 scope == UNIT_FILE_USER,
62 NULL, NULL, NULL);
63 }
64
65 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
66 char *p = NULL;
67 int r;
68
69 assert(scope >= 0);
70 assert(scope < _UNIT_FILE_SCOPE_MAX);
71 assert(ret);
72
73 switch (scope) {
74
75 case UNIT_FILE_SYSTEM:
76
77 if (root_dir && runtime)
78 asprintf(&p, "%s/run/systemd/system", root_dir);
79 else if (runtime)
80 p = strdup("/run/systemd/system");
81 else if (root_dir)
82 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
83 else
84 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
85
86 break;
87
88 case UNIT_FILE_GLOBAL:
89
90 if (root_dir)
91 return -EINVAL;
92
93 if (runtime)
94 p = strdup("/run/systemd/user");
95 else
96 p = strdup(USER_CONFIG_UNIT_PATH);
97 break;
98
99 case UNIT_FILE_USER:
100
101 if (root_dir || runtime)
102 return -EINVAL;
103
104 r = user_config_home(&p);
105 if (r <= 0)
106 return r < 0 ? r : -ENOENT;
107
108 break;
109
110 default:
111 assert_not_reached("Bad scope");
112 }
113
114 if (!p)
115 return -ENOMEM;
116
117 *ret = p;
118 return 0;
119 }
120
121 static int add_file_change(
122 UnitFileChange **changes,
123 unsigned *n_changes,
124 UnitFileChangeType type,
125 const char *path,
126 const char *source) {
127
128 UnitFileChange *c;
129 unsigned i;
130
131 assert(path);
132 assert(!changes == !n_changes);
133
134 if (!changes)
135 return 0;
136
137 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
138 if (!c)
139 return -ENOMEM;
140
141 *changes = c;
142 i = *n_changes;
143
144 c[i].type = type;
145 c[i].path = strdup(path);
146 if (!c[i].path)
147 return -ENOMEM;
148
149 if (source) {
150 c[i].source = strdup(source);
151 if (!c[i].source) {
152 free(c[i].path);
153 return -ENOMEM;
154 }
155 } else
156 c[i].source = NULL;
157
158 *n_changes = i+1;
159 return 0;
160 }
161
162 static int mark_symlink_for_removal(
163 Set **remove_symlinks_to,
164 const char *p) {
165
166 char *n;
167 int r;
168
169 assert(p);
170
171 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
172 if (r < 0)
173 return r;
174
175 n = strdup(p);
176 if (!n)
177 return -ENOMEM;
178
179 path_kill_slashes(n);
180
181 r = set_consume(*remove_symlinks_to, n);
182 if (r < 0)
183 return r == -EEXIST ? 0 : r;
184
185 return 0;
186 }
187
188 static int remove_marked_symlinks_fd(
189 Set *remove_symlinks_to,
190 int fd,
191 const char *path,
192 const char *config_path,
193 bool *deleted,
194 UnitFileChange **changes,
195 unsigned *n_changes,
196 char** files) {
197
198 int r = 0;
199 _cleanup_closedir_ DIR *d = NULL;
200
201 assert(remove_symlinks_to);
202 assert(fd >= 0);
203 assert(path);
204 assert(config_path);
205 assert(deleted);
206
207 d = fdopendir(fd);
208 if (!d) {
209 close_nointr_nofail(fd);
210 return -errno;
211 }
212
213 rewinddir(d);
214
215 for (;;) {
216 struct dirent *de;
217 union dirent_storage buf;
218 int k;
219
220 k = readdir_r(d, &buf.de, &de);
221 if (k != 0) {
222 r = -errno;
223 break;
224 }
225
226 if (!de)
227 break;
228
229 if (ignore_file(de->d_name))
230 continue;
231
232 dirent_ensure_type(d, de);
233
234 if (de->d_type == DT_DIR) {
235 int nfd, q;
236 _cleanup_free_ char *p = NULL;
237
238 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
239 if (nfd < 0) {
240 if (errno == ENOENT)
241 continue;
242
243 if (r == 0)
244 r = -errno;
245 continue;
246 }
247
248 p = path_make_absolute(de->d_name, path);
249 if (!p) {
250 close_nointr_nofail(nfd);
251 return -ENOMEM;
252 }
253
254 /* This will close nfd, regardless whether it succeeds or not */
255 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
256
257 if (r == 0)
258 r = q;
259
260 } else if (de->d_type == DT_LNK) {
261 _cleanup_free_ char *p = NULL, *dest = NULL;
262 int q;
263 bool found;
264
265 p = path_make_absolute(de->d_name, path);
266 if (!p)
267 return -ENOMEM;
268
269 q = readlink_and_canonicalize(p, &dest);
270 if (q < 0) {
271 if (q == -ENOENT)
272 continue;
273
274 if (r == 0)
275 r = q;
276 continue;
277 }
278
279 found =
280 set_get(remove_symlinks_to, dest) ||
281 set_get(remove_symlinks_to, path_get_file_name(dest));
282
283 if (unit_name_is_instance(p))
284 found = found && strv_contains(files, path_get_file_name(p));
285
286 if (found) {
287
288 if (unlink(p) < 0 && errno != ENOENT) {
289
290 if (r == 0)
291 r = -errno;
292 } else {
293 rmdir_parents(p, config_path);
294 path_kill_slashes(p);
295
296 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
297
298 if (!set_get(remove_symlinks_to, p)) {
299
300 q = mark_symlink_for_removal(&remove_symlinks_to, p);
301 if (q < 0) {
302 if (r == 0)
303 r = q;
304 } else
305 *deleted = true;
306 }
307 }
308 }
309 }
310 }
311
312 return r;
313 }
314
315 static int remove_marked_symlinks(
316 Set *remove_symlinks_to,
317 const char *config_path,
318 UnitFileChange **changes,
319 unsigned *n_changes,
320 char** files) {
321
322 int fd, r = 0;
323 bool deleted;
324
325 assert(config_path);
326
327 if (set_size(remove_symlinks_to) <= 0)
328 return 0;
329
330 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
331 if (fd < 0)
332 return -errno;
333
334 do {
335 int q, cfd;
336 deleted = false;
337
338 cfd = dup(fd);
339 if (cfd < 0) {
340 r = -errno;
341 break;
342 }
343
344 /* This takes possession of cfd and closes it */
345 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
346 if (r == 0)
347 r = q;
348 } while (deleted);
349
350 close_nointr_nofail(fd);
351
352 return r;
353 }
354
355 static int find_symlinks_fd(
356 const char *name,
357 int fd,
358 const char *path,
359 const char *config_path,
360 bool *same_name_link) {
361
362 int r = 0;
363 _cleanup_closedir_ DIR *d = NULL;
364
365 assert(name);
366 assert(fd >= 0);
367 assert(path);
368 assert(config_path);
369 assert(same_name_link);
370
371 d = fdopendir(fd);
372 if (!d) {
373 close_nointr_nofail(fd);
374 return -errno;
375 }
376
377 for (;;) {
378 int k;
379 struct dirent *de;
380 union dirent_storage buf;
381
382 k = readdir_r(d, &buf.de, &de);
383 if (k != 0)
384 return -errno;
385
386 if (!de)
387 return r;
388
389 if (ignore_file(de->d_name))
390 continue;
391
392 dirent_ensure_type(d, de);
393
394 if (de->d_type == DT_DIR) {
395 int nfd, q;
396 _cleanup_free_ char *p = NULL;
397
398 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
399 if (nfd < 0) {
400 if (errno == ENOENT)
401 continue;
402
403 if (r == 0)
404 r = -errno;
405 continue;
406 }
407
408 p = path_make_absolute(de->d_name, path);
409 if (!p) {
410 close_nointr_nofail(nfd);
411 return -ENOMEM;
412 }
413
414 /* This will close nfd, regardless whether it succeeds or not */
415 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
416
417 if (q > 0)
418 return 1;
419
420 if (r == 0)
421 r = q;
422
423 } else if (de->d_type == DT_LNK) {
424 _cleanup_free_ char *p = NULL, *dest = NULL;
425 bool found_path, found_dest, b = false;
426 int q;
427
428 /* Acquire symlink name */
429 p = path_make_absolute(de->d_name, path);
430 if (!p)
431 return -ENOMEM;
432
433 /* Acquire symlink destination */
434 q = readlink_and_canonicalize(p, &dest);
435 if (q < 0) {
436 if (q == -ENOENT)
437 continue;
438
439 if (r == 0)
440 r = q;
441 continue;
442 }
443
444 /* Check if the symlink itself matches what we
445 * are looking for */
446 if (path_is_absolute(name))
447 found_path = path_equal(p, name);
448 else
449 found_path = streq(de->d_name, name);
450
451 /* Check if what the symlink points to
452 * matches what we are looking for */
453 if (path_is_absolute(name))
454 found_dest = path_equal(dest, name);
455 else
456 found_dest = streq(path_get_file_name(dest), name);
457
458 if (found_path && found_dest) {
459 _cleanup_free_ char *t = NULL;
460
461 /* Filter out same name links in the main
462 * config path */
463 t = path_make_absolute(name, config_path);
464 if (!t)
465 return -ENOMEM;
466
467 b = path_equal(t, p);
468 }
469
470 if (b)
471 *same_name_link = true;
472 else if (found_path || found_dest)
473 return 1;
474 }
475 }
476
477 return r;
478 }
479
480 static int find_symlinks(
481 const char *name,
482 const char *config_path,
483 bool *same_name_link) {
484
485 int fd;
486
487 assert(name);
488 assert(config_path);
489 assert(same_name_link);
490
491 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
492 if (fd < 0) {
493 if (errno == ENOENT)
494 return 0;
495 return -errno;
496 }
497
498 /* This takes possession of fd and closes it */
499 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
500 }
501
502 static int find_symlinks_in_scope(
503 UnitFileScope scope,
504 const char *root_dir,
505 const char *name,
506 UnitFileState *state) {
507
508 int r;
509 _cleanup_free_ char *path = NULL;
510 bool same_name_link_runtime = false, same_name_link = false;
511
512 assert(scope >= 0);
513 assert(scope < _UNIT_FILE_SCOPE_MAX);
514 assert(name);
515
516 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
517
518 /* First look in runtime config path */
519 r = get_config_path(scope, true, root_dir, &path);
520 if (r < 0)
521 return r;
522
523 r = find_symlinks(name, path, &same_name_link_runtime);
524 if (r < 0)
525 return r;
526 else if (r > 0) {
527 *state = UNIT_FILE_ENABLED_RUNTIME;
528 return r;
529 }
530 }
531
532 /* Then look in the normal config path */
533 r = get_config_path(scope, false, root_dir, &path);
534 if (r < 0)
535 return r;
536
537 r = find_symlinks(name, path, &same_name_link);
538 if (r < 0)
539 return r;
540 else if (r > 0) {
541 *state = UNIT_FILE_ENABLED;
542 return r;
543 }
544
545 /* Hmm, we didn't find it, but maybe we found the same name
546 * link? */
547 if (same_name_link_runtime) {
548 *state = UNIT_FILE_LINKED_RUNTIME;
549 return 1;
550 } else if (same_name_link) {
551 *state = UNIT_FILE_LINKED;
552 return 1;
553 }
554
555 return 0;
556 }
557
558 int unit_file_mask(
559 UnitFileScope scope,
560 bool runtime,
561 const char *root_dir,
562 char *files[],
563 bool force,
564 UnitFileChange **changes,
565 unsigned *n_changes) {
566
567 char **i;
568 _cleanup_free_ char *prefix;
569 int r;
570
571 assert(scope >= 0);
572 assert(scope < _UNIT_FILE_SCOPE_MAX);
573
574 r = get_config_path(scope, runtime, root_dir, &prefix);
575 if (r < 0)
576 return r;
577
578 STRV_FOREACH(i, files) {
579 _cleanup_free_ char *path = NULL;
580
581 if (!unit_name_is_valid(*i, true)) {
582 if (r == 0)
583 r = -EINVAL;
584 continue;
585 }
586
587 path = path_make_absolute(*i, prefix);
588 if (!path) {
589 r = -ENOMEM;
590 break;
591 }
592
593 if (symlink("/dev/null", path) >= 0) {
594 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
595
596 continue;
597 }
598
599 if (errno == EEXIST) {
600
601 if (null_or_empty_path(path) > 0)
602 continue;
603
604 if (force) {
605 unlink(path);
606
607 if (symlink("/dev/null", path) >= 0) {
608
609 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
610 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
611
612 continue;
613 }
614 }
615
616 if (r == 0)
617 r = -EEXIST;
618 } else {
619 if (r == 0)
620 r = -errno;
621 }
622 }
623
624 return r;
625 }
626
627 int unit_file_unmask(
628 UnitFileScope scope,
629 bool runtime,
630 const char *root_dir,
631 char *files[],
632 UnitFileChange **changes,
633 unsigned *n_changes) {
634
635 char **i, *config_path = NULL;
636 int r, q;
637 Set *remove_symlinks_to = NULL;
638
639 assert(scope >= 0);
640 assert(scope < _UNIT_FILE_SCOPE_MAX);
641
642 r = get_config_path(scope, runtime, root_dir, &config_path);
643 if (r < 0)
644 goto finish;
645
646 STRV_FOREACH(i, files) {
647 char *path;
648
649 if (!unit_name_is_valid(*i, true)) {
650 if (r == 0)
651 r = -EINVAL;
652 continue;
653 }
654
655 path = path_make_absolute(*i, config_path);
656 if (!path) {
657 r = -ENOMEM;
658 break;
659 }
660
661 q = null_or_empty_path(path);
662 if (q > 0) {
663 if (unlink(path) >= 0) {
664 mark_symlink_for_removal(&remove_symlinks_to, path);
665 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
666
667 free(path);
668 continue;
669 }
670
671 q = -errno;
672 }
673
674 if (q != -ENOENT && r == 0)
675 r = q;
676
677 free(path);
678 }
679
680
681 finish:
682 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
683 if (r == 0)
684 r = q;
685
686 set_free_free(remove_symlinks_to);
687 free(config_path);
688
689 return r;
690 }
691
692 int unit_file_link(
693 UnitFileScope scope,
694 bool runtime,
695 const char *root_dir,
696 char *files[],
697 bool force,
698 UnitFileChange **changes,
699 unsigned *n_changes) {
700
701 _cleanup_lookup_paths_free_ LookupPaths paths = {};
702 char **i;
703 _cleanup_free_ char *config_path = NULL;
704 int r, q;
705
706 assert(scope >= 0);
707 assert(scope < _UNIT_FILE_SCOPE_MAX);
708
709 r = lookup_paths_init_from_scope(&paths, scope);
710 if (r < 0)
711 return r;
712
713 r = get_config_path(scope, runtime, root_dir, &config_path);
714 if (r < 0)
715 return r;
716
717 STRV_FOREACH(i, files) {
718 _cleanup_free_ char *path = NULL;
719 char *fn;
720 struct stat st;
721
722 fn = path_get_file_name(*i);
723
724 if (!path_is_absolute(*i) ||
725 !unit_name_is_valid(fn, true)) {
726 if (r == 0)
727 r = -EINVAL;
728 continue;
729 }
730
731 if (lstat(*i, &st) < 0) {
732 if (r == 0)
733 r = -errno;
734 continue;
735 }
736
737 if (!S_ISREG(st.st_mode)) {
738 r = -ENOENT;
739 continue;
740 }
741
742 q = in_search_path(*i, paths.unit_path);
743 if (q < 0)
744 return q;
745
746 if (q > 0)
747 continue;
748
749 path = path_make_absolute(fn, config_path);
750 if (!path)
751 return -ENOMEM;
752
753 if (symlink(*i, path) >= 0) {
754 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
755 continue;
756 }
757
758 if (errno == EEXIST) {
759 _cleanup_free_ char *dest = NULL;
760
761 q = readlink_and_make_absolute(path, &dest);
762
763 if (q < 0 && errno != ENOENT) {
764 if (r == 0)
765 r = q;
766 continue;
767 }
768
769 if (q >= 0 && path_equal(dest, *i))
770 continue;
771
772 if (force) {
773 unlink(path);
774
775 if (symlink(*i, path) >= 0) {
776
777 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
778 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
779
780 continue;
781 }
782 }
783
784 if (r == 0)
785 r = -EEXIST;
786 } else {
787 if (r == 0)
788 r = -errno;
789 }
790 }
791
792 return r;
793 }
794
795 void unit_file_list_free(Hashmap *h) {
796 UnitFileList *i;
797
798 while ((i = hashmap_steal_first(h))) {
799 free(i->path);
800 free(i);
801 }
802
803 hashmap_free(h);
804 }
805
806 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
807 unsigned i;
808
809 assert(changes || n_changes == 0);
810
811 if (!changes)
812 return;
813
814 for (i = 0; i < n_changes; i++) {
815 free(changes[i].path);
816 free(changes[i].source);
817 }
818
819 free(changes);
820 }
821
822 static void install_info_free(InstallInfo *i) {
823 assert(i);
824
825 free(i->name);
826 free(i->path);
827 strv_free(i->aliases);
828 strv_free(i->wanted_by);
829 strv_free(i->required_by);
830 free(i);
831 }
832
833 static void install_info_hashmap_free(Hashmap *m) {
834 InstallInfo *i;
835
836 if (!m)
837 return;
838
839 while ((i = hashmap_steal_first(m)))
840 install_info_free(i);
841
842 hashmap_free(m);
843 }
844
845 static void install_context_done(InstallContext *c) {
846 assert(c);
847
848 install_info_hashmap_free(c->will_install);
849 install_info_hashmap_free(c->have_installed);
850
851 c->will_install = c->have_installed = NULL;
852 }
853
854 static int install_info_add(
855 InstallContext *c,
856 const char *name,
857 const char *path) {
858 InstallInfo *i = NULL;
859 int r;
860
861 assert(c);
862 assert(name || path);
863
864 if (!name)
865 name = path_get_file_name(path);
866
867 if (!unit_name_is_valid(name, true))
868 return -EINVAL;
869
870 if (hashmap_get(c->have_installed, name) ||
871 hashmap_get(c->will_install, name))
872 return 0;
873
874 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
875 if (r < 0)
876 return r;
877
878 i = new0(InstallInfo, 1);
879 if (!i)
880 return -ENOMEM;
881
882 i->name = strdup(name);
883 if (!i->name) {
884 r = -ENOMEM;
885 goto fail;
886 }
887
888 if (path) {
889 i->path = strdup(path);
890 if (!i->path) {
891 r = -ENOMEM;
892 goto fail;
893 }
894 }
895
896 r = hashmap_put(c->will_install, i->name, i);
897 if (r < 0)
898 goto fail;
899
900 return 0;
901
902 fail:
903 if (i)
904 install_info_free(i);
905
906 return r;
907 }
908
909 static int install_info_add_auto(
910 InstallContext *c,
911 const char *name_or_path) {
912
913 assert(c);
914 assert(name_or_path);
915
916 if (path_is_absolute(name_or_path))
917 return install_info_add(c, NULL, name_or_path);
918 else
919 return install_info_add(c, name_or_path, NULL);
920 }
921
922 static int config_parse_also(const char *unit,
923 const char *filename,
924 unsigned line,
925 const char *section,
926 const char *lvalue,
927 int ltype,
928 const char *rvalue,
929 void *data,
930 void *userdata) {
931
932 char *w;
933 size_t l;
934 char *state;
935 InstallContext *c = data;
936
937 assert(filename);
938 assert(lvalue);
939 assert(rvalue);
940
941 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
942 _cleanup_free_ char *n;
943 int r;
944
945 n = strndup(w, l);
946 if (!n)
947 return -ENOMEM;
948
949 r = install_info_add(c, n, NULL);
950 if (r < 0)
951 return r;
952 }
953
954 return 0;
955 }
956
957 static int config_parse_user(const char *unit,
958 const char *filename,
959 unsigned line,
960 const char *section,
961 const char *lvalue,
962 int ltype,
963 const char *rvalue,
964 void *data,
965 void *userdata) {
966
967 InstallInfo *i = data;
968 char* printed;
969
970 assert(filename);
971 assert(lvalue);
972 assert(rvalue);
973
974 printed = install_full_printf(i, rvalue);
975 if (!printed)
976 return -ENOMEM;
977
978 free(i->user);
979 i->user = printed;
980
981 return 0;
982 }
983
984 static int unit_file_load(
985 InstallContext *c,
986 InstallInfo *info,
987 const char *path,
988 bool allow_symlink) {
989
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 }
997 };
998
999 int fd;
1000 _cleanup_fclose_ FILE *f = NULL;
1001 int r;
1002
1003 assert(c);
1004 assert(info);
1005 assert(path);
1006
1007 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1008 if (fd < 0)
1009 return -errno;
1010
1011 f = fdopen(fd, "re");
1012 if (!f) {
1013 close_nointr_nofail(fd);
1014 return -ENOMEM;
1015 }
1016
1017 r = config_parse(NULL, path, f, NULL,
1018 config_item_table_lookup, (void*) items, true, true, info);
1019 if (r < 0)
1020 return r;
1021
1022 return
1023 strv_length(info->aliases) +
1024 strv_length(info->wanted_by) +
1025 strv_length(info->required_by);
1026 }
1027
1028 static int unit_file_search(
1029 InstallContext *c,
1030 InstallInfo *info,
1031 LookupPaths *paths,
1032 const char *root_dir,
1033 bool allow_symlink) {
1034
1035 char **p;
1036 int r;
1037
1038 assert(c);
1039 assert(info);
1040 assert(paths);
1041
1042 if (info->path)
1043 return unit_file_load(c, info, info->path, allow_symlink);
1044
1045 assert(info->name);
1046
1047 STRV_FOREACH(p, paths->unit_path) {
1048 char *path = NULL;
1049
1050 if (isempty(root_dir))
1051 asprintf(&path, "%s/%s", *p, info->name);
1052 else
1053 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1054
1055 if (!path)
1056 return -ENOMEM;
1057
1058 r = unit_file_load(c, info, path, allow_symlink);
1059
1060 if (r >= 0)
1061 info->path = path;
1062 else {
1063 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1064 /* unit file doesn't exist, however instance enablement was request */
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;
1069
1070 template = unit_name_template(info->name);
1071 if (!template) {
1072 free(path);
1073 return -ENOMEM;
1074 }
1075
1076 /* we will reuse path variable since we don't need it anymore */
1077 template_dir = path;
1078 *(strrchr(path, '/') + 1) = '\0';
1079
1080 template_path = strjoin(template_dir, template, NULL);
1081 if (!template_path) {
1082 free(path);
1083 free(template);
1084 return -ENOMEM;
1085 }
1086
1087 /* let's try to load template unit */
1088 r = unit_file_load(c, info, template_path, allow_symlink);
1089 if (r >= 0) {
1090 info->path = strdup(template_path);
1091 if (!info->path) {
1092 free(path);
1093 free(template);
1094 free(template_path);
1095 return -ENOMEM;
1096 }
1097 }
1098
1099 free(template);
1100 free(template_path);
1101 }
1102 free(path);
1103 }
1104
1105 if (r != -ENOENT && r != -ELOOP)
1106 return r;
1107 }
1108
1109 return -ENOENT;
1110 }
1111
1112 static int unit_file_can_install(
1113 LookupPaths *paths,
1114 const char *root_dir,
1115 const char *name,
1116 bool allow_symlink) {
1117
1118 _cleanup_install_context_done_ InstallContext c = {};
1119 InstallInfo *i;
1120 int r;
1121
1122 assert(paths);
1123 assert(name);
1124
1125 r = install_info_add_auto(&c, name);
1126 if (r < 0)
1127 return r;
1128
1129 assert_se(i = hashmap_first(c.will_install));
1130
1131 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1132
1133 if (r >= 0)
1134 r =
1135 strv_length(i->aliases) +
1136 strv_length(i->wanted_by) +
1137 strv_length(i->required_by);
1138
1139 return r;
1140 }
1141
1142 static int create_symlink(
1143 const char *old_path,
1144 const char *new_path,
1145 bool force,
1146 UnitFileChange **changes,
1147 unsigned *n_changes) {
1148
1149 _cleanup_free_ char *dest = NULL;
1150 int r;
1151
1152 assert(old_path);
1153 assert(new_path);
1154
1155 mkdir_parents_label(new_path, 0755);
1156
1157 if (symlink(old_path, new_path) >= 0) {
1158 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1159 return 0;
1160 }
1161
1162 if (errno != EEXIST)
1163 return -errno;
1164
1165 r = readlink_and_make_absolute(new_path, &dest);
1166 if (r < 0)
1167 return r;
1168
1169 if (path_equal(dest, old_path))
1170 return 0;
1171
1172 if (!force)
1173 return -EEXIST;
1174
1175 unlink(new_path);
1176
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);
1180 return 0;
1181 }
1182
1183 return -errno;
1184 }
1185
1186 static int install_info_symlink_alias(
1187 InstallInfo *i,
1188 const char *config_path,
1189 bool force,
1190 UnitFileChange **changes,
1191 unsigned *n_changes) {
1192
1193 char **s;
1194 int r = 0, q;
1195
1196 assert(i);
1197 assert(config_path);
1198
1199 STRV_FOREACH(s, i->aliases) {
1200 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1201
1202 dst = install_full_printf(i, *s);
1203 if (!dst)
1204 return -ENOMEM;
1205
1206 alias_path = path_make_absolute(dst, config_path);
1207 if (!alias_path)
1208 return -ENOMEM;
1209
1210 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1211 if (r == 0)
1212 r = q;
1213 }
1214
1215 return r;
1216 }
1217
1218 static int install_info_symlink_wants(
1219 InstallInfo *i,
1220 const char *config_path,
1221 bool force,
1222 UnitFileChange **changes,
1223 unsigned *n_changes) {
1224
1225 char **s;
1226 int r = 0, q;
1227
1228 assert(i);
1229 assert(config_path);
1230
1231 STRV_FOREACH(s, i->wanted_by) {
1232 _cleanup_free_ char *path = NULL, *dst = NULL;
1233
1234 dst = install_full_printf(i, *s);
1235 if (!dst)
1236 return -ENOMEM;
1237
1238 if (!unit_name_is_valid(dst, true)) {
1239 r = -EINVAL;
1240 continue;
1241 }
1242
1243 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1244 return -ENOMEM;
1245
1246 q = create_symlink(i->path, path, force, changes, n_changes);
1247
1248 if (r == 0)
1249 r = q;
1250 }
1251
1252 return r;
1253 }
1254
1255 static int install_info_symlink_requires(
1256 InstallInfo *i,
1257 const char *config_path,
1258 bool force,
1259 UnitFileChange **changes,
1260 unsigned *n_changes) {
1261
1262 char **s;
1263 int r = 0, q;
1264
1265 assert(i);
1266 assert(config_path);
1267
1268 STRV_FOREACH(s, i->required_by) {
1269 _cleanup_free_ char *path = NULL, *dst = NULL;
1270
1271 dst = install_full_printf(i, *s);
1272 if (!dst)
1273 return -ENOMEM;
1274
1275 if (!unit_name_is_valid(dst, true)) {
1276 r = -EINVAL;
1277 continue;
1278 }
1279
1280 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1281 return -ENOMEM;
1282
1283 q = create_symlink(i->path, path, force, changes, n_changes);
1284
1285 if (r == 0)
1286 r = q;
1287 }
1288
1289 return r;
1290 }
1291
1292 static int install_info_symlink_link(
1293 InstallInfo *i,
1294 LookupPaths *paths,
1295 const char *config_path,
1296 bool force,
1297 UnitFileChange **changes,
1298 unsigned *n_changes) {
1299
1300 int r;
1301 _cleanup_free_ char *path = NULL;
1302
1303 assert(i);
1304 assert(paths);
1305 assert(config_path);
1306 assert(i->path);
1307
1308 r = in_search_path(i->path, paths->unit_path);
1309 if (r != 0)
1310 return r;
1311
1312 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1313 return -ENOMEM;
1314
1315 r = create_symlink(i->path, path, force, changes, n_changes);
1316 return r;
1317 }
1318
1319 static int install_info_apply(
1320 InstallInfo *i,
1321 LookupPaths *paths,
1322 const char *config_path,
1323 bool force,
1324 UnitFileChange **changes,
1325 unsigned *n_changes) {
1326
1327 int r, q;
1328
1329 assert(i);
1330 assert(paths);
1331 assert(config_path);
1332
1333 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1334
1335 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1336 if (r == 0)
1337 r = q;
1338
1339 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1340 if (r == 0)
1341 r = q;
1342
1343 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1344 if (r == 0)
1345 r = q;
1346
1347 return r;
1348 }
1349
1350 static int install_context_apply(
1351 InstallContext *c,
1352 LookupPaths *paths,
1353 const char *config_path,
1354 const char *root_dir,
1355 bool force,
1356 UnitFileChange **changes,
1357 unsigned *n_changes) {
1358
1359 InstallInfo *i;
1360 int r = 0, q;
1361
1362 assert(c);
1363 assert(paths);
1364 assert(config_path);
1365
1366 while ((i = hashmap_first(c->will_install))) {
1367
1368 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1369 if (q < 0)
1370 return q;
1371
1372 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1373
1374 q = unit_file_search(c, i, paths, root_dir, false);
1375 if (q < 0) {
1376 if (r >= 0)
1377 r = q;
1378
1379 return r;
1380 } else if (r >= 0)
1381 r += q;
1382
1383 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1384 if (r >= 0 && q < 0)
1385 r = q;
1386 }
1387
1388 return r;
1389 }
1390
1391 static int install_context_mark_for_removal(
1392 InstallContext *c,
1393 LookupPaths *paths,
1394 Set **remove_symlinks_to,
1395 const char *config_path,
1396 const char *root_dir) {
1397
1398 InstallInfo *i;
1399 int r = 0, q;
1400
1401 assert(c);
1402 assert(paths);
1403 assert(config_path);
1404
1405 /* Marks all items for removal */
1406
1407 while ((i = hashmap_first(c->will_install))) {
1408
1409 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1410 if (q < 0)
1411 return q;
1412
1413 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1414
1415 q = unit_file_search(c, i, paths, root_dir, false);
1416 if (q == -ENOENT) {
1417 /* do nothing */
1418 } else if (q < 0) {
1419 if (r >= 0)
1420 r = q;
1421
1422 return r;
1423 } else if (r >= 0)
1424 r += q;
1425
1426 if (unit_name_is_instance(i->name)) {
1427 char *unit_file = NULL;
1428
1429 unit_file = path_get_file_name(i->path);
1430
1431 if (unit_name_is_instance(unit_file))
1432 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1433 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1434 else
1435 /* does not exist, thus we will mark for removal symlinks to template unit file */
1436 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1437 } else
1438 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1439
1440 if (r >= 0 && q < 0)
1441 r = q;
1442 }
1443
1444 return r;
1445 }
1446
1447 int unit_file_enable(
1448 UnitFileScope scope,
1449 bool runtime,
1450 const char *root_dir,
1451 char *files[],
1452 bool force,
1453 UnitFileChange **changes,
1454 unsigned *n_changes) {
1455
1456 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1457 _cleanup_install_context_done_ InstallContext c = {};
1458 char **i;
1459 _cleanup_free_ char *config_path = NULL;
1460 int r;
1461
1462 assert(scope >= 0);
1463 assert(scope < _UNIT_FILE_SCOPE_MAX);
1464
1465 r = lookup_paths_init_from_scope(&paths, scope);
1466 if (r < 0)
1467 return r;
1468
1469 r = get_config_path(scope, runtime, root_dir, &config_path);
1470 if (r < 0)
1471 return r;
1472
1473 STRV_FOREACH(i, files) {
1474 r = install_info_add_auto(&c, *i);
1475 if (r < 0)
1476 return r;
1477 }
1478
1479 /* This will return the number of symlink rules that were
1480 supposed to be created, not the ones actually created. This is
1481 useful to determine whether the passed files had any
1482 installation data at all. */
1483 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1484 return r;
1485 }
1486
1487 int unit_file_disable(
1488 UnitFileScope scope,
1489 bool runtime,
1490 const char *root_dir,
1491 char *files[],
1492 UnitFileChange **changes,
1493 unsigned *n_changes) {
1494
1495 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1496 _cleanup_install_context_done_ InstallContext c = {};
1497 char **i;
1498 _cleanup_free_ char *config_path = NULL;
1499 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1500 int r, q;
1501
1502 assert(scope >= 0);
1503 assert(scope < _UNIT_FILE_SCOPE_MAX);
1504
1505 r = lookup_paths_init_from_scope(&paths, scope);
1506 if (r < 0)
1507 return r;
1508
1509 r = get_config_path(scope, runtime, root_dir, &config_path);
1510 if (r < 0)
1511 return r;
1512
1513 STRV_FOREACH(i, files) {
1514 r = install_info_add_auto(&c, *i);
1515 if (r < 0)
1516 return r;
1517 }
1518
1519 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1520
1521 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1522 if (r == 0)
1523 r = q;
1524
1525 return r;
1526 }
1527
1528 int unit_file_reenable(
1529 UnitFileScope scope,
1530 bool runtime,
1531 const char *root_dir,
1532 char *files[],
1533 bool force,
1534 UnitFileChange **changes,
1535 unsigned *n_changes) {
1536
1537 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1538 _cleanup_install_context_done_ InstallContext c = {};
1539 char **i;
1540 _cleanup_free_ char *config_path = NULL;
1541 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1542 int r, q;
1543
1544 assert(scope >= 0);
1545 assert(scope < _UNIT_FILE_SCOPE_MAX);
1546
1547 r = lookup_paths_init_from_scope(&paths, scope);
1548 if (r < 0)
1549 return r;
1550
1551 r = get_config_path(scope, runtime, root_dir, &config_path);
1552 if (r < 0)
1553 return r;
1554
1555 STRV_FOREACH(i, files) {
1556 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1557 if (r < 0)
1558 return r;
1559
1560 r = install_info_add_auto(&c, *i);
1561 if (r < 0)
1562 return r;
1563 }
1564
1565 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1566
1567 /* Returns number of symlinks that where supposed to be installed. */
1568 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1569 if (r == 0)
1570 r = q;
1571
1572 return r;
1573 }
1574
1575 int unit_file_set_default(
1576 UnitFileScope scope,
1577 const char *root_dir,
1578 char *file,
1579 UnitFileChange **changes,
1580 unsigned *n_changes) {
1581
1582 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1583 _cleanup_install_context_done_ InstallContext c = {};
1584 _cleanup_free_ char *config_path = NULL;
1585 char *path;
1586 int r;
1587 InstallInfo *i = NULL;
1588
1589 assert(scope >= 0);
1590 assert(scope < _UNIT_FILE_SCOPE_MAX);
1591
1592 if (unit_name_to_type(file) != UNIT_TARGET)
1593 return -EINVAL;
1594
1595 r = lookup_paths_init_from_scope(&paths, scope);
1596 if (r < 0)
1597 return r;
1598
1599 r = get_config_path(scope, false, root_dir, &config_path);
1600 if (r < 0)
1601 return r;
1602
1603 r = install_info_add_auto(&c, file);
1604 if (r < 0)
1605 return r;
1606
1607 i = (InstallInfo*)hashmap_first(c.will_install);
1608
1609 r = unit_file_search(&c, i, &paths, root_dir, false);
1610 if (r < 0)
1611 return r;
1612
1613 path = strappenda(config_path, "/default.target");
1614 r = create_symlink(i->path, path, true, changes, n_changes);
1615 if (r < 0)
1616 return r;
1617
1618 return 0;
1619 }
1620
1621 int unit_file_get_default(
1622 UnitFileScope scope,
1623 const char *root_dir,
1624 char **name) {
1625
1626 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1627 char **p;
1628 int r;
1629
1630 r = lookup_paths_init_from_scope(&paths, scope);
1631 if (r < 0)
1632 return r;
1633
1634 STRV_FOREACH(p, paths.unit_path) {
1635 _cleanup_free_ char *path = NULL, *tmp = NULL;
1636
1637 if (isempty(root_dir))
1638 path = strappend(*p, "/default.target");
1639 else
1640 path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1641
1642 if (!path)
1643 return -ENOMEM;
1644
1645 r = readlink_malloc(path, &tmp);
1646 if (r == -ENOENT)
1647 continue;
1648 else if (r < 0)
1649 return r;
1650
1651 *name = strdup(path_get_file_name(tmp));
1652 if (!*name)
1653 return -ENOMEM;
1654
1655 return 0;
1656 }
1657
1658 return -ENOENT;
1659 }
1660
1661 UnitFileState unit_file_get_state(
1662 UnitFileScope scope,
1663 const char *root_dir,
1664 const char *name) {
1665
1666 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1667 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1668 char **i;
1669 _cleanup_free_ char *path = NULL;
1670 int r;
1671
1672 assert(scope >= 0);
1673 assert(scope < _UNIT_FILE_SCOPE_MAX);
1674 assert(name);
1675
1676 if (root_dir && scope != UNIT_FILE_SYSTEM)
1677 return -EINVAL;
1678
1679 if (!unit_name_is_valid(name, true))
1680 return -EINVAL;
1681
1682 r = lookup_paths_init_from_scope(&paths, scope);
1683 if (r < 0)
1684 return r;
1685
1686 STRV_FOREACH(i, paths.unit_path) {
1687 struct stat st;
1688
1689 free(path);
1690 path = NULL;
1691
1692 if (root_dir)
1693 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1694 else
1695 asprintf(&path, "%s/%s", *i, name);
1696
1697 if (!path)
1698 return -ENOMEM;
1699
1700 /*
1701 * Search for a unit file in our default paths, to
1702 * be sure, that there are no broken symlinks.
1703 */
1704 if (lstat(path, &st) < 0) {
1705 r = -errno;
1706 if (errno != ENOENT)
1707 return r;
1708
1709 if (!unit_name_is_instance(name))
1710 continue;
1711 } else {
1712 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1713 return -ENOENT;
1714
1715 r = null_or_empty_path(path);
1716 if (r < 0 && r != -ENOENT)
1717 return r;
1718 else if (r > 0) {
1719 state = path_startswith(*i, "/run") ?
1720 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1721 return state;
1722 }
1723 }
1724
1725 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1726 if (r < 0)
1727 return r;
1728 else if (r > 0)
1729 return state;
1730
1731 r = unit_file_can_install(&paths, root_dir, path, true);
1732 if (r < 0 && errno != ENOENT)
1733 return r;
1734 else if (r > 0)
1735 return UNIT_FILE_DISABLED;
1736 else if (r == 0)
1737 return UNIT_FILE_STATIC;
1738 }
1739
1740 return r < 0 ? r : state;
1741 }
1742
1743 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1744 _cleanup_strv_free_ char **files = NULL;
1745 char **i;
1746 int r;
1747
1748 assert(scope >= 0);
1749 assert(scope < _UNIT_FILE_SCOPE_MAX);
1750 assert(name);
1751
1752 if (scope == UNIT_FILE_SYSTEM)
1753 r = conf_files_list(&files, ".preset", NULL,
1754 "/etc/systemd/system-preset",
1755 "/usr/local/lib/systemd/system-preset",
1756 "/usr/lib/systemd/system-preset",
1757 #ifdef HAVE_SPLIT_USR
1758 "/lib/systemd/system-preset",
1759 #endif
1760 NULL);
1761 else if (scope == UNIT_FILE_GLOBAL)
1762 r = conf_files_list(&files, ".preset", NULL,
1763 "/etc/systemd/user-preset",
1764 "/usr/local/lib/systemd/user-preset",
1765 "/usr/lib/systemd/user-preset",
1766 NULL);
1767 else
1768 return 1;
1769
1770 if (r < 0)
1771 return r;
1772
1773 STRV_FOREACH(i, files) {
1774 _cleanup_fclose_ FILE *f;
1775
1776 f = fopen(*i, "re");
1777 if (!f) {
1778 if (errno == ENOENT)
1779 continue;
1780
1781 return -errno;
1782 }
1783
1784 for (;;) {
1785 char line[LINE_MAX], *l;
1786
1787 if (!fgets(line, sizeof(line), f))
1788 break;
1789
1790 l = strstrip(line);
1791 if (!*l)
1792 continue;
1793
1794 if (strchr(COMMENTS "\n", *l))
1795 continue;
1796
1797 if (first_word(l, "enable")) {
1798 l += 6;
1799 l += strspn(l, WHITESPACE);
1800
1801 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1802 return 1;
1803
1804 } else if (first_word(l, "disable")) {
1805 l += 7;
1806 l += strspn(l, WHITESPACE);
1807
1808 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1809 return 0;
1810
1811 } else
1812 log_debug("Couldn't parse line '%s'", l);
1813 }
1814 }
1815
1816 /* Default is "enable" */
1817 return 1;
1818 }
1819
1820 int unit_file_preset(
1821 UnitFileScope scope,
1822 bool runtime,
1823 const char *root_dir,
1824 char *files[],
1825 bool force,
1826 UnitFileChange **changes,
1827 unsigned *n_changes) {
1828
1829 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1830 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1831 char **i;
1832 _cleanup_free_ char *config_path = NULL;
1833 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1834 int r, q;
1835
1836 assert(scope >= 0);
1837 assert(scope < _UNIT_FILE_SCOPE_MAX);
1838
1839 r = lookup_paths_init_from_scope(&paths, scope);
1840 if (r < 0)
1841 return r;
1842
1843 r = get_config_path(scope, runtime, root_dir, &config_path);
1844 if (r < 0)
1845 return r;
1846
1847 STRV_FOREACH(i, files) {
1848
1849 if (!unit_name_is_valid(*i, true))
1850 return -EINVAL;
1851
1852 r = unit_file_query_preset(scope, *i);
1853 if (r < 0)
1854 return r;
1855
1856 if (r)
1857 r = install_info_add_auto(&plus, *i);
1858 else
1859 r = install_info_add_auto(&minus, *i);
1860
1861 if (r < 0)
1862 return r;
1863 }
1864
1865 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1866 config_path, root_dir);
1867
1868 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1869 changes, n_changes, files);
1870 if (r == 0)
1871 r = q;
1872
1873 /* Returns number of symlinks that where supposed to be installed. */
1874 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1875 changes, n_changes);
1876 if (r == 0)
1877 r = q;
1878
1879 return r;
1880 }
1881
1882 static void unitfilelist_free(UnitFileList **f) {
1883 if (!*f)
1884 return;
1885
1886 free((*f)->path);
1887 free(*f);
1888 }
1889
1890 int unit_file_get_list(
1891 UnitFileScope scope,
1892 const char *root_dir,
1893 Hashmap *h) {
1894
1895 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1896 char **i;
1897 _cleanup_free_ char *buf = NULL;
1898 _cleanup_closedir_ DIR *d = NULL;
1899 int r;
1900
1901 assert(scope >= 0);
1902 assert(scope < _UNIT_FILE_SCOPE_MAX);
1903 assert(h);
1904
1905 if (root_dir && scope != UNIT_FILE_SYSTEM)
1906 return -EINVAL;
1907
1908 r = lookup_paths_init_from_scope(&paths, scope);
1909 if (r < 0)
1910 return r;
1911
1912 STRV_FOREACH(i, paths.unit_path) {
1913 const char *units_dir;
1914
1915 free(buf);
1916 buf = NULL;
1917
1918 if (root_dir) {
1919 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1920 return -ENOMEM;
1921
1922 units_dir = buf;
1923 } else
1924 units_dir = *i;
1925
1926 if (d)
1927 closedir(d);
1928
1929 d = opendir(units_dir);
1930 if (!d) {
1931 if (errno == ENOENT)
1932 continue;
1933
1934 return -errno;
1935 }
1936
1937 for (;;) {
1938 struct dirent *de;
1939 union dirent_storage buffer;
1940 UnitFileList __attribute__((cleanup(unitfilelist_free)))
1941 *f = NULL;
1942
1943 r = readdir_r(d, &buffer.de, &de);
1944 if (r != 0)
1945 return -r;
1946
1947 if (!de)
1948 break;
1949
1950 if (ignore_file(de->d_name))
1951 continue;
1952
1953 if (!unit_name_is_valid(de->d_name, true))
1954 continue;
1955
1956 if (hashmap_get(h, de->d_name))
1957 continue;
1958
1959 r = dirent_ensure_type(d, de);
1960 if (r < 0) {
1961 if (r == -ENOENT)
1962 continue;
1963
1964 return r;
1965 }
1966
1967 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1968 continue;
1969
1970 f = new0(UnitFileList, 1);
1971 if (!f)
1972 return -ENOMEM;
1973
1974 f->path = path_make_absolute(de->d_name, units_dir);
1975 if (!f->path)
1976 return -ENOMEM;
1977
1978 r = null_or_empty_path(f->path);
1979 if (r < 0 && r != -ENOENT)
1980 return r;
1981 else if (r > 0) {
1982 f->state =
1983 path_startswith(*i, "/run") ?
1984 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1985 goto found;
1986 }
1987
1988 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1989 if (r < 0)
1990 return r;
1991 else if (r > 0) {
1992 f->state = UNIT_FILE_ENABLED;
1993 goto found;
1994 }
1995
1996 r = unit_file_can_install(&paths, root_dir, f->path, true);
1997 if (r == -EINVAL || /* Invalid setting? */
1998 r == -EBADMSG || /* Invalid format? */
1999 r == -ENOENT /* Included file not found? */)
2000 f->state = UNIT_FILE_INVALID;
2001 else if (r < 0)
2002 return r;
2003 else if (r > 0)
2004 f->state = UNIT_FILE_DISABLED;
2005 else
2006 f->state = UNIT_FILE_STATIC;
2007
2008 found:
2009 r = hashmap_put(h, path_get_file_name(f->path), f);
2010 if (r < 0)
2011 return r;
2012 f = NULL; /* prevent cleanup */
2013 }
2014 }
2015
2016 return r;
2017 }
2018
2019 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2020 [UNIT_FILE_ENABLED] = "enabled",
2021 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2022 [UNIT_FILE_LINKED] = "linked",
2023 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2024 [UNIT_FILE_MASKED] = "masked",
2025 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2026 [UNIT_FILE_STATIC] = "static",
2027 [UNIT_FILE_DISABLED] = "disabled",
2028 [UNIT_FILE_INVALID] = "invalid",
2029 };
2030
2031 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2032
2033 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2034 [UNIT_FILE_SYMLINK] = "symlink",
2035 [UNIT_FILE_UNLINK] = "unlink",
2036 };
2037
2038 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);