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