chiark / gitweb /
bus-proxyd: explicitly address messages to unique and well-known name
[elogind.git] / src / tmpfiles / tmpfiles.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering, Kay Sievers
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 <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <limits.h>
28 #include <dirent.h>
29 #include <grp.h>
30 #include <pwd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <getopt.h>
35 #include <stdbool.h>
36 #include <time.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <glob.h>
40 #include <fnmatch.h>
41 #include <sys/capability.h>
42
43 #include "log.h"
44 #include "util.h"
45 #include "macro.h"
46 #include "missing.h"
47 #include "mkdir.h"
48 #include "path-util.h"
49 #include "strv.h"
50 #include "label.h"
51 #include "set.h"
52 #include "conf-files.h"
53 #include "capability.h"
54 #include "specifier.h"
55 #include "build.h"
56 #include "copy.h"
57
58 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
59  * them in the file system. This is intended to be used to create
60  * properly owned directories beneath /tmp, /var/tmp, /run, which are
61  * volatile and hence need to be recreated on bootup. */
62
63 typedef enum ItemType {
64         /* These ones take file names */
65         CREATE_FILE = 'f',
66         TRUNCATE_FILE = 'F',
67         CREATE_DIRECTORY = 'd',
68         TRUNCATE_DIRECTORY = 'D',
69         CREATE_FIFO = 'p',
70         CREATE_SYMLINK = 'L',
71         CREATE_CHAR_DEVICE = 'c',
72         CREATE_BLOCK_DEVICE = 'b',
73         COPY_FILES = 'C',
74
75         /* These ones take globs */
76         WRITE_FILE = 'w',
77         IGNORE_PATH = 'x',
78         IGNORE_DIRECTORY_PATH = 'X',
79         REMOVE_PATH = 'r',
80         RECURSIVE_REMOVE_PATH = 'R',
81         ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
82         RELABEL_PATH = 'z',
83         RECURSIVE_RELABEL_PATH = 'Z',
84 } ItemType;
85
86 typedef struct Item {
87         ItemType type;
88
89         char *path;
90         char *argument;
91         uid_t uid;
92         gid_t gid;
93         mode_t mode;
94         usec_t age;
95
96         dev_t major_minor;
97
98         bool uid_set:1;
99         bool gid_set:1;
100         bool mode_set:1;
101         bool age_set:1;
102         bool mask_perms:1;
103
104         bool keep_first_level:1;
105
106         bool force:1;
107
108         bool done:1;
109 } Item;
110
111 static bool arg_create = false;
112 static bool arg_clean = false;
113 static bool arg_remove = false;
114 static bool arg_boot = false;
115
116 static char **arg_include_prefixes = NULL;
117 static char **arg_exclude_prefixes = NULL;
118 static char *arg_root = NULL;
119
120 static const char conf_file_dirs[] =
121         "/etc/tmpfiles.d\0"
122         "/run/tmpfiles.d\0"
123         "/usr/local/lib/tmpfiles.d\0"
124         "/usr/lib/tmpfiles.d\0"
125 #ifdef HAVE_SPLIT_USR
126         "/lib/tmpfiles.d\0"
127 #endif
128         ;
129
130 #define MAX_DEPTH 256
131
132 static Hashmap *items = NULL, *globs = NULL;
133 static Set *unix_sockets = NULL;
134
135 static bool needs_glob(ItemType t) {
136         return IN_SET(t,
137                       WRITE_FILE,
138                       IGNORE_PATH,
139                       IGNORE_DIRECTORY_PATH,
140                       REMOVE_PATH,
141                       RECURSIVE_REMOVE_PATH,
142                       ADJUST_MODE,
143                       RELABEL_PATH,
144                       RECURSIVE_RELABEL_PATH);
145 }
146
147 static struct Item* find_glob(Hashmap *h, const char *match) {
148         Item *j;
149         Iterator i;
150
151         HASHMAP_FOREACH(j, h, i)
152                 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
153                         return j;
154
155         return NULL;
156 }
157
158 static void load_unix_sockets(void) {
159         _cleanup_fclose_ FILE *f = NULL;
160         char line[LINE_MAX];
161
162         if (unix_sockets)
163                 return;
164
165         /* We maintain a cache of the sockets we found in
166          * /proc/net/unix to speed things up a little. */
167
168         unix_sockets = set_new(&string_hash_ops);
169         if (!unix_sockets)
170                 return;
171
172         f = fopen("/proc/net/unix", "re");
173         if (!f)
174                 return;
175
176         /* Skip header */
177         if (!fgets(line, sizeof(line), f))
178                 goto fail;
179
180         for (;;) {
181                 char *p, *s;
182                 int k;
183
184                 if (!fgets(line, sizeof(line), f))
185                         break;
186
187                 truncate_nl(line);
188
189                 p = strchr(line, ':');
190                 if (!p)
191                         continue;
192
193                 if (strlen(p) < 37)
194                         continue;
195
196                 p += 37;
197                 p += strspn(p, WHITESPACE);
198                 p += strcspn(p, WHITESPACE); /* skip one more word */
199                 p += strspn(p, WHITESPACE);
200
201                 if (*p != '/')
202                         continue;
203
204                 s = strdup(p);
205                 if (!s)
206                         goto fail;
207
208                 path_kill_slashes(s);
209
210                 k = set_consume(unix_sockets, s);
211                 if (k < 0 && k != -EEXIST)
212                         goto fail;
213         }
214
215         return;
216
217 fail:
218         set_free_free(unix_sockets);
219         unix_sockets = NULL;
220 }
221
222 static bool unix_socket_alive(const char *fn) {
223         assert(fn);
224
225         load_unix_sockets();
226
227         if (unix_sockets)
228                 return !!set_get(unix_sockets, (char*) fn);
229
230         /* We don't know, so assume yes */
231         return true;
232 }
233
234 static int dir_is_mount_point(DIR *d, const char *subdir) {
235
236         union file_handle_union h = {
237                 .handle.handle_bytes = MAX_HANDLE_SZ
238         };
239
240         int mount_id_parent, mount_id;
241         int r_p, r;
242
243         r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
244         if (r_p < 0)
245                 r_p = -errno;
246
247         h.handle.handle_bytes = MAX_HANDLE_SZ;
248         r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
249         if (r < 0)
250                 r = -errno;
251
252         /* got no handle; make no assumptions, return error */
253         if (r_p < 0 && r < 0)
254                 return r_p;
255
256         /* got both handles; if they differ, it is a mount point */
257         if (r_p >= 0 && r >= 0)
258                 return mount_id_parent != mount_id;
259
260         /* got only one handle; assume different mount points if one
261          * of both queries was not supported by the filesystem */
262         if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
263                 return true;
264
265         /* return error */
266         if (r_p < 0)
267                 return r_p;
268         return r;
269 }
270
271 static int dir_cleanup(
272                 Item *i,
273                 const char *p,
274                 DIR *d,
275                 const struct stat *ds,
276                 usec_t cutoff,
277                 dev_t rootdev,
278                 bool mountpoint,
279                 int maxdepth,
280                 bool keep_this_level) {
281
282         struct dirent *dent;
283         struct timespec times[2];
284         bool deleted = false;
285         int r = 0;
286
287         while ((dent = readdir(d))) {
288                 struct stat s;
289                 usec_t age;
290                 _cleanup_free_ char *sub_path = NULL;
291
292                 if (streq(dent->d_name, ".") ||
293                     streq(dent->d_name, ".."))
294                         continue;
295
296                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
297                         if (errno == ENOENT)
298                                 continue;
299
300                         /* FUSE, NFS mounts, SELinux might return EACCES */
301                         if (errno == EACCES)
302                                 log_debug("stat(%s/%s) failed: %m", p, dent->d_name);
303                         else
304                                 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
305                         r = -errno;
306                         continue;
307                 }
308
309                 /* Stay on the same filesystem */
310                 if (s.st_dev != rootdev)
311                         continue;
312
313                 /* Try to detect bind mounts of the same filesystem instance; they
314                  * do not differ in device major/minors. This type of query is not
315                  * supported on all kernels or filesystem types though. */
316                 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0)
317                         continue;
318
319                 /* Do not delete read-only files owned by root */
320                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
321                         continue;
322
323                 sub_path = strjoin(p, "/", dent->d_name, NULL);
324                 if (!sub_path) {
325                         r = log_oom();
326                         goto finish;
327                 }
328
329                 /* Is there an item configured for this path? */
330                 if (hashmap_get(items, sub_path))
331                         continue;
332
333                 if (find_glob(globs, sub_path))
334                         continue;
335
336                 if (S_ISDIR(s.st_mode)) {
337
338                         if (mountpoint &&
339                             streq(dent->d_name, "lost+found") &&
340                             s.st_uid == 0)
341                                 continue;
342
343                         if (maxdepth <= 0)
344                                 log_warning("Reached max depth on %s.", sub_path);
345                         else {
346                                 _cleanup_closedir_ DIR *sub_dir;
347                                 int q;
348
349                                 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
350                                 if (!sub_dir) {
351                                         if (errno != ENOENT) {
352                                                 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
353                                                 r = -errno;
354                                         }
355
356                                         continue;
357                                 }
358
359                                 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
360                                 if (q < 0)
361                                         r = q;
362                         }
363
364                         /* Note: if you are wondering why we don't
365                          * support the sticky bit for excluding
366                          * directories from cleaning like we do it for
367                          * other file system objects: well, the sticky
368                          * bit already has a meaning for directories,
369                          * so we don't want to overload that. */
370
371                         if (keep_this_level)
372                                 continue;
373
374                         /* Ignore ctime, we change it when deleting */
375                         age = MAX(timespec_load(&s.st_mtim),
376                                   timespec_load(&s.st_atim));
377                         if (age >= cutoff)
378                                 continue;
379
380                         if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
381                                 log_debug("rmdir '%s'", sub_path);
382
383                                 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
384                                         if (errno != ENOENT && errno != ENOTEMPTY) {
385                                                 log_error("rmdir(%s): %m", sub_path);
386                                                 r = -errno;
387                                         }
388                                 }
389                         }
390
391                 } else {
392                         /* Skip files for which the sticky bit is
393                          * set. These are semantics we define, and are
394                          * unknown elsewhere. See XDG_RUNTIME_DIR
395                          * specification for details. */
396                         if (s.st_mode & S_ISVTX)
397                                 continue;
398
399                         if (mountpoint && S_ISREG(s.st_mode)) {
400                                 if (streq(dent->d_name, ".journal") &&
401                                     s.st_uid == 0)
402                                         continue;
403
404                                 if (streq(dent->d_name, "aquota.user") ||
405                                     streq(dent->d_name, "aquota.group"))
406                                         continue;
407                         }
408
409                         /* Ignore sockets that are listed in /proc/net/unix */
410                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
411                                 continue;
412
413                         /* Ignore device nodes */
414                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
415                                 continue;
416
417                         /* Keep files on this level around if this is
418                          * requested */
419                         if (keep_this_level)
420                                 continue;
421
422                         age = MAX3(timespec_load(&s.st_mtim),
423                                    timespec_load(&s.st_atim),
424                                    timespec_load(&s.st_ctim));
425
426                         if (age >= cutoff)
427                                 continue;
428
429                         log_debug("unlink '%s'", sub_path);
430
431                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
432                                 if (errno != ENOENT) {
433                                         log_error("unlink(%s): %m", sub_path);
434                                         r = -errno;
435                                 }
436                         }
437
438                         deleted = true;
439                 }
440         }
441
442 finish:
443         if (deleted) {
444                 /* Restore original directory timestamps */
445                 times[0] = ds->st_atim;
446                 times[1] = ds->st_mtim;
447
448                 if (futimens(dirfd(d), times) < 0)
449                         log_error("utimensat(%s): %m", p);
450         }
451
452         return r;
453 }
454
455 static int item_set_perms(Item *i, const char *path) {
456         struct stat st;
457         bool st_valid;
458
459         assert(i);
460         assert(path);
461
462         st_valid = stat(path, &st) == 0;
463
464         /* not using i->path directly because it may be a glob */
465         if (i->mode_set) {
466                 mode_t m = i->mode;
467
468                 if (i->mask_perms && st_valid) {
469                         if (!(st.st_mode & 0111))
470                                 m &= ~0111;
471                         if (!(st.st_mode & 0222))
472                                 m &= ~0222;
473                         if (!(st.st_mode & 0444))
474                                 m &= ~0444;
475                         if (!S_ISDIR(st.st_mode))
476                                 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
477                 }
478
479                 if (!st_valid || m != (st.st_mode & 07777)) {
480                         if (chmod(path, m) < 0) {
481                                 log_error("chmod(%s) failed: %m", path);
482                                 return -errno;
483                         }
484                 }
485         }
486
487         if ((!st_valid || (i->uid != st.st_uid || i->gid != st.st_gid)) &&
488             (i->uid_set || i->gid_set))
489                 if (chown(path,
490                           i->uid_set ? i->uid : (uid_t) -1,
491                           i->gid_set ? i->gid : (gid_t) -1) < 0) {
492
493                         log_error("chown(%s) failed: %m", path);
494                         return -errno;
495                 }
496
497         return label_fix(path, false, false);
498 }
499
500 static int write_one_file(Item *i, const char *path) {
501         _cleanup_close_ int fd = -1;
502         int flags, r = 0;
503         struct stat st;
504
505         assert(i);
506         assert(path);
507
508         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
509                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
510
511         RUN_WITH_UMASK(0000) {
512                 mac_selinux_create_file_prepare(path, S_IFREG);
513                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
514                 mac_selinux_create_file_clear();
515         }
516
517         if (fd < 0) {
518                 if (i->type == WRITE_FILE && errno == ENOENT)
519                         return 0;
520
521                 log_error("Failed to create file %s: %m", path);
522                 return -errno;
523         }
524
525         if (i->argument) {
526                 _cleanup_free_ char *unescaped;
527                 ssize_t n;
528                 size_t l;
529
530                 unescaped = cunescape(i->argument);
531                 if (!unescaped)
532                         return log_oom();
533
534                 l = strlen(unescaped);
535                 n = write(fd, unescaped, l);
536
537                 if (n < 0 || (size_t) n < l) {
538                         log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
539                         return n < 0 ? n : -EIO;
540                 }
541         }
542
543         fd = safe_close(fd);
544
545         if (stat(path, &st) < 0) {
546                 log_error("stat(%s) failed: %m", path);
547                 return -errno;
548         }
549
550         if (!S_ISREG(st.st_mode)) {
551                 log_error("%s is not a file.", path);
552                 return -EEXIST;
553         }
554
555         r = item_set_perms(i, path);
556         if (r < 0)
557                 return r;
558
559         return 0;
560 }
561
562 static int item_set_perms_children(Item *i, const char *path) {
563         _cleanup_closedir_ DIR *d;
564         int r = 0;
565
566         assert(i);
567         assert(path);
568
569         /* This returns the first error we run into, but nevertheless
570          * tries to go on */
571
572         d = opendir(path);
573         if (!d)
574                 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
575
576         for (;;) {
577                 _cleanup_free_ char *p = NULL;
578                 struct dirent *de;
579                 int q;
580
581                 errno = 0;
582                 de = readdir(d);
583                 if (!de) {
584                         if (errno != 0 && r == 0)
585                                 r = -errno;
586
587                         break;
588                 }
589
590                 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
591                         continue;
592
593                 p = strjoin(path, "/", de->d_name, NULL);
594                 if (!p)
595                         return -ENOMEM;
596
597                 q = item_set_perms(i, p);
598                 if (q < 0 && q != -ENOENT && r == 0)
599                         r = q;
600
601                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
602                         q = item_set_perms_children(i, p);
603                         if (q < 0 && r == 0)
604                                 r = q;
605                 }
606         }
607
608         return r;
609 }
610
611 static int item_set_perms_recursive(Item *i, const char *path) {
612         int r, q;
613
614         assert(i);
615         assert(path);
616
617         r = item_set_perms(i, path);
618         if (r < 0)
619                 return r;
620
621         q = item_set_perms_children(i, path);
622         if (q < 0 && r == 0)
623                 r = q;
624
625         return r;
626 }
627
628 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
629         _cleanup_globfree_ glob_t g = {};
630         int r = 0, k;
631         char **fn;
632
633         errno = 0;
634         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
635         if (k != 0 && k != GLOB_NOMATCH) {
636                 if (errno == 0)
637                         errno = EIO;
638
639                 log_error("glob(%s) failed: %m", i->path);
640                 return -errno;
641         }
642
643         STRV_FOREACH(fn, g.gl_pathv) {
644                 k = action(i, *fn);
645                 if (k < 0 && r == 0)
646                         r = k;
647         }
648
649         return r;
650 }
651
652 static int create_item(Item *i) {
653         struct stat st;
654         int r = 0;
655
656         assert(i);
657
658         switch (i->type) {
659
660         case IGNORE_PATH:
661         case IGNORE_DIRECTORY_PATH:
662         case REMOVE_PATH:
663         case RECURSIVE_REMOVE_PATH:
664                 return 0;
665
666         case CREATE_FILE:
667         case TRUNCATE_FILE:
668                 r = write_one_file(i, i->path);
669                 if (r < 0)
670                         return r;
671                 break;
672
673         case COPY_FILES:
674                 r = copy_tree(i->argument, i->path, false);
675                 if (r < 0) {
676                         struct stat a, b;
677
678                         if (r != -EEXIST) {
679                                 log_error("Failed to copy files to %s: %s", i->path, strerror(-r));
680                                 return -r;
681                         }
682
683                         if (stat(i->argument, &a) < 0) {
684                                 log_error("stat(%s) failed: %m", i->argument);
685                                 return -errno;
686                         }
687
688                         if (stat(i->path, &b) < 0) {
689                                 log_error("stat(%s) failed: %m", i->path);
690                                 return -errno;
691                         }
692
693                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
694                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
695                                 return 0;
696                         }
697                 }
698
699                 r = item_set_perms(i, i->path);
700                 if (r < 0)
701                         return r;
702
703                 break;
704
705         case WRITE_FILE:
706                 r = glob_item(i, write_one_file);
707                 if (r < 0)
708                         return r;
709
710                 break;
711
712         case TRUNCATE_DIRECTORY:
713         case CREATE_DIRECTORY:
714
715                 RUN_WITH_UMASK(0000) {
716                         mkdir_parents_label(i->path, 0755);
717                         r = mkdir_label(i->path, i->mode);
718                 }
719
720                 if (r < 0) {
721                         if (r != -EEXIST) {
722                                 log_error("Failed to create directory %s: %s", i->path, strerror(-r));
723                                 return r;
724                         }
725
726                         if (stat(i->path, &st) < 0) {
727                                 log_error("stat(%s) failed: %m", i->path);
728                                 return -errno;
729                         }
730
731                         if (!S_ISDIR(st.st_mode)) {
732                                 log_debug("%s already exists and is not a directory.", i->path);
733                                 return 0;
734                         }
735                 }
736
737                 r = item_set_perms(i, i->path);
738                 if (r < 0)
739                         return r;
740
741                 break;
742
743         case CREATE_FIFO:
744
745                 RUN_WITH_UMASK(0000) {
746                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
747                         r = mkfifo(i->path, i->mode);
748                         mac_selinux_create_file_clear();
749                 }
750
751                 if (r < 0) {
752                         if (errno != EEXIST) {
753                                 log_error("Failed to create fifo %s: %m", i->path);
754                                 return -errno;
755                         }
756
757                         if (stat(i->path, &st) < 0) {
758                                 log_error("stat(%s) failed: %m", i->path);
759                                 return -errno;
760                         }
761
762                         if (!S_ISFIFO(st.st_mode)) {
763
764                                 if (i->force) {
765
766                                         RUN_WITH_UMASK(0000) {
767                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
768                                                 r = mkfifo_atomic(i->path, i->mode);
769                                                 mac_selinux_create_file_clear();
770                                         }
771
772                                         if (r < 0) {
773                                                 log_error("Failed to create fifo %s: %s", i->path, strerror(-r));
774                                                 return r;
775                                         }
776                                 } else {
777                                         log_debug("%s is not a fifo.", i->path);
778                                         return 0;
779                                 }
780                         }
781                 }
782
783                 r = item_set_perms(i, i->path);
784                 if (r < 0)
785                         return r;
786
787                 break;
788
789         case CREATE_SYMLINK:
790
791                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
792                 r = symlink(i->argument, i->path);
793                 mac_selinux_create_file_clear();
794
795                 if (r < 0) {
796                         _cleanup_free_ char *x = NULL;
797
798                         if (errno != EEXIST) {
799                                 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
800                                 return -errno;
801                         }
802
803                         r = readlink_malloc(i->path, &x);
804                         if (r < 0 || !streq(i->argument, x)) {
805
806                                 if (i->force) {
807                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
808                                         r = symlink_atomic(i->argument, i->path);
809                                         mac_selinux_create_file_clear();
810
811                                         if (r < 0) {
812                                                 log_error("symlink(%s, %s) failed: %s", i->argument, i->path, strerror(-r));
813                                                 return r;
814                                         }
815                                 } else {
816                                         log_debug("%s is not a symlink or does not point to the correct path.", i->path);
817                                         return 0;
818                                 }
819                         }
820                 }
821
822                 break;
823
824         case CREATE_BLOCK_DEVICE:
825         case CREATE_CHAR_DEVICE: {
826                 mode_t file_type;
827
828                 if (have_effective_cap(CAP_MKNOD) == 0) {
829                         /* In a container we lack CAP_MKNOD. We
830                         shouldn't attempt to create the device node in
831                         that case to avoid noise, and we don't support
832                         virtualized devices in containers anyway. */
833
834                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
835                         return 0;
836                 }
837
838                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
839
840                 RUN_WITH_UMASK(0000) {
841                         mac_selinux_create_file_prepare(i->path, file_type);
842                         r = mknod(i->path, i->mode | file_type, i->major_minor);
843                         mac_selinux_create_file_clear();
844                 }
845
846                 if (r < 0) {
847                         if (errno == EPERM) {
848                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
849                                           "skipping creation of device node %s.", i->path);
850                                 return 0;
851                         }
852
853                         if (errno != EEXIST) {
854                                 log_error("Failed to create device node %s: %m", i->path);
855                                 return -errno;
856                         }
857
858                         if (stat(i->path, &st) < 0) {
859                                 log_error("stat(%s) failed: %m", i->path);
860                                 return -errno;
861                         }
862
863                         if ((st.st_mode & S_IFMT) != file_type) {
864
865                                 if (i->force) {
866
867                                         RUN_WITH_UMASK(0000) {
868                                                 mac_selinux_create_file_prepare(i->path, file_type);
869                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
870                                                 mac_selinux_create_file_clear();
871                                         }
872
873                                         if (r < 0) {
874                                                 log_error("Failed to create device node %s: %s", i->path, strerror(-r));
875                                                 return r;
876                                         }
877                                 } else {
878                                         log_debug("%s is not a device node.", i->path);
879                                         return 0;
880                                 }
881                         }
882                 }
883
884                 r = item_set_perms(i, i->path);
885                 if (r < 0)
886                         return r;
887
888                 break;
889         }
890
891         case ADJUST_MODE:
892         case RELABEL_PATH:
893
894                 r = glob_item(i, item_set_perms);
895                 if (r < 0)
896                         return r;
897                 break;
898
899         case RECURSIVE_RELABEL_PATH:
900
901                 r = glob_item(i, item_set_perms_recursive);
902                 if (r < 0)
903                         return r;
904
905                 break;
906         }
907
908         log_debug("%s created successfully.", i->path);
909
910         return 0;
911 }
912
913 static int remove_item_instance(Item *i, const char *instance) {
914         int r;
915
916         assert(i);
917
918         switch (i->type) {
919
920         case CREATE_FILE:
921         case TRUNCATE_FILE:
922         case CREATE_DIRECTORY:
923         case CREATE_FIFO:
924         case CREATE_SYMLINK:
925         case CREATE_BLOCK_DEVICE:
926         case CREATE_CHAR_DEVICE:
927         case IGNORE_PATH:
928         case IGNORE_DIRECTORY_PATH:
929         case ADJUST_MODE:
930         case RELABEL_PATH:
931         case RECURSIVE_RELABEL_PATH:
932         case WRITE_FILE:
933         case COPY_FILES:
934                 break;
935
936         case REMOVE_PATH:
937                 if (remove(instance) < 0 && errno != ENOENT) {
938                         log_error("remove(%s): %m", instance);
939                         return -errno;
940                 }
941
942                 break;
943
944         case TRUNCATE_DIRECTORY:
945         case RECURSIVE_REMOVE_PATH:
946                 /* FIXME: we probably should use dir_cleanup() here
947                  * instead of rm_rf() so that 'x' is honoured. */
948                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
949                 if (r < 0 && r != -ENOENT) {
950                         log_error("rm_rf(%s): %s", instance, strerror(-r));
951                         return r;
952                 }
953
954                 break;
955         }
956
957         return 0;
958 }
959
960 static int remove_item(Item *i) {
961         int r = 0;
962
963         assert(i);
964
965         switch (i->type) {
966
967         case CREATE_FILE:
968         case TRUNCATE_FILE:
969         case CREATE_DIRECTORY:
970         case CREATE_FIFO:
971         case CREATE_SYMLINK:
972         case CREATE_CHAR_DEVICE:
973         case CREATE_BLOCK_DEVICE:
974         case IGNORE_PATH:
975         case IGNORE_DIRECTORY_PATH:
976         case ADJUST_MODE:
977         case RELABEL_PATH:
978         case RECURSIVE_RELABEL_PATH:
979         case WRITE_FILE:
980         case COPY_FILES:
981                 break;
982
983         case REMOVE_PATH:
984         case TRUNCATE_DIRECTORY:
985         case RECURSIVE_REMOVE_PATH:
986                 r = glob_item(i, remove_item_instance);
987                 break;
988         }
989
990         return r;
991 }
992
993 static int clean_item_instance(Item *i, const char* instance) {
994         _cleanup_closedir_ DIR *d = NULL;
995         struct stat s, ps;
996         bool mountpoint;
997         int r;
998         usec_t cutoff, n;
999
1000         assert(i);
1001
1002         if (!i->age_set)
1003                 return 0;
1004
1005         n = now(CLOCK_REALTIME);
1006         if (n < i->age)
1007                 return 0;
1008
1009         cutoff = n - i->age;
1010
1011         d = opendir(instance);
1012         if (!d) {
1013                 if (errno == ENOENT || errno == ENOTDIR)
1014                         return 0;
1015
1016                 log_error("Failed to open directory %s: %m", i->path);
1017                 return -errno;
1018         }
1019
1020         if (fstat(dirfd(d), &s) < 0) {
1021                 log_error("stat(%s) failed: %m", i->path);
1022                 return -errno;
1023         }
1024
1025         if (!S_ISDIR(s.st_mode)) {
1026                 log_error("%s is not a directory.", i->path);
1027                 return -ENOTDIR;
1028         }
1029
1030         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
1031                 log_error("stat(%s/..) failed: %m", i->path);
1032                 return -errno;
1033         }
1034
1035         mountpoint = s.st_dev != ps.st_dev ||
1036                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1037
1038         r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1039                         MAX_DEPTH, i->keep_first_level);
1040         return r;
1041 }
1042
1043 static int clean_item(Item *i) {
1044         int r = 0;
1045
1046         assert(i);
1047
1048         switch (i->type) {
1049         case CREATE_DIRECTORY:
1050         case TRUNCATE_DIRECTORY:
1051         case IGNORE_PATH:
1052         case COPY_FILES:
1053                 clean_item_instance(i, i->path);
1054                 break;
1055         case IGNORE_DIRECTORY_PATH:
1056                 r = glob_item(i, clean_item_instance);
1057                 break;
1058         default:
1059                 break;
1060         }
1061
1062         return r;
1063 }
1064
1065 static int process_item(Item *i) {
1066         int r, q, p;
1067         _cleanup_free_ char *prefix = NULL;
1068
1069         assert(i);
1070
1071         if (i->done)
1072                 return 0;
1073
1074         i->done = true;
1075
1076         prefix = malloc(strlen(i->path) + 1);
1077         if (!prefix)
1078                 return log_oom();
1079
1080         PATH_FOREACH_PREFIX(prefix, i->path) {
1081                 Item *j;
1082
1083                 j = hashmap_get(items, prefix);
1084                 if (j)
1085                         process_item(j);
1086         }
1087
1088         r = arg_create ? create_item(i) : 0;
1089         q = arg_remove ? remove_item(i) : 0;
1090         p = arg_clean ? clean_item(i) : 0;
1091
1092         if (r < 0)
1093                 return r;
1094
1095         if (q < 0)
1096                 return q;
1097
1098         return p;
1099 }
1100
1101 static void item_free(Item *i) {
1102
1103         if (!i)
1104                 return;
1105
1106         free(i->path);
1107         free(i->argument);
1108         free(i);
1109 }
1110
1111 DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
1112
1113 static bool item_equal(Item *a, Item *b) {
1114         assert(a);
1115         assert(b);
1116
1117         if (!streq_ptr(a->path, b->path))
1118                 return false;
1119
1120         if (a->type != b->type)
1121                 return false;
1122
1123         if (a->uid_set != b->uid_set ||
1124             (a->uid_set && a->uid != b->uid))
1125             return false;
1126
1127         if (a->gid_set != b->gid_set ||
1128             (a->gid_set && a->gid != b->gid))
1129             return false;
1130
1131         if (a->mode_set != b->mode_set ||
1132             (a->mode_set && a->mode != b->mode))
1133             return false;
1134
1135         if (a->age_set != b->age_set ||
1136             (a->age_set && a->age != b->age))
1137             return false;
1138
1139         if ((a->type == CREATE_FILE ||
1140              a->type == TRUNCATE_FILE ||
1141              a->type == WRITE_FILE ||
1142              a->type == CREATE_SYMLINK ||
1143              a->type == COPY_FILES) &&
1144             !streq_ptr(a->argument, b->argument))
1145                 return false;
1146
1147         if ((a->type == CREATE_CHAR_DEVICE ||
1148              a->type == CREATE_BLOCK_DEVICE) &&
1149             a->major_minor != b->major_minor)
1150                 return false;
1151
1152         return true;
1153 }
1154
1155 static bool should_include_path(const char *path) {
1156         char **prefix;
1157
1158         STRV_FOREACH(prefix, arg_exclude_prefixes)
1159                 if (path_startswith(path, *prefix))
1160                         return false;
1161
1162         STRV_FOREACH(prefix, arg_include_prefixes)
1163                 if (path_startswith(path, *prefix))
1164                         return true;
1165
1166         /* no matches, so we should include this path only if we
1167          * have no whitelist at all */
1168         return strv_length(arg_include_prefixes) == 0;
1169 }
1170
1171 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1172
1173         static const Specifier specifier_table[] = {
1174                 { 'm', specifier_machine_id, NULL },
1175                 { 'b', specifier_boot_id, NULL },
1176                 { 'H', specifier_host_name, NULL },
1177                 { 'v', specifier_kernel_release, NULL },
1178                 {}
1179         };
1180
1181         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1182         _cleanup_(item_freep) Item *i = NULL;
1183         Item *existing;
1184         char type;
1185         Hashmap *h;
1186         int r, n = -1;
1187
1188         assert(fname);
1189         assert(line >= 1);
1190         assert(buffer);
1191
1192         r = sscanf(buffer,
1193                    "%ms %ms %ms %ms %ms %ms %n",
1194                    &action,
1195                    &path,
1196                    &mode,
1197                    &user,
1198                    &group,
1199                    &age,
1200                    &n);
1201         if (r < 2) {
1202                 log_error("[%s:%u] Syntax error.", fname, line);
1203                 return -EIO;
1204         }
1205
1206         if (isempty(action)) {
1207                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1208                 return -EINVAL;
1209         }
1210
1211         if (strlen(action) > 1 && !in_charset(action+1, "!+")) {
1212                 log_error("[%s:%u] Unknown modifiers in command '%s'", fname, line, action);
1213                 return -EINVAL;
1214         }
1215
1216         if (strchr(action+1, '!') && !arg_boot)
1217                 return 0;
1218
1219         type = action[0];
1220
1221         i = new0(Item, 1);
1222         if (!i)
1223                 return log_oom();
1224
1225         i->force = !!strchr(action+1, '+');
1226
1227         r = specifier_printf(path, specifier_table, NULL, &i->path);
1228         if (r < 0) {
1229                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1230                 return r;
1231         }
1232
1233         if (n >= 0)  {
1234                 n += strspn(buffer+n, WHITESPACE);
1235                 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1236                         i->argument = unquote(buffer+n, "\"");
1237                         if (!i->argument)
1238                                 return log_oom();
1239                 }
1240         }
1241
1242         switch (type) {
1243
1244         case CREATE_FILE:
1245         case TRUNCATE_FILE:
1246         case CREATE_DIRECTORY:
1247         case TRUNCATE_DIRECTORY:
1248         case CREATE_FIFO:
1249         case IGNORE_PATH:
1250         case IGNORE_DIRECTORY_PATH:
1251         case REMOVE_PATH:
1252         case RECURSIVE_REMOVE_PATH:
1253         case ADJUST_MODE:
1254         case RELABEL_PATH:
1255         case RECURSIVE_RELABEL_PATH:
1256                 break;
1257
1258         case CREATE_SYMLINK:
1259                 if (!i->argument) {
1260                         i->argument = strappend("/usr/share/factory", i->path);
1261                         if (!i->argument)
1262                                 return log_oom();
1263                 }
1264                 break;
1265
1266         case WRITE_FILE:
1267                 if (!i->argument) {
1268                         log_error("[%s:%u] Write file requires argument.", fname, line);
1269                         return -EBADMSG;
1270                 }
1271                 break;
1272
1273         case COPY_FILES:
1274                 if (!i->argument) {
1275                         i->argument = strappend("/usr/share/factory", i->path);
1276                         if (!i->argument)
1277                                 return log_oom();
1278                 }
1279
1280                 if (!path_is_absolute(i->argument)) {
1281                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1282                         return -EBADMSG;
1283                 }
1284
1285                 path_kill_slashes(i->argument);
1286                 break;
1287
1288         case CREATE_CHAR_DEVICE:
1289         case CREATE_BLOCK_DEVICE: {
1290                 unsigned major, minor;
1291
1292                 if (!i->argument) {
1293                         log_error("[%s:%u] Device file requires argument.", fname, line);
1294                         return -EBADMSG;
1295                 }
1296
1297                 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1298                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1299                         return -EBADMSG;
1300                 }
1301
1302                 i->major_minor = makedev(major, minor);
1303                 break;
1304         }
1305
1306         default:
1307                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, type);
1308                 return -EBADMSG;
1309         }
1310
1311         i->type = type;
1312
1313         if (!path_is_absolute(i->path)) {
1314                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1315                 return -EBADMSG;
1316         }
1317
1318         path_kill_slashes(i->path);
1319
1320         if (!should_include_path(i->path))
1321                 return 0;
1322
1323         if (arg_root) {
1324                 char *p;
1325
1326                 p = strappend(arg_root, i->path);
1327                 if (!p)
1328                         return log_oom();
1329
1330                 free(i->path);
1331                 i->path = p;
1332         }
1333
1334         if (user && !streq(user, "-")) {
1335                 const char *u = user;
1336
1337                 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1338                 if (r < 0) {
1339                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1340                         return r;
1341                 }
1342
1343                 i->uid_set = true;
1344         }
1345
1346         if (group && !streq(group, "-")) {
1347                 const char *g = group;
1348
1349                 r = get_group_creds(&g, &i->gid);
1350                 if (r < 0) {
1351                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1352                         return r;
1353                 }
1354
1355                 i->gid_set = true;
1356         }
1357
1358         if (mode && !streq(mode, "-")) {
1359                 const char *mm = mode;
1360                 unsigned m;
1361
1362                 if (*mm == '~') {
1363                         i->mask_perms = true;
1364                         mm++;
1365                 }
1366
1367                 if (sscanf(mm, "%o", &m) != 1) {
1368                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1369                         return -ENOENT;
1370                 }
1371
1372                 i->mode = m;
1373                 i->mode_set = true;
1374         } else
1375                 i->mode =
1376                         i->type == CREATE_DIRECTORY ||
1377                         i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1378
1379         if (age && !streq(age, "-")) {
1380                 const char *a = age;
1381
1382                 if (*a == '~') {
1383                         i->keep_first_level = true;
1384                         a++;
1385                 }
1386
1387                 if (parse_sec(a, &i->age) < 0) {
1388                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1389                         return -EBADMSG;
1390                 }
1391
1392                 i->age_set = true;
1393         }
1394
1395         h = needs_glob(i->type) ? globs : items;
1396
1397         existing = hashmap_get(h, i->path);
1398         if (existing) {
1399
1400                 /* Two identical items are fine */
1401                 if (!item_equal(existing, i))
1402                         log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1403
1404                 return 0;
1405         }
1406
1407         r = hashmap_put(h, i->path, i);
1408         if (r < 0) {
1409                 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1410                 return r;
1411         }
1412
1413         i = NULL; /* avoid cleanup */
1414
1415         return 0;
1416 }
1417
1418 static void help(void) {
1419         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1420                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1421                "  -h --help                 Show this help\n"
1422                "     --version              Show package version\n"
1423                "     --create               Create marked files/directories\n"
1424                "     --clean                Clean up marked directories\n"
1425                "     --remove               Remove marked files/directories\n"
1426                "     --boot                 Execute actions only safe at boot\n"
1427                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1428                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n"
1429                "     --root=PATH            Operate on an alternate filesystem root\n",
1430                program_invocation_short_name);
1431 }
1432
1433 static int parse_argv(int argc, char *argv[]) {
1434
1435         enum {
1436                 ARG_VERSION = 0x100,
1437                 ARG_CREATE,
1438                 ARG_CLEAN,
1439                 ARG_REMOVE,
1440                 ARG_BOOT,
1441                 ARG_PREFIX,
1442                 ARG_EXCLUDE_PREFIX,
1443                 ARG_ROOT,
1444         };
1445
1446         static const struct option options[] = {
1447                 { "help",           no_argument,         NULL, 'h'                },
1448                 { "version",        no_argument,         NULL, ARG_VERSION        },
1449                 { "create",         no_argument,         NULL, ARG_CREATE         },
1450                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1451                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1452                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1453                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1454                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1455                 { "root",           required_argument,   NULL, ARG_ROOT           },
1456                 {}
1457         };
1458
1459         int c;
1460
1461         assert(argc >= 0);
1462         assert(argv);
1463
1464         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1465
1466                 switch (c) {
1467
1468                 case 'h':
1469                         help();
1470                         return 0;
1471
1472                 case ARG_VERSION:
1473                         puts(PACKAGE_STRING);
1474                         puts(SYSTEMD_FEATURES);
1475                         return 0;
1476
1477                 case ARG_CREATE:
1478                         arg_create = true;
1479                         break;
1480
1481                 case ARG_CLEAN:
1482                         arg_clean = true;
1483                         break;
1484
1485                 case ARG_REMOVE:
1486                         arg_remove = true;
1487                         break;
1488
1489                 case ARG_BOOT:
1490                         arg_boot = true;
1491                         break;
1492
1493                 case ARG_PREFIX:
1494                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1495                                 return log_oom();
1496                         break;
1497
1498                 case ARG_EXCLUDE_PREFIX:
1499                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1500                                 return log_oom();
1501                         break;
1502
1503                 case ARG_ROOT:
1504                         free(arg_root);
1505                         arg_root = path_make_absolute_cwd(optarg);
1506                         if (!arg_root)
1507                                 return log_oom();
1508
1509                         path_kill_slashes(arg_root);
1510                         break;
1511
1512                 case '?':
1513                         return -EINVAL;
1514
1515                 default:
1516                         assert_not_reached("Unhandled option");
1517                 }
1518
1519         if (!arg_clean && !arg_create && !arg_remove) {
1520                 log_error("You need to specify at least one of --clean, --create or --remove.");
1521                 return -EINVAL;
1522         }
1523
1524         return 1;
1525 }
1526
1527 static int read_config_file(const char *fn, bool ignore_enoent) {
1528         _cleanup_fclose_ FILE *f = NULL;
1529         char line[LINE_MAX];
1530         Iterator iterator;
1531         unsigned v = 0;
1532         Item *i;
1533         int r;
1534
1535         assert(fn);
1536
1537         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1538         if (r < 0) {
1539                 if (ignore_enoent && r == -ENOENT)
1540                         return 0;
1541
1542                 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1543                 return r;
1544         }
1545
1546         FOREACH_LINE(line, f, break) {
1547                 char *l;
1548                 int k;
1549
1550                 v++;
1551
1552                 l = strstrip(line);
1553                 if (*l == '#' || *l == 0)
1554                         continue;
1555
1556                 k = parse_line(fn, v, l);
1557                 if (k < 0 && r == 0)
1558                         r = k;
1559         }
1560
1561         /* we have to determine age parameter for each entry of type X */
1562         HASHMAP_FOREACH(i, globs, iterator) {
1563                 Iterator iter;
1564                 Item *j, *candidate_item = NULL;
1565
1566                 if (i->type != IGNORE_DIRECTORY_PATH)
1567                         continue;
1568
1569                 HASHMAP_FOREACH(j, items, iter) {
1570                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1571                                 continue;
1572
1573                         if (path_equal(j->path, i->path)) {
1574                                 candidate_item = j;
1575                                 break;
1576                         }
1577
1578                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1579                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1580                                 candidate_item = j;
1581                 }
1582
1583                 if (candidate_item && candidate_item->age_set) {
1584                         i->age = candidate_item->age;
1585                         i->age_set = true;
1586                 }
1587         }
1588
1589         if (ferror(f)) {
1590                 log_error("Failed to read from file %s: %m", fn);
1591                 if (r == 0)
1592                         r = -EIO;
1593         }
1594
1595         return r;
1596 }
1597
1598 int main(int argc, char *argv[]) {
1599         int r, k;
1600         Item *i;
1601         Iterator iterator;
1602
1603         r = parse_argv(argc, argv);
1604         if (r <= 0)
1605                 goto finish;
1606
1607         log_set_target(LOG_TARGET_AUTO);
1608         log_parse_environment();
1609         log_open();
1610
1611         umask(0022);
1612
1613         mac_selinux_init(NULL);
1614
1615         items = hashmap_new(&string_hash_ops);
1616         globs = hashmap_new(&string_hash_ops);
1617
1618         if (!items || !globs) {
1619                 r = log_oom();
1620                 goto finish;
1621         }
1622
1623         r = 0;
1624
1625         if (optind < argc) {
1626                 int j;
1627
1628                 for (j = optind; j < argc; j++) {
1629                         k = read_config_file(argv[j], false);
1630                         if (k < 0 && r == 0)
1631                                 r = k;
1632                 }
1633
1634         } else {
1635                 _cleanup_strv_free_ char **files = NULL;
1636                 char **f;
1637
1638                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1639                 if (r < 0) {
1640                         log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1641                         goto finish;
1642                 }
1643
1644                 STRV_FOREACH(f, files) {
1645                         k = read_config_file(*f, true);
1646                         if (k < 0 && r == 0)
1647                                 r = k;
1648                 }
1649         }
1650
1651         HASHMAP_FOREACH(i, globs, iterator)
1652                 process_item(i);
1653
1654         HASHMAP_FOREACH(i, items, iterator)
1655                 process_item(i);
1656
1657 finish:
1658         while ((i = hashmap_steal_first(items)))
1659                 item_free(i);
1660
1661         while ((i = hashmap_steal_first(globs)))
1662                 item_free(i);
1663
1664         hashmap_free(items);
1665         hashmap_free(globs);
1666
1667         free(arg_include_prefixes);
1668         free(arg_exclude_prefixes);
1669         free(arg_root);
1670
1671         set_free_free(unix_sockets);
1672
1673         mac_selinux_finish();
1674
1675         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1676 }