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