chiark / gitweb /
install: simplify and clarify disabling logic for instanced units
[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                 bool force,
1835                 UnitFileChange **changes,
1836                 unsigned *n_changes) {
1837
1838         _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1839         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
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
1848         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1849         if (r < 0)
1850                 return r;
1851
1852         r = get_config_path(scope, runtime, root_dir, &config_path);
1853         if (r < 0)
1854                 return r;
1855
1856         STRV_FOREACH(i, files) {
1857
1858                 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1859                         return -EINVAL;
1860
1861                 r = unit_file_query_preset(scope, *i);
1862                 if (r < 0)
1863                         return r;
1864
1865                 if (r)
1866                         r = install_info_add_auto(&plus, *i);
1867                 else
1868                         r = install_info_add_auto(&minus, *i);
1869                 if (r < 0)
1870                         return r;
1871         }
1872
1873         r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1874
1875         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1876         if (r == 0)
1877                 r = q;
1878
1879         /* Returns number of symlinks that where supposed to be installed. */
1880         q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1881                                   changes, n_changes);
1882         if (r == 0)
1883                 r = q;
1884
1885         return r;
1886 }
1887
1888 static void unitfilelist_free(UnitFileList **f) {
1889         if (!*f)
1890                 return;
1891
1892         free((*f)->path);
1893         free(*f);
1894 }
1895 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1896
1897 int unit_file_get_list(
1898                 UnitFileScope scope,
1899                 const char *root_dir,
1900                 Hashmap *h) {
1901
1902         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1903         char **i;
1904         int r;
1905
1906         assert(scope >= 0);
1907         assert(scope < _UNIT_FILE_SCOPE_MAX);
1908         assert(h);
1909
1910         if (root_dir && scope != UNIT_FILE_SYSTEM)
1911                 return -EINVAL;
1912
1913         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1914         if (r < 0)
1915                 return r;
1916
1917         STRV_FOREACH(i, paths.unit_path) {
1918                 _cleanup_closedir_ DIR *d = NULL;
1919                 _cleanup_free_ char *buf = NULL;
1920                 const char *units_dir;
1921
1922                 if (!isempty(root_dir)) {
1923                         buf = strjoin(root_dir, "/", *i, NULL);
1924                         if (!buf)
1925                                 return -ENOMEM;
1926
1927                         units_dir = buf;
1928                 } else
1929                         units_dir = *i;
1930
1931                 d = opendir(units_dir);
1932                 if (!d) {
1933                         if (errno == ENOENT)
1934                                 continue;
1935
1936                         return -errno;
1937                 }
1938
1939                 for (;;) {
1940                         struct dirent *de;
1941                         _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1942
1943                         errno = 0;
1944                         de = readdir(d);
1945                         if (!de && errno != 0)
1946                                 return -errno;
1947
1948                         if (!de)
1949                                 break;
1950
1951                         if (ignore_file(de->d_name))
1952                                 continue;
1953
1954                         if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1955                                 continue;
1956
1957                         if (hashmap_get(h, de->d_name))
1958                                 continue;
1959
1960                         dirent_ensure_type(d, de);
1961
1962                         if (!IN_SET(de->d_type, DT_LNK, DT_REG))
1963                                 continue;
1964
1965                         f = new0(UnitFileList, 1);
1966                         if (!f)
1967                                 return -ENOMEM;
1968
1969                         f->path = path_make_absolute(de->d_name, units_dir);
1970                         if (!f->path)
1971                                 return -ENOMEM;
1972
1973                         r = null_or_empty_path(f->path);
1974                         if (r < 0 && r != -ENOENT)
1975                                 return r;
1976                         else if (r > 0) {
1977                                 f->state =
1978                                         path_startswith(*i, "/run") ?
1979                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1980                                 goto found;
1981                         }
1982
1983                         r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1984                         if (r < 0)
1985                                 return r;
1986                         else if (r > 0) {
1987                                 f->state = UNIT_FILE_ENABLED;
1988                                 goto found;
1989                         }
1990
1991                         r = unit_file_can_install(&paths, root_dir, f->path, true);
1992                         if (r == -EINVAL ||  /* Invalid setting? */
1993                             r == -EBADMSG || /* Invalid format? */
1994                             r == -ENOENT     /* Included file not found? */)
1995                                 f->state = UNIT_FILE_INVALID;
1996                         else if (r < 0)
1997                                 return r;
1998                         else if (r > 0)
1999                                 f->state = UNIT_FILE_DISABLED;
2000                         else
2001                                 f->state = UNIT_FILE_STATIC;
2002
2003                 found:
2004                         r = hashmap_put(h, basename(f->path), f);
2005                         if (r < 0)
2006                                 return r;
2007                         f = NULL; /* prevent cleanup */
2008                 }
2009         }
2010
2011         return r;
2012 }
2013
2014 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2015         [UNIT_FILE_ENABLED] = "enabled",
2016         [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2017         [UNIT_FILE_LINKED] = "linked",
2018         [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2019         [UNIT_FILE_MASKED] = "masked",
2020         [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2021         [UNIT_FILE_STATIC] = "static",
2022         [UNIT_FILE_DISABLED] = "disabled",
2023         [UNIT_FILE_INVALID] = "invalid",
2024 };
2025
2026 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2027
2028 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2029         [UNIT_FILE_SYMLINK] = "symlink",
2030         [UNIT_FILE_UNLINK] = "unlink",
2031 };
2032
2033 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);