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