chiark / gitweb /
7edeeb742840ffbe96ed32a7b0e8c8b8873ee121
[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 dup = NULL;
618         int r;
619
620         if (modify) {
621                 r = acls_for_file(path, type, acl, &dup);
622                 if (r < 0)
623                         return r;
624
625                 r = calc_acl_mask_if_needed(&dup);
626                 if (r < 0)
627                         return r;
628         } else {
629                 dup = acl_dup(acl);
630                 if (!dup)
631                         return -errno;
632
633                 /* the mask was already added earlier if needed */
634         }
635
636         r = add_base_acls_if_needed(&dup, path);
637         if (r < 0)
638                 return r;
639
640         r = acl_set_file(path, type, dup);
641         if (r < 0) {
642                 _cleanup_(acl_free_charpp) char *t;
643
644                 r = -errno;
645                 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
646                 log_error_errno(r,
647                                 "Setting %s ACL \"%s\" on %s failed: %m",
648                                 type == ACL_TYPE_ACCESS ? "access" : "default",
649                                 strna(t), path);
650         }
651
652         return r;
653 }
654
655 static int path_set_acls(Item *item, const char *path) {
656 #ifdef HAVE_ACL
657         int r;
658
659         assert(item);
660         assert(path);
661
662         if (item->acl_access) {
663                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
664                 if (r < 0)
665                         return r;
666         }
667
668         if (item->acl_default) {
669                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
670                 if (r < 0)
671                         return r;
672         }
673 #endif
674
675         return 0;
676 }
677
678 static int write_one_file(Item *i, const char *path) {
679         _cleanup_close_ int fd = -1;
680         int flags, r = 0;
681         struct stat st;
682
683         assert(i);
684         assert(path);
685
686         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
687                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
688
689         RUN_WITH_UMASK(0000) {
690                 mac_selinux_create_file_prepare(path, S_IFREG);
691                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
692                 mac_selinux_create_file_clear();
693         }
694
695         if (fd < 0) {
696                 if (i->type == WRITE_FILE && errno == ENOENT)
697                         return 0;
698
699                 log_error_errno(errno, "Failed to create file %s: %m", path);
700                 return -errno;
701         }
702
703         if (i->argument) {
704                 _cleanup_free_ char *unescaped;
705                 ssize_t n;
706                 size_t l;
707
708                 unescaped = cunescape(i->argument);
709                 if (!unescaped)
710                         return log_oom();
711
712                 l = strlen(unescaped);
713                 n = write(fd, unescaped, l);
714
715                 if (n < 0 || (size_t) n < l) {
716                         log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
717                         return n < 0 ? n : -EIO;
718                 }
719         }
720
721         fd = safe_close(fd);
722
723         if (stat(path, &st) < 0)
724                 return log_error_errno(errno, "stat(%s) failed: %m", path);
725
726         if (!S_ISREG(st.st_mode)) {
727                 log_error("%s is not a file.", path);
728                 return -EEXIST;
729         }
730
731         r = path_set_perms(i, path);
732         if (r < 0)
733                 return r;
734
735         return 0;
736 }
737
738 typedef int (*action_t)(Item *, const char *);
739
740 static int item_do_children(Item *i, const char *path, action_t action) {
741         _cleanup_closedir_ DIR *d;
742         int r = 0;
743
744         assert(i);
745         assert(path);
746
747         /* This returns the first error we run into, but nevertheless
748          * tries to go on */
749
750         d = opendir(path);
751         if (!d)
752                 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
753
754         for (;;) {
755                 _cleanup_free_ char *p = NULL;
756                 struct dirent *de;
757                 int q;
758
759                 errno = 0;
760                 de = readdir(d);
761                 if (!de) {
762                         if (errno != 0 && r == 0)
763                                 r = -errno;
764
765                         break;
766                 }
767
768                 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
769                         continue;
770
771                 p = strjoin(path, "/", de->d_name, NULL);
772                 if (!p)
773                         return -ENOMEM;
774
775                 q = action(i, p);
776                 if (q < 0 && q != -ENOENT && r == 0)
777                         r = q;
778
779                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
780                         q = item_do_children(i, p, action);
781                         if (q < 0 && r == 0)
782                                 r = q;
783                 }
784         }
785
786         return r;
787 }
788
789 static int glob_item(Item *i, action_t action, bool recursive) {
790         _cleanup_globfree_ glob_t g = {};
791         int r = 0, k;
792         char **fn;
793
794         errno = 0;
795         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
796         if (k != 0 && k != GLOB_NOMATCH)
797                 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
798
799         STRV_FOREACH(fn, g.gl_pathv) {
800                 k = action(i, *fn);
801                 if (k < 0 && r == 0)
802                         r = k;
803
804                 if (recursive) {
805                         k = item_do_children(i, *fn, action);
806                         if (k < 0 && r == 0)
807                                 r = k;
808                 }
809         }
810
811         return r;
812 }
813
814 static int create_item(Item *i) {
815         struct stat st;
816         int r = 0;
817
818         assert(i);
819
820         switch (i->type) {
821
822         case IGNORE_PATH:
823         case IGNORE_DIRECTORY_PATH:
824         case REMOVE_PATH:
825         case RECURSIVE_REMOVE_PATH:
826                 return 0;
827
828         case CREATE_FILE:
829         case TRUNCATE_FILE:
830                 r = write_one_file(i, i->path);
831                 if (r < 0)
832                         return r;
833                 break;
834
835         case COPY_FILES:
836                 r = copy_tree(i->argument, i->path, false);
837                 if (r < 0) {
838                         struct stat a, b;
839
840                         if (r != -EEXIST)
841                                 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
842
843                         if (stat(i->argument, &a) < 0)
844                                 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
845
846                         if (stat(i->path, &b) < 0)
847                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
848
849                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
850                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
851                                 return 0;
852                         }
853                 }
854
855                 r = path_set_perms(i, i->path);
856                 if (r < 0)
857                         return r;
858
859                 break;
860
861         case WRITE_FILE:
862                 r = glob_item(i, write_one_file, false);
863                 if (r < 0)
864                         return r;
865
866                 break;
867
868         case CREATE_DIRECTORY:
869         case TRUNCATE_DIRECTORY:
870         case CREATE_SUBVOLUME:
871
872                 RUN_WITH_UMASK(0000)
873                         mkdir_parents_label(i->path, 0755);
874
875                 if (i->type == CREATE_SUBVOLUME) {
876                         RUN_WITH_UMASK((~i->mode) & 0777)
877                                 r = btrfs_subvol_make(i->path);
878                 } else
879                         r = 0;
880
881                 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY) {
882                         RUN_WITH_UMASK(0000)
883                                 r = mkdir_label(i->path, i->mode);
884                 }
885
886                 if (r < 0) {
887                         if (r != -EEXIST)
888                                 return log_error_errno(r, "Failed to create directory or subvolume %s: %m", i->path);
889
890                         if (stat(i->path, &st) < 0)
891                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
892
893                         if (!S_ISDIR(st.st_mode)) {
894                                 log_debug("%s already exists and is not a directory.", i->path);
895                                 return 0;
896                         }
897                 }
898
899                 r = path_set_perms(i, i->path);
900                 if (r < 0)
901                         return r;
902
903                 break;
904
905         case CREATE_FIFO:
906
907                 RUN_WITH_UMASK(0000) {
908                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
909                         r = mkfifo(i->path, i->mode);
910                         mac_selinux_create_file_clear();
911                 }
912
913                 if (r < 0) {
914                         if (errno != EEXIST)
915                                 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
916
917                         if (stat(i->path, &st) < 0)
918                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
919
920                         if (!S_ISFIFO(st.st_mode)) {
921
922                                 if (i->force) {
923
924                                         RUN_WITH_UMASK(0000) {
925                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
926                                                 r = mkfifo_atomic(i->path, i->mode);
927                                                 mac_selinux_create_file_clear();
928                                         }
929
930                                         if (r < 0)
931                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
932                                 } else {
933                                         log_debug("%s is not a fifo.", i->path);
934                                         return 0;
935                                 }
936                         }
937                 }
938
939                 r = path_set_perms(i, i->path);
940                 if (r < 0)
941                         return r;
942
943                 break;
944
945         case CREATE_SYMLINK:
946
947                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
948                 r = symlink(i->argument, i->path);
949                 mac_selinux_create_file_clear();
950
951                 if (r < 0) {
952                         _cleanup_free_ char *x = NULL;
953
954                         if (errno != EEXIST)
955                                 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
956
957                         r = readlink_malloc(i->path, &x);
958                         if (r < 0 || !streq(i->argument, x)) {
959
960                                 if (i->force) {
961                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
962                                         r = symlink_atomic(i->argument, i->path);
963                                         mac_selinux_create_file_clear();
964
965                                         if (r < 0)
966                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
967                                 } else {
968                                         log_debug("%s is not a symlink or does not point to the correct path.", i->path);
969                                         return 0;
970                                 }
971                         }
972                 }
973
974                 break;
975
976         case CREATE_BLOCK_DEVICE:
977         case CREATE_CHAR_DEVICE: {
978                 mode_t file_type;
979
980                 if (have_effective_cap(CAP_MKNOD) == 0) {
981                         /* In a container we lack CAP_MKNOD. We
982                         shouldn't attempt to create the device node in
983                         that case to avoid noise, and we don't support
984                         virtualized devices in containers anyway. */
985
986                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
987                         return 0;
988                 }
989
990                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
991
992                 RUN_WITH_UMASK(0000) {
993                         mac_selinux_create_file_prepare(i->path, file_type);
994                         r = mknod(i->path, i->mode | file_type, i->major_minor);
995                         mac_selinux_create_file_clear();
996                 }
997
998                 if (r < 0) {
999                         if (errno == EPERM) {
1000                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
1001                                           "skipping creation of device node %s.", i->path);
1002                                 return 0;
1003                         }
1004
1005                         if (errno != EEXIST)
1006                                 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1007
1008                         if (stat(i->path, &st) < 0)
1009                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1010
1011                         if ((st.st_mode & S_IFMT) != file_type) {
1012
1013                                 if (i->force) {
1014
1015                                         RUN_WITH_UMASK(0000) {
1016                                                 mac_selinux_create_file_prepare(i->path, file_type);
1017                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1018                                                 mac_selinux_create_file_clear();
1019                                         }
1020
1021                                         if (r < 0)
1022                                                 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1023                                 } else {
1024                                         log_debug("%s is not a device node.", i->path);
1025                                         return 0;
1026                                 }
1027                         }
1028                 }
1029
1030                 r = path_set_perms(i, i->path);
1031                 if (r < 0)
1032                         return r;
1033
1034                 break;
1035         }
1036
1037         case ADJUST_MODE:
1038         case RELABEL_PATH:
1039                 r = glob_item(i, path_set_perms, false);
1040                 if (r < 0)
1041                         return r;
1042                 break;
1043
1044         case RECURSIVE_RELABEL_PATH:
1045                 r = glob_item(i, path_set_perms, true);
1046                 if (r < 0)
1047                         return r;
1048                 break;
1049
1050         case SET_XATTR:
1051                 r = glob_item(i, path_set_xattrs, false);
1052                 if (r < 0)
1053                         return r;
1054                 break;
1055
1056         case RECURSIVE_SET_XATTR:
1057                 r = glob_item(i, path_set_xattrs, true);
1058                 if (r < 0)
1059                         return r;
1060                 break;
1061
1062         case SET_ACL:
1063                 r = glob_item(i, path_set_acls, false);
1064                 if (r < 0)
1065                         return r;
1066                 break;
1067
1068         case RECURSIVE_SET_ACL:
1069                 r = glob_item(i, path_set_acls, true);
1070                 if (r < 0)
1071                         return r;
1072                 break;
1073         }
1074
1075         log_debug("%s created successfully.", i->path);
1076
1077         return 0;
1078 }
1079
1080 static int remove_item_instance(Item *i, const char *instance) {
1081         int r;
1082
1083         assert(i);
1084
1085         switch (i->type) {
1086
1087         case CREATE_FILE:
1088         case TRUNCATE_FILE:
1089         case CREATE_DIRECTORY:
1090         case CREATE_SUBVOLUME:
1091         case CREATE_FIFO:
1092         case CREATE_SYMLINK:
1093         case CREATE_BLOCK_DEVICE:
1094         case CREATE_CHAR_DEVICE:
1095         case IGNORE_PATH:
1096         case IGNORE_DIRECTORY_PATH:
1097         case ADJUST_MODE:
1098         case RELABEL_PATH:
1099         case RECURSIVE_RELABEL_PATH:
1100         case WRITE_FILE:
1101         case COPY_FILES:
1102         case SET_XATTR:
1103         case RECURSIVE_SET_XATTR:
1104         case SET_ACL:
1105         case RECURSIVE_SET_ACL:
1106                 break;
1107
1108         case REMOVE_PATH:
1109                 if (remove(instance) < 0 && errno != ENOENT)
1110                         return log_error_errno(errno, "rm(%s): %m", instance);
1111
1112                 break;
1113
1114         case TRUNCATE_DIRECTORY:
1115         case RECURSIVE_REMOVE_PATH:
1116                 /* FIXME: we probably should use dir_cleanup() here
1117                  * instead of rm_rf() so that 'x' is honoured. */
1118                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1119                 if (r < 0 && r != -ENOENT)
1120                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1121
1122                 break;
1123         }
1124
1125         return 0;
1126 }
1127
1128 static int remove_item(Item *i) {
1129         int r = 0;
1130
1131         assert(i);
1132
1133         switch (i->type) {
1134
1135         case CREATE_FILE:
1136         case TRUNCATE_FILE:
1137         case CREATE_DIRECTORY:
1138         case CREATE_SUBVOLUME:
1139         case CREATE_FIFO:
1140         case CREATE_SYMLINK:
1141         case CREATE_CHAR_DEVICE:
1142         case CREATE_BLOCK_DEVICE:
1143         case IGNORE_PATH:
1144         case IGNORE_DIRECTORY_PATH:
1145         case ADJUST_MODE:
1146         case RELABEL_PATH:
1147         case RECURSIVE_RELABEL_PATH:
1148         case WRITE_FILE:
1149         case COPY_FILES:
1150         case SET_XATTR:
1151         case RECURSIVE_SET_XATTR:
1152         case SET_ACL:
1153         case RECURSIVE_SET_ACL:
1154                 break;
1155
1156         case REMOVE_PATH:
1157         case TRUNCATE_DIRECTORY:
1158         case RECURSIVE_REMOVE_PATH:
1159                 r = glob_item(i, remove_item_instance, false);
1160                 break;
1161         }
1162
1163         return r;
1164 }
1165
1166 static int clean_item_instance(Item *i, const char* instance) {
1167         _cleanup_closedir_ DIR *d = NULL;
1168         struct stat s, ps;
1169         bool mountpoint;
1170         int r;
1171         usec_t cutoff, n;
1172
1173         assert(i);
1174
1175         if (!i->age_set)
1176                 return 0;
1177
1178         n = now(CLOCK_REALTIME);
1179         if (n < i->age)
1180                 return 0;
1181
1182         cutoff = n - i->age;
1183
1184         d = opendir(instance);
1185         if (!d) {
1186                 if (errno == ENOENT || errno == ENOTDIR)
1187                         return 0;
1188
1189                 log_error_errno(errno, "Failed to open directory %s: %m", i->path);
1190                 return -errno;
1191         }
1192
1193         if (fstat(dirfd(d), &s) < 0)
1194                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1195
1196         if (!S_ISDIR(s.st_mode)) {
1197                 log_error("%s is not a directory.", i->path);
1198                 return -ENOTDIR;
1199         }
1200
1201         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1202                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1203
1204         mountpoint = s.st_dev != ps.st_dev ||
1205                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1206
1207         r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1208                         MAX_DEPTH, i->keep_first_level);
1209         return r;
1210 }
1211
1212 static int clean_item(Item *i) {
1213         int r = 0;
1214
1215         assert(i);
1216
1217         switch (i->type) {
1218         case CREATE_DIRECTORY:
1219         case CREATE_SUBVOLUME:
1220         case TRUNCATE_DIRECTORY:
1221         case IGNORE_PATH:
1222         case COPY_FILES:
1223                 clean_item_instance(i, i->path);
1224                 break;
1225         case IGNORE_DIRECTORY_PATH:
1226                 r = glob_item(i, clean_item_instance, false);
1227                 break;
1228         default:
1229                 break;
1230         }
1231
1232         return r;
1233 }
1234
1235 static int process_item_array(ItemArray *array);
1236
1237 static int process_item(Item *i) {
1238         int r, q, p, t = 0;
1239         _cleanup_free_ char *prefix = NULL;
1240
1241         assert(i);
1242
1243         if (i->done)
1244                 return 0;
1245
1246         i->done = true;
1247
1248         prefix = malloc(strlen(i->path) + 1);
1249         if (!prefix)
1250                 return log_oom();
1251
1252         PATH_FOREACH_PREFIX(prefix, i->path) {
1253                 ItemArray *j;
1254
1255                 j = hashmap_get(items, prefix);
1256                 if (j) {
1257                         int s;
1258
1259                         s = process_item_array(j);
1260                         if (s < 0 && t == 0)
1261                                 t = s;
1262                 }
1263         }
1264
1265         r = arg_create ? create_item(i) : 0;
1266         q = arg_remove ? remove_item(i) : 0;
1267         p = arg_clean ? clean_item(i) : 0;
1268
1269         return t < 0 ? t :
1270                 r < 0 ? r :
1271                 q < 0 ? q :
1272                 p;
1273 }
1274
1275 static int process_item_array(ItemArray *array) {
1276         unsigned n;
1277         int r = 0, k;
1278
1279         assert(array);
1280
1281         for (n = 0; n < array->count; n++) {
1282                 k = process_item(array->items + n);
1283                 if (k < 0 && r == 0)
1284                         r = k;
1285         }
1286
1287         return r;
1288 }
1289
1290 static void item_free_contents(Item *i) {
1291         assert(i);
1292         free(i->path);
1293         free(i->argument);
1294         strv_free(i->xattrs);
1295
1296 #ifdef HAVE_ACL
1297         acl_free(i->acl_access);
1298         acl_free(i->acl_default);
1299 #endif
1300 }
1301
1302 static void item_array_free(ItemArray *a) {
1303         unsigned n;
1304
1305         if (!a)
1306                 return;
1307
1308         for (n = 0; n < a->count; n++)
1309                 item_free_contents(a->items + n);
1310         free(a->items);
1311         free(a);
1312 }
1313
1314 static bool item_compatible(Item *a, Item *b) {
1315         assert(a);
1316         assert(b);
1317         assert(streq(a->path, b->path));
1318
1319         if (takes_ownership(a->type) && takes_ownership(b->type))
1320                 /* check if the items are the same */
1321                 return  streq_ptr(a->argument, b->argument) &&
1322
1323                         a->uid_set == b->uid_set &&
1324                         a->uid == b->uid &&
1325
1326                         a->gid_set == b->gid_set &&
1327                         a->gid == b->gid &&
1328
1329                         a->mode_set == b->mode_set &&
1330                         a->mode == b->mode &&
1331
1332                         a->age_set == b->age_set &&
1333                         a->age == b->age &&
1334
1335                         a->mask_perms == b->mask_perms &&
1336
1337                         a->keep_first_level == b->keep_first_level &&
1338
1339                         a->major_minor == b->major_minor;
1340
1341         return true;
1342 }
1343
1344 static bool should_include_path(const char *path) {
1345         char **prefix;
1346
1347         STRV_FOREACH(prefix, arg_exclude_prefixes)
1348                 if (path_startswith(path, *prefix))
1349                         return false;
1350
1351         STRV_FOREACH(prefix, arg_include_prefixes)
1352                 if (path_startswith(path, *prefix))
1353                         return true;
1354
1355         /* no matches, so we should include this path only if we
1356          * have no whitelist at all */
1357         return strv_length(arg_include_prefixes) == 0;
1358 }
1359
1360 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1361
1362         static const Specifier specifier_table[] = {
1363                 { 'm', specifier_machine_id, NULL },
1364                 { 'b', specifier_boot_id, NULL },
1365                 { 'H', specifier_host_name, NULL },
1366                 { 'v', specifier_kernel_release, NULL },
1367                 {}
1368         };
1369
1370         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1371         _cleanup_(item_free_contents) Item i = {};
1372         ItemArray *existing;
1373         Hashmap *h;
1374         int r, c = -1, pos;
1375         bool force = false, boot = false;
1376
1377         assert(fname);
1378         assert(line >= 1);
1379         assert(buffer);
1380
1381         r = sscanf(buffer,
1382                    "%ms %ms %ms %ms %ms %ms %n",
1383                    &action,
1384                    &path,
1385                    &mode,
1386                    &user,
1387                    &group,
1388                    &age,
1389                    &c);
1390         if (r < 2) {
1391                 log_error("[%s:%u] Syntax error.", fname, line);
1392                 return -EIO;
1393         }
1394
1395         if (isempty(action)) {
1396                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1397                 return -EINVAL;
1398         }
1399
1400         for (pos = 1; action[pos]; pos++) {
1401                 if (action[pos] == '!' && !boot)
1402                         boot = true;
1403                 else if (action[pos] == '+' && !force)
1404                         force = true;
1405                 else {
1406                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1407                                   fname, line, action);
1408                         return -EINVAL;
1409                 }
1410         }
1411
1412         if (boot && !arg_boot)
1413                 return 0;
1414
1415         i.type = action[0];
1416         i.force = force;
1417
1418         r = specifier_printf(path, specifier_table, NULL, &i.path);
1419         if (r < 0) {
1420                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1421                 return r;
1422         }
1423
1424         if (c >= 0)  {
1425                 c += strspn(buffer+c, WHITESPACE);
1426                 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1427                         i.argument = unquote(buffer+c, "\"");
1428                         if (!i.argument)
1429                                 return log_oom();
1430                 }
1431         }
1432
1433         switch (i.type) {
1434
1435         case CREATE_FILE:
1436         case TRUNCATE_FILE:
1437         case CREATE_DIRECTORY:
1438         case CREATE_SUBVOLUME:
1439         case TRUNCATE_DIRECTORY:
1440         case CREATE_FIFO:
1441         case IGNORE_PATH:
1442         case IGNORE_DIRECTORY_PATH:
1443         case REMOVE_PATH:
1444         case RECURSIVE_REMOVE_PATH:
1445         case ADJUST_MODE:
1446         case RELABEL_PATH:
1447         case RECURSIVE_RELABEL_PATH:
1448                 break;
1449
1450         case CREATE_SYMLINK:
1451                 if (!i.argument) {
1452                         i.argument = strappend("/usr/share/factory/", i.path);
1453                         if (!i.argument)
1454                                 return log_oom();
1455                 }
1456                 break;
1457
1458         case WRITE_FILE:
1459                 if (!i.argument) {
1460                         log_error("[%s:%u] Write file requires argument.", fname, line);
1461                         return -EBADMSG;
1462                 }
1463                 break;
1464
1465         case COPY_FILES:
1466                 if (!i.argument) {
1467                         i.argument = strappend("/usr/share/factory/", i.path);
1468                         if (!i.argument)
1469                                 return log_oom();
1470                 } else if (!path_is_absolute(i.argument)) {
1471                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1472                         return -EBADMSG;
1473                 }
1474
1475                 path_kill_slashes(i.argument);
1476                 break;
1477
1478         case CREATE_CHAR_DEVICE:
1479         case CREATE_BLOCK_DEVICE: {
1480                 unsigned major, minor;
1481
1482                 if (!i.argument) {
1483                         log_error("[%s:%u] Device file requires argument.", fname, line);
1484                         return -EBADMSG;
1485                 }
1486
1487                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1488                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1489                         return -EBADMSG;
1490                 }
1491
1492                 i.major_minor = makedev(major, minor);
1493                 break;
1494         }
1495
1496         case SET_XATTR:
1497         case RECURSIVE_SET_XATTR:
1498                 if (!i.argument) {
1499                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1500                         return -EBADMSG;
1501                 }
1502                 r = get_xattrs_from_arg(&i);
1503                 if (r < 0)
1504                         return r;
1505                 break;
1506
1507         case SET_ACL:
1508         case RECURSIVE_SET_ACL:
1509                 if (!i.argument) {
1510                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1511                         return -EBADMSG;
1512                 }
1513                 r = get_acls_from_arg(&i);
1514                 if (r < 0)
1515                         return r;
1516                 break;
1517
1518         default:
1519                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, i.type);
1520                 return -EBADMSG;
1521         }
1522
1523         if (!path_is_absolute(i.path)) {
1524                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1525                 return -EBADMSG;
1526         }
1527
1528         path_kill_slashes(i.path);
1529
1530         if (!should_include_path(i.path))
1531                 return 0;
1532
1533         if (arg_root) {
1534                 char *p;
1535
1536                 p = strappend(arg_root, i.path);
1537                 if (!p)
1538                         return log_oom();
1539
1540                 free(i.path);
1541                 i.path = p;
1542         }
1543
1544         if (user && !streq(user, "-")) {
1545                 const char *u = user;
1546
1547                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1548                 if (r < 0) {
1549                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1550                         return r;
1551                 }
1552
1553                 i.uid_set = true;
1554         }
1555
1556         if (group && !streq(group, "-")) {
1557                 const char *g = group;
1558
1559                 r = get_group_creds(&g, &i.gid);
1560                 if (r < 0) {
1561                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1562                         return r;
1563                 }
1564
1565                 i.gid_set = true;
1566         }
1567
1568         if (mode && !streq(mode, "-")) {
1569                 const char *mm = mode;
1570                 unsigned m;
1571
1572                 if (*mm == '~') {
1573                         i.mask_perms = true;
1574                         mm++;
1575                 }
1576
1577                 if (sscanf(mm, "%o", &m) != 1) {
1578                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1579                         return -ENOENT;
1580                 }
1581
1582                 i.mode = m;
1583                 i.mode_set = true;
1584         } else
1585                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1586                         ? 0755 : 0644;
1587
1588         if (age && !streq(age, "-")) {
1589                 const char *a = age;
1590
1591                 if (*a == '~') {
1592                         i.keep_first_level = true;
1593                         a++;
1594                 }
1595
1596                 if (parse_sec(a, &i.age) < 0) {
1597                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1598                         return -EBADMSG;
1599                 }
1600
1601                 i.age_set = true;
1602         }
1603
1604         h = needs_glob(i.type) ? globs : items;
1605
1606         existing = hashmap_get(h, i.path);
1607         if (existing) {
1608                 unsigned n;
1609
1610                 for (n = 0; n < existing->count; n++) {
1611                         if (!item_compatible(existing->items + n, &i))
1612                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1613                                             fname, line, i.path);
1614                 }
1615         } else {
1616                 existing = new0(ItemArray, 1);
1617                 r = hashmap_put(h, i.path, existing);
1618                 if (r < 0)
1619                         return log_oom();
1620         }
1621
1622         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1623                 return log_oom();
1624
1625         memcpy(existing->items + existing->count++, &i, sizeof(i));
1626         zero(i);
1627         return 0;
1628 }
1629
1630 static void help(void) {
1631         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1632                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1633                "  -h --help                 Show this help\n"
1634                "     --version              Show package version\n"
1635                "     --create               Create marked files/directories\n"
1636                "     --clean                Clean up marked directories\n"
1637                "     --remove               Remove marked files/directories\n"
1638                "     --boot                 Execute actions only safe at boot\n"
1639                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1640                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n"
1641                "     --root=PATH            Operate on an alternate filesystem root\n",
1642                program_invocation_short_name);
1643 }
1644
1645 static int parse_argv(int argc, char *argv[]) {
1646
1647         enum {
1648                 ARG_VERSION = 0x100,
1649                 ARG_CREATE,
1650                 ARG_CLEAN,
1651                 ARG_REMOVE,
1652                 ARG_BOOT,
1653                 ARG_PREFIX,
1654                 ARG_EXCLUDE_PREFIX,
1655                 ARG_ROOT,
1656         };
1657
1658         static const struct option options[] = {
1659                 { "help",           no_argument,         NULL, 'h'                },
1660                 { "version",        no_argument,         NULL, ARG_VERSION        },
1661                 { "create",         no_argument,         NULL, ARG_CREATE         },
1662                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1663                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1664                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1665                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1666                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1667                 { "root",           required_argument,   NULL, ARG_ROOT           },
1668                 {}
1669         };
1670
1671         int c;
1672
1673         assert(argc >= 0);
1674         assert(argv);
1675
1676         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1677
1678                 switch (c) {
1679
1680                 case 'h':
1681                         help();
1682                         return 0;
1683
1684                 case ARG_VERSION:
1685                         puts(PACKAGE_STRING);
1686                         puts(SYSTEMD_FEATURES);
1687                         return 0;
1688
1689                 case ARG_CREATE:
1690                         arg_create = true;
1691                         break;
1692
1693                 case ARG_CLEAN:
1694                         arg_clean = true;
1695                         break;
1696
1697                 case ARG_REMOVE:
1698                         arg_remove = true;
1699                         break;
1700
1701                 case ARG_BOOT:
1702                         arg_boot = true;
1703                         break;
1704
1705                 case ARG_PREFIX:
1706                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1707                                 return log_oom();
1708                         break;
1709
1710                 case ARG_EXCLUDE_PREFIX:
1711                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1712                                 return log_oom();
1713                         break;
1714
1715                 case ARG_ROOT:
1716                         free(arg_root);
1717                         arg_root = path_make_absolute_cwd(optarg);
1718                         if (!arg_root)
1719                                 return log_oom();
1720
1721                         path_kill_slashes(arg_root);
1722                         break;
1723
1724                 case '?':
1725                         return -EINVAL;
1726
1727                 default:
1728                         assert_not_reached("Unhandled option");
1729                 }
1730
1731         if (!arg_clean && !arg_create && !arg_remove) {
1732                 log_error("You need to specify at least one of --clean, --create or --remove.");
1733                 return -EINVAL;
1734         }
1735
1736         return 1;
1737 }
1738
1739 static int read_config_file(const char *fn, bool ignore_enoent) {
1740         _cleanup_fclose_ FILE *f = NULL;
1741         char line[LINE_MAX];
1742         Iterator iterator;
1743         unsigned v = 0;
1744         Item *i;
1745         int r;
1746
1747         assert(fn);
1748
1749         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1750         if (r < 0) {
1751                 if (ignore_enoent && r == -ENOENT)
1752                         return 0;
1753
1754                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1755         }
1756
1757         FOREACH_LINE(line, f, break) {
1758                 char *l;
1759                 int k;
1760
1761                 v++;
1762
1763                 l = strstrip(line);
1764                 if (*l == '#' || *l == 0)
1765                         continue;
1766
1767                 k = parse_line(fn, v, l);
1768                 if (k < 0 && r == 0)
1769                         r = k;
1770         }
1771
1772         /* we have to determine age parameter for each entry of type X */
1773         HASHMAP_FOREACH(i, globs, iterator) {
1774                 Iterator iter;
1775                 Item *j, *candidate_item = NULL;
1776
1777                 if (i->type != IGNORE_DIRECTORY_PATH)
1778                         continue;
1779
1780                 HASHMAP_FOREACH(j, items, iter) {
1781                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1782                                 continue;
1783
1784                         if (path_equal(j->path, i->path)) {
1785                                 candidate_item = j;
1786                                 break;
1787                         }
1788
1789                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1790                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1791                                 candidate_item = j;
1792                 }
1793
1794                 if (candidate_item && candidate_item->age_set) {
1795                         i->age = candidate_item->age;
1796                         i->age_set = true;
1797                 }
1798         }
1799
1800         if (ferror(f)) {
1801                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1802                 if (r == 0)
1803                         r = -EIO;
1804         }
1805
1806         return r;
1807 }
1808
1809 int main(int argc, char *argv[]) {
1810         int r, k;
1811         ItemArray *a;
1812         Iterator iterator;
1813
1814         r = parse_argv(argc, argv);
1815         if (r <= 0)
1816                 goto finish;
1817
1818         log_set_target(LOG_TARGET_AUTO);
1819         log_parse_environment();
1820         log_open();
1821
1822         umask(0022);
1823
1824         mac_selinux_init(NULL);
1825
1826         items = hashmap_new(&string_hash_ops);
1827         globs = hashmap_new(&string_hash_ops);
1828
1829         if (!items || !globs) {
1830                 r = log_oom();
1831                 goto finish;
1832         }
1833
1834         r = 0;
1835
1836         if (optind < argc) {
1837                 int j;
1838
1839                 for (j = optind; j < argc; j++) {
1840                         k = read_config_file(argv[j], false);
1841                         if (k < 0 && r == 0)
1842                                 r = k;
1843                 }
1844
1845         } else {
1846                 _cleanup_strv_free_ char **files = NULL;
1847                 char **f;
1848
1849                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1850                 if (r < 0) {
1851                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1852                         goto finish;
1853                 }
1854
1855                 STRV_FOREACH(f, files) {
1856                         k = read_config_file(*f, true);
1857                         if (k < 0 && r == 0)
1858                                 r = k;
1859                 }
1860         }
1861
1862         HASHMAP_FOREACH(a, globs, iterator) {
1863                 k = process_item_array(a);
1864                 if (k < 0 && r == 0)
1865                         r = k;
1866         }
1867
1868         HASHMAP_FOREACH(a, items, iterator) {
1869                 k = process_item_array(a);
1870                 if (k < 0 && r == 0)
1871                         r = k;
1872         }
1873
1874 finish:
1875         while ((a = hashmap_steal_first(items)))
1876                 item_array_free(a);
1877
1878         while ((a = hashmap_steal_first(globs)))
1879                 item_array_free(a);
1880
1881         hashmap_free(items);
1882         hashmap_free(globs);
1883
1884         free(arg_include_prefixes);
1885         free(arg_exclude_prefixes);
1886         free(arg_root);
1887
1888         set_free_free(unix_sockets);
1889
1890         mac_selinux_finish();
1891
1892         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1893 }