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