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