1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering, Kay Sievers
7 Copyright 2015 Zbigniew Jędrzejewski-Szmek
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/xattr.h>
49 #include "path-util.h"
53 #include "conf-files.h"
54 #include "capability.h"
55 #include "specifier.h"
58 #include "selinux-util.h"
59 #include "btrfs-util.h"
62 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
63 * them in the file system. This is intended to be used to create
64 * properly owned directories beneath /tmp, /var/tmp, /run, which are
65 * volatile and hence need to be recreated on bootup. */
67 typedef enum ItemType {
68 /* These ones take file names */
71 CREATE_DIRECTORY = 'd',
72 TRUNCATE_DIRECTORY = 'D',
73 CREATE_SUBVOLUME = 'v',
76 CREATE_CHAR_DEVICE = 'c',
77 CREATE_BLOCK_DEVICE = 'b',
80 /* These ones take globs */
82 RECURSIVE_SET_XATTR = 'T',
84 RECURSIVE_SET_ACL = 'A',
87 IGNORE_DIRECTORY_PATH = 'X',
89 RECURSIVE_REMOVE_PATH = 'R',
90 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
92 RECURSIVE_RELABEL_PATH = 'Z',
118 bool keep_first_level:1;
125 typedef struct ItemArray {
131 static bool arg_create = false;
132 static bool arg_clean = false;
133 static bool arg_remove = false;
134 static bool arg_boot = false;
136 static char **arg_include_prefixes = NULL;
137 static char **arg_exclude_prefixes = NULL;
138 static char *arg_root = NULL;
140 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
142 #define MAX_DEPTH 256
144 static Hashmap *items = NULL, *globs = NULL;
145 static Set *unix_sockets = NULL;
147 static bool needs_glob(ItemType t) {
151 IGNORE_DIRECTORY_PATH,
153 RECURSIVE_REMOVE_PATH,
156 RECURSIVE_RELABEL_PATH,
163 static bool takes_ownership(ItemType t) {
178 IGNORE_DIRECTORY_PATH,
180 RECURSIVE_REMOVE_PATH);
183 static struct Item* find_glob(Hashmap *h, const char *match) {
187 HASHMAP_FOREACH(j, h, i) {
190 for (n = 0; n < j->count; n++) {
191 Item *item = j->items + n;
193 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
201 static void load_unix_sockets(void) {
202 _cleanup_fclose_ FILE *f = NULL;
208 /* We maintain a cache of the sockets we found in
209 * /proc/net/unix to speed things up a little. */
211 unix_sockets = set_new(&string_hash_ops);
215 f = fopen("/proc/net/unix", "re");
220 if (!fgets(line, sizeof(line), f))
227 if (!fgets(line, sizeof(line), f))
232 p = strchr(line, ':');
240 p += strspn(p, WHITESPACE);
241 p += strcspn(p, WHITESPACE); /* skip one more word */
242 p += strspn(p, WHITESPACE);
251 path_kill_slashes(s);
253 k = set_consume(unix_sockets, s);
254 if (k < 0 && k != -EEXIST)
261 set_free_free(unix_sockets);
265 static bool unix_socket_alive(const char *fn) {
271 return !!set_get(unix_sockets, (char*) fn);
273 /* We don't know, so assume yes */
277 static int dir_is_mount_point(DIR *d, const char *subdir) {
279 union file_handle_union h = FILE_HANDLE_INIT;
280 int mount_id_parent, mount_id;
283 r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
287 h.handle.handle_bytes = MAX_HANDLE_SZ;
288 r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
292 /* got no handle; make no assumptions, return error */
293 if (r_p < 0 && r < 0)
296 /* got both handles; if they differ, it is a mount point */
297 if (r_p >= 0 && r >= 0)
298 return mount_id_parent != mount_id;
300 /* got only one handle; assume different mount points if one
301 * of both queries was not supported by the filesystem */
302 if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
311 static DIR* xopendirat_nomod(int dirfd, const char *path) {
314 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
316 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
317 dirfd == AT_FDCWD ? "" : "sub", path);
318 if (errno == EPERM) {
319 dir = xopendirat(dirfd, path, O_NOFOLLOW);
321 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
322 dirfd == AT_FDCWD ? "" : "sub", path);
329 static DIR* opendir_nomod(const char *path) {
330 return xopendirat_nomod(AT_FDCWD, path);
333 static int dir_cleanup(
337 const struct stat *ds,
342 bool keep_this_level) {
345 struct timespec times[2];
346 bool deleted = false;
349 while ((dent = readdir(d))) {
352 _cleanup_free_ char *sub_path = NULL;
354 if (STR_IN_SET(dent->d_name, ".", ".."))
357 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
361 /* FUSE, NFS mounts, SELinux might return EACCES */
363 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
365 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
370 /* Stay on the same filesystem */
371 if (s.st_dev != rootdev) {
372 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
376 /* Try to detect bind mounts of the same filesystem instance; they
377 * do not differ in device major/minors. This type of query is not
378 * supported on all kernels or filesystem types though. */
379 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
380 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
385 /* Do not delete read-only files owned by root */
386 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
387 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
391 sub_path = strjoin(p, "/", dent->d_name, NULL);
397 /* Is there an item configured for this path? */
398 if (hashmap_get(items, sub_path)) {
399 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
403 if (find_glob(globs, sub_path)) {
404 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
408 if (S_ISDIR(s.st_mode)) {
411 streq(dent->d_name, "lost+found") &&
413 log_debug("Ignoring \"%s\".", sub_path);
418 log_warning("Reached max depth on \"%s\".", sub_path);
420 _cleanup_closedir_ DIR *sub_dir;
423 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
426 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
431 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
436 /* Note: if you are wondering why we don't
437 * support the sticky bit for excluding
438 * directories from cleaning like we do it for
439 * other file system objects: well, the sticky
440 * bit already has a meaning for directories,
441 * so we don't want to overload that. */
443 if (keep_this_level) {
444 log_debug("Keeping \"%s\".", sub_path);
448 /* Ignore ctime, we change it when deleting */
449 age = timespec_load(&s.st_mtim);
451 char a[FORMAT_TIMESTAMP_MAX];
452 /* Follows spelling in stat(1). */
453 log_debug("Directory \"%s\": modify time %s is too new.",
455 format_timestamp_us(a, sizeof(a), age));
459 age = timespec_load(&s.st_atim);
461 char a[FORMAT_TIMESTAMP_MAX];
462 log_debug("Directory \"%s\": access time %s is too new.",
464 format_timestamp_us(a, sizeof(a), age));
468 if (i->type == IGNORE_DIRECTORY_PATH && streq(dent->d_name, p))
469 log_debug("Ignoring directory \"%s\"", sub_path);
471 log_debug("Removing directory \"%s\".", sub_path);
473 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
474 if (errno != ENOENT && errno != ENOTEMPTY) {
475 log_error_errno(errno, "rmdir(%s): %m", sub_path);
482 /* Skip files for which the sticky bit is
483 * set. These are semantics we define, and are
484 * unknown elsewhere. See XDG_RUNTIME_DIR
485 * specification for details. */
486 if (s.st_mode & S_ISVTX) {
487 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
491 if (mountpoint && S_ISREG(s.st_mode))
492 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
493 streq(dent->d_name, "aquota.user") ||
494 streq(dent->d_name, "aquota.group")) {
495 log_debug("Skipping \"%s\".", sub_path);
499 /* Ignore sockets that are listed in /proc/net/unix */
500 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
501 log_debug("Skipping \"%s\": live socket.", sub_path);
505 /* Ignore device nodes */
506 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
507 log_debug("Skipping \"%s\": a device.", sub_path);
511 /* Keep files on this level around if this is
513 if (keep_this_level) {
514 log_debug("Keeping \"%s\".", sub_path);
518 age = timespec_load(&s.st_mtim);
520 char a[FORMAT_TIMESTAMP_MAX];
521 /* Follows spelling in stat(1). */
522 log_debug("File \"%s\": modify time %s is too new.",
524 format_timestamp_us(a, sizeof(a), age));
528 age = timespec_load(&s.st_atim);
530 char a[FORMAT_TIMESTAMP_MAX];
531 log_debug("File \"%s\": access time %s is too new.",
533 format_timestamp_us(a, sizeof(a), age));
537 age = timespec_load(&s.st_ctim);
539 char a[FORMAT_TIMESTAMP_MAX];
540 log_debug("File \"%s\": change time %s is too new.",
542 format_timestamp_us(a, sizeof(a), age));
546 log_debug("unlink \"%s\"", sub_path);
548 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
550 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
559 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
561 /* Restore original directory timestamps */
562 times[0] = ds->st_atim;
563 times[1] = ds->st_mtim;
565 age1 = timespec_load(&ds->st_atim);
566 age2 = timespec_load(&ds->st_mtim);
567 log_debug("Restoring access and modification time on \"%s\": %s, %s",
569 format_timestamp_us(a, sizeof(a), age1),
570 format_timestamp_us(b, sizeof(b), age2));
571 if (futimens(dirfd(d), times) < 0)
572 log_error_errno(errno, "utimensat(%s): %m", p);
578 static int path_set_perms(Item *i, const char *path) {
585 st_valid = stat(path, &st) == 0;
587 /* not using i->path directly because it may be a glob */
591 if (i->mask_perms && st_valid) {
592 if (!(st.st_mode & 0111))
594 if (!(st.st_mode & 0222))
596 if (!(st.st_mode & 0444))
598 if (!S_ISDIR(st.st_mode))
599 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
602 if (st_valid && m == (st.st_mode & 07777))
603 log_debug("\"%s\" has right mode %o", path, st.st_mode);
605 log_debug("chmod \"%s\" to mode %o", path, m);
606 if (chmod(path, m) < 0)
607 return log_error_errno(errno, "chmod(%s) failed: %m", path);
611 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
612 (i->uid_set || i->gid_set)) {
613 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
615 i->uid_set ? i->uid : UID_INVALID,
616 i->gid_set ? i->gid : GID_INVALID);
618 i->uid_set ? i->uid : UID_INVALID,
619 i->gid_set ? i->gid : GID_INVALID) < 0)
621 return log_error_errno(errno, "chown(%s) failed: %m", path);
624 return label_fix(path, false, false);
627 static int get_xattrs_from_arg(Item *i) {
637 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
638 _cleanup_free_ char *tmp = NULL, *name = NULL,
639 *value = NULL, *value2 = NULL, *_xattr = xattr;
641 r = split_pair(xattr, "=", &name, &value);
643 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
647 if (strempty(name) || strempty(value)) {
648 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
652 tmp = unquote(value, "\"");
656 value2 = cunescape(tmp);
660 if (strv_push_pair(&i->xattrs, name, value2) < 0)
662 name = value2 = NULL;
668 static int path_set_xattrs(Item *i, const char *path) {
669 char **name, **value;
674 STRV_FOREACH_PAIR(name, value, i->xattrs) {
678 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
679 if (lsetxattr(path, *name, *value, n, 0) < 0) {
680 log_error("Setting extended attribute %s=%s on %s failed: %m",
681 *name, *value, path);
688 static int get_acls_from_arg(Item *item) {
691 _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
695 /* If force (= modify) is set, we will not modify the acl
696 * afterwards, so the mask can be added now if necessary. */
697 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
699 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
702 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
708 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
709 _cleanup_(acl_freep) acl_t dup = NULL;
711 _cleanup_(acl_free_charpp) char *t = NULL;
714 r = acls_for_file(path, type, acl, &dup);
718 r = calc_acl_mask_if_needed(&dup);
726 /* the mask was already added earlier if needed */
729 r = add_base_acls_if_needed(&dup, path);
733 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
734 log_debug("\"%s\": setting %s ACL \"%s\"", path,
735 type == ACL_TYPE_ACCESS ? "access" : "default",
738 r = acl_set_file(path, type, dup);
740 return log_error_errno(-errno,
741 "Setting %s ACL \"%s\" on %s failed: %m",
742 type == ACL_TYPE_ACCESS ? "access" : "default",
747 static int path_set_acls(Item *item, const char *path) {
754 if (item->acl_access) {
755 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
760 if (item->acl_default) {
761 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
770 static int write_one_file(Item *i, const char *path) {
771 _cleanup_close_ int fd = -1;
778 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
779 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
781 RUN_WITH_UMASK(0000) {
782 mac_selinux_create_file_prepare(path, S_IFREG);
783 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
784 mac_selinux_create_file_clear();
788 if (i->type == WRITE_FILE && errno == ENOENT) {
789 log_debug_errno(errno, "Not writing \"%s\": %m", path);
793 log_error_errno(errno, "Failed to create file %s: %m", path);
798 _cleanup_free_ char *unescaped;
800 log_debug("%s to \"%s\".",
801 i->type == CREATE_FILE ? "Appending" : "Writing", path);
803 unescaped = cunescape(i->argument);
807 r = loop_write(fd, unescaped, strlen(unescaped), false);
809 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
811 log_debug("\"%s\" has been created.", path);
815 if (stat(path, &st) < 0)
816 return log_error_errno(errno, "stat(%s) failed: %m", path);
818 if (!S_ISREG(st.st_mode)) {
819 log_error("%s is not a file.", path);
823 r = path_set_perms(i, path);
830 typedef int (*action_t)(Item *, const char *);
832 static int item_do_children(Item *i, const char *path, action_t action) {
833 _cleanup_closedir_ DIR *d;
839 /* This returns the first error we run into, but nevertheless
842 d = opendir_nomod(path);
844 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
847 _cleanup_free_ char *p = NULL;
854 if (errno != 0 && r == 0)
860 if (STR_IN_SET(de->d_name, ".", ".."))
863 p = strjoin(path, "/", de->d_name, NULL);
868 if (q < 0 && q != -ENOENT && r == 0)
871 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
872 q = item_do_children(i, p, action);
881 static int glob_item(Item *i, action_t action, bool recursive) {
882 DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES
883 DISABLE_WARNING_DECLARATION_AFTER_STATEMENT
884 _cleanup_globfree_ glob_t g = {
885 .gl_closedir = closedir,
886 .gl_readdir = readdir,
887 .gl_opendir = opendir_nomod,
897 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
898 if (k != 0 && k != GLOB_NOMATCH)
899 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
901 STRV_FOREACH(fn, g.gl_pathv) {
907 k = item_do_children(i, *fn, action);
916 static int create_item(Item *i) {
922 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
927 case IGNORE_DIRECTORY_PATH:
929 case RECURSIVE_REMOVE_PATH:
934 r = write_one_file(i, i->path);
940 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
941 r = copy_tree(i->argument, i->path, false);
946 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
948 if (stat(i->argument, &a) < 0)
949 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
951 if (stat(i->path, &b) < 0)
952 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
954 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
955 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
960 r = path_set_perms(i, i->path);
967 r = glob_item(i, write_one_file, false);
973 case CREATE_DIRECTORY:
974 case TRUNCATE_DIRECTORY:
975 case CREATE_SUBVOLUME:
978 mkdir_parents_label(i->path, 0755);
980 if (i->type == CREATE_SUBVOLUME)
981 RUN_WITH_UMASK((~i->mode) & 0777) {
982 r = btrfs_subvol_make(i->path);
983 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
988 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
990 r = mkdir_label(i->path, i->mode);
994 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
996 if (stat(i->path, &st) < 0)
997 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
999 if (!S_ISDIR(st.st_mode)) {
1000 log_debug("\"%s\" already exists and is not a directory.", i->path);
1004 log_debug("Created directory \"%s\".", i->path);
1006 r = path_set_perms(i, i->path);
1014 RUN_WITH_UMASK(0000) {
1015 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1016 r = mkfifo(i->path, i->mode);
1017 mac_selinux_create_file_clear();
1021 if (errno != EEXIST)
1022 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1024 if (stat(i->path, &st) < 0)
1025 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1027 if (!S_ISFIFO(st.st_mode)) {
1031 RUN_WITH_UMASK(0000) {
1032 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1033 r = mkfifo_atomic(i->path, i->mode);
1034 mac_selinux_create_file_clear();
1038 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1040 log_debug("%s is not a fifo.", i->path);
1045 log_debug("Created fifo \"%s\".", i->path);
1047 r = path_set_perms(i, i->path);
1053 case CREATE_SYMLINK:
1055 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1056 r = symlink(i->argument, i->path);
1057 mac_selinux_create_file_clear();
1060 _cleanup_free_ char *x = NULL;
1062 if (errno != EEXIST)
1063 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1065 r = readlink_malloc(i->path, &x);
1066 if (r < 0 || !streq(i->argument, x)) {
1069 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1070 r = symlink_atomic(i->argument, i->path);
1071 mac_selinux_create_file_clear();
1074 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1076 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1081 log_debug("Created symlink \"%s\".", i->path);
1085 case CREATE_BLOCK_DEVICE:
1086 case CREATE_CHAR_DEVICE: {
1089 if (have_effective_cap(CAP_MKNOD) == 0) {
1090 /* In a container we lack CAP_MKNOD. We
1091 shouldn't attempt to create the device node in
1092 that case to avoid noise, and we don't support
1093 virtualized devices in containers anyway. */
1095 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1099 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1101 RUN_WITH_UMASK(0000) {
1102 mac_selinux_create_file_prepare(i->path, file_type);
1103 r = mknod(i->path, i->mode | file_type, i->major_minor);
1104 mac_selinux_create_file_clear();
1108 if (errno == EPERM) {
1109 log_debug("We lack permissions, possibly because of cgroup configuration; "
1110 "skipping creation of device node %s.", i->path);
1114 if (errno != EEXIST)
1115 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1117 if (stat(i->path, &st) < 0)
1118 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1120 if ((st.st_mode & S_IFMT) != file_type) {
1124 RUN_WITH_UMASK(0000) {
1125 mac_selinux_create_file_prepare(i->path, file_type);
1126 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1127 mac_selinux_create_file_clear();
1131 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1133 log_debug("%s is not a device node.", i->path);
1138 log_debug("Created %s device node \"%s\" %u:%u.",
1139 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1140 i->path, major(i->mode), minor(i->mode));
1142 r = path_set_perms(i, i->path);
1151 r = glob_item(i, path_set_perms, false);
1156 case RECURSIVE_RELABEL_PATH:
1157 r = glob_item(i, path_set_perms, true);
1163 r = glob_item(i, path_set_xattrs, false);
1168 case RECURSIVE_SET_XATTR:
1169 r = glob_item(i, path_set_xattrs, true);
1175 r = glob_item(i, path_set_acls, false);
1180 case RECURSIVE_SET_ACL:
1181 r = glob_item(i, path_set_acls, true);
1187 log_debug("%s created successfully.", i->path);
1192 static int remove_item_instance(Item *i, const char *instance) {
1200 if (remove(instance) < 0 && errno != ENOENT)
1201 return log_error_errno(errno, "rm(%s): %m", instance);
1205 case TRUNCATE_DIRECTORY:
1206 case RECURSIVE_REMOVE_PATH:
1207 /* FIXME: we probably should use dir_cleanup() here
1208 * instead of rm_rf() so that 'x' is honoured. */
1209 log_debug("rm -rf \"%s\"", instance);
1210 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1211 if (r < 0 && r != -ENOENT)
1212 return log_error_errno(r, "rm_rf(%s): %m", instance);
1217 assert_not_reached("wut?");
1223 static int remove_item(Item *i) {
1228 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1234 case CREATE_DIRECTORY:
1235 case CREATE_SUBVOLUME:
1237 case CREATE_SYMLINK:
1238 case CREATE_CHAR_DEVICE:
1239 case CREATE_BLOCK_DEVICE:
1241 case IGNORE_DIRECTORY_PATH:
1244 case RECURSIVE_RELABEL_PATH:
1248 case RECURSIVE_SET_XATTR:
1250 case RECURSIVE_SET_ACL:
1254 case TRUNCATE_DIRECTORY:
1255 case RECURSIVE_REMOVE_PATH:
1256 r = glob_item(i, remove_item_instance, false);
1263 static int clean_item_instance(Item *i, const char* instance) {
1264 _cleanup_closedir_ DIR *d = NULL;
1268 char timestamp[FORMAT_TIMESTAMP_MAX];
1275 n = now(CLOCK_REALTIME);
1279 cutoff = n - i->age;
1281 d = opendir_nomod(instance);
1283 if (errno == ENOENT || errno == ENOTDIR) {
1284 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1288 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1292 if (fstat(dirfd(d), &s) < 0)
1293 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1295 if (!S_ISDIR(s.st_mode)) {
1296 log_error("%s is not a directory.", i->path);
1300 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1301 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1303 mountpoint = s.st_dev != ps.st_dev ||
1304 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1306 log_debug("Cleanup threshold for %s \"%s\" is %s",
1307 mountpoint ? "mount point" : "directory",
1309 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1311 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1312 MAX_DEPTH, i->keep_first_level);
1315 static int clean_item(Item *i) {
1320 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1323 case CREATE_DIRECTORY:
1324 case CREATE_SUBVOLUME:
1325 case TRUNCATE_DIRECTORY:
1328 clean_item_instance(i, i->path);
1330 case IGNORE_DIRECTORY_PATH:
1331 r = glob_item(i, clean_item_instance, false);
1340 static int process_item_array(ItemArray *array);
1342 static int process_item(Item *i) {
1344 _cleanup_free_ char *prefix = NULL;
1353 prefix = malloc(strlen(i->path) + 1);
1357 PATH_FOREACH_PREFIX(prefix, i->path) {
1360 j = hashmap_get(items, prefix);
1364 s = process_item_array(j);
1365 if (s < 0 && t == 0)
1370 r = arg_create ? create_item(i) : 0;
1371 q = arg_remove ? remove_item(i) : 0;
1372 p = arg_clean ? clean_item(i) : 0;
1380 static int process_item_array(ItemArray *array) {
1386 for (n = 0; n < array->count; n++) {
1387 k = process_item(array->items + n);
1388 if (k < 0 && r == 0)
1395 static void item_free_contents(Item *i) {
1399 strv_free(i->xattrs);
1402 acl_free(i->acl_access);
1403 acl_free(i->acl_default);
1407 static void item_array_free(ItemArray *a) {
1413 for (n = 0; n < a->count; n++)
1414 item_free_contents(a->items + n);
1419 static bool item_compatible(Item *a, Item *b) {
1422 assert(streq(a->path, b->path));
1424 if (takes_ownership(a->type) && takes_ownership(b->type))
1425 /* check if the items are the same */
1426 return streq_ptr(a->argument, b->argument) &&
1428 a->uid_set == b->uid_set &&
1431 a->gid_set == b->gid_set &&
1434 a->mode_set == b->mode_set &&
1435 a->mode == b->mode &&
1437 a->age_set == b->age_set &&
1440 a->mask_perms == b->mask_perms &&
1442 a->keep_first_level == b->keep_first_level &&
1444 a->major_minor == b->major_minor;
1449 static bool should_include_path(const char *path) {
1452 STRV_FOREACH(prefix, arg_exclude_prefixes)
1453 if (path_startswith(path, *prefix)) {
1454 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1459 STRV_FOREACH(prefix, arg_include_prefixes)
1460 if (path_startswith(path, *prefix)) {
1461 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1465 /* no matches, so we should include this path only if we
1466 * have no whitelist at all */
1467 if (strv_length(arg_include_prefixes) == 0)
1470 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1474 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1476 static const Specifier specifier_table[] = {
1477 { 'm', specifier_machine_id, NULL },
1478 { 'b', specifier_boot_id, NULL },
1479 { 'H', specifier_host_name, NULL },
1480 { 'v', specifier_kernel_release, NULL },
1484 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1485 _cleanup_(item_free_contents) Item i = {};
1486 ItemArray *existing;
1489 bool force = false, boot = false;
1496 "%ms %ms %ms %ms %ms %ms %n",
1505 log_error("[%s:%u] Syntax error.", fname, line);
1509 if (isempty(action)) {
1510 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1514 for (pos = 1; action[pos]; pos++) {
1515 if (action[pos] == '!' && !boot)
1517 else if (action[pos] == '+' && !force)
1520 log_error("[%s:%u] Unknown modifiers in command '%s'",
1521 fname, line, action);
1526 if (boot && !arg_boot) {
1527 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1535 r = specifier_printf(path, specifier_table, NULL, &i.path);
1537 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1542 c += strspn(buffer+c, WHITESPACE);
1543 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1544 i.argument = unquote(buffer+c, "\"");
1554 case CREATE_DIRECTORY:
1555 case CREATE_SUBVOLUME:
1556 case TRUNCATE_DIRECTORY:
1559 case IGNORE_DIRECTORY_PATH:
1561 case RECURSIVE_REMOVE_PATH:
1564 case RECURSIVE_RELABEL_PATH:
1567 case CREATE_SYMLINK:
1569 i.argument = strappend("/usr/share/factory/", i.path);
1577 log_error("[%s:%u] Write file requires argument.", fname, line);
1584 i.argument = strappend("/usr/share/factory/", i.path);
1587 } else if (!path_is_absolute(i.argument)) {
1588 log_error("[%s:%u] Source path is not absolute.", fname, line);
1592 path_kill_slashes(i.argument);
1595 case CREATE_CHAR_DEVICE:
1596 case CREATE_BLOCK_DEVICE: {
1597 unsigned major, minor;
1600 log_error("[%s:%u] Device file requires argument.", fname, line);
1604 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1605 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1609 i.major_minor = makedev(major, minor);
1614 case RECURSIVE_SET_XATTR:
1616 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1619 r = get_xattrs_from_arg(&i);
1625 case RECURSIVE_SET_ACL:
1627 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1630 r = get_acls_from_arg(&i);
1636 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1640 if (!path_is_absolute(i.path)) {
1641 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1645 path_kill_slashes(i.path);
1647 if (!should_include_path(i.path))
1653 p = strappend(arg_root, i.path);
1661 if (user && !streq(user, "-")) {
1662 const char *u = user;
1664 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1666 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1673 if (group && !streq(group, "-")) {
1674 const char *g = group;
1676 r = get_group_creds(&g, &i.gid);
1678 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1685 if (mode && !streq(mode, "-")) {
1686 const char *mm = mode;
1690 i.mask_perms = true;
1694 if (sscanf(mm, "%o", &m) != 1) {
1695 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1702 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1705 if (age && !streq(age, "-")) {
1706 const char *a = age;
1709 i.keep_first_level = true;
1713 if (parse_sec(a, &i.age) < 0) {
1714 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1721 h = needs_glob(i.type) ? globs : items;
1723 existing = hashmap_get(h, i.path);
1727 for (n = 0; n < existing->count; n++) {
1728 if (!item_compatible(existing->items + n, &i))
1729 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1730 fname, line, i.path);
1733 existing = new0(ItemArray, 1);
1734 r = hashmap_put(h, i.path, existing);
1739 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1742 memcpy(existing->items + existing->count++, &i, sizeof(i));
1747 static void help(void) {
1748 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1749 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1750 " -h --help Show this help\n"
1751 " --version Show package version\n"
1752 " --create Create marked files/directories\n"
1753 " --clean Clean up marked directories\n"
1754 " --remove Remove marked files/directories\n"
1755 " --boot Execute actions only safe at boot\n"
1756 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
1757 " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n"
1758 " --root=PATH Operate on an alternate filesystem root\n",
1759 program_invocation_short_name);
1762 static int parse_argv(int argc, char *argv[]) {
1765 ARG_VERSION = 0x100,
1775 static const struct option options[] = {
1776 { "help", no_argument, NULL, 'h' },
1777 { "version", no_argument, NULL, ARG_VERSION },
1778 { "create", no_argument, NULL, ARG_CREATE },
1779 { "clean", no_argument, NULL, ARG_CLEAN },
1780 { "remove", no_argument, NULL, ARG_REMOVE },
1781 { "boot", no_argument, NULL, ARG_BOOT },
1782 { "prefix", required_argument, NULL, ARG_PREFIX },
1783 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1784 { "root", required_argument, NULL, ARG_ROOT },
1793 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1802 puts(PACKAGE_STRING);
1803 puts(SYSTEMD_FEATURES);
1823 if (strv_push(&arg_include_prefixes, optarg) < 0)
1827 case ARG_EXCLUDE_PREFIX:
1828 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1834 arg_root = path_make_absolute_cwd(optarg);
1838 path_kill_slashes(arg_root);
1845 assert_not_reached("Unhandled option");
1848 if (!arg_clean && !arg_create && !arg_remove) {
1849 log_error("You need to specify at least one of --clean, --create or --remove.");
1856 static int read_config_file(const char *fn, bool ignore_enoent) {
1857 _cleanup_fclose_ FILE *f = NULL;
1858 char line[LINE_MAX];
1866 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1868 if (ignore_enoent && r == -ENOENT) {
1869 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1873 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1875 log_debug("Reading config file \"%s\".", fn);
1877 FOREACH_LINE(line, f, break) {
1884 if (*l == '#' || *l == 0)
1887 k = parse_line(fn, v, l);
1888 if (k < 0 && r == 0)
1892 /* we have to determine age parameter for each entry of type X */
1893 HASHMAP_FOREACH(i, globs, iterator) {
1895 Item *j, *candidate_item = NULL;
1897 if (i->type != IGNORE_DIRECTORY_PATH)
1900 HASHMAP_FOREACH(j, items, iter) {
1901 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1904 if (path_equal(j->path, i->path)) {
1909 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1910 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1914 if (candidate_item && candidate_item->age_set) {
1915 i->age = candidate_item->age;
1921 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1929 int main(int argc, char *argv[]) {
1934 r = parse_argv(argc, argv);
1938 log_set_target(LOG_TARGET_AUTO);
1939 log_parse_environment();
1944 mac_selinux_init(NULL);
1946 items = hashmap_new(&string_hash_ops);
1947 globs = hashmap_new(&string_hash_ops);
1949 if (!items || !globs) {
1956 if (optind < argc) {
1959 for (j = optind; j < argc; j++) {
1960 k = read_config_file(argv[j], false);
1961 if (k < 0 && r == 0)
1966 _cleanup_strv_free_ char **files = NULL;
1969 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1971 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1975 STRV_FOREACH(f, files) {
1976 k = read_config_file(*f, true);
1977 if (k < 0 && r == 0)
1982 HASHMAP_FOREACH(a, globs, iterator) {
1983 k = process_item_array(a);
1984 if (k < 0 && r == 0)
1988 HASHMAP_FOREACH(a, items, iterator) {
1989 k = process_item_array(a);
1990 if (k < 0 && r == 0)
1995 while ((a = hashmap_steal_first(items)))
1998 while ((a = hashmap_steal_first(globs)))
2001 hashmap_free(items);
2002 hashmap_free(globs);
2004 free(arg_include_prefixes);
2005 free(arg_exclude_prefixes);
2008 set_free_free(unix_sockets);
2010 mac_selinux_finish();
2012 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;