chiark / gitweb /
tmpfiles: only execute chmod()/chown() when needed
[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_func, string_compare_func);
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 == -ENOTSUP || r == -ENOSYS || r == -ENOTSUP)
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                 label_context_set(path, S_IFREG);
513                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
514                 label_context_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                         label_context_set(i->path, S_IFIFO);
747                         r = mkfifo(i->path, i->mode);
748                         label_context_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                                                 label_context_set(i->path, S_IFIFO);
768                                                 r = mkfifo_atomic(i->path, i->mode);
769                                                 label_context_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                 label_context_set(i->path, S_IFLNK);
792                 r = symlink(i->argument, i->path);
793                 label_context_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                                         label_context_set(i->path, S_IFLNK);
808                                         r = symlink_atomic(i->argument, i->path);
809                                         label_context_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                         label_context_set(i->path, file_type);
842                         r = mknod(i->path, i->mode | file_type, i->major_minor);
843                         label_context_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                                                 label_context_set(i->path, file_type);
869                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
870                                                 label_context_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         char prefix[PATH_MAX];
1068
1069         assert(i);
1070
1071         if (i->done)
1072                 return 0;
1073
1074         i->done = true;
1075
1076         PATH_FOREACH_PREFIX(prefix, i->path) {
1077                 Item *j;
1078
1079                 j = hashmap_get(items, prefix);
1080                 if (j)
1081                         process_item(j);
1082         }
1083
1084         r = arg_create ? create_item(i) : 0;
1085         q = arg_remove ? remove_item(i) : 0;
1086         p = arg_clean ? clean_item(i) : 0;
1087
1088         if (r < 0)
1089                 return r;
1090
1091         if (q < 0)
1092                 return q;
1093
1094         return p;
1095 }
1096
1097 static void item_free(Item *i) {
1098
1099         if (!i)
1100                 return;
1101
1102         free(i->path);
1103         free(i->argument);
1104         free(i);
1105 }
1106
1107 DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
1108
1109 static bool item_equal(Item *a, Item *b) {
1110         assert(a);
1111         assert(b);
1112
1113         if (!streq_ptr(a->path, b->path))
1114                 return false;
1115
1116         if (a->type != b->type)
1117                 return false;
1118
1119         if (a->uid_set != b->uid_set ||
1120             (a->uid_set && a->uid != b->uid))
1121             return false;
1122
1123         if (a->gid_set != b->gid_set ||
1124             (a->gid_set && a->gid != b->gid))
1125             return false;
1126
1127         if (a->mode_set != b->mode_set ||
1128             (a->mode_set && a->mode != b->mode))
1129             return false;
1130
1131         if (a->age_set != b->age_set ||
1132             (a->age_set && a->age != b->age))
1133             return false;
1134
1135         if ((a->type == CREATE_FILE ||
1136              a->type == TRUNCATE_FILE ||
1137              a->type == WRITE_FILE ||
1138              a->type == CREATE_SYMLINK ||
1139              a->type == COPY_FILES) &&
1140             !streq_ptr(a->argument, b->argument))
1141                 return false;
1142
1143         if ((a->type == CREATE_CHAR_DEVICE ||
1144              a->type == CREATE_BLOCK_DEVICE) &&
1145             a->major_minor != b->major_minor)
1146                 return false;
1147
1148         return true;
1149 }
1150
1151 static bool should_include_path(const char *path) {
1152         char **prefix;
1153
1154         STRV_FOREACH(prefix, arg_exclude_prefixes)
1155                 if (path_startswith(path, *prefix))
1156                         return false;
1157
1158         STRV_FOREACH(prefix, arg_include_prefixes)
1159                 if (path_startswith(path, *prefix))
1160                         return true;
1161
1162         /* no matches, so we should include this path only if we
1163          * have no whitelist at all */
1164         return strv_length(arg_include_prefixes) == 0;
1165 }
1166
1167 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1168
1169         static const Specifier specifier_table[] = {
1170                 { 'm', specifier_machine_id, NULL },
1171                 { 'b', specifier_boot_id, NULL },
1172                 { 'H', specifier_host_name, NULL },
1173                 { 'v', specifier_kernel_release, NULL },
1174                 {}
1175         };
1176
1177         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1178         _cleanup_(item_freep) Item *i = NULL;
1179         Item *existing;
1180         char type;
1181         Hashmap *h;
1182         int r, n = -1;
1183
1184         assert(fname);
1185         assert(line >= 1);
1186         assert(buffer);
1187
1188         r = sscanf(buffer,
1189                    "%ms %ms %ms %ms %ms %ms %n",
1190                    &action,
1191                    &path,
1192                    &mode,
1193                    &user,
1194                    &group,
1195                    &age,
1196                    &n);
1197         if (r < 2) {
1198                 log_error("[%s:%u] Syntax error.", fname, line);
1199                 return -EIO;
1200         }
1201
1202         if (isempty(action)) {
1203                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1204                 return -EINVAL;
1205         }
1206
1207         if (strlen(action) > 1 && !in_charset(action+1, "!+")) {
1208                 log_error("[%s:%u] Unknown modifiers in command '%s'", fname, line, action);
1209                 return -EINVAL;
1210         }
1211
1212         if (strchr(action+1, '!') && !arg_boot)
1213                 return 0;
1214
1215         type = action[0];
1216
1217         i = new0(Item, 1);
1218         if (!i)
1219                 return log_oom();
1220
1221         i->force = !!strchr(action+1, '+');
1222
1223         r = specifier_printf(path, specifier_table, NULL, &i->path);
1224         if (r < 0) {
1225                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1226                 return r;
1227         }
1228
1229         if (n >= 0)  {
1230                 n += strspn(buffer+n, WHITESPACE);
1231                 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1232                         i->argument = unquote(buffer+n, "\"");
1233                         if (!i->argument)
1234                                 return log_oom();
1235                 }
1236         }
1237
1238         switch (type) {
1239
1240         case CREATE_FILE:
1241         case TRUNCATE_FILE:
1242         case CREATE_DIRECTORY:
1243         case TRUNCATE_DIRECTORY:
1244         case CREATE_FIFO:
1245         case IGNORE_PATH:
1246         case IGNORE_DIRECTORY_PATH:
1247         case REMOVE_PATH:
1248         case RECURSIVE_REMOVE_PATH:
1249         case ADJUST_MODE:
1250         case RELABEL_PATH:
1251         case RECURSIVE_RELABEL_PATH:
1252                 break;
1253
1254         case CREATE_SYMLINK:
1255                 if (!i->argument) {
1256                         i->argument = strappend("/usr/share/factory", i->path);
1257                         if (!i->argument)
1258                                 return log_oom();
1259                 }
1260                 break;
1261
1262         case WRITE_FILE:
1263                 if (!i->argument) {
1264                         log_error("[%s:%u] Write file requires argument.", fname, line);
1265                         return -EBADMSG;
1266                 }
1267                 break;
1268
1269         case COPY_FILES:
1270                 if (!i->argument) {
1271                         i->argument = strappend("/usr/share/factory", i->path);
1272                         if (!i->argument)
1273                                 return log_oom();
1274                 }
1275
1276                 if (!path_is_absolute(i->argument)) {
1277                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1278                         return -EBADMSG;
1279                 }
1280
1281                 path_kill_slashes(i->argument);
1282                 break;
1283
1284         case CREATE_CHAR_DEVICE:
1285         case CREATE_BLOCK_DEVICE: {
1286                 unsigned major, minor;
1287
1288                 if (!i->argument) {
1289                         log_error("[%s:%u] Device file requires argument.", fname, line);
1290                         return -EBADMSG;
1291                 }
1292
1293                 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1294                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1295                         return -EBADMSG;
1296                 }
1297
1298                 i->major_minor = makedev(major, minor);
1299                 break;
1300         }
1301
1302         default:
1303                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, type);
1304                 return -EBADMSG;
1305         }
1306
1307         i->type = type;
1308
1309         if (!path_is_absolute(i->path)) {
1310                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1311                 return -EBADMSG;
1312         }
1313
1314         path_kill_slashes(i->path);
1315
1316         if (!should_include_path(i->path))
1317                 return 0;
1318
1319         if (arg_root) {
1320                 char *p;
1321
1322                 p = strappend(arg_root, i->path);
1323                 if (!p)
1324                         return log_oom();
1325
1326                 free(i->path);
1327                 i->path = p;
1328         }
1329
1330         if (user && !streq(user, "-")) {
1331                 const char *u = user;
1332
1333                 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1334                 if (r < 0) {
1335                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1336                         return r;
1337                 }
1338
1339                 i->uid_set = true;
1340         }
1341
1342         if (group && !streq(group, "-")) {
1343                 const char *g = group;
1344
1345                 r = get_group_creds(&g, &i->gid);
1346                 if (r < 0) {
1347                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1348                         return r;
1349                 }
1350
1351                 i->gid_set = true;
1352         }
1353
1354         if (mode && !streq(mode, "-")) {
1355                 const char *mm = mode;
1356                 unsigned m;
1357
1358                 if (*mm == '~') {
1359                         i->mask_perms = true;
1360                         mm++;
1361                 }
1362
1363                 if (sscanf(mm, "%o", &m) != 1) {
1364                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1365                         return -ENOENT;
1366                 }
1367
1368                 i->mode = m;
1369                 i->mode_set = true;
1370         } else
1371                 i->mode =
1372                         i->type == CREATE_DIRECTORY ||
1373                         i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1374
1375         if (age && !streq(age, "-")) {
1376                 const char *a = age;
1377
1378                 if (*a == '~') {
1379                         i->keep_first_level = true;
1380                         a++;
1381                 }
1382
1383                 if (parse_sec(a, &i->age) < 0) {
1384                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1385                         return -EBADMSG;
1386                 }
1387
1388                 i->age_set = true;
1389         }
1390
1391         h = needs_glob(i->type) ? globs : items;
1392
1393         existing = hashmap_get(h, i->path);
1394         if (existing) {
1395
1396                 /* Two identical items are fine */
1397                 if (!item_equal(existing, i))
1398                         log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1399
1400                 return 0;
1401         }
1402
1403         r = hashmap_put(h, i->path, i);
1404         if (r < 0) {
1405                 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1406                 return r;
1407         }
1408
1409         i = NULL; /* avoid cleanup */
1410
1411         return 0;
1412 }
1413
1414 static void help(void) {
1415         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1416                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1417                "  -h --help                 Show this help\n"
1418                "     --version              Show package version\n"
1419                "     --create               Create marked files/directories\n"
1420                "     --clean                Clean up marked directories\n"
1421                "     --remove               Remove marked files/directories\n"
1422                "     --boot                 Execute actions only safe at boot\n"
1423                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1424                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n"
1425                "     --root=PATH            Operate on an alternate filesystem root\n",
1426                program_invocation_short_name);
1427 }
1428
1429 static int parse_argv(int argc, char *argv[]) {
1430
1431         enum {
1432                 ARG_VERSION = 0x100,
1433                 ARG_CREATE,
1434                 ARG_CLEAN,
1435                 ARG_REMOVE,
1436                 ARG_BOOT,
1437                 ARG_PREFIX,
1438                 ARG_EXCLUDE_PREFIX,
1439                 ARG_ROOT,
1440         };
1441
1442         static const struct option options[] = {
1443                 { "help",           no_argument,         NULL, 'h'                },
1444                 { "version",        no_argument,         NULL, ARG_VERSION        },
1445                 { "create",         no_argument,         NULL, ARG_CREATE         },
1446                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1447                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1448                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1449                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1450                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1451                 { "root",           required_argument,   NULL, ARG_ROOT           },
1452                 {}
1453         };
1454
1455         int c;
1456
1457         assert(argc >= 0);
1458         assert(argv);
1459
1460         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1461
1462                 switch (c) {
1463
1464                 case 'h':
1465                         help();
1466                         return 0;
1467
1468                 case ARG_VERSION:
1469                         puts(PACKAGE_STRING);
1470                         puts(SYSTEMD_FEATURES);
1471                         return 0;
1472
1473                 case ARG_CREATE:
1474                         arg_create = true;
1475                         break;
1476
1477                 case ARG_CLEAN:
1478                         arg_clean = true;
1479                         break;
1480
1481                 case ARG_REMOVE:
1482                         arg_remove = true;
1483                         break;
1484
1485                 case ARG_BOOT:
1486                         arg_boot = true;
1487                         break;
1488
1489                 case ARG_PREFIX:
1490                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1491                                 return log_oom();
1492                         break;
1493
1494                 case ARG_EXCLUDE_PREFIX:
1495                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1496                                 return log_oom();
1497                         break;
1498
1499                 case ARG_ROOT:
1500                         free(arg_root);
1501                         arg_root = path_make_absolute_cwd(optarg);
1502                         if (!arg_root)
1503                                 return log_oom();
1504
1505                         path_kill_slashes(arg_root);
1506                         break;
1507
1508                 case '?':
1509                         return -EINVAL;
1510
1511                 default:
1512                         assert_not_reached("Unhandled option");
1513                 }
1514
1515         if (!arg_clean && !arg_create && !arg_remove) {
1516                 log_error("You need to specify at least one of --clean, --create or --remove.");
1517                 return -EINVAL;
1518         }
1519
1520         return 1;
1521 }
1522
1523 static int read_config_file(const char *fn, bool ignore_enoent) {
1524         _cleanup_fclose_ FILE *f = NULL;
1525         char line[LINE_MAX];
1526         Iterator iterator;
1527         unsigned v = 0;
1528         Item *i;
1529         int r;
1530
1531         assert(fn);
1532
1533         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1534         if (r < 0) {
1535                 if (ignore_enoent && r == -ENOENT)
1536                         return 0;
1537
1538                 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1539                 return r;
1540         }
1541
1542         FOREACH_LINE(line, f, break) {
1543                 char *l;
1544                 int k;
1545
1546                 v++;
1547
1548                 l = strstrip(line);
1549                 if (*l == '#' || *l == 0)
1550                         continue;
1551
1552                 k = parse_line(fn, v, l);
1553                 if (k < 0 && r == 0)
1554                         r = k;
1555         }
1556
1557         /* we have to determine age parameter for each entry of type X */
1558         HASHMAP_FOREACH(i, globs, iterator) {
1559                 Iterator iter;
1560                 Item *j, *candidate_item = NULL;
1561
1562                 if (i->type != IGNORE_DIRECTORY_PATH)
1563                         continue;
1564
1565                 HASHMAP_FOREACH(j, items, iter) {
1566                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1567                                 continue;
1568
1569                         if (path_equal(j->path, i->path)) {
1570                                 candidate_item = j;
1571                                 break;
1572                         }
1573
1574                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1575                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1576                                 candidate_item = j;
1577                 }
1578
1579                 if (candidate_item) {
1580                         i->age = candidate_item->age;
1581                         i->age_set = true;
1582                 }
1583         }
1584
1585         if (ferror(f)) {
1586                 log_error("Failed to read from file %s: %m", fn);
1587                 if (r == 0)
1588                         r = -EIO;
1589         }
1590
1591         return r;
1592 }
1593
1594 int main(int argc, char *argv[]) {
1595         int r, k;
1596         Item *i;
1597         Iterator iterator;
1598
1599         r = parse_argv(argc, argv);
1600         if (r <= 0)
1601                 goto finish;
1602
1603         log_set_target(LOG_TARGET_AUTO);
1604         log_parse_environment();
1605         log_open();
1606
1607         umask(0022);
1608
1609         label_init(NULL);
1610
1611         items = hashmap_new(string_hash_func, string_compare_func);
1612         globs = hashmap_new(string_hash_func, string_compare_func);
1613
1614         if (!items || !globs) {
1615                 r = log_oom();
1616                 goto finish;
1617         }
1618
1619         r = 0;
1620
1621         if (optind < argc) {
1622                 int j;
1623
1624                 for (j = optind; j < argc; j++) {
1625                         k = read_config_file(argv[j], false);
1626                         if (k < 0 && r == 0)
1627                                 r = k;
1628                 }
1629
1630         } else {
1631                 _cleanup_strv_free_ char **files = NULL;
1632                 char **f;
1633
1634                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1635                 if (r < 0) {
1636                         log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1637                         goto finish;
1638                 }
1639
1640                 STRV_FOREACH(f, files) {
1641                         k = read_config_file(*f, true);
1642                         if (k < 0 && r == 0)
1643                                 r = k;
1644                 }
1645         }
1646
1647         HASHMAP_FOREACH(i, globs, iterator)
1648                 process_item(i);
1649
1650         HASHMAP_FOREACH(i, items, iterator)
1651                 process_item(i);
1652
1653 finish:
1654         while ((i = hashmap_steal_first(items)))
1655                 item_free(i);
1656
1657         while ((i = hashmap_steal_first(globs)))
1658                 item_free(i);
1659
1660         hashmap_free(items);
1661         hashmap_free(globs);
1662
1663         free(arg_include_prefixes);
1664         free(arg_exclude_prefixes);
1665         free(arg_root);
1666
1667         set_free_free(unix_sockets);
1668
1669         label_finish();
1670
1671         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1672 }