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