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