]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
17e03e59cd4da58641911b50007d69fc1d73a551
[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 <fnmatch.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "alloc-util.h"
29 #include "conf-files.h"
30 #include "conf-parser.h"
31 #include "dirent-util.h"
32 #include "fd-util.h"
33 #include "fileio.h"
34 #include "fs-util.h"
35 #include "hashmap.h"
36 #include "install-printf.h"
37 #include "install.h"
38 #include "mkdir.h"
39 #include "path-lookup.h"
40 #include "path-util.h"
41 #include "set.h"
42 #include "special.h"
43 #include "stat-util.h"
44 #include "string-table.h"
45 #include "string-util.h"
46 #include "strv.h"
47 #include "unit-name.h"
48 #include "util.h"
49
50 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
51
52 typedef enum SearchFlags {
53 SEARCH_LOAD = 1,
54 SEARCH_FOLLOW_CONFIG_SYMLINKS = 2,
55 } SearchFlags;
56
57 typedef struct {
58 OrderedHashmap *will_process;
59 OrderedHashmap *have_processed;
60 } InstallContext;
61
62 static int in_search_path(const char *path, char **search) {
63 _cleanup_free_ char *parent = NULL;
64 char **i;
65
66 assert(path);
67
68 parent = dirname_malloc(path);
69 if (!parent)
70 return -ENOMEM;
71
72 STRV_FOREACH(i, search)
73 if (path_equal(parent, *i))
74 return true;
75
76 return false;
77 }
78
79 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
80 char *p = NULL;
81 int r;
82
83 assert(scope >= 0);
84 assert(scope < _UNIT_FILE_SCOPE_MAX);
85 assert(ret);
86
87 /* This determines where we shall create or remove our
88 * installation ("configuration") symlinks */
89
90 switch (scope) {
91
92 case UNIT_FILE_SYSTEM:
93
94 if (runtime)
95 p = path_join(root_dir, "/run/systemd/system", NULL);
96 else
97 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
98 break;
99
100 case UNIT_FILE_GLOBAL:
101
102 if (root_dir)
103 return -EINVAL;
104
105 if (runtime)
106 p = strdup("/run/systemd/user");
107 else
108 p = strdup(USER_CONFIG_UNIT_PATH);
109 break;
110
111 case UNIT_FILE_USER:
112
113 if (root_dir)
114 return -EINVAL;
115
116 if (runtime)
117 r = user_runtime_dir(&p);
118 else
119 r = user_config_home(&p);
120 if (r < 0)
121 return r;
122 if (r == 0)
123 return -ENOENT;
124
125 break;
126
127 default:
128 assert_not_reached("Bad scope");
129 }
130
131 if (!p)
132 return -ENOMEM;
133
134 *ret = p;
135 return 0;
136 }
137
138 static bool is_config_path(UnitFileScope scope, const char *path) {
139 int r;
140
141 assert(scope >= 0);
142 assert(scope < _UNIT_FILE_SCOPE_MAX);
143 assert(path);
144
145 /* Checks whether the specified path is intended for
146 * configuration or is outside of it */
147
148 switch (scope) {
149
150 case UNIT_FILE_SYSTEM:
151 case UNIT_FILE_GLOBAL:
152 return path_startswith(path, "/etc") ||
153 path_startswith(path, SYSTEM_CONFIG_UNIT_PATH) ||
154 path_startswith(path, "/run");
155
156
157 case UNIT_FILE_USER: {
158 _cleanup_free_ char *p = NULL;
159
160 r = user_config_home(&p);
161 if (r < 0)
162 return r;
163 if (r > 0 && path_startswith(path, p))
164 return true;
165
166 p = mfree(p);
167
168 r = user_runtime_dir(&p);
169 if (r < 0)
170 return r;
171 if (r > 0 && path_startswith(path, p))
172 return true;
173
174 return false;
175 }
176
177 default:
178 assert_not_reached("Bad scope");
179 }
180 }
181
182
183 static int verify_root_dir(UnitFileScope scope, const char **root_dir) {
184 int r;
185
186 assert(root_dir);
187
188 /* Verifies that the specified root directory to operate on
189 * makes sense. Reset it to NULL if it is the root directory
190 * or set to empty */
191
192 if (isempty(*root_dir) || path_equal(*root_dir, "/")) {
193 *root_dir = NULL;
194 return 0;
195 }
196
197 if (scope != UNIT_FILE_SYSTEM)
198 return -EINVAL;
199
200 r = is_dir(*root_dir, true);
201 if (r < 0)
202 return r;
203 if (r == 0)
204 return -ENOTDIR;
205
206 return 0;
207 }
208
209 int unit_file_changes_add(
210 UnitFileChange **changes,
211 unsigned *n_changes,
212 UnitFileChangeType type,
213 const char *path,
214 const char *source) {
215
216 UnitFileChange *c;
217 unsigned i;
218
219 assert(path);
220 assert(!changes == !n_changes);
221
222 if (!changes)
223 return 0;
224
225 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
226 if (!c)
227 return -ENOMEM;
228
229 *changes = c;
230 i = *n_changes;
231
232 c[i].type = type;
233 c[i].path = strdup(path);
234 if (!c[i].path)
235 return -ENOMEM;
236
237 path_kill_slashes(c[i].path);
238
239 if (source) {
240 c[i].source = strdup(source);
241 if (!c[i].source) {
242 free(c[i].path);
243 return -ENOMEM;
244 }
245
246 path_kill_slashes(c[i].path);
247 } else
248 c[i].source = NULL;
249
250 *n_changes = i+1;
251 return 0;
252 }
253
254 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
255 unsigned i;
256
257 assert(changes || n_changes == 0);
258
259 if (!changes)
260 return;
261
262 for (i = 0; i < n_changes; i++) {
263 free(changes[i].path);
264 free(changes[i].source);
265 }
266
267 free(changes);
268 }
269
270 static int create_symlink(
271 const char *old_path,
272 const char *new_path,
273 bool force,
274 UnitFileChange **changes,
275 unsigned *n_changes) {
276
277 _cleanup_free_ char *dest = NULL;
278 int r;
279
280 assert(old_path);
281 assert(new_path);
282
283 /* Actually create a symlink, and remember that we did. Is
284 * smart enough to check if there's already a valid symlink in
285 * place. */
286
287 mkdir_parents_label(new_path, 0755);
288
289 if (symlink(old_path, new_path) >= 0) {
290 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
291 return 0;
292 }
293
294 if (errno != EEXIST)
295 return -errno;
296
297 r = readlink_malloc(new_path, &dest);
298 if (r < 0)
299 return r;
300
301 if (path_equal(dest, old_path))
302 return 0;
303
304 if (!force)
305 return -EEXIST;
306
307 r = symlink_atomic(old_path, new_path);
308 if (r < 0)
309 return r;
310
311 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
312 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
313
314 return 0;
315 }
316
317 static int mark_symlink_for_removal(
318 Set **remove_symlinks_to,
319 const char *p) {
320
321 char *n;
322 int r;
323
324 assert(p);
325
326 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
327 if (r < 0)
328 return r;
329
330 n = strdup(p);
331 if (!n)
332 return -ENOMEM;
333
334 path_kill_slashes(n);
335
336 r = set_consume(*remove_symlinks_to, n);
337 if (r == -EEXIST)
338 return 0;
339 if (r < 0)
340 return r;
341
342 return 1;
343 }
344
345 static int remove_marked_symlinks_fd(
346 Set *remove_symlinks_to,
347 int fd,
348 const char *path,
349 const char *config_path,
350 bool *restart,
351 UnitFileChange **changes,
352 unsigned *n_changes) {
353
354 _cleanup_closedir_ DIR *d = NULL;
355 struct dirent *de;
356 int r = 0;
357
358 assert(remove_symlinks_to);
359 assert(fd >= 0);
360 assert(path);
361 assert(config_path);
362 assert(restart);
363
364 d = fdopendir(fd);
365 if (!d) {
366 safe_close(fd);
367 return -errno;
368 }
369
370 rewinddir(d);
371
372 FOREACH_DIRENT(de, d, return -errno) {
373
374 dirent_ensure_type(d, de);
375
376 if (de->d_type == DT_DIR) {
377 _cleanup_free_ char *p = NULL;
378 int nfd, q;
379
380 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
381 if (nfd < 0) {
382 if (errno == ENOENT)
383 continue;
384
385 if (r == 0)
386 r = -errno;
387 continue;
388 }
389
390 p = path_make_absolute(de->d_name, path);
391 if (!p) {
392 safe_close(nfd);
393 return -ENOMEM;
394 }
395
396 /* This will close nfd, regardless whether it succeeds or not */
397 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, restart, changes, n_changes);
398 if (q < 0 && r == 0)
399 r = q;
400
401 } else if (de->d_type == DT_LNK) {
402 _cleanup_free_ char *p = NULL, *dest = NULL;
403 bool found;
404 int q;
405
406 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
407 continue;
408
409 p = path_make_absolute(de->d_name, path);
410 if (!p)
411 return -ENOMEM;
412
413 q = readlink_malloc(p, &dest);
414 if (q < 0) {
415 if (q == -ENOENT)
416 continue;
417
418 if (r == 0)
419 r = q;
420 continue;
421 }
422
423 /* We remove all links pointing to a file or
424 * path that is marked, as well as all files
425 * sharing the same name as a file that is
426 * marked. */
427
428 found =
429 set_contains(remove_symlinks_to, dest) ||
430 set_contains(remove_symlinks_to, basename(dest)) ||
431 set_contains(remove_symlinks_to, de->d_name);
432
433 if (!found)
434 continue;
435
436 if (unlink(p) < 0 && errno != ENOENT) {
437 if (r == 0)
438 r = -errno;
439 continue;
440 }
441
442 path_kill_slashes(p);
443 (void) rmdir_parents(p, config_path);
444
445 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
446
447 q = mark_symlink_for_removal(&remove_symlinks_to, p);
448 if (q < 0)
449 return q;
450 if (q > 0)
451 *restart = true;
452 }
453 }
454
455 return r;
456 }
457
458 static int remove_marked_symlinks(
459 Set *remove_symlinks_to,
460 const char *config_path,
461 UnitFileChange **changes,
462 unsigned *n_changes) {
463
464 _cleanup_close_ int fd = -1;
465 bool restart;
466 int r = 0;
467
468 assert(config_path);
469
470 if (set_size(remove_symlinks_to) <= 0)
471 return 0;
472
473 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
474 if (fd < 0)
475 return -errno;
476
477 do {
478 int q, cfd;
479 restart = false;
480
481 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
482 if (cfd < 0)
483 return -errno;
484
485 /* This takes possession of cfd and closes it */
486 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &restart, changes, n_changes);
487 if (r == 0)
488 r = q;
489 } while (restart);
490
491 return r;
492 }
493
494 static int find_symlinks_fd(
495 const char *root_dir,
496 const char *name,
497 int fd,
498 const char *path,
499 const char *config_path,
500 bool *same_name_link) {
501
502 _cleanup_closedir_ DIR *d = NULL;
503 struct dirent *de;
504 int r = 0;
505
506 assert(name);
507 assert(fd >= 0);
508 assert(path);
509 assert(config_path);
510 assert(same_name_link);
511
512 d = fdopendir(fd);
513 if (!d) {
514 safe_close(fd);
515 return -errno;
516 }
517
518 FOREACH_DIRENT(de, d, return -errno) {
519
520 dirent_ensure_type(d, de);
521
522 if (de->d_type == DT_DIR) {
523 _cleanup_free_ char *p = NULL;
524 int nfd, q;
525
526 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
527 if (nfd < 0) {
528 if (errno == ENOENT)
529 continue;
530
531 if (r == 0)
532 r = -errno;
533 continue;
534 }
535
536 p = path_make_absolute(de->d_name, path);
537 if (!p) {
538 safe_close(nfd);
539 return -ENOMEM;
540 }
541
542 /* This will close nfd, regardless whether it succeeds or not */
543 q = find_symlinks_fd(root_dir, name, nfd, p, config_path, same_name_link);
544 if (q > 0)
545 return 1;
546 if (r == 0)
547 r = q;
548
549 } else if (de->d_type == DT_LNK) {
550 _cleanup_free_ char *p = NULL, *dest = NULL;
551 bool found_path, found_dest, b = false;
552 int q;
553
554 /* Acquire symlink name */
555 p = path_make_absolute(de->d_name, path);
556 if (!p)
557 return -ENOMEM;
558
559 /* Acquire symlink destination */
560 q = readlink_malloc(p, &dest);
561 if (q == -ENOENT)
562 continue;
563 if (q < 0) {
564 if (r == 0)
565 r = q;
566 continue;
567 }
568
569 /* Make absolute */
570 if (!path_is_absolute(dest)) {
571 char *x;
572
573 x = prefix_root(root_dir, dest);
574 if (!x)
575 return -ENOMEM;
576
577 free(dest);
578 dest = x;
579 }
580
581 /* Check if the symlink itself matches what we
582 * are looking for */
583 if (path_is_absolute(name))
584 found_path = path_equal(p, name);
585 else
586 found_path = streq(de->d_name, name);
587
588 /* Check if what the symlink points to
589 * matches what we are looking for */
590 if (path_is_absolute(name))
591 found_dest = path_equal(dest, name);
592 else
593 found_dest = streq(basename(dest), name);
594
595 if (found_path && found_dest) {
596 _cleanup_free_ char *t = NULL;
597
598 /* Filter out same name links in the main
599 * config path */
600 t = path_make_absolute(name, config_path);
601 if (!t)
602 return -ENOMEM;
603
604 b = path_equal(t, p);
605 }
606
607 if (b)
608 *same_name_link = true;
609 else if (found_path || found_dest)
610 return 1;
611 }
612 }
613
614 return r;
615 }
616
617 static int find_symlinks(
618 const char *root_dir,
619 const char *name,
620 const char *config_path,
621 bool *same_name_link) {
622
623 int fd;
624
625 assert(name);
626 assert(config_path);
627 assert(same_name_link);
628
629 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
630 if (fd < 0) {
631 if (errno == ENOENT)
632 return 0;
633 return -errno;
634 }
635
636 /* This takes possession of fd and closes it */
637 return find_symlinks_fd(root_dir, name, fd, config_path, config_path, same_name_link);
638 }
639
640 static int find_symlinks_in_scope(
641 UnitFileScope scope,
642 const char *root_dir,
643 const char *name,
644 UnitFileState *state) {
645
646 _cleanup_free_ char *normal_path = NULL, *runtime_path = NULL;
647 bool same_name_link_runtime = false, same_name_link = false;
648 int r;
649
650 assert(scope >= 0);
651 assert(scope < _UNIT_FILE_SCOPE_MAX);
652 assert(name);
653
654 /* First look in the normal config path */
655 r = get_config_path(scope, false, root_dir, &normal_path);
656 if (r < 0)
657 return r;
658
659 r = find_symlinks(root_dir, name, normal_path, &same_name_link);
660 if (r < 0)
661 return r;
662 if (r > 0) {
663 *state = UNIT_FILE_ENABLED;
664 return r;
665 }
666
667 /* Then look in runtime config path */
668 r = get_config_path(scope, true, root_dir, &runtime_path);
669 if (r < 0)
670 return r;
671
672 r = find_symlinks(root_dir, name, runtime_path, &same_name_link_runtime);
673 if (r < 0)
674 return r;
675 if (r > 0) {
676 *state = UNIT_FILE_ENABLED_RUNTIME;
677 return r;
678 }
679
680 /* Hmm, we didn't find it, but maybe we found the same name
681 * link? */
682 if (same_name_link) {
683 *state = UNIT_FILE_LINKED;
684 return 1;
685 }
686 if (same_name_link_runtime) {
687 *state = UNIT_FILE_LINKED_RUNTIME;
688 return 1;
689 }
690
691 return 0;
692 }
693
694 static void install_info_free(UnitFileInstallInfo *i) {
695
696 if (!i)
697 return;
698
699 free(i->name);
700 free(i->path);
701 strv_free(i->aliases);
702 strv_free(i->wanted_by);
703 strv_free(i->required_by);
704 strv_free(i->also);
705 free(i->default_instance);
706 free(i->symlink_target);
707 free(i);
708 }
709
710 static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) {
711 UnitFileInstallInfo *i;
712
713 if (!m)
714 return NULL;
715
716 while ((i = ordered_hashmap_steal_first(m)))
717 install_info_free(i);
718
719 return ordered_hashmap_free(m);
720 }
721
722 static void install_context_done(InstallContext *c) {
723 assert(c);
724
725 c->will_process = install_info_hashmap_free(c->will_process);
726 c->have_processed = install_info_hashmap_free(c->have_processed);
727 }
728
729 static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) {
730 UnitFileInstallInfo *i;
731
732 i = ordered_hashmap_get(c->have_processed, name);
733 if (i)
734 return i;
735
736 return ordered_hashmap_get(c->will_process, name);
737 }
738
739 static int install_info_add(
740 InstallContext *c,
741 const char *name,
742 const char *path,
743 UnitFileInstallInfo **ret) {
744
745 UnitFileInstallInfo *i = NULL;
746 int r;
747
748 assert(c);
749 assert(name || path);
750
751 if (!name)
752 name = basename(path);
753
754 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
755 return -EINVAL;
756
757 i = install_info_find(c, name);
758 if (i) {
759 if (ret)
760 *ret = i;
761 return 0;
762 }
763
764 r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
765 if (r < 0)
766 return r;
767
768 i = new0(UnitFileInstallInfo, 1);
769 if (!i)
770 return -ENOMEM;
771 i->type = _UNIT_FILE_TYPE_INVALID;
772
773 i->name = strdup(name);
774 if (!i->name) {
775 r = -ENOMEM;
776 goto fail;
777 }
778
779 if (path) {
780 i->path = strdup(path);
781 if (!i->path) {
782 r = -ENOMEM;
783 goto fail;
784 }
785 }
786
787 r = ordered_hashmap_put(c->will_process, i->name, i);
788 if (r < 0)
789 goto fail;
790
791 if (ret)
792 *ret = i;
793
794 return 0;
795
796 fail:
797 install_info_free(i);
798 return r;
799 }
800
801 static int install_info_add_auto(
802 InstallContext *c,
803 const char *name_or_path,
804 UnitFileInstallInfo **ret) {
805
806 assert(c);
807 assert(name_or_path);
808
809 if (path_is_absolute(name_or_path))
810 return install_info_add(c, NULL, name_or_path, ret);
811 else
812 return install_info_add(c, name_or_path, NULL, ret);
813 }
814
815 static int config_parse_also(
816 const char *unit,
817 const char *filename,
818 unsigned line,
819 const char *section,
820 unsigned section_line,
821 const char *lvalue,
822 int ltype,
823 const char *rvalue,
824 void *data,
825 void *userdata) {
826
827 UnitFileInstallInfo *i = userdata;
828 InstallContext *c = data;
829 int r;
830
831 assert(filename);
832 assert(lvalue);
833 assert(rvalue);
834
835 for (;;) {
836 _cleanup_free_ char *word = NULL;
837
838 r = extract_first_word(&rvalue, &word, NULL, 0);
839 if (r < 0)
840 return r;
841 if (r == 0)
842 break;
843
844 r = install_info_add(c, word, NULL, NULL);
845 if (r < 0)
846 return r;
847
848 r = strv_push(&i->also, word);
849 if (r < 0)
850 return r;
851
852 word = NULL;
853 }
854
855 return 0;
856 }
857
858 static int config_parse_default_instance(
859 const char *unit,
860 const char *filename,
861 unsigned line,
862 const char *section,
863 unsigned section_line,
864 const char *lvalue,
865 int ltype,
866 const char *rvalue,
867 void *data,
868 void *userdata) {
869
870 UnitFileInstallInfo *i = data;
871 char *printed;
872 int r;
873
874 assert(filename);
875 assert(lvalue);
876 assert(rvalue);
877
878 r = install_full_printf(i, rvalue, &printed);
879 if (r < 0)
880 return r;
881
882 if (!unit_instance_is_valid(printed)) {
883 free(printed);
884 return -EINVAL;
885 }
886
887 free(i->default_instance);
888 i->default_instance = printed;
889
890 return 0;
891 }
892
893 static int unit_file_load(
894 InstallContext *c,
895 UnitFileInstallInfo *info,
896 const char *path,
897 const char *root_dir,
898 SearchFlags flags) {
899
900 const ConfigTableItem items[] = {
901 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
902 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
903 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
904 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
905 { "Install", "Also", config_parse_also, 0, c },
906 {}
907 };
908
909 _cleanup_fclose_ FILE *f = NULL;
910 _cleanup_close_ int fd = -1;
911 struct stat st;
912 int r;
913
914 assert(c);
915 assert(info);
916 assert(path);
917
918 path = prefix_roota(root_dir, path);
919
920 if (!(flags & SEARCH_LOAD)) {
921 r = lstat(path, &st);
922 if (r < 0)
923 return -errno;
924
925 if (null_or_empty(&st))
926 info->type = UNIT_FILE_TYPE_MASKED;
927 else if (S_ISREG(st.st_mode))
928 info->type = UNIT_FILE_TYPE_REGULAR;
929 else if (S_ISLNK(st.st_mode))
930 return -ELOOP;
931 else if (S_ISDIR(st.st_mode))
932 return -EISDIR;
933 else
934 return -ENOTTY;
935
936 return 0;
937 }
938
939 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
940 if (fd < 0)
941 return -errno;
942 if (fstat(fd, &st) < 0)
943 return -errno;
944 if (null_or_empty(&st)) {
945 info->type = UNIT_FILE_TYPE_MASKED;
946 return 0;
947 }
948 if (S_ISDIR(st.st_mode))
949 return -EISDIR;
950 if (!S_ISREG(st.st_mode))
951 return -ENOTTY;
952
953 f = fdopen(fd, "re");
954 if (!f)
955 return -errno;
956 fd = -1;
957
958 r = config_parse(NULL, path, f,
959 NULL,
960 config_item_table_lookup, items,
961 true, true, false, info);
962 if (r < 0)
963 return r;
964
965 info->type = UNIT_FILE_TYPE_REGULAR;
966
967 return
968 (int) strv_length(info->aliases) +
969 (int) strv_length(info->wanted_by) +
970 (int) strv_length(info->required_by);
971 }
972
973 static int unit_file_load_or_readlink(
974 InstallContext *c,
975 UnitFileInstallInfo *info,
976 const char *path,
977 const char *root_dir,
978 SearchFlags flags) {
979
980 _cleanup_free_ char *np = NULL;
981 int r;
982
983 r = unit_file_load(c, info, path, root_dir, flags);
984 if (r != -ELOOP)
985 return r;
986
987 /* This is a symlink, let's read it. */
988
989 r = readlink_and_make_absolute_root(root_dir, path, &np);
990 if (r < 0)
991 return r;
992
993 if (path_equal(np, "/dev/null"))
994 info->type = UNIT_FILE_TYPE_MASKED;
995 else {
996 const char *bn;
997 UnitType a, b;
998
999 bn = basename(np);
1000
1001 if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
1002
1003 if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
1004 return -EINVAL;
1005
1006 } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1007
1008 if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
1009 return -EINVAL;
1010
1011 } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
1012
1013 if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
1014 return -EINVAL;
1015 } else
1016 return -EINVAL;
1017
1018 /* Enforce that the symlink destination does not
1019 * change the unit file type. */
1020
1021 a = unit_name_to_type(info->name);
1022 b = unit_name_to_type(bn);
1023 if (a < 0 || b < 0 || a != b)
1024 return -EINVAL;
1025
1026 info->type = UNIT_FILE_TYPE_SYMLINK;
1027 info->symlink_target = np;
1028 np = NULL;
1029 }
1030
1031 return 0;
1032 }
1033
1034 static int unit_file_search(
1035 InstallContext *c,
1036 UnitFileInstallInfo *info,
1037 const LookupPaths *paths,
1038 const char *root_dir,
1039 SearchFlags flags) {
1040
1041 char **p;
1042 int r;
1043
1044 assert(c);
1045 assert(info);
1046 assert(paths);
1047
1048 /* Was this unit already loaded? */
1049 if (info->type != _UNIT_FILE_TYPE_INVALID)
1050 return 0;
1051
1052 if (info->path)
1053 return unit_file_load_or_readlink(c, info, info->path, root_dir, flags);
1054
1055 assert(info->name);
1056
1057 STRV_FOREACH(p, paths->unit_path) {
1058 _cleanup_free_ char *path = NULL;
1059
1060 path = strjoin(*p, "/", info->name, NULL);
1061 if (!path)
1062 return -ENOMEM;
1063
1064 r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
1065 if (r < 0) {
1066 if (r != -ENOENT)
1067 return r;
1068 } else {
1069 info->path = path;
1070 path = NULL;
1071 return r;
1072 }
1073 }
1074
1075 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1076
1077 /* Unit file doesn't exist, however instance
1078 * enablement was requested. We will check if it is
1079 * possible to load template unit file. */
1080
1081 _cleanup_free_ char *template = NULL;
1082
1083 r = unit_name_template(info->name, &template);
1084 if (r < 0)
1085 return r;
1086
1087 STRV_FOREACH(p, paths->unit_path) {
1088 _cleanup_free_ char *path = NULL;
1089
1090 path = strjoin(*p, "/", template, NULL);
1091 if (!path)
1092 return -ENOMEM;
1093
1094 r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
1095 if (r < 0) {
1096 if (r != -ENOENT)
1097 return r;
1098 } else {
1099 info->path = path;
1100 path = NULL;
1101 return r;
1102 }
1103 }
1104 }
1105
1106 return -ENOENT;
1107 }
1108
1109 static int install_info_follow(
1110 InstallContext *c,
1111 UnitFileInstallInfo *i,
1112 const char *root_dir,
1113 SearchFlags flags) {
1114
1115 assert(c);
1116 assert(i);
1117
1118 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1119 return -EINVAL;
1120 if (!i->symlink_target)
1121 return -EINVAL;
1122
1123 /* If the basename doesn't match, the caller should add a
1124 * complete new entry for this. */
1125
1126 if (!streq(basename(i->symlink_target), i->name))
1127 return -EXDEV;
1128
1129 free(i->path);
1130 i->path = i->symlink_target;
1131 i->symlink_target = NULL;
1132 i->type = _UNIT_FILE_TYPE_INVALID;
1133
1134 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1135 }
1136
1137 static int install_info_traverse(
1138 UnitFileScope scope,
1139 InstallContext *c,
1140 const char *root_dir,
1141 const LookupPaths *paths,
1142 UnitFileInstallInfo *start,
1143 SearchFlags flags,
1144 UnitFileInstallInfo **ret) {
1145
1146 UnitFileInstallInfo *i;
1147 unsigned k = 0;
1148 int r;
1149
1150 assert(paths);
1151 assert(start);
1152 assert(c);
1153
1154 r = unit_file_search(c, start, paths, root_dir, flags);
1155 if (r < 0)
1156 return r;
1157
1158 i = start;
1159 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1160 /* Follow the symlink */
1161
1162 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1163 return -ELOOP;
1164
1165 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS) && is_config_path(scope, i->path))
1166 return -ELOOP;
1167
1168 r = install_info_follow(c, i, root_dir, flags);
1169 if (r < 0) {
1170 _cleanup_free_ char *buffer = NULL;
1171 const char *bn;
1172
1173 if (r != -EXDEV)
1174 return r;
1175
1176 /* Target has a different name, create a new
1177 * install info object for that, and continue
1178 * with that. */
1179
1180 bn = basename(i->symlink_target);
1181
1182 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1183 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1184
1185 _cleanup_free_ char *instance = NULL;
1186
1187 r = unit_name_to_instance(i->name, &instance);
1188 if (r < 0)
1189 return r;
1190
1191 r = unit_name_replace_instance(bn, instance, &buffer);
1192 if (r < 0)
1193 return r;
1194
1195 bn = buffer;
1196 }
1197
1198 r = install_info_add(c, bn, NULL, &i);
1199 if (r < 0)
1200 return r;
1201
1202 r = unit_file_search(c, i, paths, root_dir, flags);
1203 if (r < 0)
1204 return r;
1205 }
1206
1207 /* Try again, with the new target we found. */
1208 }
1209
1210 if (ret)
1211 *ret = i;
1212
1213 return 0;
1214 }
1215
1216 static int install_info_discover(
1217 UnitFileScope scope,
1218 InstallContext *c,
1219 const char *root_dir,
1220 const LookupPaths *paths,
1221 const char *name,
1222 SearchFlags flags,
1223 UnitFileInstallInfo **ret) {
1224
1225 UnitFileInstallInfo *i;
1226 int r;
1227
1228 assert(c);
1229 assert(paths);
1230 assert(name);
1231
1232 r = install_info_add_auto(c, name, &i);
1233 if (r < 0)
1234 return r;
1235
1236 return install_info_traverse(scope, c, root_dir, paths, i, flags, ret);
1237 }
1238
1239 static int install_info_symlink_alias(
1240 UnitFileInstallInfo *i,
1241 const char *config_path,
1242 bool force,
1243 UnitFileChange **changes,
1244 unsigned *n_changes) {
1245
1246 char **s;
1247 int r = 0, q;
1248
1249 assert(i);
1250 assert(config_path);
1251
1252 STRV_FOREACH(s, i->aliases) {
1253 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1254
1255 q = install_full_printf(i, *s, &dst);
1256 if (q < 0)
1257 return q;
1258
1259 alias_path = path_make_absolute(dst, config_path);
1260 if (!alias_path)
1261 return -ENOMEM;
1262
1263 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1264 if (r == 0)
1265 r = q;
1266 }
1267
1268 return r;
1269 }
1270
1271 static int install_info_symlink_wants(
1272 UnitFileInstallInfo *i,
1273 const char *config_path,
1274 char **list,
1275 const char *suffix,
1276 bool force,
1277 UnitFileChange **changes,
1278 unsigned *n_changes) {
1279
1280 _cleanup_free_ char *buf = NULL;
1281 const char *n;
1282 char **s;
1283 int r = 0, q;
1284
1285 assert(i);
1286 assert(config_path);
1287
1288 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
1289
1290 /* Don't install any symlink if there's no default
1291 * instance configured */
1292
1293 if (!i->default_instance)
1294 return 0;
1295
1296 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1297 if (r < 0)
1298 return r;
1299
1300 n = buf;
1301 } else
1302 n = i->name;
1303
1304 STRV_FOREACH(s, list) {
1305 _cleanup_free_ char *path = NULL, *dst = NULL;
1306
1307 q = install_full_printf(i, *s, &dst);
1308 if (q < 0)
1309 return q;
1310
1311 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1312 r = -EINVAL;
1313 continue;
1314 }
1315
1316 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1317 if (!path)
1318 return -ENOMEM;
1319
1320 q = create_symlink(i->path, path, force, changes, n_changes);
1321 if (r == 0)
1322 r = q;
1323 }
1324
1325 return r;
1326 }
1327
1328 static int install_info_symlink_link(
1329 UnitFileInstallInfo *i,
1330 const LookupPaths *paths,
1331 const char *config_path,
1332 const char *root_dir,
1333 bool force,
1334 UnitFileChange **changes,
1335 unsigned *n_changes) {
1336
1337 _cleanup_free_ char *path = NULL;
1338 int r;
1339
1340 assert(i);
1341 assert(paths);
1342 assert(config_path);
1343 assert(i->path);
1344
1345 r = in_search_path(i->path, paths->unit_path);
1346 if (r != 0)
1347 return r;
1348
1349 path = strjoin(config_path, "/", i->name, NULL);
1350 if (!path)
1351 return -ENOMEM;
1352
1353 return create_symlink(i->path, path, force, changes, n_changes);
1354 }
1355
1356 static int install_info_apply(
1357 UnitFileInstallInfo *i,
1358 const LookupPaths *paths,
1359 const char *config_path,
1360 const char *root_dir,
1361 bool force,
1362 UnitFileChange **changes,
1363 unsigned *n_changes) {
1364
1365 int r, q;
1366
1367 assert(i);
1368 assert(paths);
1369 assert(config_path);
1370
1371 if (i->type != UNIT_FILE_TYPE_REGULAR)
1372 return 0;
1373
1374 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1375
1376 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1377 if (r == 0)
1378 r = q;
1379
1380 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1381 if (r == 0)
1382 r = q;
1383
1384 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1385 if (r == 0)
1386 r = q;
1387
1388 return r;
1389 }
1390
1391 static int install_context_apply(
1392 UnitFileScope scope,
1393 InstallContext *c,
1394 const LookupPaths *paths,
1395 const char *config_path,
1396 const char *root_dir,
1397 bool force,
1398 SearchFlags flags,
1399 UnitFileChange **changes,
1400 unsigned *n_changes) {
1401
1402 UnitFileInstallInfo *i;
1403 int r;
1404
1405 assert(c);
1406 assert(paths);
1407 assert(config_path);
1408
1409 if (ordered_hashmap_isempty(c->will_process))
1410 return 0;
1411
1412 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1413 if (r < 0)
1414 return r;
1415
1416 r = 0;
1417 while ((i = ordered_hashmap_first(c->will_process))) {
1418 int q;
1419
1420 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1421 if (q < 0)
1422 return q;
1423
1424 r = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL);
1425 if (r < 0)
1426 return r;
1427
1428 if (i->type != UNIT_FILE_TYPE_REGULAR)
1429 continue;
1430
1431 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1432 if (r >= 0) {
1433 if (q < 0)
1434 r = q;
1435 else
1436 r+= q;
1437 }
1438 }
1439
1440 return r;
1441 }
1442
1443 static int install_context_mark_for_removal(
1444 UnitFileScope scope,
1445 InstallContext *c,
1446 const LookupPaths *paths,
1447 Set **remove_symlinks_to,
1448 const char *config_path,
1449 const char *root_dir) {
1450
1451 UnitFileInstallInfo *i;
1452 int r;
1453
1454 assert(c);
1455 assert(paths);
1456 assert(config_path);
1457
1458 /* Marks all items for removal */
1459
1460 if (ordered_hashmap_isempty(c->will_process))
1461 return 0;
1462
1463 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1464 if (r < 0)
1465 return r;
1466
1467 while ((i = ordered_hashmap_first(c->will_process))) {
1468
1469 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1470 if (r < 0)
1471 return r;
1472
1473 r = install_info_traverse(scope, c, root_dir, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
1474 if (r < 0)
1475 return r;
1476
1477 if (i->type != UNIT_FILE_TYPE_REGULAR)
1478 continue;
1479
1480 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
1481 if (r < 0)
1482 return r;
1483 }
1484
1485 return 0;
1486 }
1487
1488 int unit_file_mask(
1489 UnitFileScope scope,
1490 bool runtime,
1491 const char *root_dir,
1492 char **files,
1493 bool force,
1494 UnitFileChange **changes,
1495 unsigned *n_changes) {
1496
1497 _cleanup_free_ char *prefix = NULL;
1498 char **i;
1499 int r;
1500
1501 assert(scope >= 0);
1502 assert(scope < _UNIT_FILE_SCOPE_MAX);
1503
1504 r = verify_root_dir(scope, &root_dir);
1505 if (r < 0)
1506 return r;
1507
1508 r = get_config_path(scope, runtime, root_dir, &prefix);
1509 if (r < 0)
1510 return r;
1511
1512 STRV_FOREACH(i, files) {
1513 _cleanup_free_ char *path = NULL;
1514 int q;
1515
1516 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
1517 if (r == 0)
1518 r = -EINVAL;
1519 continue;
1520 }
1521
1522 path = path_make_absolute(*i, prefix);
1523 if (!path)
1524 return -ENOMEM;
1525
1526 q = create_symlink("/dev/null", path, force, changes, n_changes);
1527 if (q < 0 && r >= 0)
1528 r = q;
1529 }
1530
1531 return r;
1532 }
1533
1534 int unit_file_unmask(
1535 UnitFileScope scope,
1536 bool runtime,
1537 const char *root_dir,
1538 char **files,
1539 UnitFileChange **changes,
1540 unsigned *n_changes) {
1541
1542 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1543 _cleanup_free_ char *config_path = NULL;
1544 _cleanup_free_ char **todo = NULL;
1545 size_t n_todo = 0, n_allocated = 0;
1546 char **i;
1547 int r, q;
1548
1549 assert(scope >= 0);
1550 assert(scope < _UNIT_FILE_SCOPE_MAX);
1551
1552 r = verify_root_dir(scope, &root_dir);
1553 if (r < 0)
1554 return r;
1555
1556 r = get_config_path(scope, runtime, root_dir, &config_path);
1557 if (r < 0)
1558 return r;
1559
1560 STRV_FOREACH(i, files) {
1561 _cleanup_free_ char *path = NULL;
1562
1563 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1564 return -EINVAL;
1565
1566 path = path_make_absolute(*i, config_path);
1567 if (!path)
1568 return -ENOMEM;
1569
1570 r = null_or_empty_path(path);
1571 if (r == -ENOENT)
1572 continue;
1573 if (r < 0)
1574 return r;
1575 if (r == 0)
1576 continue;
1577
1578 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1579 return -ENOMEM;
1580
1581 todo[n_todo++] = *i;
1582 }
1583
1584 strv_uniq(todo);
1585
1586 r = 0;
1587 STRV_FOREACH(i, todo) {
1588 _cleanup_free_ char *path = NULL;
1589
1590 path = path_make_absolute(*i, config_path);
1591 if (!path)
1592 return -ENOMEM;
1593
1594 if (unlink(path) < 0) {
1595 if (errno != -ENOENT && r >= 0)
1596 r = -errno;
1597 } else {
1598 q = mark_symlink_for_removal(&remove_symlinks_to, path);
1599 if (q < 0)
1600 return q;
1601
1602 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
1603 }
1604 }
1605
1606 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
1607 if (r >= 0)
1608 r = q;
1609
1610 return r;
1611 }
1612
1613 int unit_file_link(
1614 UnitFileScope scope,
1615 bool runtime,
1616 const char *root_dir,
1617 char **files,
1618 bool force,
1619 UnitFileChange **changes,
1620 unsigned *n_changes) {
1621
1622 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1623 _cleanup_free_ char *config_path = NULL;
1624 _cleanup_free_ char **todo = NULL;
1625 size_t n_todo = 0, n_allocated = 0;
1626 char **i;
1627 int r, q;
1628
1629 assert(scope >= 0);
1630 assert(scope < _UNIT_FILE_SCOPE_MAX);
1631
1632 r = verify_root_dir(scope, &root_dir);
1633 if (r < 0)
1634 return r;
1635
1636 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1637 if (r < 0)
1638 return r;
1639
1640 r = get_config_path(scope, runtime, root_dir, &config_path);
1641 if (r < 0)
1642 return r;
1643
1644 STRV_FOREACH(i, files) {
1645 _cleanup_free_ char *full = NULL;
1646 struct stat st;
1647 char *fn;
1648
1649 if (!path_is_absolute(*i))
1650 return -EINVAL;
1651
1652 fn = basename(*i);
1653 if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
1654 return -EINVAL;
1655
1656 full = prefix_root(root_dir, *i);
1657 if (!full)
1658 return -ENOMEM;
1659
1660 if (lstat(full, &st) < 0)
1661 return -errno;
1662 if (S_ISLNK(st.st_mode))
1663 return -ELOOP;
1664 if (S_ISDIR(st.st_mode))
1665 return -EISDIR;
1666 if (!S_ISREG(st.st_mode))
1667 return -ENOTTY;
1668
1669 q = in_search_path(*i, paths.unit_path);
1670 if (q < 0)
1671 return q;
1672 if (q > 0)
1673 continue;
1674
1675 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1676 return -ENOMEM;
1677
1678 todo[n_todo++] = *i;
1679 }
1680
1681 strv_uniq(todo);
1682
1683 r = 0;
1684 STRV_FOREACH(i, todo) {
1685 _cleanup_free_ char *path = NULL;
1686
1687 path = path_make_absolute(basename(*i), config_path);
1688 if (!path)
1689 return -ENOMEM;
1690
1691 q = create_symlink(*i, path, force, changes, n_changes);
1692 if (q < 0 && r >= 0)
1693 r = q;
1694 }
1695
1696 return r;
1697 }
1698
1699 int unit_file_add_dependency(
1700 UnitFileScope scope,
1701 bool runtime,
1702 const char *root_dir,
1703 char **files,
1704 const char *target,
1705 UnitDependency dep,
1706 bool force,
1707 UnitFileChange **changes,
1708 unsigned *n_changes) {
1709
1710 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1711 _cleanup_(install_context_done) InstallContext c = {};
1712 _cleanup_free_ char *config_path = NULL;
1713 UnitFileInstallInfo *i, *target_info;
1714 char **f;
1715 int r;
1716
1717 assert(scope >= 0);
1718 assert(scope < _UNIT_FILE_SCOPE_MAX);
1719 assert(target);
1720
1721 if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
1722 return -EINVAL;
1723
1724 if (!unit_name_is_valid(target, UNIT_NAME_ANY))
1725 return -EINVAL;
1726
1727 r = verify_root_dir(scope, &root_dir);
1728 if (r < 0)
1729 return r;
1730
1731 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1732 if (r < 0)
1733 return r;
1734
1735 r = get_config_path(scope, runtime, root_dir, &config_path);
1736 if (r < 0)
1737 return r;
1738
1739 r = install_info_discover(scope, &c, root_dir, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
1740 if (r < 0)
1741 return r;
1742 if (target_info->type == UNIT_FILE_TYPE_MASKED)
1743 return -ESHUTDOWN;
1744
1745 assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
1746
1747 STRV_FOREACH(f, files) {
1748 char ***l;
1749
1750 r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
1751 if (r < 0)
1752 return r;
1753 if (i->type == UNIT_FILE_TYPE_MASKED)
1754 return -ESHUTDOWN;
1755
1756 assert(i->type == UNIT_FILE_TYPE_REGULAR);
1757
1758 /* We didn't actually load anything from the unit
1759 * file, but instead just add in our new symlink to
1760 * create. */
1761
1762 if (dep == UNIT_WANTS)
1763 l = &i->wanted_by;
1764 else
1765 l = &i->required_by;
1766
1767 strv_free(*l);
1768 *l = strv_new(target_info->name, NULL);
1769 if (!*l)
1770 return -ENOMEM;
1771 }
1772
1773 return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
1774 }
1775
1776 int unit_file_enable(
1777 UnitFileScope scope,
1778 bool runtime,
1779 const char *root_dir,
1780 char **files,
1781 bool force,
1782 UnitFileChange **changes,
1783 unsigned *n_changes) {
1784
1785 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1786 _cleanup_(install_context_done) InstallContext c = {};
1787 _cleanup_free_ char *config_path = NULL;
1788 UnitFileInstallInfo *i;
1789 char **f;
1790 int r;
1791
1792 assert(scope >= 0);
1793 assert(scope < _UNIT_FILE_SCOPE_MAX);
1794
1795 r = verify_root_dir(scope, &root_dir);
1796 if (r < 0)
1797 return r;
1798
1799 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1800 if (r < 0)
1801 return r;
1802
1803 r = get_config_path(scope, runtime, root_dir, &config_path);
1804 if (r < 0)
1805 return r;
1806
1807 STRV_FOREACH(f, files) {
1808 r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_LOAD, &i);
1809 if (r < 0)
1810 return r;
1811 if (i->type == UNIT_FILE_TYPE_MASKED)
1812 return -ESHUTDOWN;
1813
1814 assert(i->type == UNIT_FILE_TYPE_REGULAR);
1815 }
1816
1817 /* This will return the number of symlink rules that were
1818 supposed to be created, not the ones actually created. This
1819 is useful to determine whether the passed files had any
1820 installation data at all. */
1821
1822 return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
1823 }
1824
1825 int unit_file_disable(
1826 UnitFileScope scope,
1827 bool runtime,
1828 const char *root_dir,
1829 char **files,
1830 UnitFileChange **changes,
1831 unsigned *n_changes) {
1832
1833 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1834 _cleanup_(install_context_done) InstallContext c = {};
1835 _cleanup_free_ char *config_path = NULL;
1836 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1837 char **i;
1838 int r;
1839
1840 assert(scope >= 0);
1841 assert(scope < _UNIT_FILE_SCOPE_MAX);
1842
1843 r = verify_root_dir(scope, &root_dir);
1844 if (r < 0)
1845 return r;
1846
1847 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1848 if (r < 0)
1849 return r;
1850
1851 r = get_config_path(scope, runtime, root_dir, &config_path);
1852 if (r < 0)
1853 return r;
1854
1855 STRV_FOREACH(i, files) {
1856 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1857 return -EINVAL;
1858
1859 r = install_info_add(&c, *i, NULL, NULL);
1860 if (r < 0)
1861 return r;
1862 }
1863
1864 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, root_dir);
1865 if (r < 0)
1866 return r;
1867
1868 return remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
1869 }
1870
1871 int unit_file_reenable(
1872 UnitFileScope scope,
1873 bool runtime,
1874 const char *root_dir,
1875 char **files,
1876 bool force,
1877 UnitFileChange **changes,
1878 unsigned *n_changes) {
1879
1880 char **n;
1881 int r;
1882 size_t l, i;
1883
1884 /* First, we invoke the disable command with only the basename... */
1885 l = strv_length(files);
1886 n = newa(char*, l+1);
1887 for (i = 0; i < l; i++)
1888 n[i] = basename(files[i]);
1889 n[i] = NULL;
1890
1891 r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes);
1892 if (r < 0)
1893 return r;
1894
1895 /* But the enable command with the full name */
1896 return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes);
1897 }
1898
1899 int unit_file_set_default(
1900 UnitFileScope scope,
1901 const char *root_dir,
1902 const char *name,
1903 bool force,
1904 UnitFileChange **changes,
1905 unsigned *n_changes) {
1906
1907 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1908 _cleanup_(install_context_done) InstallContext c = {};
1909 _cleanup_free_ char *config_path = NULL;
1910 UnitFileInstallInfo *i;
1911 const char *path;
1912 int r;
1913
1914 assert(scope >= 0);
1915 assert(scope < _UNIT_FILE_SCOPE_MAX);
1916 assert(name);
1917
1918 if (unit_name_to_type(name) != UNIT_TARGET)
1919 return -EINVAL;
1920 if (streq(name, SPECIAL_DEFAULT_TARGET))
1921 return -EINVAL;
1922
1923 r = verify_root_dir(scope, &root_dir);
1924 if (r < 0)
1925 return r;
1926
1927 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1928 if (r < 0)
1929 return r;
1930
1931 r = get_config_path(scope, false, root_dir, &config_path);
1932 if (r < 0)
1933 return r;
1934
1935 r = install_info_discover(scope, &c, root_dir, &paths, name, 0, &i);
1936 if (r < 0)
1937 return r;
1938 if (i->type == UNIT_FILE_TYPE_MASKED)
1939 return -ESHUTDOWN;
1940
1941 path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET);
1942
1943 return create_symlink(i->path, path, force, changes, n_changes);
1944 }
1945
1946 int unit_file_get_default(
1947 UnitFileScope scope,
1948 const char *root_dir,
1949 char **name) {
1950
1951 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1952 _cleanup_(install_context_done) InstallContext c = {};
1953 UnitFileInstallInfo *i;
1954 char *n;
1955 int r;
1956
1957 assert(scope >= 0);
1958 assert(scope < _UNIT_FILE_SCOPE_MAX);
1959 assert(name);
1960
1961 r = verify_root_dir(scope, &root_dir);
1962 if (r < 0)
1963 return r;
1964
1965 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1966 if (r < 0)
1967 return r;
1968
1969 r = install_info_discover(scope, &c, root_dir, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
1970 if (r < 0)
1971 return r;
1972 if (i->type == UNIT_FILE_TYPE_MASKED)
1973 return -ESHUTDOWN;
1974
1975 n = strdup(i->name);
1976 if (!n)
1977 return -ENOMEM;
1978
1979 *name = n;
1980 return 0;
1981 }
1982
1983 int unit_file_lookup_state(
1984 UnitFileScope scope,
1985 const char *root_dir,
1986 const LookupPaths *paths,
1987 const char *name,
1988 UnitFileState *ret) {
1989
1990 _cleanup_(install_context_done) InstallContext c = {};
1991 UnitFileInstallInfo *i;
1992 UnitFileState state;
1993 int r;
1994
1995 assert(paths);
1996 assert(name);
1997
1998 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
1999 return -EINVAL;
2000
2001 r = verify_root_dir(scope, &root_dir);
2002 if (r < 0)
2003 return r;
2004
2005 r = install_info_discover(scope, &c, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2006 if (r < 0)
2007 return r;
2008
2009 /* Shortcut things, if the caller just wants to know if this unit exists. */
2010 if (!ret)
2011 return 0;
2012
2013 switch (i->type) {
2014
2015 case UNIT_FILE_TYPE_MASKED:
2016 state = path_startswith(i->path, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2017 break;
2018
2019 case UNIT_FILE_TYPE_REGULAR:
2020 r = find_symlinks_in_scope(scope, root_dir, i->name, &state);
2021 if (r < 0)
2022 return r;
2023 if (r == 0) {
2024 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i))
2025 state = UNIT_FILE_DISABLED;
2026 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i))
2027 state = UNIT_FILE_INDIRECT;
2028 else
2029 state = UNIT_FILE_STATIC;
2030 }
2031
2032 break;
2033
2034 default:
2035 assert_not_reached("Unexpect unit file type.");
2036 }
2037
2038 *ret = state;
2039 return 0;
2040 }
2041
2042 int unit_file_get_state(
2043 UnitFileScope scope,
2044 const char *root_dir,
2045 const char *name,
2046 UnitFileState *ret) {
2047
2048 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2049 int r;
2050
2051 assert(scope >= 0);
2052 assert(scope < _UNIT_FILE_SCOPE_MAX);
2053 assert(name);
2054
2055 r = verify_root_dir(scope, &root_dir);
2056 if (r < 0)
2057 return r;
2058
2059 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2060 if (r < 0)
2061 return r;
2062
2063 return unit_file_lookup_state(scope, root_dir, &paths, name, ret);
2064 }
2065
2066 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
2067 _cleanup_strv_free_ char **files = NULL;
2068 char **p;
2069 int r;
2070
2071 assert(scope >= 0);
2072 assert(scope < _UNIT_FILE_SCOPE_MAX);
2073 assert(name);
2074
2075 r = verify_root_dir(scope, &root_dir);
2076 if (r < 0)
2077 return r;
2078
2079 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2080 return -EINVAL;
2081
2082 if (scope == UNIT_FILE_SYSTEM)
2083 r = conf_files_list(&files, ".preset", root_dir,
2084 "/etc/systemd/system-preset",
2085 "/usr/local/lib/systemd/system-preset",
2086 "/usr/lib/systemd/system-preset",
2087 #ifdef HAVE_SPLIT_USR
2088 "/lib/systemd/system-preset",
2089 #endif
2090 NULL);
2091 else if (scope == UNIT_FILE_GLOBAL)
2092 r = conf_files_list(&files, ".preset", root_dir,
2093 "/etc/systemd/user-preset",
2094 "/usr/local/lib/systemd/user-preset",
2095 "/usr/lib/systemd/user-preset",
2096 NULL);
2097 else
2098 return 1; /* Default is "enable" */
2099
2100 if (r < 0)
2101 return r;
2102
2103 STRV_FOREACH(p, files) {
2104 _cleanup_fclose_ FILE *f;
2105 char line[LINE_MAX];
2106
2107 f = fopen(*p, "re");
2108 if (!f) {
2109 if (errno == ENOENT)
2110 continue;
2111
2112 return -errno;
2113 }
2114
2115 FOREACH_LINE(line, f, return -errno) {
2116 const char *parameter;
2117 char *l;
2118
2119 l = strstrip(line);
2120
2121 if (isempty(l))
2122 continue;
2123 if (strchr(COMMENTS, *l))
2124 continue;
2125
2126 parameter = first_word(l, "enable");
2127 if (parameter) {
2128 if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
2129 log_debug("Preset file says enable %s.", name);
2130 return 1;
2131 }
2132
2133 continue;
2134 }
2135
2136 parameter = first_word(l, "disable");
2137 if (parameter) {
2138 if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
2139 log_debug("Preset file says disable %s.", name);
2140 return 0;
2141 }
2142
2143 continue;
2144 }
2145
2146 log_debug("Couldn't parse line '%s'", l);
2147 }
2148 }
2149
2150 /* Default is "enable" */
2151 log_debug("Preset file doesn't say anything about %s, enabling.", name);
2152 return 1;
2153 }
2154
2155 static int execute_preset(
2156 UnitFileScope scope,
2157 InstallContext *plus,
2158 InstallContext *minus,
2159 const LookupPaths *paths,
2160 const char *config_path,
2161 const char *root_dir,
2162 char **files,
2163 UnitFilePresetMode mode,
2164 bool force,
2165 UnitFileChange **changes,
2166 unsigned *n_changes) {
2167
2168 int r;
2169
2170 assert(plus);
2171 assert(minus);
2172 assert(paths);
2173 assert(config_path);
2174
2175 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2176 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2177
2178 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, root_dir);
2179 if (r < 0)
2180 return r;
2181
2182 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
2183 } else
2184 r = 0;
2185
2186 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2187 int q;
2188
2189 /* Returns number of symlinks that where supposed to be installed. */
2190 q = install_context_apply(scope, plus, paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
2191 if (r >= 0) {
2192 if (q < 0)
2193 r = q;
2194 else
2195 r+= q;
2196 }
2197 }
2198
2199 return r;
2200 }
2201
2202 static int preset_prepare_one(
2203 UnitFileScope scope,
2204 InstallContext *plus,
2205 InstallContext *minus,
2206 LookupPaths *paths,
2207 const char *root_dir,
2208 UnitFilePresetMode mode,
2209 const char *name) {
2210
2211 UnitFileInstallInfo *i;
2212 int r;
2213
2214 if (install_info_find(plus, name) ||
2215 install_info_find(minus, name))
2216 return 0;
2217
2218 r = unit_file_query_preset(scope, root_dir, name);
2219 if (r < 0)
2220 return r;
2221
2222 if (r > 0) {
2223 r = install_info_discover(scope, plus, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2224 if (r < 0)
2225 return r;
2226
2227 if (i->type == UNIT_FILE_TYPE_MASKED)
2228 return -ESHUTDOWN;
2229 } else
2230 r = install_info_discover(scope, minus, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2231
2232 return r;
2233 }
2234
2235 int unit_file_preset(
2236 UnitFileScope scope,
2237 bool runtime,
2238 const char *root_dir,
2239 char **files,
2240 UnitFilePresetMode mode,
2241 bool force,
2242 UnitFileChange **changes,
2243 unsigned *n_changes) {
2244
2245 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2246 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2247 _cleanup_free_ char *config_path = NULL;
2248 char **i;
2249 int r;
2250
2251 assert(scope >= 0);
2252 assert(scope < _UNIT_FILE_SCOPE_MAX);
2253 assert(mode < _UNIT_FILE_PRESET_MAX);
2254
2255 r = verify_root_dir(scope, &root_dir);
2256 if (r < 0)
2257 return r;
2258
2259 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2260 if (r < 0)
2261 return r;
2262
2263 r = get_config_path(scope, runtime, root_dir, &config_path);
2264 if (r < 0)
2265 return r;
2266
2267 STRV_FOREACH(i, files) {
2268 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2269 return -EINVAL;
2270
2271 r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, *i);
2272 if (r < 0)
2273 return r;
2274 }
2275
2276 return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, files, mode, force, changes, n_changes);
2277 }
2278
2279 int unit_file_preset_all(
2280 UnitFileScope scope,
2281 bool runtime,
2282 const char *root_dir,
2283 UnitFilePresetMode mode,
2284 bool force,
2285 UnitFileChange **changes,
2286 unsigned *n_changes) {
2287
2288 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2289 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2290 _cleanup_free_ char *config_path = NULL;
2291 char **i;
2292 int r;
2293
2294 assert(scope >= 0);
2295 assert(scope < _UNIT_FILE_SCOPE_MAX);
2296 assert(mode < _UNIT_FILE_PRESET_MAX);
2297
2298 r = verify_root_dir(scope, &root_dir);
2299 if (r < 0)
2300 return r;
2301
2302 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2303 if (r < 0)
2304 return r;
2305
2306 r = get_config_path(scope, runtime, root_dir, &config_path);
2307 if (r < 0)
2308 return r;
2309
2310 STRV_FOREACH(i, paths.unit_path) {
2311 _cleanup_closedir_ DIR *d = NULL;
2312 _cleanup_free_ char *units_dir;
2313 struct dirent *de;
2314
2315 units_dir = path_join(root_dir, *i, NULL);
2316 if (!units_dir)
2317 return -ENOMEM;
2318
2319 d = opendir(units_dir);
2320 if (!d) {
2321 if (errno == ENOENT)
2322 continue;
2323
2324 return -errno;
2325 }
2326
2327 FOREACH_DIRENT(de, d, return -errno) {
2328
2329 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2330 continue;
2331
2332 dirent_ensure_type(d, de);
2333
2334 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2335 continue;
2336
2337 r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, de->d_name);
2338 if (r < 0)
2339 return r;
2340 }
2341 }
2342
2343 return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, NULL, mode, force, changes, n_changes);
2344 }
2345
2346 static void unit_file_list_free_one(UnitFileList *f) {
2347 if (!f)
2348 return;
2349
2350 free(f->path);
2351 free(f);
2352 }
2353
2354 Hashmap* unit_file_list_free(Hashmap *h) {
2355 UnitFileList *i;
2356
2357 while ((i = hashmap_steal_first(h)))
2358 unit_file_list_free_one(i);
2359
2360 return hashmap_free(h);
2361 }
2362
2363 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2364
2365 int unit_file_get_list(
2366 UnitFileScope scope,
2367 const char *root_dir,
2368 Hashmap *h) {
2369
2370 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2371 char **i;
2372 int r;
2373
2374 assert(scope >= 0);
2375 assert(scope < _UNIT_FILE_SCOPE_MAX);
2376 assert(h);
2377
2378 r = verify_root_dir(scope, &root_dir);
2379 if (r < 0)
2380 return r;
2381
2382 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2383 if (r < 0)
2384 return r;
2385
2386 STRV_FOREACH(i, paths.unit_path) {
2387 _cleanup_closedir_ DIR *d = NULL;
2388 _cleanup_free_ char *units_dir;
2389 struct dirent *de;
2390
2391 units_dir = path_join(root_dir, *i, NULL);
2392 if (!units_dir)
2393 return -ENOMEM;
2394
2395 d = opendir(units_dir);
2396 if (!d) {
2397 if (errno == ENOENT)
2398 continue;
2399
2400 return -errno;
2401 }
2402
2403 FOREACH_DIRENT(de, d, return -errno) {
2404 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2405
2406 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2407 continue;
2408
2409 if (hashmap_get(h, de->d_name))
2410 continue;
2411
2412 dirent_ensure_type(d, de);
2413
2414 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2415 continue;
2416
2417 f = new0(UnitFileList, 1);
2418 if (!f)
2419 return -ENOMEM;
2420
2421 f->path = path_make_absolute(de->d_name, units_dir);
2422 if (!f->path)
2423 return -ENOMEM;
2424
2425 r = unit_file_lookup_state(scope, root_dir, &paths, basename(f->path), &f->state);
2426 if (r < 0)
2427 f->state = UNIT_FILE_BAD;
2428
2429 r = hashmap_put(h, basename(f->path), f);
2430 if (r < 0)
2431 return r;
2432
2433 f = NULL; /* prevent cleanup */
2434 }
2435 }
2436
2437 return 0;
2438 }
2439
2440 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2441 [UNIT_FILE_ENABLED] = "enabled",
2442 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2443 [UNIT_FILE_LINKED] = "linked",
2444 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2445 [UNIT_FILE_MASKED] = "masked",
2446 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2447 [UNIT_FILE_STATIC] = "static",
2448 [UNIT_FILE_DISABLED] = "disabled",
2449 [UNIT_FILE_INDIRECT] = "indirect",
2450 [UNIT_FILE_BAD] = "bad",
2451 };
2452
2453 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2454
2455 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2456 [UNIT_FILE_SYMLINK] = "symlink",
2457 [UNIT_FILE_UNLINK] = "unlink",
2458 };
2459
2460 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2461
2462 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2463 [UNIT_FILE_PRESET_FULL] = "full",
2464 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2465 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2466 };
2467
2468 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);