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