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