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