chiark / gitweb /
tmpfiles: rename --unsafe to --boot
[elogind.git] / src / tmpfiles / tmpfiles.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering, Kay Sievers
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <limits.h>
28 #include <dirent.h>
29 #include <grp.h>
30 #include <pwd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <getopt.h>
35 #include <stdbool.h>
36 #include <time.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <glob.h>
40 #include <fnmatch.h>
41 #include <sys/capability.h>
42
43 #include "log.h"
44 #include "util.h"
45 #include "macro.h"
46 #include "missing.h"
47 #include "mkdir.h"
48 #include "path-util.h"
49 #include "strv.h"
50 #include "label.h"
51 #include "set.h"
52 #include "conf-files.h"
53 #include "capability.h"
54 #include "specifier.h"
55 #include "build.h"
56
57 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
58  * them in the file system. This is intended to be used to create
59  * properly owned directories beneath /tmp, /var/tmp, /run, which are
60  * volatile and hence need to be recreated on bootup. */
61
62 typedef enum ItemType {
63         /* These ones take file names */
64         CREATE_FILE = 'f',
65         TRUNCATE_FILE = 'F',
66         WRITE_FILE = 'w',
67         CREATE_DIRECTORY = 'd',
68         TRUNCATE_DIRECTORY = 'D',
69         CREATE_FIFO = 'p',
70         CREATE_SYMLINK = 'L',
71         CREATE_CHAR_DEVICE = 'c',
72         CREATE_BLOCK_DEVICE = 'b',
73         ADJUST_MODE = 'm',
74
75         /* These ones take globs */
76         IGNORE_PATH = 'x',
77         IGNORE_DIRECTORY_PATH = 'X',
78         REMOVE_PATH = 'r',
79         RECURSIVE_REMOVE_PATH = 'R',
80         RELABEL_PATH = 'z',
81         RECURSIVE_RELABEL_PATH = 'Z'
82 } ItemType;
83
84 typedef struct Item {
85         ItemType type;
86
87         char *path;
88         char *argument;
89         uid_t uid;
90         gid_t gid;
91         mode_t mode;
92         usec_t age;
93
94         dev_t major_minor;
95
96         bool uid_set:1;
97         bool gid_set:1;
98         bool mode_set:1;
99         bool age_set:1;
100
101         bool keep_first_level:1;
102 } Item;
103
104 static Hashmap *items = NULL, *globs = NULL;
105 static Set *unix_sockets = NULL;
106
107 static bool arg_create = false;
108 static bool arg_clean = false;
109 static bool arg_remove = false;
110 static bool arg_boot = false;
111
112 static char **include_prefixes = NULL;
113 static char **exclude_prefixes = NULL;
114
115 static const char conf_file_dirs[] =
116         "/etc/tmpfiles.d\0"
117         "/run/tmpfiles.d\0"
118         "/usr/local/lib/tmpfiles.d\0"
119         "/usr/lib/tmpfiles.d\0"
120 #ifdef HAVE_SPLIT_USR
121         "/lib/tmpfiles.d\0"
122 #endif
123         ;
124
125 #define MAX_DEPTH 256
126
127 static bool needs_glob(ItemType t) {
128         return t == IGNORE_PATH || t == IGNORE_DIRECTORY_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
129 }
130
131 static struct Item* find_glob(Hashmap *h, const char *match) {
132         Item *j;
133         Iterator i;
134
135         HASHMAP_FOREACH(j, h, i)
136                 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
137                         return j;
138
139         return NULL;
140 }
141
142 static void load_unix_sockets(void) {
143         _cleanup_fclose_ FILE *f = NULL;
144         char line[LINE_MAX];
145
146         if (unix_sockets)
147                 return;
148
149         /* We maintain a cache of the sockets we found in
150          * /proc/net/unix to speed things up a little. */
151
152         unix_sockets = set_new(string_hash_func, string_compare_func);
153         if (!unix_sockets)
154                 return;
155
156         f = fopen("/proc/net/unix", "re");
157         if (!f)
158                 return;
159
160         /* Skip header */
161         if (!fgets(line, sizeof(line), f))
162                 goto fail;
163
164         for (;;) {
165                 char *p, *s;
166                 int k;
167
168                 if (!fgets(line, sizeof(line), f))
169                         break;
170
171                 truncate_nl(line);
172
173                 p = strchr(line, ':');
174                 if (!p)
175                         continue;
176
177                 if (strlen(p) < 37)
178                         continue;
179
180                 p += 37;
181                 p += strspn(p, WHITESPACE);
182                 p += strcspn(p, WHITESPACE); /* skip one more word */
183                 p += strspn(p, WHITESPACE);
184
185                 if (*p != '/')
186                         continue;
187
188                 s = strdup(p);
189                 if (!s)
190                         goto fail;
191
192                 path_kill_slashes(s);
193
194                 k = set_consume(unix_sockets, s);
195                 if (k < 0 && k != -EEXIST)
196                         goto fail;
197         }
198
199         return;
200
201 fail:
202         set_free_free(unix_sockets);
203         unix_sockets = NULL;
204 }
205
206 static bool unix_socket_alive(const char *fn) {
207         assert(fn);
208
209         load_unix_sockets();
210
211         if (unix_sockets)
212                 return !!set_get(unix_sockets, (char*) fn);
213
214         /* We don't know, so assume yes */
215         return true;
216 }
217
218 static int dir_is_mount_point(DIR *d, const char *subdir) {
219         struct file_handle *h;
220         int mount_id_parent, mount_id;
221         int r_p, r;
222
223         h = alloca(MAX_HANDLE_SZ);
224
225         h->handle_bytes = MAX_HANDLE_SZ;
226         r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0);
227         if (r_p < 0)
228                 r_p = -errno;
229
230         h->handle_bytes = MAX_HANDLE_SZ;
231         r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0);
232         if (r < 0)
233                 r = -errno;
234
235         /* got no handle; make no assumptions, return error */
236         if (r_p < 0 && r < 0)
237                 return r_p;
238
239         /* got both handles; if they differ, it is a mount point */
240         if (r_p >= 0 && r >= 0)
241                 return mount_id_parent != mount_id;
242
243         /* got only one handle; assume different mount points if one
244          * of both queries was not supported by the filesystem */
245         if (r_p == -ENOSYS || r_p == -ENOTSUP || r == -ENOSYS || r == -ENOTSUP)
246                 return true;
247
248         /* return error */
249         if (r_p < 0)
250                 return r_p;
251         return r;
252 }
253
254 static int dir_cleanup(
255                 Item *i,
256                 const char *p,
257                 DIR *d,
258                 const struct stat *ds,
259                 usec_t cutoff,
260                 dev_t rootdev,
261                 bool mountpoint,
262                 int maxdepth,
263                 bool keep_this_level) {
264
265         struct dirent *dent;
266         struct timespec times[2];
267         bool deleted = false;
268         int r = 0;
269
270         while ((dent = readdir(d))) {
271                 struct stat s;
272                 usec_t age;
273                 _cleanup_free_ char *sub_path = NULL;
274
275                 if (streq(dent->d_name, ".") ||
276                     streq(dent->d_name, ".."))
277                         continue;
278
279                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
280                         if (errno == ENOENT)
281                                 continue;
282
283                         /* FUSE, NFS mounts, SELinux might return EACCES */
284                         if (errno == EACCES)
285                                 log_debug("stat(%s/%s) failed: %m", p, dent->d_name);
286                         else
287                                 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
288                         r = -errno;
289                         continue;
290                 }
291
292                 /* Stay on the same filesystem */
293                 if (s.st_dev != rootdev)
294                         continue;
295
296                 /* Try to detect bind mounts of the same filesystem instance; they
297                  * do not differ in device major/minors. This type of query is not
298                  * supported on all kernels or filesystem types though. */
299                 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0)
300                         continue;
301
302                 /* Do not delete read-only files owned by root */
303                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
304                         continue;
305
306                 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
307                         r = log_oom();
308                         goto finish;
309                 }
310
311                 /* Is there an item configured for this path? */
312                 if (hashmap_get(items, sub_path))
313                         continue;
314
315                 if (find_glob(globs, sub_path))
316                         continue;
317
318                 if (S_ISDIR(s.st_mode)) {
319
320                         if (mountpoint &&
321                             streq(dent->d_name, "lost+found") &&
322                             s.st_uid == 0)
323                                 continue;
324
325                         if (maxdepth <= 0)
326                                 log_warning("Reached max depth on %s.", sub_path);
327                         else {
328                                 _cleanup_closedir_ DIR *sub_dir;
329                                 int q;
330
331                                 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
332                                 if (sub_dir == NULL) {
333                                         if (errno != ENOENT) {
334                                                 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
335                                                 r = -errno;
336                                         }
337
338                                         continue;
339                                 }
340
341                                 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
342
343                                 if (q < 0)
344                                         r = q;
345                         }
346
347                         /* Note: if you are wondering why we don't
348                          * support the sticky bit for excluding
349                          * directories from cleaning like we do it for
350                          * other file system objects: well, the sticky
351                          * bit already has a meaning for directories,
352                          * so we don't want to overload that. */
353
354                         if (keep_this_level)
355                                 continue;
356
357                         /* Ignore ctime, we change it when deleting */
358                         age = MAX(timespec_load(&s.st_mtim),
359                                   timespec_load(&s.st_atim));
360                         if (age >= cutoff)
361                                 continue;
362
363                         if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
364                                 log_debug("rmdir '%s'", sub_path);
365
366                                 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
367                                         if (errno != ENOENT && errno != ENOTEMPTY) {
368                                                 log_error("rmdir(%s): %m", sub_path);
369                                                 r = -errno;
370                                         }
371                                 }
372                         }
373
374                 } else {
375                         /* Skip files for which the sticky bit is
376                          * set. These are semantics we define, and are
377                          * unknown elsewhere. See XDG_RUNTIME_DIR
378                          * specification for details. */
379                         if (s.st_mode & S_ISVTX)
380                                 continue;
381
382                         if (mountpoint && S_ISREG(s.st_mode)) {
383                                 if (streq(dent->d_name, ".journal") &&
384                                     s.st_uid == 0)
385                                         continue;
386
387                                 if (streq(dent->d_name, "aquota.user") ||
388                                     streq(dent->d_name, "aquota.group"))
389                                         continue;
390                         }
391
392                         /* Ignore sockets that are listed in /proc/net/unix */
393                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
394                                 continue;
395
396                         /* Ignore device nodes */
397                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
398                                 continue;
399
400                         /* Keep files on this level around if this is
401                          * requested */
402                         if (keep_this_level)
403                                 continue;
404
405                         age = MAX3(timespec_load(&s.st_mtim),
406                                    timespec_load(&s.st_atim),
407                                    timespec_load(&s.st_ctim));
408
409                         if (age >= cutoff)
410                                 continue;
411
412                         log_debug("unlink '%s'", sub_path);
413
414                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
415                                 if (errno != ENOENT) {
416                                         log_error("unlink(%s): %m", sub_path);
417                                         r = -errno;
418                                 }
419                         }
420
421                         deleted = true;
422                 }
423         }
424
425 finish:
426         if (deleted) {
427                 /* Restore original directory timestamps */
428                 times[0] = ds->st_atim;
429                 times[1] = ds->st_mtim;
430
431                 if (futimens(dirfd(d), times) < 0)
432                         log_error("utimensat(%s): %m", p);
433         }
434
435         return r;
436 }
437
438 static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) {
439         int r;
440
441         /* not using i->path directly because it may be a glob */
442         if (i->mode_set)
443                 if (chmod(path, i->mode) < 0) {
444                         if (errno != ENOENT || !ignore_enoent) {
445                                 log_error("chmod(%s) failed: %m", path);
446                                 return -errno;
447                         }
448                 }
449
450         if (i->uid_set || i->gid_set)
451                 if (chown(path,
452                           i->uid_set ? i->uid : (uid_t) -1,
453                           i->gid_set ? i->gid : (gid_t) -1) < 0) {
454
455                         if (errno != ENOENT || !ignore_enoent) {
456                                 log_error("chown(%s) failed: %m", path);
457                                 return -errno;
458                         }
459                 }
460
461         r = label_fix(path, false, false);
462         return r == -ENOENT && ignore_enoent ? 0 : r;
463 }
464
465 static int item_set_perms(Item *i, const char *path) {
466         return item_set_perms_full(i, path, false);
467 }
468
469 static int write_one_file(Item *i, const char *path) {
470         int e, flags;
471         int fd = -1;
472         struct stat st;
473         int r = 0;
474
475         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
476                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
477
478         RUN_WITH_UMASK(0) {
479                 label_context_set(path, S_IFREG);
480                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
481                 e = errno;
482                 label_context_clear();
483                 errno = e;
484         }
485
486         if (fd < 0) {
487                 if (i->type == WRITE_FILE && errno == ENOENT)
488                         return 0;
489
490                 log_error("Failed to create file %s: %m", path);
491                 return -errno;
492         }
493
494         if (i->argument) {
495                 ssize_t n;
496                 size_t l;
497                 _cleanup_free_ char *unescaped;
498
499                 unescaped = cunescape(i->argument);
500                 if (unescaped == NULL) {
501                         close_nointr_nofail(fd);
502                         return log_oom();
503                 }
504
505                 l = strlen(unescaped);
506                 n = write(fd, unescaped, l);
507
508                 if (n < 0 || (size_t) n < l) {
509                         log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
510                         close_nointr_nofail(fd);
511                         return n < 0 ? n : -EIO;
512                 }
513         }
514
515         close_nointr_nofail(fd);
516
517         if (stat(path, &st) < 0) {
518                 log_error("stat(%s) failed: %m", path);
519                 return -errno;
520         }
521
522         if (!S_ISREG(st.st_mode)) {
523                 log_error("%s is not a file.", path);
524                 return -EEXIST;
525         }
526
527         r = item_set_perms(i, path);
528         if (r < 0)
529                 return r;
530
531         return 0;
532 }
533
534 static int recursive_relabel_children(Item *i, const char *path) {
535         _cleanup_closedir_ DIR *d;
536         int ret = 0;
537
538         /* This returns the first error we run into, but nevertheless
539          * tries to go on */
540
541         d = opendir(path);
542         if (!d)
543                 return errno == ENOENT ? 0 : -errno;
544
545         for (;;) {
546                 struct dirent *de;
547                 bool is_dir;
548                 int r;
549                 _cleanup_free_ char *entry_path = NULL;
550
551                 errno = 0;
552                 de = readdir(d);
553                 if (!de && errno != 0) {
554                         if (ret == 0)
555                                 ret = -errno;
556                         break;
557                 }
558
559                 if (!de)
560                         break;
561
562                 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
563                         continue;
564
565                 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
566                         if (ret == 0)
567                                 ret = -ENOMEM;
568                         continue;
569                 }
570
571                 if (de->d_type == DT_UNKNOWN) {
572                         struct stat st;
573
574                         if (lstat(entry_path, &st) < 0) {
575                                 if (ret == 0 && errno != ENOENT)
576                                         ret = -errno;
577                                 continue;
578                         }
579
580                         is_dir = S_ISDIR(st.st_mode);
581
582                 } else
583                         is_dir = de->d_type == DT_DIR;
584
585                 r = item_set_perms(i, entry_path);
586                 if (r < 0) {
587                         if (ret == 0 && r != -ENOENT)
588                                 ret = r;
589                         continue;
590                 }
591
592                 if (is_dir) {
593                         r = recursive_relabel_children(i, entry_path);
594                         if (r < 0 && ret == 0)
595                                 ret = r;
596                 }
597         }
598
599         return ret;
600 }
601
602 static int recursive_relabel(Item *i, const char *path) {
603         int r;
604         struct stat st;
605
606         r = item_set_perms(i, path);
607         if (r < 0)
608                 return r;
609
610         if (lstat(path, &st) < 0)
611                 return -errno;
612
613         if (S_ISDIR(st.st_mode))
614                 r = recursive_relabel_children(i, path);
615
616         return r;
617 }
618
619 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
620         int r = 0, k;
621         _cleanup_globfree_ glob_t g = {};
622         char **fn;
623
624         errno = 0;
625         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
626         if (k != 0)
627                 if (k != GLOB_NOMATCH) {
628                         if (errno > 0)
629                                 errno = EIO;
630
631                         log_error("glob(%s) failed: %m", i->path);
632                         return -errno;
633                 }
634
635         STRV_FOREACH(fn, g.gl_pathv) {
636                 k = action(i, *fn);
637                 if (k < 0)
638                         r = k;
639         }
640
641         return r;
642 }
643
644 static int create_item(Item *i) {
645         int e;
646         struct stat st;
647         int r = 0;
648
649         assert(i);
650
651         switch (i->type) {
652
653         case IGNORE_PATH:
654         case IGNORE_DIRECTORY_PATH:
655         case REMOVE_PATH:
656         case RECURSIVE_REMOVE_PATH:
657                 return 0;
658
659         case CREATE_FILE:
660         case TRUNCATE_FILE:
661                 r = write_one_file(i, i->path);
662                 if (r < 0)
663                         return r;
664                 break;
665
666         case WRITE_FILE:
667                 r = glob_item(i, write_one_file);
668                 if (r < 0)
669                         return r;
670
671                 break;
672
673         case ADJUST_MODE:
674                 r = item_set_perms_full(i, i->path, true);
675                 if (r < 0)
676                         return r;
677
678                 break;
679
680         case TRUNCATE_DIRECTORY:
681         case CREATE_DIRECTORY:
682
683                 RUN_WITH_UMASK(0000) {
684                         mkdir_parents_label(i->path, 0755);
685                         r = mkdir(i->path, i->mode);
686                 }
687
688                 if (r < 0 && errno != EEXIST) {
689                         log_error("Failed to create directory %s: %m", i->path);
690                         return -errno;
691                 }
692
693                 if (stat(i->path, &st) < 0) {
694                         log_error("stat(%s) failed: %m", i->path);
695                         return -errno;
696                 }
697
698                 if (!S_ISDIR(st.st_mode)) {
699                         log_error("%s is not a directory.", i->path);
700                         return -EEXIST;
701                 }
702
703                 r = item_set_perms(i, i->path);
704                 if (r < 0)
705                         return r;
706
707                 break;
708
709         case CREATE_FIFO:
710
711                 RUN_WITH_UMASK(0000) {
712                         r = mkfifo(i->path, i->mode);
713                 }
714
715                 if (r < 0 && errno != EEXIST) {
716                         log_error("Failed to create fifo %s: %m", i->path);
717                         return -errno;
718                 }
719
720                 if (stat(i->path, &st) < 0) {
721                         log_error("stat(%s) failed: %m", i->path);
722                         return -errno;
723                 }
724
725                 if (!S_ISFIFO(st.st_mode)) {
726                         log_error("%s is not a fifo.", i->path);
727                         return -EEXIST;
728                 }
729
730                 r = item_set_perms(i, i->path);
731                 if (r < 0)
732                         return r;
733
734                 break;
735
736         case CREATE_SYMLINK: {
737                 char *x;
738
739                 label_context_set(i->path, S_IFLNK);
740                 r = symlink(i->argument, i->path);
741                 e = errno;
742                 label_context_clear();
743                 errno = e;
744
745                 if (r < 0 && errno != EEXIST) {
746                         log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
747                         return -errno;
748                 }
749
750                 r = readlink_malloc(i->path, &x);
751                 if (r < 0) {
752                         log_error("readlink(%s) failed: %s", i->path, strerror(-r));
753                         return -errno;
754                 }
755
756                 if (!streq(i->argument, x)) {
757                         free(x);
758                         log_error("%s is not the right symlinks.", i->path);
759                         return -EEXIST;
760                 }
761
762                 free(x);
763                 break;
764         }
765
766         case CREATE_BLOCK_DEVICE:
767         case CREATE_CHAR_DEVICE: {
768                 mode_t file_type;
769
770                 if (have_effective_cap(CAP_MKNOD) == 0) {
771                         /* In a container we lack CAP_MKNOD. We
772                         shouldn't attempt to create the device node in
773                         that case to avoid noise, and we don't support
774                         virtualized devices in containers anyway. */
775
776                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
777                         return 0;
778                 }
779
780                 file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
781
782                 RUN_WITH_UMASK(0000) {
783                         label_context_set(i->path, file_type);
784                         r = mknod(i->path, i->mode | file_type, i->major_minor);
785                         e = errno;
786                         label_context_clear();
787                         errno = e;
788                 }
789
790                 if (r < 0 && errno != EEXIST) {
791                         log_error("Failed to create device node %s: %m", i->path);
792                         return -errno;
793                 }
794
795                 if (stat(i->path, &st) < 0) {
796                         log_error("stat(%s) failed: %m", i->path);
797                         return -errno;
798                 }
799
800                 if ((st.st_mode & S_IFMT) != file_type) {
801                         log_error("%s is not a device node.", i->path);
802                         return -EEXIST;
803                 }
804
805                 r = item_set_perms(i, i->path);
806                 if (r < 0)
807                         return r;
808
809                 break;
810         }
811
812         case RELABEL_PATH:
813
814                 r = glob_item(i, item_set_perms);
815                 if (r < 0)
816                         return r;
817                 break;
818
819         case RECURSIVE_RELABEL_PATH:
820
821                 r = glob_item(i, recursive_relabel);
822                 if (r < 0)
823                         return r;
824         }
825
826         log_debug("%s created successfully.", i->path);
827
828         return 0;
829 }
830
831 static int remove_item_instance(Item *i, const char *instance) {
832         int r;
833
834         assert(i);
835
836         switch (i->type) {
837
838         case CREATE_FILE:
839         case TRUNCATE_FILE:
840         case CREATE_DIRECTORY:
841         case CREATE_FIFO:
842         case CREATE_SYMLINK:
843         case CREATE_BLOCK_DEVICE:
844         case CREATE_CHAR_DEVICE:
845         case IGNORE_PATH:
846         case IGNORE_DIRECTORY_PATH:
847         case RELABEL_PATH:
848         case RECURSIVE_RELABEL_PATH:
849         case WRITE_FILE:
850         case ADJUST_MODE:
851                 break;
852
853         case REMOVE_PATH:
854                 if (remove(instance) < 0 && errno != ENOENT) {
855                         log_error("remove(%s): %m", instance);
856                         return -errno;
857                 }
858
859                 break;
860
861         case TRUNCATE_DIRECTORY:
862         case RECURSIVE_REMOVE_PATH:
863                 /* FIXME: we probably should use dir_cleanup() here
864                  * instead of rm_rf() so that 'x' is honoured. */
865                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
866                 if (r < 0 && r != -ENOENT) {
867                         log_error("rm_rf(%s): %s", instance, strerror(-r));
868                         return r;
869                 }
870
871                 break;
872         }
873
874         return 0;
875 }
876
877 static int remove_item(Item *i) {
878         int r = 0;
879
880         assert(i);
881
882         switch (i->type) {
883
884         case CREATE_FILE:
885         case TRUNCATE_FILE:
886         case CREATE_DIRECTORY:
887         case CREATE_FIFO:
888         case CREATE_SYMLINK:
889         case CREATE_CHAR_DEVICE:
890         case CREATE_BLOCK_DEVICE:
891         case IGNORE_PATH:
892         case IGNORE_DIRECTORY_PATH:
893         case RELABEL_PATH:
894         case RECURSIVE_RELABEL_PATH:
895         case WRITE_FILE:
896         case ADJUST_MODE:
897                 break;
898
899         case REMOVE_PATH:
900         case TRUNCATE_DIRECTORY:
901         case RECURSIVE_REMOVE_PATH:
902                 r = glob_item(i, remove_item_instance);
903                 break;
904         }
905
906         return r;
907 }
908
909 static int clean_item_instance(Item *i, const char* instance) {
910         _cleanup_closedir_ DIR *d = NULL;
911         struct stat s, ps;
912         bool mountpoint;
913         int r;
914         usec_t cutoff, n;
915
916         assert(i);
917
918         if (!i->age_set)
919                 return 0;
920
921         n = now(CLOCK_REALTIME);
922         if (n < i->age)
923                 return 0;
924
925         cutoff = n - i->age;
926
927         d = opendir(instance);
928         if (!d) {
929                 if (errno == ENOENT || errno == ENOTDIR)
930                         return 0;
931
932                 log_error("Failed to open directory %s: %m", i->path);
933                 return -errno;
934         }
935
936         if (fstat(dirfd(d), &s) < 0) {
937                 log_error("stat(%s) failed: %m", i->path);
938                 return -errno;
939         }
940
941         if (!S_ISDIR(s.st_mode)) {
942                 log_error("%s is not a directory.", i->path);
943                 return -ENOTDIR;
944         }
945
946         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
947                 log_error("stat(%s/..) failed: %m", i->path);
948                 return -errno;
949         }
950
951         mountpoint = s.st_dev != ps.st_dev ||
952                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
953
954         r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
955                         MAX_DEPTH, i->keep_first_level);
956         return r;
957 }
958
959 static int clean_item(Item *i) {
960         int r = 0;
961
962         assert(i);
963
964         switch (i->type) {
965         case CREATE_DIRECTORY:
966         case TRUNCATE_DIRECTORY:
967         case IGNORE_PATH:
968                 clean_item_instance(i, i->path);
969                 break;
970         case IGNORE_DIRECTORY_PATH:
971                 r = glob_item(i, clean_item_instance);
972                 break;
973         default:
974                 break;
975         }
976
977         return r;
978 }
979
980 static int process_item(Item *i) {
981         int r, q, p;
982
983         assert(i);
984
985         r = arg_create ? create_item(i) : 0;
986         q = arg_remove ? remove_item(i) : 0;
987         p = arg_clean ? clean_item(i) : 0;
988
989         if (r < 0)
990                 return r;
991
992         if (q < 0)
993                 return q;
994
995         return p;
996 }
997
998 static void item_free(Item *i) {
999         assert(i);
1000
1001         free(i->path);
1002         free(i->argument);
1003         free(i);
1004 }
1005
1006 DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
1007 #define _cleanup_item_free_ _cleanup_(item_freep)
1008
1009 static bool item_equal(Item *a, Item *b) {
1010         assert(a);
1011         assert(b);
1012
1013         if (!streq_ptr(a->path, b->path))
1014                 return false;
1015
1016         if (a->type != b->type)
1017                 return false;
1018
1019         if (a->uid_set != b->uid_set ||
1020             (a->uid_set && a->uid != b->uid))
1021             return false;
1022
1023         if (a->gid_set != b->gid_set ||
1024             (a->gid_set && a->gid != b->gid))
1025             return false;
1026
1027         if (a->mode_set != b->mode_set ||
1028             (a->mode_set && a->mode != b->mode))
1029             return false;
1030
1031         if (a->age_set != b->age_set ||
1032             (a->age_set && a->age != b->age))
1033             return false;
1034
1035         if ((a->type == CREATE_FILE ||
1036              a->type == TRUNCATE_FILE ||
1037              a->type == WRITE_FILE ||
1038              a->type == CREATE_SYMLINK) &&
1039             !streq_ptr(a->argument, b->argument))
1040                 return false;
1041
1042         if ((a->type == CREATE_CHAR_DEVICE ||
1043              a->type == CREATE_BLOCK_DEVICE) &&
1044             a->major_minor != b->major_minor)
1045                 return false;
1046
1047         return true;
1048 }
1049
1050 static bool should_include_path(const char *path) {
1051         char **prefix;
1052
1053         STRV_FOREACH(prefix, exclude_prefixes) {
1054                 if (path_startswith(path, *prefix))
1055                         return false;
1056         }
1057
1058         STRV_FOREACH(prefix, include_prefixes) {
1059                 if (path_startswith(path, *prefix))
1060                         return true;
1061         }
1062
1063         /* no matches, so we should include this path only if we
1064          * have no whitelist at all */
1065         return strv_length(include_prefixes) == 0;
1066 }
1067
1068 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1069
1070         static const Specifier specifier_table[] = {
1071                 { 'm', specifier_machine_id, NULL },
1072                 { 'b', specifier_boot_id, NULL },
1073                 { 'H', specifier_host_name, NULL },
1074                 { 'v', specifier_kernel_release, NULL },
1075                 {}
1076         };
1077
1078         _cleanup_item_free_ Item *i = NULL;
1079         Item *existing;
1080         _cleanup_free_ char
1081                 *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1082         char type;
1083         Hashmap *h;
1084         int r, n = -1;
1085
1086         assert(fname);
1087         assert(line >= 1);
1088         assert(buffer);
1089
1090         r = sscanf(buffer,
1091                    "%ms %ms %ms %ms %ms %ms %n",
1092                    &action,
1093                    &path,
1094                    &mode,
1095                    &user,
1096                    &group,
1097                    &age,
1098                    &n);
1099         if (r < 2) {
1100                 log_error("[%s:%u] Syntax error.", fname, line);
1101                 return -EIO;
1102         }
1103
1104         if (strlen(action) > 2 || (strlen(action) > 1 && action[1] != '!')) {
1105                 log_error("[%s:%u] Unknown modifier '%s'", fname, line, action);
1106                 return -EINVAL;
1107         } else if (strlen(action) > 1 && !arg_boot)
1108                 return 0;
1109
1110         type = action[0];
1111
1112         i = new0(Item, 1);
1113         if (!i)
1114                 return log_oom();
1115
1116         r = specifier_printf(path, specifier_table, NULL, &i->path);
1117         if (r < 0) {
1118                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1119                 return r;
1120         }
1121
1122         if (n >= 0)  {
1123                 n += strspn(buffer+n, WHITESPACE);
1124                 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1125                         i->argument = unquote(buffer+n, "\"");
1126                         if (!i->argument)
1127                                 return log_oom();
1128                 }
1129         }
1130
1131         switch(type) {
1132
1133         case CREATE_FILE:
1134         case TRUNCATE_FILE:
1135         case CREATE_DIRECTORY:
1136         case TRUNCATE_DIRECTORY:
1137         case CREATE_FIFO:
1138         case IGNORE_PATH:
1139         case IGNORE_DIRECTORY_PATH:
1140         case REMOVE_PATH:
1141         case RECURSIVE_REMOVE_PATH:
1142         case RELABEL_PATH:
1143         case RECURSIVE_RELABEL_PATH:
1144         case ADJUST_MODE:
1145                 break;
1146
1147         case CREATE_SYMLINK:
1148                 if (!i->argument) {
1149                         log_error("[%s:%u] Symlink file requires argument.", fname, line);
1150                         return -EBADMSG;
1151                 }
1152                 break;
1153
1154         case WRITE_FILE:
1155                 if (!i->argument) {
1156                         log_error("[%s:%u] Write file requires argument.", fname, line);
1157                         return -EBADMSG;
1158                 }
1159                 break;
1160
1161         case CREATE_CHAR_DEVICE:
1162         case CREATE_BLOCK_DEVICE: {
1163                 unsigned major, minor;
1164
1165                 if (!i->argument) {
1166                         log_error("[%s:%u] Device file requires argument.", fname, line);
1167                         return -EBADMSG;
1168                 }
1169
1170                 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1171                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1172                         return -EBADMSG;
1173                 }
1174
1175                 i->major_minor = makedev(major, minor);
1176                 break;
1177         }
1178
1179         default:
1180                 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1181                 return -EBADMSG;
1182         }
1183
1184         i->type = type;
1185
1186         if (!path_is_absolute(i->path)) {
1187                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1188                 return -EBADMSG;
1189         }
1190
1191         path_kill_slashes(i->path);
1192
1193         if (!should_include_path(i->path))
1194                 return 0;
1195
1196         if (user && !streq(user, "-")) {
1197                 const char *u = user;
1198
1199                 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1200                 if (r < 0) {
1201                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1202                         return r;
1203                 }
1204
1205                 i->uid_set = true;
1206         }
1207
1208         if (group && !streq(group, "-")) {
1209                 const char *g = group;
1210
1211                 r = get_group_creds(&g, &i->gid);
1212                 if (r < 0) {
1213                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1214                         return r;
1215                 }
1216
1217                 i->gid_set = true;
1218         }
1219
1220         if (mode && !streq(mode, "-")) {
1221                 unsigned m;
1222
1223                 if (sscanf(mode, "%o", &m) != 1) {
1224                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1225                         return -ENOENT;
1226                 }
1227
1228                 i->mode = m;
1229                 i->mode_set = true;
1230         } else
1231                 i->mode =
1232                         i->type == CREATE_DIRECTORY ||
1233                         i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1234
1235         if (age && !streq(age, "-")) {
1236                 const char *a = age;
1237
1238                 if (*a == '~') {
1239                         i->keep_first_level = true;
1240                         a++;
1241                 }
1242
1243                 if (parse_sec(a, &i->age) < 0) {
1244                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1245                         return -EBADMSG;
1246                 }
1247
1248                 i->age_set = true;
1249         }
1250
1251         h = needs_glob(i->type) ? globs : items;
1252
1253         existing = hashmap_get(h, i->path);
1254         if (existing) {
1255
1256                 /* Two identical items are fine */
1257                 if (!item_equal(existing, i))
1258                         log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1259
1260                 return 0;
1261         }
1262
1263         r = hashmap_put(h, i->path, i);
1264         if (r < 0) {
1265                 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1266                 return r;
1267         }
1268
1269         i = NULL; /* avoid cleanup */
1270
1271         return 0;
1272 }
1273
1274 static int help(void) {
1275
1276         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1277                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1278                "  -h --help                 Show this help\n"
1279                "     --version              Show package version\n"
1280                "     --create               Create marked files/directories\n"
1281                "     --clean                Clean up marked directories\n"
1282                "     --remove               Remove marked files/directories\n"
1283                "     --boot                 Execute actions only safe at boot\n"
1284                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1285                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n",
1286                program_invocation_short_name);
1287
1288         return 0;
1289 }
1290
1291 static int parse_argv(int argc, char *argv[]) {
1292
1293         enum {
1294                 ARG_VERSION = 0x100,
1295                 ARG_CREATE,
1296                 ARG_CLEAN,
1297                 ARG_REMOVE,
1298                 ARG_BOOT,
1299                 ARG_PREFIX,
1300                 ARG_EXCLUDE_PREFIX,
1301         };
1302
1303         static const struct option options[] = {
1304                 { "help",           no_argument,         NULL, 'h'                },
1305                 { "version",        no_argument,         NULL, ARG_VERSION        },
1306                 { "create",         no_argument,         NULL, ARG_CREATE         },
1307                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1308                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1309                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1310                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1311                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1312                 {}
1313         };
1314
1315         int c;
1316
1317         assert(argc >= 0);
1318         assert(argv);
1319
1320         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1321
1322                 switch (c) {
1323
1324                 case 'h':
1325                         return help();
1326
1327                 case ARG_VERSION:
1328                         puts(PACKAGE_STRING);
1329                         puts(SYSTEMD_FEATURES);
1330                         return 0;
1331
1332                 case ARG_CREATE:
1333                         arg_create = true;
1334                         break;
1335
1336                 case ARG_CLEAN:
1337                         arg_clean = true;
1338                         break;
1339
1340                 case ARG_REMOVE:
1341                         arg_remove = true;
1342                         break;
1343
1344                 case ARG_BOOT:
1345                         arg_boot = true;
1346                         break;
1347
1348                 case ARG_PREFIX:
1349                         if (strv_extend(&include_prefixes, optarg) < 0)
1350                                 return log_oom();
1351                         break;
1352
1353                 case ARG_EXCLUDE_PREFIX:
1354                         if (strv_extend(&exclude_prefixes, optarg) < 0)
1355                                 return log_oom();
1356                         break;
1357
1358                 case '?':
1359                         return -EINVAL;
1360
1361                 default:
1362                         assert_not_reached("Unhandled option");
1363                 }
1364         }
1365
1366         if (!arg_clean && !arg_create && !arg_remove) {
1367                 log_error("You need to specify at least one of --clean, --create or --remove.");
1368                 return -EINVAL;
1369         }
1370
1371         return 1;
1372 }
1373
1374 static int read_config_file(const char *fn, bool ignore_enoent) {
1375         _cleanup_fclose_ FILE *f = NULL;
1376         char line[LINE_MAX];
1377         Iterator iterator;
1378         unsigned v = 0;
1379         Item *i;
1380         int r;
1381
1382         assert(fn);
1383
1384         r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f);
1385         if (r < 0) {
1386                 if (ignore_enoent && r == -ENOENT)
1387                         return 0;
1388
1389                 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1390                 return r;
1391         }
1392
1393         FOREACH_LINE(line, f, break) {
1394                 char *l;
1395                 int k;
1396
1397                 v++;
1398
1399                 l = strstrip(line);
1400                 if (*l == '#' || *l == 0)
1401                         continue;
1402
1403                 k = parse_line(fn, v, l);
1404                 if (k < 0 && r == 0)
1405                         r = k;
1406         }
1407
1408         /* we have to determine age parameter for each entry of type X */
1409         HASHMAP_FOREACH(i, globs, iterator) {
1410                 Iterator iter;
1411                 Item *j, *candidate_item = NULL;
1412
1413                 if (i->type != IGNORE_DIRECTORY_PATH)
1414                         continue;
1415
1416                 HASHMAP_FOREACH(j, items, iter) {
1417                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1418                                 continue;
1419
1420                         if (path_equal(j->path, i->path)) {
1421                                 candidate_item = j;
1422                                 break;
1423                         }
1424
1425                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1426                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1427                                 candidate_item = j;
1428                 }
1429
1430                 if (candidate_item) {
1431                         i->age = candidate_item->age;
1432                         i->age_set = true;
1433                 }
1434         }
1435
1436         if (ferror(f)) {
1437                 log_error("Failed to read from file %s: %m", fn);
1438                 if (r == 0)
1439                         r = -EIO;
1440         }
1441
1442         return r;
1443 }
1444
1445 int main(int argc, char *argv[]) {
1446         int r, k;
1447         Item *i;
1448         Iterator iterator;
1449
1450         r = parse_argv(argc, argv);
1451         if (r <= 0)
1452                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1453
1454         log_set_target(LOG_TARGET_AUTO);
1455         log_parse_environment();
1456         log_open();
1457
1458         umask(0022);
1459
1460         label_init(NULL);
1461
1462         items = hashmap_new(string_hash_func, string_compare_func);
1463         globs = hashmap_new(string_hash_func, string_compare_func);
1464
1465         if (!items || !globs) {
1466                 r = log_oom();
1467                 goto finish;
1468         }
1469
1470         r = 0;
1471
1472         if (optind < argc) {
1473                 int j;
1474
1475                 for (j = optind; j < argc; j++) {
1476                         k = read_config_file(argv[j], false);
1477                         if (k < 0 && r == 0)
1478                                 r = k;
1479                 }
1480
1481         } else {
1482                 _cleanup_strv_free_ char **files = NULL;
1483                 char **f;
1484
1485                 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
1486                 if (r < 0) {
1487                         log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1488                         goto finish;
1489                 }
1490
1491                 STRV_FOREACH(f, files) {
1492                         k = read_config_file(*f, true);
1493                         if (k < 0 && r == 0)
1494                                 r = k;
1495                 }
1496         }
1497
1498         HASHMAP_FOREACH(i, globs, iterator)
1499                 process_item(i);
1500
1501         HASHMAP_FOREACH(i, items, iterator)
1502                 process_item(i);
1503
1504 finish:
1505         while ((i = hashmap_steal_first(items)))
1506                 item_free(i);
1507
1508         while ((i = hashmap_steal_first(globs)))
1509                 item_free(i);
1510
1511         hashmap_free(items);
1512         hashmap_free(globs);
1513
1514         strv_free(include_prefixes);
1515
1516         set_free_free(unix_sockets);
1517
1518         label_finish();
1519
1520         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1521 }