chiark / gitweb /
systemctl,core: allow nuking of symlinks to removed units
[elogind.git] / src / shared / install.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty <of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fnmatch.h>
27
28 #include "util.h"
29 #include "mkdir.h"
30 #include "hashmap.h"
31 #include "set.h"
32 #include "path-util.h"
33 #include "path-lookup.h"
34 #include "strv.h"
35 #include "unit-name.h"
36 #include "install.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
41
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 *path = 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
518                 /* First look in runtime config path */
519                 r = get_config_path(scope, true, root_dir, &path);
520                 if (r < 0)
521                         return r;
522
523                 r = find_symlinks(name, path, &same_name_link_runtime);
524                 if (r < 0)
525                         return r;
526                 else if (r > 0) {
527                         *state = UNIT_FILE_ENABLED_RUNTIME;
528                         return r;
529                 }
530         }
531
532         /* Then look in the normal config path */
533         r = get_config_path(scope, false, root_dir, &path);
534         if (r < 0)
535                 return r;
536
537         r = find_symlinks(name, path, &same_name_link);
538         if (r < 0)
539                 return r;
540         else if (r > 0) {
541                 *state = UNIT_FILE_ENABLED;
542                 return r;
543         }
544
545         /* Hmm, we didn't find it, but maybe we found the same name
546          * link? */
547         if (same_name_link_runtime) {
548                 *state = UNIT_FILE_LINKED_RUNTIME;
549                 return 1;
550         } else if (same_name_link) {
551                 *state = UNIT_FILE_LINKED;
552                 return 1;
553         }
554
555         return 0;
556 }
557
558 int unit_file_mask(
559                 UnitFileScope scope,
560                 bool runtime,
561                 const char *root_dir,
562                 char *files[],
563                 bool force,
564                 UnitFileChange **changes,
565                 unsigned *n_changes) {
566
567         char **i;
568         _cleanup_free_ char *prefix;
569         int r;
570
571         assert(scope >= 0);
572         assert(scope < _UNIT_FILE_SCOPE_MAX);
573
574         r = get_config_path(scope, runtime, root_dir, &prefix);
575         if (r < 0)
576                 return r;
577
578         STRV_FOREACH(i, files) {
579                 _cleanup_free_ char *path = NULL;
580
581                 if (!unit_name_is_valid(*i, true)) {
582                         if (r == 0)
583                                 r = -EINVAL;
584                         continue;
585                 }
586
587                 path = path_make_absolute(*i, prefix);
588                 if (!path) {
589                         r = -ENOMEM;
590                         break;
591                 }
592
593                 if (symlink("/dev/null", path) >= 0) {
594                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
595
596                         continue;
597                 }
598
599                 if (errno == EEXIST) {
600
601                         if (null_or_empty_path(path) > 0)
602                                 continue;
603
604                         if (force) {
605                                 unlink(path);
606
607                                 if (symlink("/dev/null", path) >= 0) {
608
609                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
610                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
611
612                                         continue;
613                                 }
614                         }
615
616                         if (r == 0)
617                                 r = -EEXIST;
618                 } else {
619                         if (r == 0)
620                                 r = -errno;
621                 }
622         }
623
624         return r;
625 }
626
627 int unit_file_unmask(
628                 UnitFileScope scope,
629                 bool runtime,
630                 const char *root_dir,
631                 char *files[],
632                 UnitFileChange **changes,
633                 unsigned *n_changes) {
634
635         char **i, *config_path = NULL;
636         int r, q;
637         Set *remove_symlinks_to = NULL;
638
639         assert(scope >= 0);
640         assert(scope < _UNIT_FILE_SCOPE_MAX);
641
642         r = get_config_path(scope, runtime, root_dir, &config_path);
643         if (r < 0)
644                 goto finish;
645
646         STRV_FOREACH(i, files) {
647                 char *path;
648
649                 if (!unit_name_is_valid(*i, true)) {
650                         if (r == 0)
651                                 r = -EINVAL;
652                         continue;
653                 }
654
655                 path = path_make_absolute(*i, config_path);
656                 if (!path) {
657                         r = -ENOMEM;
658                         break;
659                 }
660
661                 q = null_or_empty_path(path);
662                 if (q > 0) {
663                         if (unlink(path) >= 0) {
664                                 mark_symlink_for_removal(&remove_symlinks_to, path);
665                                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
666
667                                 free(path);
668                                 continue;
669                         }
670
671                         q = -errno;
672                 }
673
674                 if (q != -ENOENT && r == 0)
675                         r = q;
676
677                 free(path);
678         }
679
680
681 finish:
682         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
683         if (r == 0)
684                 r = q;
685
686         set_free_free(remove_symlinks_to);
687         free(config_path);
688
689         return r;
690 }
691
692 int unit_file_link(
693                 UnitFileScope scope,
694                 bool runtime,
695                 const char *root_dir,
696                 char *files[],
697                 bool force,
698                 UnitFileChange **changes,
699                 unsigned *n_changes) {
700
701         _cleanup_lookup_paths_free_ LookupPaths paths = {};
702         char **i;
703         _cleanup_free_ char *config_path = NULL;
704         int r, q;
705
706         assert(scope >= 0);
707         assert(scope < _UNIT_FILE_SCOPE_MAX);
708
709         r = lookup_paths_init_from_scope(&paths, scope);
710         if (r < 0)
711                 return r;
712
713         r = get_config_path(scope, runtime, root_dir, &config_path);
714         if (r < 0)
715                 return r;
716
717         STRV_FOREACH(i, files) {
718                 _cleanup_free_ char *path = NULL;
719                 char *fn;
720                 struct stat st;
721
722                 fn = path_get_file_name(*i);
723
724                 if (!path_is_absolute(*i) ||
725                     !unit_name_is_valid(fn, true)) {
726                         if (r == 0)
727                                 r = -EINVAL;
728                         continue;
729                 }
730
731                 if (lstat(*i, &st) < 0) {
732                         if (r == 0)
733                                 r = -errno;
734                         continue;
735                 }
736
737                 if (!S_ISREG(st.st_mode)) {
738                         r = -ENOENT;
739                         continue;
740                 }
741
742                 q = in_search_path(*i, paths.unit_path);
743                 if (q < 0)
744                         return q;
745
746                 if (q > 0)
747                         continue;
748
749                 path = path_make_absolute(fn, config_path);
750                 if (!path)
751                         return -ENOMEM;
752
753                 if (symlink(*i, path) >= 0) {
754                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
755                         continue;
756                 }
757
758                 if (errno == EEXIST) {
759                         _cleanup_free_ char *dest = NULL;
760
761                         q = readlink_and_make_absolute(path, &dest);
762
763                         if (q < 0 && errno != ENOENT) {
764                                 if (r == 0)
765                                         r = q;
766                                 continue;
767                         }
768
769                         if (q >= 0 && path_equal(dest, *i))
770                                 continue;
771
772                         if (force) {
773                                 unlink(path);
774
775                                 if (symlink(*i, path) >= 0) {
776
777                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
778                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
779
780                                         continue;
781                                 }
782                         }
783
784                         if (r == 0)
785                                 r = -EEXIST;
786                 } else {
787                         if (r == 0)
788                                 r = -errno;
789                 }
790         }
791
792         return r;
793 }
794
795 void unit_file_list_free(Hashmap *h) {
796         UnitFileList *i;
797
798         while ((i = hashmap_steal_first(h))) {
799                 free(i->path);
800                 free(i);
801         }
802
803         hashmap_free(h);
804 }
805
806 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
807         unsigned i;
808
809         assert(changes || n_changes == 0);
810
811         if (!changes)
812                 return;
813
814         for (i = 0; i < n_changes; i++) {
815                 free(changes[i].path);
816                 free(changes[i].source);
817         }
818
819         free(changes);
820 }
821
822 static void install_info_free(InstallInfo *i) {
823         assert(i);
824
825         free(i->name);
826         free(i->path);
827         strv_free(i->aliases);
828         strv_free(i->wanted_by);
829         strv_free(i->required_by);
830         free(i);
831 }
832
833 static void install_info_hashmap_free(Hashmap *m) {
834         InstallInfo *i;
835
836         if (!m)
837                 return;
838
839         while ((i = hashmap_steal_first(m)))
840                 install_info_free(i);
841
842         hashmap_free(m);
843 }
844
845 static void install_context_done(InstallContext *c) {
846         assert(c);
847
848         install_info_hashmap_free(c->will_install);
849         install_info_hashmap_free(c->have_installed);
850
851         c->will_install = c->have_installed = NULL;
852 }
853
854 static int install_info_add(
855                 InstallContext *c,
856                 const char *name,
857                 const char *path) {
858         InstallInfo *i = NULL;
859         int r;
860
861         assert(c);
862         assert(name || path);
863
864         if (!name)
865                 name = path_get_file_name(path);
866
867         if (!unit_name_is_valid(name, true))
868                 return -EINVAL;
869
870         if (hashmap_get(c->have_installed, name) ||
871             hashmap_get(c->will_install, name))
872                 return 0;
873
874         r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
875         if (r < 0)
876                 return r;
877
878         i = new0(InstallInfo, 1);
879         if (!i)
880                 return -ENOMEM;
881
882         i->name = strdup(name);
883         if (!i->name) {
884                 r = -ENOMEM;
885                 goto fail;
886         }
887
888         if (path) {
889                 i->path = strdup(path);
890                 if (!i->path) {
891                         r = -ENOMEM;
892                         goto fail;
893                 }
894         }
895
896         r = hashmap_put(c->will_install, i->name, i);
897         if (r < 0)
898                 goto fail;
899
900         return 0;
901
902 fail:
903         if (i)
904                 install_info_free(i);
905
906         return r;
907 }
908
909 static int install_info_add_auto(
910                 InstallContext *c,
911                 const char *name_or_path) {
912
913         assert(c);
914         assert(name_or_path);
915
916         if (path_is_absolute(name_or_path))
917                 return install_info_add(c, NULL, name_or_path);
918         else
919                 return install_info_add(c, name_or_path, NULL);
920 }
921
922 static int config_parse_also(const char *unit,
923                              const char *filename,
924                              unsigned line,
925                              const char *section,
926                              const char *lvalue,
927                              int ltype,
928                              const char *rvalue,
929                              void *data,
930                              void *userdata) {
931
932         char *w;
933         size_t l;
934         char *state;
935         InstallContext *c = data;
936
937         assert(filename);
938         assert(lvalue);
939         assert(rvalue);
940
941         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
942                 _cleanup_free_ char *n;
943                 int r;
944
945                 n = strndup(w, l);
946                 if (!n)
947                         return -ENOMEM;
948
949                 r = install_info_add(c, n, NULL);
950                 if (r < 0)
951                         return r;
952         }
953
954         return 0;
955 }
956
957 static int config_parse_user(const char *unit,
958                              const char *filename,
959                              unsigned line,
960                              const char *section,
961                              const char *lvalue,
962                              int ltype,
963                              const char *rvalue,
964                              void *data,
965                              void *userdata) {
966
967         InstallInfo *i = data;
968         char* printed;
969
970         assert(filename);
971         assert(lvalue);
972         assert(rvalue);
973
974         printed = install_full_printf(i, rvalue);
975         if (!printed)
976                 return -ENOMEM;
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 request */
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                 dst = install_full_printf(i, *s);
1203                 if (!dst)
1204                         return -ENOMEM;
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                 dst = install_full_printf(i, *s);
1235                 if (!dst)
1236                         return -ENOMEM;
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                 dst = install_full_printf(i, *s);
1272                 if (!dst)
1273                         return -ENOMEM;
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 = NULL;
1428
1429                         unit_file = path_get_file_name(i->path);
1430
1431                         if (unit_name_is_instance(unit_file))
1432                                 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1433                                 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1434                         else
1435                                 /* does not exist, thus we will mark for removal symlinks to template unit file */
1436                                 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1437                 } else
1438                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1439
1440                 if (r >= 0 && q < 0)
1441                         r = q;
1442         }
1443
1444         return r;
1445 }
1446
1447 int unit_file_enable(
1448                 UnitFileScope scope,
1449                 bool runtime,
1450                 const char *root_dir,
1451                 char *files[],
1452                 bool force,
1453                 UnitFileChange **changes,
1454                 unsigned *n_changes) {
1455
1456         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1457         _cleanup_install_context_done_ InstallContext c = {};
1458         char **i;
1459         _cleanup_free_ char *config_path = NULL;
1460         int r;
1461
1462         assert(scope >= 0);
1463         assert(scope < _UNIT_FILE_SCOPE_MAX);
1464
1465         r = lookup_paths_init_from_scope(&paths, scope);
1466         if (r < 0)
1467                 return r;
1468
1469         r = get_config_path(scope, runtime, root_dir, &config_path);
1470         if (r < 0)
1471                 return r;
1472
1473         STRV_FOREACH(i, files) {
1474                 r = install_info_add_auto(&c, *i);
1475                 if (r < 0)
1476                         return r;
1477         }
1478
1479         /* This will return the number of symlink rules that were
1480         supposed to be created, not the ones actually created. This is
1481         useful to determine whether the passed files had any
1482         installation data at all. */
1483         r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1484         return r;
1485 }
1486
1487 int unit_file_disable(
1488                 UnitFileScope scope,
1489                 bool runtime,
1490                 const char *root_dir,
1491                 char *files[],
1492                 UnitFileChange **changes,
1493                 unsigned *n_changes) {
1494
1495         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1496         _cleanup_install_context_done_ InstallContext c = {};
1497         char **i;
1498         _cleanup_free_ char *config_path = NULL;
1499         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1500         int r, q;
1501
1502         assert(scope >= 0);
1503         assert(scope < _UNIT_FILE_SCOPE_MAX);
1504
1505         r = lookup_paths_init_from_scope(&paths, scope);
1506         if (r < 0)
1507                 return r;
1508
1509         r = get_config_path(scope, runtime, root_dir, &config_path);
1510         if (r < 0)
1511                 return r;
1512
1513         STRV_FOREACH(i, files) {
1514                 r = install_info_add_auto(&c, *i);
1515                 if (r < 0)
1516                         return r;
1517         }
1518
1519         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1520
1521         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1522         if (r == 0)
1523                 r = q;
1524
1525         return r;
1526 }
1527
1528 int unit_file_reenable(
1529                 UnitFileScope scope,
1530                 bool runtime,
1531                 const char *root_dir,
1532                 char *files[],
1533                 bool force,
1534                 UnitFileChange **changes,
1535                 unsigned *n_changes) {
1536
1537         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1538         _cleanup_install_context_done_ InstallContext c = {};
1539         char **i;
1540         _cleanup_free_ char *config_path = NULL;
1541         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1542         int r, q;
1543
1544         assert(scope >= 0);
1545         assert(scope < _UNIT_FILE_SCOPE_MAX);
1546
1547         r = lookup_paths_init_from_scope(&paths, scope);
1548         if (r < 0)
1549                 return r;
1550
1551         r = get_config_path(scope, runtime, root_dir, &config_path);
1552         if (r < 0)
1553                 return r;
1554
1555         STRV_FOREACH(i, files) {
1556                 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1557                 if (r < 0)
1558                         return r;
1559
1560                 r = install_info_add_auto(&c, *i);
1561                 if (r < 0)
1562                         return r;
1563         }
1564
1565         r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1566
1567         /* Returns number of symlinks that where supposed to be installed. */
1568         q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1569         if (r == 0)
1570                 r = q;
1571
1572         return r;
1573 }
1574
1575 int unit_file_set_default(
1576                 UnitFileScope scope,
1577                 const char *root_dir,
1578                 char *file,
1579                 UnitFileChange **changes,
1580                 unsigned *n_changes) {
1581
1582         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1583         _cleanup_install_context_done_ InstallContext c = {};
1584         _cleanup_free_ char *config_path = NULL;
1585         char *path;
1586         int r;
1587         InstallInfo *i = NULL;
1588
1589         assert(scope >= 0);
1590         assert(scope < _UNIT_FILE_SCOPE_MAX);
1591
1592         if (unit_name_to_type(file) != UNIT_TARGET)
1593                 return -EINVAL;
1594
1595         r = lookup_paths_init_from_scope(&paths, scope);
1596         if (r < 0)
1597                 return r;
1598
1599         r = get_config_path(scope, false, root_dir, &config_path);
1600         if (r < 0)
1601                 return r;
1602
1603         r = install_info_add_auto(&c, file);
1604         if (r < 0)
1605                 return r;
1606
1607         i = (InstallInfo*)hashmap_first(c.will_install);
1608
1609         r = unit_file_search(&c, i, &paths, root_dir, false);
1610         if (r < 0)
1611                 return r;
1612
1613         path = strappenda(config_path, "/default.target");
1614         r = create_symlink(i->path, path, true, changes, n_changes);
1615         if (r < 0)
1616                 return r;
1617
1618         return 0;
1619 }
1620
1621 int unit_file_get_default(
1622                 UnitFileScope scope,
1623                 const char *root_dir,
1624                 char **name) {
1625
1626         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1627         char **p;
1628         int r;
1629
1630         r = lookup_paths_init_from_scope(&paths, scope);
1631         if (r < 0)
1632                 return r;
1633
1634         STRV_FOREACH(p, paths.unit_path) {
1635                 _cleanup_free_ char *path = NULL, *tmp = NULL;
1636
1637                 if (isempty(root_dir))
1638                         path = strappend(*p, "/default.target");
1639                 else
1640                         path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1641
1642                 if (!path)
1643                         return -ENOMEM;
1644
1645                 r = readlink_malloc(path, &tmp);
1646                 if (r == -ENOENT)
1647                         continue;
1648                 else if (r < 0)
1649                         return r;
1650
1651                 *name = strdup(path_get_file_name(tmp));
1652                 if (!*name)
1653                         return -ENOMEM;
1654
1655                 return 0;
1656         }
1657
1658         return -ENOENT;
1659 }
1660
1661 UnitFileState unit_file_get_state(
1662                 UnitFileScope scope,
1663                 const char *root_dir,
1664                 const char *name) {
1665
1666         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1667         UnitFileState state = _UNIT_FILE_STATE_INVALID;
1668         char **i;
1669         _cleanup_free_ char *path = NULL;
1670         int r;
1671
1672         assert(scope >= 0);
1673         assert(scope < _UNIT_FILE_SCOPE_MAX);
1674         assert(name);
1675
1676         if (root_dir && scope != UNIT_FILE_SYSTEM)
1677                 return -EINVAL;
1678
1679         if (!unit_name_is_valid(name, true))
1680                 return -EINVAL;
1681
1682         r = lookup_paths_init_from_scope(&paths, scope);
1683         if (r < 0)
1684                 return r;
1685
1686         STRV_FOREACH(i, paths.unit_path) {
1687                 struct stat st;
1688
1689                 free(path);
1690                 path = NULL;
1691
1692                 if (root_dir)
1693                         asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1694                 else
1695                         asprintf(&path, "%s/%s", *i, name);
1696
1697                 if (!path)
1698                         return -ENOMEM;
1699
1700                 /*
1701                  * Search for a unit file in our default paths, to
1702                  * be sure, that there are no broken symlinks.
1703                  */
1704                 if (lstat(path, &st) < 0) {
1705                         r = -errno;
1706                         if (errno != ENOENT)
1707                                 return r;
1708
1709                         if (!unit_name_is_instance(name))
1710                                 continue;
1711                 } else {
1712                         if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1713                                 return -ENOENT;
1714
1715                         r = null_or_empty_path(path);
1716                         if (r < 0 && r != -ENOENT)
1717                                 return r;
1718                         else if (r > 0) {
1719                                 state = path_startswith(*i, "/run") ?
1720                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1721                                 return state;
1722                         }
1723                 }
1724
1725                 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1726                 if (r < 0)
1727                         return r;
1728                 else if (r > 0)
1729                         return state;
1730
1731                 r = unit_file_can_install(&paths, root_dir, path, true);
1732                 if (r < 0 && errno != ENOENT)
1733                         return r;
1734                 else if (r > 0)
1735                         return UNIT_FILE_DISABLED;
1736                 else if (r == 0)
1737                         return UNIT_FILE_STATIC;
1738         }
1739
1740         return r < 0 ? r : state;
1741 }
1742
1743 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1744         _cleanup_strv_free_ char **files = NULL;
1745         char **i;
1746         int r;
1747
1748         assert(scope >= 0);
1749         assert(scope < _UNIT_FILE_SCOPE_MAX);
1750         assert(name);
1751
1752         if (scope == UNIT_FILE_SYSTEM)
1753                 r = conf_files_list(&files, ".preset", NULL,
1754                                     "/etc/systemd/system-preset",
1755                                     "/usr/local/lib/systemd/system-preset",
1756                                     "/usr/lib/systemd/system-preset",
1757 #ifdef HAVE_SPLIT_USR
1758                                     "/lib/systemd/system-preset",
1759 #endif
1760                                     NULL);
1761         else if (scope == UNIT_FILE_GLOBAL)
1762                 r = conf_files_list(&files, ".preset", NULL,
1763                                     "/etc/systemd/user-preset",
1764                                     "/usr/local/lib/systemd/user-preset",
1765                                     "/usr/lib/systemd/user-preset",
1766                                     NULL);
1767         else
1768                 return 1;
1769
1770         if (r < 0)
1771                 return r;
1772
1773         STRV_FOREACH(i, files) {
1774                 _cleanup_fclose_ FILE *f;
1775
1776                 f = fopen(*i, "re");
1777                 if (!f) {
1778                         if (errno == ENOENT)
1779                                 continue;
1780
1781                         return -errno;
1782                 }
1783
1784                 for (;;) {
1785                         char line[LINE_MAX], *l;
1786
1787                         if (!fgets(line, sizeof(line), f))
1788                                 break;
1789
1790                         l = strstrip(line);
1791                         if (!*l)
1792                                 continue;
1793
1794                         if (strchr(COMMENTS "\n", *l))
1795                                 continue;
1796
1797                         if (first_word(l, "enable")) {
1798                                 l += 6;
1799                                 l += strspn(l, WHITESPACE);
1800
1801                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1802                                         return 1;
1803
1804                         } else if (first_word(l, "disable")) {
1805                                 l += 7;
1806                                 l += strspn(l, WHITESPACE);
1807
1808                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1809                                         return 0;
1810
1811                         } else
1812                                 log_debug("Couldn't parse line '%s'", l);
1813                 }
1814         }
1815
1816         /* Default is "enable" */
1817         return 1;
1818 }
1819
1820 int unit_file_preset(
1821                 UnitFileScope scope,
1822                 bool runtime,
1823                 const char *root_dir,
1824                 char *files[],
1825                 bool force,
1826                 UnitFileChange **changes,
1827                 unsigned *n_changes) {
1828
1829         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1830         _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1831         char **i;
1832         _cleanup_free_ char *config_path = NULL;
1833         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1834         int r, q;
1835
1836         assert(scope >= 0);
1837         assert(scope < _UNIT_FILE_SCOPE_MAX);
1838
1839         r = lookup_paths_init_from_scope(&paths, scope);
1840         if (r < 0)
1841                 return r;
1842
1843         r = get_config_path(scope, runtime, root_dir, &config_path);
1844         if (r < 0)
1845                 return r;
1846
1847         STRV_FOREACH(i, files) {
1848
1849                 if (!unit_name_is_valid(*i, true))
1850                         return -EINVAL;
1851
1852                 r = unit_file_query_preset(scope, *i);
1853                 if (r < 0)
1854                         return r;
1855
1856                 if (r)
1857                         r = install_info_add_auto(&plus, *i);
1858                 else
1859                         r = install_info_add_auto(&minus, *i);
1860
1861                 if (r < 0)
1862                         return r;
1863         }
1864
1865         r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1866                                              config_path, root_dir);
1867
1868         q = remove_marked_symlinks(remove_symlinks_to, config_path,
1869                                    changes, n_changes, files);
1870         if (r == 0)
1871                 r = q;
1872
1873         /* Returns number of symlinks that where supposed to be installed. */
1874         q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1875                                   changes, n_changes);
1876         if (r == 0)
1877                 r = q;
1878
1879         return r;
1880 }
1881
1882 static void unitfilelist_free(UnitFileList **f) {
1883         if (!*f)
1884                 return;
1885
1886         free((*f)->path);
1887         free(*f);
1888 }
1889
1890 int unit_file_get_list(
1891                 UnitFileScope scope,
1892                 const char *root_dir,
1893                 Hashmap *h) {
1894
1895         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1896         char **i;
1897         _cleanup_free_ char *buf = NULL;
1898         _cleanup_closedir_ DIR *d = NULL;
1899         int r;
1900
1901         assert(scope >= 0);
1902         assert(scope < _UNIT_FILE_SCOPE_MAX);
1903         assert(h);
1904
1905         if (root_dir && scope != UNIT_FILE_SYSTEM)
1906                 return -EINVAL;
1907
1908         r = lookup_paths_init_from_scope(&paths, scope);
1909         if (r < 0)
1910                 return r;
1911
1912         STRV_FOREACH(i, paths.unit_path) {
1913                 const char *units_dir;
1914
1915                 free(buf);
1916                 buf = NULL;
1917
1918                 if (root_dir) {
1919                         if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1920                                 return -ENOMEM;
1921
1922                         units_dir = buf;
1923                 } else
1924                         units_dir = *i;
1925
1926                 if (d)
1927                         closedir(d);
1928
1929                 d = opendir(units_dir);
1930                 if (!d) {
1931                         if (errno == ENOENT)
1932                                 continue;
1933
1934                         return -errno;
1935                 }
1936
1937                 for (;;) {
1938                         struct dirent *de;
1939                         union dirent_storage buffer;
1940                         UnitFileList __attribute__((cleanup(unitfilelist_free)))
1941                                 *f = NULL;
1942
1943                         r = readdir_r(d, &buffer.de, &de);
1944                         if (r != 0)
1945                                 return -r;
1946
1947                         if (!de)
1948                                 break;
1949
1950                         if (ignore_file(de->d_name))
1951                                 continue;
1952
1953                         if (!unit_name_is_valid(de->d_name, true))
1954                                 continue;
1955
1956                         if (hashmap_get(h, de->d_name))
1957                                 continue;
1958
1959                         r = dirent_ensure_type(d, de);
1960                         if (r < 0) {
1961                                 if (r == -ENOENT)
1962                                         continue;
1963
1964                                 return r;
1965                         }
1966
1967                         if (de->d_type != DT_LNK && de->d_type != DT_REG)
1968                                 continue;
1969
1970                         f = new0(UnitFileList, 1);
1971                         if (!f)
1972                                 return -ENOMEM;
1973
1974                         f->path = path_make_absolute(de->d_name, units_dir);
1975                         if (!f->path)
1976                                 return -ENOMEM;
1977
1978                         r = null_or_empty_path(f->path);
1979                         if (r < 0 && r != -ENOENT)
1980                                 return r;
1981                         else if (r > 0) {
1982                                 f->state =
1983                                         path_startswith(*i, "/run") ?
1984                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1985                                 goto found;
1986                         }
1987
1988                         r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1989                         if (r < 0)
1990                                 return r;
1991                         else if (r > 0) {
1992                                 f->state = UNIT_FILE_ENABLED;
1993                                 goto found;
1994                         }
1995
1996                         r = unit_file_can_install(&paths, root_dir, f->path, true);
1997                         if (r == -EINVAL ||  /* Invalid setting? */
1998                             r == -EBADMSG || /* Invalid format? */
1999                             r == -ENOENT     /* Included file not found? */)
2000                                 f->state = UNIT_FILE_INVALID;
2001                         else if (r < 0)
2002                                 return r;
2003                         else if (r > 0)
2004                                 f->state = UNIT_FILE_DISABLED;
2005                         else
2006                                 f->state = UNIT_FILE_STATIC;
2007
2008                 found:
2009                         r = hashmap_put(h, path_get_file_name(f->path), f);
2010                         if (r < 0)
2011                                 return r;
2012                         f = NULL; /* prevent cleanup */
2013                 }
2014         }
2015
2016         return r;
2017 }
2018
2019 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2020         [UNIT_FILE_ENABLED] = "enabled",
2021         [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2022         [UNIT_FILE_LINKED] = "linked",
2023         [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2024         [UNIT_FILE_MASKED] = "masked",
2025         [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2026         [UNIT_FILE_STATIC] = "static",
2027         [UNIT_FILE_DISABLED] = "disabled",
2028         [UNIT_FILE_INVALID] = "invalid",
2029 };
2030
2031 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2032
2033 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2034         [UNIT_FILE_SYMLINK] = "symlink",
2035         [UNIT_FILE_UNLINK] = "unlink",
2036 };
2037
2038 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);