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