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