chiark / gitweb /
d70dbc470753676428c8b7fa6c47b8bd54118b24
[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 DIR* xopendirat_nomod(int dirfd, const char *path) {
312         DIR *dir;
313
314         dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
315         if (!dir) {
316                 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
317                                 dirfd == AT_FDCWD ? "" : "sub", path);
318                 if (errno == EPERM) {
319                         dir = xopendirat(dirfd, path, O_NOFOLLOW);
320                         if (!dir)
321                                 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
322                                                 dirfd == AT_FDCWD ? "" : "sub", path);
323                 }
324         }
325
326         return dir;
327 }
328
329 static DIR* opendir_nomod(const char *path) {
330         return xopendirat_nomod(AT_FDCWD, path);
331 }
332
333 static int dir_cleanup(
334                 Item *i,
335                 const char *p,
336                 DIR *d,
337                 const struct stat *ds,
338                 usec_t cutoff,
339                 dev_t rootdev,
340                 bool mountpoint,
341                 int maxdepth,
342                 bool keep_this_level) {
343
344         struct dirent *dent;
345         struct timespec times[2];
346         bool deleted = false;
347         int r = 0;
348
349         while ((dent = readdir(d))) {
350                 struct stat s;
351                 usec_t age;
352                 _cleanup_free_ char *sub_path = NULL;
353
354                 if (STR_IN_SET(dent->d_name, ".", ".."))
355                         continue;
356
357                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
358                         if (errno == ENOENT)
359                                 continue;
360
361                         /* FUSE, NFS mounts, SELinux might return EACCES */
362                         if (errno == EACCES)
363                                 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
364                         else
365                                 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
366                         r = -errno;
367                         continue;
368                 }
369
370                 /* Stay on the same filesystem */
371                 if (s.st_dev != rootdev) {
372                         log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
373                         continue;
374                 }
375
376                 /* Try to detect bind mounts of the same filesystem instance; they
377                  * do not differ in device major/minors. This type of query is not
378                  * supported on all kernels or filesystem types though. */
379                 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
380                         log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
381                                   p, dent->d_name);
382                         continue;
383                 }
384
385                 /* Do not delete read-only files owned by root */
386                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
387                         log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
388                         continue;
389                 }
390
391                 sub_path = strjoin(p, "/", dent->d_name, NULL);
392                 if (!sub_path) {
393                         r = log_oom();
394                         goto finish;
395                 }
396
397                 /* Is there an item configured for this path? */
398                 if (hashmap_get(items, sub_path)) {
399                         log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
400                         continue;
401                 }
402
403                 if (find_glob(globs, sub_path)) {
404                         log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
405                         continue;
406                 }
407
408                 if (S_ISDIR(s.st_mode)) {
409
410                         if (mountpoint &&
411                             streq(dent->d_name, "lost+found") &&
412                             s.st_uid == 0) {
413                                 log_debug("Ignoring \"%s\".", sub_path);
414                                 continue;
415                         }
416
417                         if (maxdepth <= 0)
418                                 log_warning("Reached max depth on \"%s\".", sub_path);
419                         else {
420                                 _cleanup_closedir_ DIR *sub_dir;
421                                 int q;
422
423                                 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
424                                 if (!sub_dir) {
425                                         if (errno != ENOENT)
426                                                 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
427
428                                         continue;
429                                 }
430
431                                 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
432                                 if (q < 0)
433                                         r = q;
434                         }
435
436                         /* Note: if you are wondering why we don't
437                          * support the sticky bit for excluding
438                          * directories from cleaning like we do it for
439                          * other file system objects: well, the sticky
440                          * bit already has a meaning for directories,
441                          * so we don't want to overload that. */
442
443                         if (keep_this_level) {
444                                 log_debug("Keeping \"%s\".", sub_path);
445                                 continue;
446                         }
447
448                         /* Ignore ctime, we change it when deleting */
449                         age = timespec_load(&s.st_mtim);
450                         if (age >= cutoff) {
451                                 char a[FORMAT_TIMESTAMP_MAX];
452                                 /* Follows spelling in stat(1). */
453                                 log_debug("Directory \"%s\": modify time %s is too new.",
454                                           sub_path,
455                                           format_timestamp_us(a, sizeof(a), age));
456                                 continue;
457                         }
458
459                         age = timespec_load(&s.st_atim);
460                         if (age >= cutoff) {
461                                 char a[FORMAT_TIMESTAMP_MAX];
462                                 log_debug("Directory \"%s\": access time %s is too new.",
463                                           sub_path,
464                                           format_timestamp_us(a, sizeof(a), age));
465                                 continue;
466                         }
467
468                         if (i->type == IGNORE_DIRECTORY_PATH && streq(dent->d_name, p))
469                                 log_debug("Ignoring directory \"%s\"", sub_path);
470                         else {
471                                 log_debug("Removing directory \"%s\".", sub_path);
472
473                                 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
474                                         if (errno != ENOENT && errno != ENOTEMPTY) {
475                                                 log_error_errno(errno, "rmdir(%s): %m", sub_path);
476                                                 r = -errno;
477                                         }
478                                 }
479                         }
480
481                 } else {
482                         /* Skip files for which the sticky bit is
483                          * set. These are semantics we define, and are
484                          * unknown elsewhere. See XDG_RUNTIME_DIR
485                          * specification for details. */
486                         if (s.st_mode & S_ISVTX) {
487                                 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
488                                 continue;
489                         }
490
491                         if (mountpoint && S_ISREG(s.st_mode))
492                                 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
493                                     streq(dent->d_name, "aquota.user") ||
494                                     streq(dent->d_name, "aquota.group")) {
495                                         log_debug("Skipping \"%s\".", sub_path);
496                                         continue;
497                                 }
498
499                         /* Ignore sockets that are listed in /proc/net/unix */
500                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
501                                 log_debug("Skipping \"%s\": live socket.", sub_path);
502                                 continue;
503                         }
504
505                         /* Ignore device nodes */
506                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
507                                 log_debug("Skipping \"%s\": a device.", sub_path);
508                                 continue;
509                         }
510
511                         /* Keep files on this level around if this is
512                          * requested */
513                         if (keep_this_level) {
514                                 log_debug("Keeping \"%s\".", sub_path);
515                                 continue;
516                         }
517
518                         age = timespec_load(&s.st_mtim);
519                         if (age >= cutoff) {
520                                 char a[FORMAT_TIMESTAMP_MAX];
521                                 /* Follows spelling in stat(1). */
522                                 log_debug("File \"%s\": modify time %s is too new.",
523                                           sub_path,
524                                           format_timestamp_us(a, sizeof(a), age));
525                                 continue;
526                         }
527
528                         age = timespec_load(&s.st_atim);
529                         if (age >= cutoff) {
530                                 char a[FORMAT_TIMESTAMP_MAX];
531                                 log_debug("File \"%s\": access time %s is too new.",
532                                           sub_path,
533                                           format_timestamp_us(a, sizeof(a), age));
534                                 continue;
535                         }
536
537                         age = timespec_load(&s.st_ctim);
538                         if (age >= cutoff) {
539                                 char a[FORMAT_TIMESTAMP_MAX];
540                                 log_debug("File \"%s\": change time %s is too new.",
541                                           sub_path,
542                                           format_timestamp_us(a, sizeof(a), age));
543                                 continue;
544                         }
545
546                         log_debug("unlink \"%s\"", sub_path);
547
548                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
549                                 if (errno != ENOENT)
550                                         r = log_error_errno(errno, "unlink(%s): %m", sub_path);
551
552                         deleted = true;
553                 }
554         }
555
556 finish:
557         if (deleted) {
558                 usec_t age1, age2;
559                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
560
561                 /* Restore original directory timestamps */
562                 times[0] = ds->st_atim;
563                 times[1] = ds->st_mtim;
564
565                 age1 = timespec_load(&ds->st_atim);
566                 age2 = timespec_load(&ds->st_mtim);
567                 log_debug("Restoring access and modification time on \"%s\": %s, %s",
568                           p,
569                           format_timestamp_us(a, sizeof(a), age1),
570                           format_timestamp_us(b, sizeof(b), age2));
571                 if (futimens(dirfd(d), times) < 0)
572                         log_error_errno(errno, "utimensat(%s): %m", p);
573         }
574
575         return r;
576 }
577
578 static int path_set_perms(Item *i, const char *path) {
579         struct stat st;
580         bool st_valid;
581
582         assert(i);
583         assert(path);
584
585         st_valid = stat(path, &st) == 0;
586
587         /* not using i->path directly because it may be a glob */
588         if (i->mode_set) {
589                 mode_t m = i->mode;
590
591                 if (i->mask_perms && st_valid) {
592                         if (!(st.st_mode & 0111))
593                                 m &= ~0111;
594                         if (!(st.st_mode & 0222))
595                                 m &= ~0222;
596                         if (!(st.st_mode & 0444))
597                                 m &= ~0444;
598                         if (!S_ISDIR(st.st_mode))
599                                 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
600                 }
601
602                 if (st_valid && m == (st.st_mode & 07777))
603                         log_debug("\"%s\" has right mode %o", path, st.st_mode);
604                 else {
605                         log_debug("chmod \"%s\" to mode %o", path, m);
606                         if (chmod(path, m) < 0)
607                                 return log_error_errno(errno, "chmod(%s) failed: %m", path);
608                 }
609         }
610
611         if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
612             (i->uid_set || i->gid_set)) {
613                 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
614                           path,
615                           i->uid_set ? i->uid : UID_INVALID,
616                           i->gid_set ? i->gid : GID_INVALID);
617                 if (chown(path,
618                           i->uid_set ? i->uid : UID_INVALID,
619                           i->gid_set ? i->gid : GID_INVALID) < 0)
620
621                         return log_error_errno(errno, "chown(%s) failed: %m", path);
622         }
623
624         return label_fix(path, false, false);
625 }
626
627 static int get_xattrs_from_arg(Item *i) {
628         char *xattr;
629         const char *p;
630         int r;
631
632         assert(i);
633         assert(i->argument);
634
635         p = i->argument;
636
637         while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
638                 _cleanup_free_ char *tmp = NULL, *name = NULL,
639                         *value = NULL, *value2 = NULL, *_xattr = xattr;
640
641                 r = split_pair(xattr, "=", &name, &value);
642                 if (r < 0) {
643                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
644                         continue;
645                 }
646
647                 if (strempty(name) || strempty(value)) {
648                         log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
649                         continue;
650                 }
651
652                 tmp = unquote(value, "\"");
653                 if (!tmp)
654                         return log_oom();
655
656                 value2 = cunescape(tmp);
657                 if (!value2)
658                         return log_oom();
659
660                 if (strv_push_pair(&i->xattrs, name, value2) < 0)
661                         return log_oom();
662                 name = value2 = NULL;
663         }
664
665         return r;
666 }
667
668 static int path_set_xattrs(Item *i, const char *path) {
669         char **name, **value;
670
671         assert(i);
672         assert(path);
673
674         STRV_FOREACH_PAIR(name, value, i->xattrs) {
675                 int n;
676
677                 n = strlen(*value);
678                 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
679                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
680                         log_error("Setting extended attribute %s=%s on %s failed: %m",
681                                   *name, *value, path);
682                         return -errno;
683                 }
684         }
685         return 0;
686 }
687
688 static int get_acls_from_arg(Item *item) {
689 #ifdef HAVE_ACL
690         int r;
691         _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
692
693         assert(item);
694
695         /* If force (= modify) is set, we will not modify the acl
696          * afterwards, so the mask can be added now if necessary. */
697         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
698         if (r < 0)
699                 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
700                                   item->argument);
701 #else
702         log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
703 #endif
704
705         return 0;
706 }
707
708 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
709         _cleanup_(acl_freep) acl_t dup = NULL;
710         int r;
711         _cleanup_(acl_free_charpp) char *t = NULL;
712
713         if (modify) {
714                 r = acls_for_file(path, type, acl, &dup);
715                 if (r < 0)
716                         return r;
717
718                 r = calc_acl_mask_if_needed(&dup);
719                 if (r < 0)
720                         return r;
721         } else {
722                 dup = acl_dup(acl);
723                 if (!dup)
724                         return -errno;
725
726                 /* the mask was already added earlier if needed */
727         }
728
729         r = add_base_acls_if_needed(&dup, path);
730         if (r < 0)
731                 return r;
732
733         t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
734         log_debug("\"%s\": setting %s ACL \"%s\"", path,
735                   type == ACL_TYPE_ACCESS ? "access" : "default",
736                   strna(t));
737
738         r = acl_set_file(path, type, dup);
739         if (r < 0)
740                 return log_error_errno(-errno,
741                                        "Setting %s ACL \"%s\" on %s failed: %m",
742                                        type == ACL_TYPE_ACCESS ? "access" : "default",
743                                        strna(t), path);
744         return 0;
745 }
746
747 static int path_set_acls(Item *item, const char *path) {
748 #ifdef HAVE_ACL
749         int r;
750
751         assert(item);
752         assert(path);
753
754         if (item->acl_access) {
755                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
756                 if (r < 0)
757                         return r;
758         }
759
760         if (item->acl_default) {
761                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
762                 if (r < 0)
763                         return r;
764         }
765 #endif
766
767         return 0;
768 }
769
770 static int write_one_file(Item *i, const char *path) {
771         _cleanup_close_ int fd = -1;
772         int flags, r = 0;
773         struct stat st;
774
775         assert(i);
776         assert(path);
777
778         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
779                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
780
781         RUN_WITH_UMASK(0000) {
782                 mac_selinux_create_file_prepare(path, S_IFREG);
783                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
784                 mac_selinux_create_file_clear();
785         }
786
787         if (fd < 0) {
788                 if (i->type == WRITE_FILE && errno == ENOENT) {
789                         log_debug_errno(errno, "Not writing \"%s\": %m", path);
790                         return 0;
791                 }
792
793                 log_error_errno(errno, "Failed to create file %s: %m", path);
794                 return -errno;
795         }
796
797         if (i->argument) {
798                 _cleanup_free_ char *unescaped;
799
800                 log_debug("%s to \"%s\".",
801                           i->type == CREATE_FILE ? "Appending" : "Writing", path);
802
803                 unescaped = cunescape(i->argument);
804                 if (!unescaped)
805                         return log_oom();
806
807                 r = loop_write(fd, unescaped, strlen(unescaped), false);
808                 if (r < 0)
809                         return log_error_errno(r, "Failed to write file \"%s\": %m", path);
810         } else
811                 log_debug("\"%s\" has been created.", path);
812
813         fd = safe_close(fd);
814
815         if (stat(path, &st) < 0)
816                 return log_error_errno(errno, "stat(%s) failed: %m", path);
817
818         if (!S_ISREG(st.st_mode)) {
819                 log_error("%s is not a file.", path);
820                 return -EEXIST;
821         }
822
823         r = path_set_perms(i, path);
824         if (r < 0)
825                 return r;
826
827         return 0;
828 }
829
830 typedef int (*action_t)(Item *, const char *);
831
832 static int item_do_children(Item *i, const char *path, action_t action) {
833         _cleanup_closedir_ DIR *d;
834         int r = 0;
835
836         assert(i);
837         assert(path);
838
839         /* This returns the first error we run into, but nevertheless
840          * tries to go on */
841
842         d = opendir_nomod(path);
843         if (!d)
844                 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
845
846         for (;;) {
847                 _cleanup_free_ char *p = NULL;
848                 struct dirent *de;
849                 int q;
850
851                 errno = 0;
852                 de = readdir(d);
853                 if (!de) {
854                         if (errno != 0 && r == 0)
855                                 r = -errno;
856
857                         break;
858                 }
859
860                 if (STR_IN_SET(de->d_name, ".", ".."))
861                         continue;
862
863                 p = strjoin(path, "/", de->d_name, NULL);
864                 if (!p)
865                         return -ENOMEM;
866
867                 q = action(i, p);
868                 if (q < 0 && q != -ENOENT && r == 0)
869                         r = q;
870
871                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
872                         q = item_do_children(i, p, action);
873                         if (q < 0 && r == 0)
874                                 r = q;
875                 }
876         }
877
878         return r;
879 }
880
881 static int glob_item(Item *i, action_t action, bool recursive) {
882 DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES
883 DISABLE_WARNING_DECLARATION_AFTER_STATEMENT
884         _cleanup_globfree_ glob_t g = {
885                 .gl_closedir = closedir,
886                 .gl_readdir = readdir,
887                 .gl_opendir = opendir_nomod,
888                 .gl_lstat = lstat,
889                 .gl_stat = stat,
890         };
891 REENABLE_WARNING
892 REENABLE_WARNING
893         int r = 0, k;
894         char **fn;
895
896         errno = 0;
897         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
898         if (k != 0 && k != GLOB_NOMATCH)
899                 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
900
901         STRV_FOREACH(fn, g.gl_pathv) {
902                 k = action(i, *fn);
903                 if (k < 0 && r == 0)
904                         r = k;
905
906                 if (recursive) {
907                         k = item_do_children(i, *fn, action);
908                         if (k < 0 && r == 0)
909                                 r = k;
910                 }
911         }
912
913         return r;
914 }
915
916 static int create_item(Item *i) {
917         struct stat st;
918         int r = 0;
919
920         assert(i);
921
922         log_debug("Running create action for entry %c %s", (char) i->type, i->path);
923
924         switch (i->type) {
925
926         case IGNORE_PATH:
927         case IGNORE_DIRECTORY_PATH:
928         case REMOVE_PATH:
929         case RECURSIVE_REMOVE_PATH:
930                 return 0;
931
932         case CREATE_FILE:
933         case TRUNCATE_FILE:
934                 r = write_one_file(i, i->path);
935                 if (r < 0)
936                         return r;
937                 break;
938
939         case COPY_FILES:
940                 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
941                 r = copy_tree(i->argument, i->path, false);
942                 if (r < 0) {
943                         struct stat a, b;
944
945                         if (r != -EEXIST)
946                                 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
947
948                         if (stat(i->argument, &a) < 0)
949                                 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
950
951                         if (stat(i->path, &b) < 0)
952                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
953
954                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
955                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
956                                 return 0;
957                         }
958                 }
959
960                 r = path_set_perms(i, i->path);
961                 if (r < 0)
962                         return r;
963
964                 break;
965
966         case WRITE_FILE:
967                 r = glob_item(i, write_one_file, false);
968                 if (r < 0)
969                         return r;
970
971                 break;
972
973         case CREATE_DIRECTORY:
974         case TRUNCATE_DIRECTORY:
975         case CREATE_SUBVOLUME:
976
977                 RUN_WITH_UMASK(0000)
978                         mkdir_parents_label(i->path, 0755);
979
980                 if (i->type == CREATE_SUBVOLUME)
981                         RUN_WITH_UMASK((~i->mode) & 0777) {
982                                 r = btrfs_subvol_make(i->path);
983                                 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
984                         }
985                 else
986                         r = 0;
987
988                 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
989                         RUN_WITH_UMASK(0000)
990                                 r = mkdir_label(i->path, i->mode);
991
992                 if (r < 0) {
993                         if (r != -EEXIST)
994                                 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
995
996                         if (stat(i->path, &st) < 0)
997                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
998
999                         if (!S_ISDIR(st.st_mode)) {
1000                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
1001                                 return 0;
1002                         }
1003                 }
1004                 log_debug("Created directory \"%s\".", i->path);
1005
1006                 r = path_set_perms(i, i->path);
1007                 if (r < 0)
1008                         return r;
1009
1010                 break;
1011
1012         case CREATE_FIFO:
1013
1014                 RUN_WITH_UMASK(0000) {
1015                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
1016                         r = mkfifo(i->path, i->mode);
1017                         mac_selinux_create_file_clear();
1018                 }
1019
1020                 if (r < 0) {
1021                         if (errno != EEXIST)
1022                                 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1023
1024                         if (stat(i->path, &st) < 0)
1025                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1026
1027                         if (!S_ISFIFO(st.st_mode)) {
1028
1029                                 if (i->force) {
1030
1031                                         RUN_WITH_UMASK(0000) {
1032                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1033                                                 r = mkfifo_atomic(i->path, i->mode);
1034                                                 mac_selinux_create_file_clear();
1035                                         }
1036
1037                                         if (r < 0)
1038                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1039                                 } else {
1040                                         log_debug("%s is not a fifo.", i->path);
1041                                         return 0;
1042                                 }
1043                         }
1044                 }
1045                 log_debug("Created fifo \"%s\".", i->path);
1046
1047                 r = path_set_perms(i, i->path);
1048                 if (r < 0)
1049                         return r;
1050
1051                 break;
1052
1053         case CREATE_SYMLINK:
1054
1055                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1056                 r = symlink(i->argument, i->path);
1057                 mac_selinux_create_file_clear();
1058
1059                 if (r < 0) {
1060                         _cleanup_free_ char *x = NULL;
1061
1062                         if (errno != EEXIST)
1063                                 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1064
1065                         r = readlink_malloc(i->path, &x);
1066                         if (r < 0 || !streq(i->argument, x)) {
1067
1068                                 if (i->force) {
1069                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
1070                                         r = symlink_atomic(i->argument, i->path);
1071                                         mac_selinux_create_file_clear();
1072
1073                                         if (r < 0)
1074                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1075                                 } else {
1076                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1077                                         return 0;
1078                                 }
1079                         }
1080                 }
1081                 log_debug("Created symlink \"%s\".", i->path);
1082
1083                 break;
1084
1085         case CREATE_BLOCK_DEVICE:
1086         case CREATE_CHAR_DEVICE: {
1087                 mode_t file_type;
1088
1089                 if (have_effective_cap(CAP_MKNOD) == 0) {
1090                         /* In a container we lack CAP_MKNOD. We
1091                         shouldn't attempt to create the device node in
1092                         that case to avoid noise, and we don't support
1093                         virtualized devices in containers anyway. */
1094
1095                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1096                         return 0;
1097                 }
1098
1099                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1100
1101                 RUN_WITH_UMASK(0000) {
1102                         mac_selinux_create_file_prepare(i->path, file_type);
1103                         r = mknod(i->path, i->mode | file_type, i->major_minor);
1104                         mac_selinux_create_file_clear();
1105                 }
1106
1107                 if (r < 0) {
1108                         if (errno == EPERM) {
1109                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
1110                                           "skipping creation of device node %s.", i->path);
1111                                 return 0;
1112                         }
1113
1114                         if (errno != EEXIST)
1115                                 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1116
1117                         if (stat(i->path, &st) < 0)
1118                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1119
1120                         if ((st.st_mode & S_IFMT) != file_type) {
1121
1122                                 if (i->force) {
1123
1124                                         RUN_WITH_UMASK(0000) {
1125                                                 mac_selinux_create_file_prepare(i->path, file_type);
1126                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1127                                                 mac_selinux_create_file_clear();
1128                                         }
1129
1130                                         if (r < 0)
1131                                                 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1132                                 } else {
1133                                         log_debug("%s is not a device node.", i->path);
1134                                         return 0;
1135                                 }
1136                         }
1137                 }
1138                 log_debug("Created %s device node \"%s\" %u:%u.",
1139                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1140                           i->path, major(i->mode), minor(i->mode));
1141
1142                 r = path_set_perms(i, i->path);
1143                 if (r < 0)
1144                         return r;
1145
1146                 break;
1147         }
1148
1149         case ADJUST_MODE:
1150         case RELABEL_PATH:
1151                 r = glob_item(i, path_set_perms, false);
1152                 if (r < 0)
1153                         return r;
1154                 break;
1155
1156         case RECURSIVE_RELABEL_PATH:
1157                 r = glob_item(i, path_set_perms, true);
1158                 if (r < 0)
1159                         return r;
1160                 break;
1161
1162         case SET_XATTR:
1163                 r = glob_item(i, path_set_xattrs, false);
1164                 if (r < 0)
1165                         return r;
1166                 break;
1167
1168         case RECURSIVE_SET_XATTR:
1169                 r = glob_item(i, path_set_xattrs, true);
1170                 if (r < 0)
1171                         return r;
1172                 break;
1173
1174         case SET_ACL:
1175                 r = glob_item(i, path_set_acls, false);
1176                 if (r < 0)
1177                         return r;
1178                 break;
1179
1180         case RECURSIVE_SET_ACL:
1181                 r = glob_item(i, path_set_acls, true);
1182                 if (r < 0)
1183                         return r;
1184                 break;
1185         }
1186
1187         log_debug("%s created successfully.", i->path);
1188
1189         return 0;
1190 }
1191
1192 static int remove_item_instance(Item *i, const char *instance) {
1193         int r;
1194
1195         assert(i);
1196
1197         switch (i->type) {
1198
1199         case REMOVE_PATH:
1200                 if (remove(instance) < 0 && errno != ENOENT)
1201                         return log_error_errno(errno, "rm(%s): %m", instance);
1202
1203                 break;
1204
1205         case TRUNCATE_DIRECTORY:
1206         case RECURSIVE_REMOVE_PATH:
1207                 /* FIXME: we probably should use dir_cleanup() here
1208                  * instead of rm_rf() so that 'x' is honoured. */
1209                 log_debug("rm -rf \"%s\"", instance);
1210                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1211                 if (r < 0 && r != -ENOENT)
1212                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1213
1214                 break;
1215
1216         default:
1217                 assert_not_reached("wut?");
1218         }
1219
1220         return 0;
1221 }
1222
1223 static int remove_item(Item *i) {
1224         int r = 0;
1225
1226         assert(i);
1227
1228         log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1229
1230         switch (i->type) {
1231
1232         case CREATE_FILE:
1233         case TRUNCATE_FILE:
1234         case CREATE_DIRECTORY:
1235         case CREATE_SUBVOLUME:
1236         case CREATE_FIFO:
1237         case CREATE_SYMLINK:
1238         case CREATE_CHAR_DEVICE:
1239         case CREATE_BLOCK_DEVICE:
1240         case IGNORE_PATH:
1241         case IGNORE_DIRECTORY_PATH:
1242         case ADJUST_MODE:
1243         case RELABEL_PATH:
1244         case RECURSIVE_RELABEL_PATH:
1245         case WRITE_FILE:
1246         case COPY_FILES:
1247         case SET_XATTR:
1248         case RECURSIVE_SET_XATTR:
1249         case SET_ACL:
1250         case RECURSIVE_SET_ACL:
1251                 break;
1252
1253         case REMOVE_PATH:
1254         case TRUNCATE_DIRECTORY:
1255         case RECURSIVE_REMOVE_PATH:
1256                 r = glob_item(i, remove_item_instance, false);
1257                 break;
1258         }
1259
1260         return r;
1261 }
1262
1263 static int clean_item_instance(Item *i, const char* instance) {
1264         _cleanup_closedir_ DIR *d = NULL;
1265         struct stat s, ps;
1266         bool mountpoint;
1267         usec_t cutoff, n;
1268         char timestamp[FORMAT_TIMESTAMP_MAX];
1269
1270         assert(i);
1271
1272         if (!i->age_set)
1273                 return 0;
1274
1275         n = now(CLOCK_REALTIME);
1276         if (n < i->age)
1277                 return 0;
1278
1279         cutoff = n - i->age;
1280
1281         d = opendir_nomod(instance);
1282         if (!d) {
1283                 if (errno == ENOENT || errno == ENOTDIR) {
1284                         log_debug_errno(errno, "Directory \"%s\": %m", instance);
1285                         return 0;
1286                 }
1287
1288                 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1289                 return -errno;
1290         }
1291
1292         if (fstat(dirfd(d), &s) < 0)
1293                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1294
1295         if (!S_ISDIR(s.st_mode)) {
1296                 log_error("%s is not a directory.", i->path);
1297                 return -ENOTDIR;
1298         }
1299
1300         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1301                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1302
1303         mountpoint = s.st_dev != ps.st_dev ||
1304                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1305
1306         log_debug("Cleanup threshold for %s \"%s\" is %s",
1307                   mountpoint ? "mount point" : "directory",
1308                   instance,
1309                   format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1310
1311         return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1312                            MAX_DEPTH, i->keep_first_level);
1313 }
1314
1315 static int clean_item(Item *i) {
1316         int r = 0;
1317
1318         assert(i);
1319
1320         log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1321
1322         switch (i->type) {
1323         case CREATE_DIRECTORY:
1324         case CREATE_SUBVOLUME:
1325         case TRUNCATE_DIRECTORY:
1326         case IGNORE_PATH:
1327         case COPY_FILES:
1328                 clean_item_instance(i, i->path);
1329                 break;
1330         case IGNORE_DIRECTORY_PATH:
1331                 r = glob_item(i, clean_item_instance, false);
1332                 break;
1333         default:
1334                 break;
1335         }
1336
1337         return r;
1338 }
1339
1340 static int process_item_array(ItemArray *array);
1341
1342 static int process_item(Item *i) {
1343         int r, q, p, t = 0;
1344         _cleanup_free_ char *prefix = NULL;
1345
1346         assert(i);
1347
1348         if (i->done)
1349                 return 0;
1350
1351         i->done = true;
1352
1353         prefix = malloc(strlen(i->path) + 1);
1354         if (!prefix)
1355                 return log_oom();
1356
1357         PATH_FOREACH_PREFIX(prefix, i->path) {
1358                 ItemArray *j;
1359
1360                 j = hashmap_get(items, prefix);
1361                 if (j) {
1362                         int s;
1363
1364                         s = process_item_array(j);
1365                         if (s < 0 && t == 0)
1366                                 t = s;
1367                 }
1368         }
1369
1370         r = arg_create ? create_item(i) : 0;
1371         q = arg_remove ? remove_item(i) : 0;
1372         p = arg_clean ? clean_item(i) : 0;
1373
1374         return t < 0 ? t :
1375                 r < 0 ? r :
1376                 q < 0 ? q :
1377                 p;
1378 }
1379
1380 static int process_item_array(ItemArray *array) {
1381         unsigned n;
1382         int r = 0, k;
1383
1384         assert(array);
1385
1386         for (n = 0; n < array->count; n++) {
1387                 k = process_item(array->items + n);
1388                 if (k < 0 && r == 0)
1389                         r = k;
1390         }
1391
1392         return r;
1393 }
1394
1395 static void item_free_contents(Item *i) {
1396         assert(i);
1397         free(i->path);
1398         free(i->argument);
1399         strv_free(i->xattrs);
1400
1401 #ifdef HAVE_ACL
1402         acl_free(i->acl_access);
1403         acl_free(i->acl_default);
1404 #endif
1405 }
1406
1407 static void item_array_free(ItemArray *a) {
1408         unsigned n;
1409
1410         if (!a)
1411                 return;
1412
1413         for (n = 0; n < a->count; n++)
1414                 item_free_contents(a->items + n);
1415         free(a->items);
1416         free(a);
1417 }
1418
1419 static bool item_compatible(Item *a, Item *b) {
1420         assert(a);
1421         assert(b);
1422         assert(streq(a->path, b->path));
1423
1424         if (takes_ownership(a->type) && takes_ownership(b->type))
1425                 /* check if the items are the same */
1426                 return  streq_ptr(a->argument, b->argument) &&
1427
1428                         a->uid_set == b->uid_set &&
1429                         a->uid == b->uid &&
1430
1431                         a->gid_set == b->gid_set &&
1432                         a->gid == b->gid &&
1433
1434                         a->mode_set == b->mode_set &&
1435                         a->mode == b->mode &&
1436
1437                         a->age_set == b->age_set &&
1438                         a->age == b->age &&
1439
1440                         a->mask_perms == b->mask_perms &&
1441
1442                         a->keep_first_level == b->keep_first_level &&
1443
1444                         a->major_minor == b->major_minor;
1445
1446         return true;
1447 }
1448
1449 static bool should_include_path(const char *path) {
1450         char **prefix;
1451
1452         STRV_FOREACH(prefix, arg_exclude_prefixes)
1453                 if (path_startswith(path, *prefix)) {
1454                         log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1455                                   path, *prefix);
1456                         return false;
1457                 }
1458
1459         STRV_FOREACH(prefix, arg_include_prefixes)
1460                 if (path_startswith(path, *prefix)) {
1461                         log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1462                         return true;
1463                 }
1464
1465         /* no matches, so we should include this path only if we
1466          * have no whitelist at all */
1467         if (strv_length(arg_include_prefixes) == 0)
1468                 return true;
1469
1470         log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1471         return false;
1472 }
1473
1474 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1475
1476         static const Specifier specifier_table[] = {
1477                 { 'm', specifier_machine_id, NULL },
1478                 { 'b', specifier_boot_id, NULL },
1479                 { 'H', specifier_host_name, NULL },
1480                 { 'v', specifier_kernel_release, NULL },
1481                 {}
1482         };
1483
1484         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1485         _cleanup_(item_free_contents) Item i = {};
1486         ItemArray *existing;
1487         Hashmap *h;
1488         int r, c = -1, pos;
1489         bool force = false, boot = false;
1490
1491         assert(fname);
1492         assert(line >= 1);
1493         assert(buffer);
1494
1495         r = sscanf(buffer,
1496                    "%ms %ms %ms %ms %ms %ms %n",
1497                    &action,
1498                    &path,
1499                    &mode,
1500                    &user,
1501                    &group,
1502                    &age,
1503                    &c);
1504         if (r < 2) {
1505                 log_error("[%s:%u] Syntax error.", fname, line);
1506                 return -EIO;
1507         }
1508
1509         if (isempty(action)) {
1510                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1511                 return -EINVAL;
1512         }
1513
1514         for (pos = 1; action[pos]; pos++) {
1515                 if (action[pos] == '!' && !boot)
1516                         boot = true;
1517                 else if (action[pos] == '+' && !force)
1518                         force = true;
1519                 else {
1520                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1521                                   fname, line, action);
1522                         return -EINVAL;
1523                 }
1524         }
1525
1526         if (boot && !arg_boot) {
1527                 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1528                           action, path);
1529                 return 0;
1530         }
1531
1532         i.type = action[0];
1533         i.force = force;
1534
1535         r = specifier_printf(path, specifier_table, NULL, &i.path);
1536         if (r < 0) {
1537                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1538                 return r;
1539         }
1540
1541         if (c >= 0)  {
1542                 c += strspn(buffer+c, WHITESPACE);
1543                 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1544                         i.argument = unquote(buffer+c, "\"");
1545                         if (!i.argument)
1546                                 return log_oom();
1547                 }
1548         }
1549
1550         switch (i.type) {
1551
1552         case CREATE_FILE:
1553         case TRUNCATE_FILE:
1554         case CREATE_DIRECTORY:
1555         case CREATE_SUBVOLUME:
1556         case TRUNCATE_DIRECTORY:
1557         case CREATE_FIFO:
1558         case IGNORE_PATH:
1559         case IGNORE_DIRECTORY_PATH:
1560         case REMOVE_PATH:
1561         case RECURSIVE_REMOVE_PATH:
1562         case ADJUST_MODE:
1563         case RELABEL_PATH:
1564         case RECURSIVE_RELABEL_PATH:
1565                 break;
1566
1567         case CREATE_SYMLINK:
1568                 if (!i.argument) {
1569                         i.argument = strappend("/usr/share/factory/", i.path);
1570                         if (!i.argument)
1571                                 return log_oom();
1572                 }
1573                 break;
1574
1575         case WRITE_FILE:
1576                 if (!i.argument) {
1577                         log_error("[%s:%u] Write file requires argument.", fname, line);
1578                         return -EBADMSG;
1579                 }
1580                 break;
1581
1582         case COPY_FILES:
1583                 if (!i.argument) {
1584                         i.argument = strappend("/usr/share/factory/", i.path);
1585                         if (!i.argument)
1586                                 return log_oom();
1587                 } else if (!path_is_absolute(i.argument)) {
1588                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1589                         return -EBADMSG;
1590                 }
1591
1592                 path_kill_slashes(i.argument);
1593                 break;
1594
1595         case CREATE_CHAR_DEVICE:
1596         case CREATE_BLOCK_DEVICE: {
1597                 unsigned major, minor;
1598
1599                 if (!i.argument) {
1600                         log_error("[%s:%u] Device file requires argument.", fname, line);
1601                         return -EBADMSG;
1602                 }
1603
1604                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1605                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1606                         return -EBADMSG;
1607                 }
1608
1609                 i.major_minor = makedev(major, minor);
1610                 break;
1611         }
1612
1613         case SET_XATTR:
1614         case RECURSIVE_SET_XATTR:
1615                 if (!i.argument) {
1616                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1617                         return -EBADMSG;
1618                 }
1619                 r = get_xattrs_from_arg(&i);
1620                 if (r < 0)
1621                         return r;
1622                 break;
1623
1624         case SET_ACL:
1625         case RECURSIVE_SET_ACL:
1626                 if (!i.argument) {
1627                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1628                         return -EBADMSG;
1629                 }
1630                 r = get_acls_from_arg(&i);
1631                 if (r < 0)
1632                         return r;
1633                 break;
1634
1635         default:
1636                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1637                 return -EBADMSG;
1638         }
1639
1640         if (!path_is_absolute(i.path)) {
1641                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1642                 return -EBADMSG;
1643         }
1644
1645         path_kill_slashes(i.path);
1646
1647         if (!should_include_path(i.path))
1648                 return 0;
1649
1650         if (arg_root) {
1651                 char *p;
1652
1653                 p = strappend(arg_root, i.path);
1654                 if (!p)
1655                         return log_oom();
1656
1657                 free(i.path);
1658                 i.path = p;
1659         }
1660
1661         if (user && !streq(user, "-")) {
1662                 const char *u = user;
1663
1664                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1665                 if (r < 0) {
1666                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1667                         return r;
1668                 }
1669
1670                 i.uid_set = true;
1671         }
1672
1673         if (group && !streq(group, "-")) {
1674                 const char *g = group;
1675
1676                 r = get_group_creds(&g, &i.gid);
1677                 if (r < 0) {
1678                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1679                         return r;
1680                 }
1681
1682                 i.gid_set = true;
1683         }
1684
1685         if (mode && !streq(mode, "-")) {
1686                 const char *mm = mode;
1687                 unsigned m;
1688
1689                 if (*mm == '~') {
1690                         i.mask_perms = true;
1691                         mm++;
1692                 }
1693
1694                 if (sscanf(mm, "%o", &m) != 1) {
1695                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1696                         return -ENOENT;
1697                 }
1698
1699                 i.mode = m;
1700                 i.mode_set = true;
1701         } else
1702                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1703                         ? 0755 : 0644;
1704
1705         if (age && !streq(age, "-")) {
1706                 const char *a = age;
1707
1708                 if (*a == '~') {
1709                         i.keep_first_level = true;
1710                         a++;
1711                 }
1712
1713                 if (parse_sec(a, &i.age) < 0) {
1714                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1715                         return -EBADMSG;
1716                 }
1717
1718                 i.age_set = true;
1719         }
1720
1721         h = needs_glob(i.type) ? globs : items;
1722
1723         existing = hashmap_get(h, i.path);
1724         if (existing) {
1725                 unsigned n;
1726
1727                 for (n = 0; n < existing->count; n++) {
1728                         if (!item_compatible(existing->items + n, &i))
1729                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1730                                             fname, line, i.path);
1731                 }
1732         } else {
1733                 existing = new0(ItemArray, 1);
1734                 r = hashmap_put(h, i.path, existing);
1735                 if (r < 0)
1736                         return log_oom();
1737         }
1738
1739         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1740                 return log_oom();
1741
1742         memcpy(existing->items + existing->count++, &i, sizeof(i));
1743         zero(i);
1744         return 0;
1745 }
1746
1747 static void help(void) {
1748         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1749                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1750                "  -h --help                 Show this help\n"
1751                "     --version              Show package version\n"
1752                "     --create               Create marked files/directories\n"
1753                "     --clean                Clean up marked directories\n"
1754                "     --remove               Remove marked files/directories\n"
1755                "     --boot                 Execute actions only safe at boot\n"
1756                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1757                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n"
1758                "     --root=PATH            Operate on an alternate filesystem root\n",
1759                program_invocation_short_name);
1760 }
1761
1762 static int parse_argv(int argc, char *argv[]) {
1763
1764         enum {
1765                 ARG_VERSION = 0x100,
1766                 ARG_CREATE,
1767                 ARG_CLEAN,
1768                 ARG_REMOVE,
1769                 ARG_BOOT,
1770                 ARG_PREFIX,
1771                 ARG_EXCLUDE_PREFIX,
1772                 ARG_ROOT,
1773         };
1774
1775         static const struct option options[] = {
1776                 { "help",           no_argument,         NULL, 'h'                },
1777                 { "version",        no_argument,         NULL, ARG_VERSION        },
1778                 { "create",         no_argument,         NULL, ARG_CREATE         },
1779                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1780                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1781                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1782                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1783                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1784                 { "root",           required_argument,   NULL, ARG_ROOT           },
1785                 {}
1786         };
1787
1788         int c;
1789
1790         assert(argc >= 0);
1791         assert(argv);
1792
1793         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1794
1795                 switch (c) {
1796
1797                 case 'h':
1798                         help();
1799                         return 0;
1800
1801                 case ARG_VERSION:
1802                         puts(PACKAGE_STRING);
1803                         puts(SYSTEMD_FEATURES);
1804                         return 0;
1805
1806                 case ARG_CREATE:
1807                         arg_create = true;
1808                         break;
1809
1810                 case ARG_CLEAN:
1811                         arg_clean = true;
1812                         break;
1813
1814                 case ARG_REMOVE:
1815                         arg_remove = true;
1816                         break;
1817
1818                 case ARG_BOOT:
1819                         arg_boot = true;
1820                         break;
1821
1822                 case ARG_PREFIX:
1823                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1824                                 return log_oom();
1825                         break;
1826
1827                 case ARG_EXCLUDE_PREFIX:
1828                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1829                                 return log_oom();
1830                         break;
1831
1832                 case ARG_ROOT:
1833                         free(arg_root);
1834                         arg_root = path_make_absolute_cwd(optarg);
1835                         if (!arg_root)
1836                                 return log_oom();
1837
1838                         path_kill_slashes(arg_root);
1839                         break;
1840
1841                 case '?':
1842                         return -EINVAL;
1843
1844                 default:
1845                         assert_not_reached("Unhandled option");
1846                 }
1847
1848         if (!arg_clean && !arg_create && !arg_remove) {
1849                 log_error("You need to specify at least one of --clean, --create or --remove.");
1850                 return -EINVAL;
1851         }
1852
1853         return 1;
1854 }
1855
1856 static int read_config_file(const char *fn, bool ignore_enoent) {
1857         _cleanup_fclose_ FILE *f = NULL;
1858         char line[LINE_MAX];
1859         Iterator iterator;
1860         unsigned v = 0;
1861         Item *i;
1862         int r;
1863
1864         assert(fn);
1865
1866         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1867         if (r < 0) {
1868                 if (ignore_enoent && r == -ENOENT) {
1869                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1870                         return 0;
1871                 }
1872
1873                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1874         }
1875         log_debug("Reading config file \"%s\".", fn);
1876
1877         FOREACH_LINE(line, f, break) {
1878                 char *l;
1879                 int k;
1880
1881                 v++;
1882
1883                 l = strstrip(line);
1884                 if (*l == '#' || *l == 0)
1885                         continue;
1886
1887                 k = parse_line(fn, v, l);
1888                 if (k < 0 && r == 0)
1889                         r = k;
1890         }
1891
1892         /* we have to determine age parameter for each entry of type X */
1893         HASHMAP_FOREACH(i, globs, iterator) {
1894                 Iterator iter;
1895                 Item *j, *candidate_item = NULL;
1896
1897                 if (i->type != IGNORE_DIRECTORY_PATH)
1898                         continue;
1899
1900                 HASHMAP_FOREACH(j, items, iter) {
1901                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1902                                 continue;
1903
1904                         if (path_equal(j->path, i->path)) {
1905                                 candidate_item = j;
1906                                 break;
1907                         }
1908
1909                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1910                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1911                                 candidate_item = j;
1912                 }
1913
1914                 if (candidate_item && candidate_item->age_set) {
1915                         i->age = candidate_item->age;
1916                         i->age_set = true;
1917                 }
1918         }
1919
1920         if (ferror(f)) {
1921                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1922                 if (r == 0)
1923                         r = -EIO;
1924         }
1925
1926         return r;
1927 }
1928
1929 int main(int argc, char *argv[]) {
1930         int r, k;
1931         ItemArray *a;
1932         Iterator iterator;
1933
1934         r = parse_argv(argc, argv);
1935         if (r <= 0)
1936                 goto finish;
1937
1938         log_set_target(LOG_TARGET_AUTO);
1939         log_parse_environment();
1940         log_open();
1941
1942         umask(0022);
1943
1944         mac_selinux_init(NULL);
1945
1946         items = hashmap_new(&string_hash_ops);
1947         globs = hashmap_new(&string_hash_ops);
1948
1949         if (!items || !globs) {
1950                 r = log_oom();
1951                 goto finish;
1952         }
1953
1954         r = 0;
1955
1956         if (optind < argc) {
1957                 int j;
1958
1959                 for (j = optind; j < argc; j++) {
1960                         k = read_config_file(argv[j], false);
1961                         if (k < 0 && r == 0)
1962                                 r = k;
1963                 }
1964
1965         } else {
1966                 _cleanup_strv_free_ char **files = NULL;
1967                 char **f;
1968
1969                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1970                 if (r < 0) {
1971                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1972                         goto finish;
1973                 }
1974
1975                 STRV_FOREACH(f, files) {
1976                         k = read_config_file(*f, true);
1977                         if (k < 0 && r == 0)
1978                                 r = k;
1979                 }
1980         }
1981
1982         HASHMAP_FOREACH(a, globs, iterator) {
1983                 k = process_item_array(a);
1984                 if (k < 0 && r == 0)
1985                         r = k;
1986         }
1987
1988         HASHMAP_FOREACH(a, items, iterator) {
1989                 k = process_item_array(a);
1990                 if (k < 0 && r == 0)
1991                         r = k;
1992         }
1993
1994 finish:
1995         while ((a = hashmap_steal_first(items)))
1996                 item_array_free(a);
1997
1998         while ((a = hashmap_steal_first(globs)))
1999                 item_array_free(a);
2000
2001         hashmap_free(items);
2002         hashmap_free(globs);
2003
2004         free(arg_include_prefixes);
2005         free(arg_exclude_prefixes);
2006         free(arg_root);
2007
2008         set_free_free(unix_sockets);
2009
2010         mac_selinux_finish();
2011
2012         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2013 }