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 _cleanup_globfree_ glob_t g = {
883 .gl_closedir = (void (*)(void *)) closedir,
884 .gl_readdir = (struct dirent *(*)(void *)) readdir,
885 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
893 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
894 if (k != 0 && k != GLOB_NOMATCH)
895 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
897 STRV_FOREACH(fn, g.gl_pathv) {
903 k = item_do_children(i, *fn, action);
912 static int create_item(Item *i) {
918 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
923 case IGNORE_DIRECTORY_PATH:
925 case RECURSIVE_REMOVE_PATH:
930 r = write_one_file(i, i->path);
936 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
937 r = copy_tree(i->argument, i->path, false);
942 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
944 if (stat(i->argument, &a) < 0)
945 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
947 if (stat(i->path, &b) < 0)
948 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
950 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
951 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
956 r = path_set_perms(i, i->path);
963 r = glob_item(i, write_one_file, false);
969 case CREATE_DIRECTORY:
970 case TRUNCATE_DIRECTORY:
971 case CREATE_SUBVOLUME:
974 mkdir_parents_label(i->path, 0755);
976 if (i->type == CREATE_SUBVOLUME)
977 RUN_WITH_UMASK((~i->mode) & 0777) {
978 r = btrfs_subvol_make(i->path);
979 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
984 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
986 r = mkdir_label(i->path, i->mode);
990 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
992 if (stat(i->path, &st) < 0)
993 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
995 if (!S_ISDIR(st.st_mode)) {
996 log_debug("\"%s\" already exists and is not a directory.", i->path);
1000 log_debug("Created directory \"%s\".", i->path);
1002 r = path_set_perms(i, i->path);
1010 RUN_WITH_UMASK(0000) {
1011 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1012 r = mkfifo(i->path, i->mode);
1013 mac_selinux_create_file_clear();
1017 if (errno != EEXIST)
1018 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1020 if (stat(i->path, &st) < 0)
1021 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1023 if (!S_ISFIFO(st.st_mode)) {
1027 RUN_WITH_UMASK(0000) {
1028 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1029 r = mkfifo_atomic(i->path, i->mode);
1030 mac_selinux_create_file_clear();
1034 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1036 log_debug("%s is not a fifo.", i->path);
1041 log_debug("Created fifo \"%s\".", i->path);
1043 r = path_set_perms(i, i->path);
1049 case CREATE_SYMLINK:
1051 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1052 r = symlink(i->argument, i->path);
1053 mac_selinux_create_file_clear();
1056 _cleanup_free_ char *x = NULL;
1058 if (errno != EEXIST)
1059 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1061 r = readlink_malloc(i->path, &x);
1062 if (r < 0 || !streq(i->argument, x)) {
1065 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1066 r = symlink_atomic(i->argument, i->path);
1067 mac_selinux_create_file_clear();
1070 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1072 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1077 log_debug("Created symlink \"%s\".", i->path);
1081 case CREATE_BLOCK_DEVICE:
1082 case CREATE_CHAR_DEVICE: {
1085 if (have_effective_cap(CAP_MKNOD) == 0) {
1086 /* In a container we lack CAP_MKNOD. We
1087 shouldn't attempt to create the device node in
1088 that case to avoid noise, and we don't support
1089 virtualized devices in containers anyway. */
1091 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1095 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1097 RUN_WITH_UMASK(0000) {
1098 mac_selinux_create_file_prepare(i->path, file_type);
1099 r = mknod(i->path, i->mode | file_type, i->major_minor);
1100 mac_selinux_create_file_clear();
1104 if (errno == EPERM) {
1105 log_debug("We lack permissions, possibly because of cgroup configuration; "
1106 "skipping creation of device node %s.", i->path);
1110 if (errno != EEXIST)
1111 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1113 if (stat(i->path, &st) < 0)
1114 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1116 if ((st.st_mode & S_IFMT) != file_type) {
1120 RUN_WITH_UMASK(0000) {
1121 mac_selinux_create_file_prepare(i->path, file_type);
1122 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1123 mac_selinux_create_file_clear();
1127 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1129 log_debug("%s is not a device node.", i->path);
1134 log_debug("Created %s device node \"%s\" %u:%u.",
1135 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1136 i->path, major(i->mode), minor(i->mode));
1138 r = path_set_perms(i, i->path);
1147 r = glob_item(i, path_set_perms, false);
1152 case RECURSIVE_RELABEL_PATH:
1153 r = glob_item(i, path_set_perms, true);
1159 r = glob_item(i, path_set_xattrs, false);
1164 case RECURSIVE_SET_XATTR:
1165 r = glob_item(i, path_set_xattrs, true);
1171 r = glob_item(i, path_set_acls, false);
1176 case RECURSIVE_SET_ACL:
1177 r = glob_item(i, path_set_acls, true);
1183 log_debug("%s created successfully.", i->path);
1188 static int remove_item_instance(Item *i, const char *instance) {
1196 if (remove(instance) < 0 && errno != ENOENT)
1197 return log_error_errno(errno, "rm(%s): %m", instance);
1201 case TRUNCATE_DIRECTORY:
1202 case RECURSIVE_REMOVE_PATH:
1203 /* FIXME: we probably should use dir_cleanup() here
1204 * instead of rm_rf() so that 'x' is honoured. */
1205 log_debug("rm -rf \"%s\"", instance);
1206 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1207 if (r < 0 && r != -ENOENT)
1208 return log_error_errno(r, "rm_rf(%s): %m", instance);
1213 assert_not_reached("wut?");
1219 static int remove_item(Item *i) {
1224 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1230 case CREATE_DIRECTORY:
1231 case CREATE_SUBVOLUME:
1233 case CREATE_SYMLINK:
1234 case CREATE_CHAR_DEVICE:
1235 case CREATE_BLOCK_DEVICE:
1237 case IGNORE_DIRECTORY_PATH:
1240 case RECURSIVE_RELABEL_PATH:
1244 case RECURSIVE_SET_XATTR:
1246 case RECURSIVE_SET_ACL:
1250 case TRUNCATE_DIRECTORY:
1251 case RECURSIVE_REMOVE_PATH:
1252 r = glob_item(i, remove_item_instance, false);
1259 static int clean_item_instance(Item *i, const char* instance) {
1260 _cleanup_closedir_ DIR *d = NULL;
1264 char timestamp[FORMAT_TIMESTAMP_MAX];
1271 n = now(CLOCK_REALTIME);
1275 cutoff = n - i->age;
1277 d = opendir_nomod(instance);
1279 if (errno == ENOENT || errno == ENOTDIR) {
1280 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1284 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1288 if (fstat(dirfd(d), &s) < 0)
1289 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1291 if (!S_ISDIR(s.st_mode)) {
1292 log_error("%s is not a directory.", i->path);
1296 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1297 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1299 mountpoint = s.st_dev != ps.st_dev ||
1300 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1302 log_debug("Cleanup threshold for %s \"%s\" is %s",
1303 mountpoint ? "mount point" : "directory",
1305 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1307 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1308 MAX_DEPTH, i->keep_first_level);
1311 static int clean_item(Item *i) {
1316 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1319 case CREATE_DIRECTORY:
1320 case CREATE_SUBVOLUME:
1321 case TRUNCATE_DIRECTORY:
1324 clean_item_instance(i, i->path);
1326 case IGNORE_DIRECTORY_PATH:
1327 r = glob_item(i, clean_item_instance, false);
1336 static int process_item_array(ItemArray *array);
1338 static int process_item(Item *i) {
1340 _cleanup_free_ char *prefix = NULL;
1349 prefix = malloc(strlen(i->path) + 1);
1353 PATH_FOREACH_PREFIX(prefix, i->path) {
1356 j = hashmap_get(items, prefix);
1360 s = process_item_array(j);
1361 if (s < 0 && t == 0)
1366 r = arg_create ? create_item(i) : 0;
1367 q = arg_remove ? remove_item(i) : 0;
1368 p = arg_clean ? clean_item(i) : 0;
1376 static int process_item_array(ItemArray *array) {
1382 for (n = 0; n < array->count; n++) {
1383 k = process_item(array->items + n);
1384 if (k < 0 && r == 0)
1391 static void item_free_contents(Item *i) {
1395 strv_free(i->xattrs);
1398 acl_free(i->acl_access);
1399 acl_free(i->acl_default);
1403 static void item_array_free(ItemArray *a) {
1409 for (n = 0; n < a->count; n++)
1410 item_free_contents(a->items + n);
1415 static bool item_compatible(Item *a, Item *b) {
1418 assert(streq(a->path, b->path));
1420 if (takes_ownership(a->type) && takes_ownership(b->type))
1421 /* check if the items are the same */
1422 return streq_ptr(a->argument, b->argument) &&
1424 a->uid_set == b->uid_set &&
1427 a->gid_set == b->gid_set &&
1430 a->mode_set == b->mode_set &&
1431 a->mode == b->mode &&
1433 a->age_set == b->age_set &&
1436 a->mask_perms == b->mask_perms &&
1438 a->keep_first_level == b->keep_first_level &&
1440 a->major_minor == b->major_minor;
1445 static bool should_include_path(const char *path) {
1448 STRV_FOREACH(prefix, arg_exclude_prefixes)
1449 if (path_startswith(path, *prefix)) {
1450 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1455 STRV_FOREACH(prefix, arg_include_prefixes)
1456 if (path_startswith(path, *prefix)) {
1457 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1461 /* no matches, so we should include this path only if we
1462 * have no whitelist at all */
1463 if (strv_length(arg_include_prefixes) == 0)
1466 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1470 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1472 static const Specifier specifier_table[] = {
1473 { 'm', specifier_machine_id, NULL },
1474 { 'b', specifier_boot_id, NULL },
1475 { 'H', specifier_host_name, NULL },
1476 { 'v', specifier_kernel_release, NULL },
1480 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1481 _cleanup_(item_free_contents) Item i = {};
1482 ItemArray *existing;
1485 bool force = false, boot = false;
1492 "%ms %ms %ms %ms %ms %ms %n",
1501 log_error("[%s:%u] Syntax error.", fname, line);
1505 if (isempty(action)) {
1506 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1510 for (pos = 1; action[pos]; pos++) {
1511 if (action[pos] == '!' && !boot)
1513 else if (action[pos] == '+' && !force)
1516 log_error("[%s:%u] Unknown modifiers in command '%s'",
1517 fname, line, action);
1522 if (boot && !arg_boot) {
1523 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1531 r = specifier_printf(path, specifier_table, NULL, &i.path);
1533 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1538 c += strspn(buffer+c, WHITESPACE);
1539 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1540 i.argument = unquote(buffer+c, "\"");
1550 case CREATE_DIRECTORY:
1551 case CREATE_SUBVOLUME:
1552 case TRUNCATE_DIRECTORY:
1555 case IGNORE_DIRECTORY_PATH:
1557 case RECURSIVE_REMOVE_PATH:
1560 case RECURSIVE_RELABEL_PATH:
1563 case CREATE_SYMLINK:
1565 i.argument = strappend("/usr/share/factory/", i.path);
1573 log_error("[%s:%u] Write file requires argument.", fname, line);
1580 i.argument = strappend("/usr/share/factory/", i.path);
1583 } else if (!path_is_absolute(i.argument)) {
1584 log_error("[%s:%u] Source path is not absolute.", fname, line);
1588 path_kill_slashes(i.argument);
1591 case CREATE_CHAR_DEVICE:
1592 case CREATE_BLOCK_DEVICE: {
1593 unsigned major, minor;
1596 log_error("[%s:%u] Device file requires argument.", fname, line);
1600 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1601 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1605 i.major_minor = makedev(major, minor);
1610 case RECURSIVE_SET_XATTR:
1612 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1615 r = get_xattrs_from_arg(&i);
1621 case RECURSIVE_SET_ACL:
1623 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1626 r = get_acls_from_arg(&i);
1632 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1636 if (!path_is_absolute(i.path)) {
1637 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1641 path_kill_slashes(i.path);
1643 if (!should_include_path(i.path))
1649 p = strappend(arg_root, i.path);
1657 if (user && !streq(user, "-")) {
1658 const char *u = user;
1660 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1662 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1669 if (group && !streq(group, "-")) {
1670 const char *g = group;
1672 r = get_group_creds(&g, &i.gid);
1674 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1681 if (mode && !streq(mode, "-")) {
1682 const char *mm = mode;
1686 i.mask_perms = true;
1690 if (sscanf(mm, "%o", &m) != 1) {
1691 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1698 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1701 if (age && !streq(age, "-")) {
1702 const char *a = age;
1705 i.keep_first_level = true;
1709 if (parse_sec(a, &i.age) < 0) {
1710 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1717 h = needs_glob(i.type) ? globs : items;
1719 existing = hashmap_get(h, i.path);
1723 for (n = 0; n < existing->count; n++) {
1724 if (!item_compatible(existing->items + n, &i))
1725 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1726 fname, line, i.path);
1729 existing = new0(ItemArray, 1);
1730 r = hashmap_put(h, i.path, existing);
1735 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1738 memcpy(existing->items + existing->count++, &i, sizeof(i));
1743 static void help(void) {
1744 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1745 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1746 " -h --help Show this help\n"
1747 " --version Show package version\n"
1748 " --create Create marked files/directories\n"
1749 " --clean Clean up marked directories\n"
1750 " --remove Remove marked files/directories\n"
1751 " --boot Execute actions only safe at boot\n"
1752 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
1753 " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n"
1754 " --root=PATH Operate on an alternate filesystem root\n",
1755 program_invocation_short_name);
1758 static int parse_argv(int argc, char *argv[]) {
1761 ARG_VERSION = 0x100,
1771 static const struct option options[] = {
1772 { "help", no_argument, NULL, 'h' },
1773 { "version", no_argument, NULL, ARG_VERSION },
1774 { "create", no_argument, NULL, ARG_CREATE },
1775 { "clean", no_argument, NULL, ARG_CLEAN },
1776 { "remove", no_argument, NULL, ARG_REMOVE },
1777 { "boot", no_argument, NULL, ARG_BOOT },
1778 { "prefix", required_argument, NULL, ARG_PREFIX },
1779 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1780 { "root", required_argument, NULL, ARG_ROOT },
1789 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1798 puts(PACKAGE_STRING);
1799 puts(SYSTEMD_FEATURES);
1819 if (strv_push(&arg_include_prefixes, optarg) < 0)
1823 case ARG_EXCLUDE_PREFIX:
1824 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1830 arg_root = path_make_absolute_cwd(optarg);
1834 path_kill_slashes(arg_root);
1841 assert_not_reached("Unhandled option");
1844 if (!arg_clean && !arg_create && !arg_remove) {
1845 log_error("You need to specify at least one of --clean, --create or --remove.");
1852 static int read_config_file(const char *fn, bool ignore_enoent) {
1853 _cleanup_fclose_ FILE *f = NULL;
1854 char line[LINE_MAX];
1862 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1864 if (ignore_enoent && r == -ENOENT) {
1865 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1869 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1871 log_debug("Reading config file \"%s\".", fn);
1873 FOREACH_LINE(line, f, break) {
1880 if (*l == '#' || *l == 0)
1883 k = parse_line(fn, v, l);
1884 if (k < 0 && r == 0)
1888 /* we have to determine age parameter for each entry of type X */
1889 HASHMAP_FOREACH(i, globs, iterator) {
1891 Item *j, *candidate_item = NULL;
1893 if (i->type != IGNORE_DIRECTORY_PATH)
1896 HASHMAP_FOREACH(j, items, iter) {
1897 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1900 if (path_equal(j->path, i->path)) {
1905 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1906 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1910 if (candidate_item && candidate_item->age_set) {
1911 i->age = candidate_item->age;
1917 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1925 int main(int argc, char *argv[]) {
1930 r = parse_argv(argc, argv);
1934 log_set_target(LOG_TARGET_AUTO);
1935 log_parse_environment();
1940 mac_selinux_init(NULL);
1942 items = hashmap_new(&string_hash_ops);
1943 globs = hashmap_new(&string_hash_ops);
1945 if (!items || !globs) {
1952 if (optind < argc) {
1955 for (j = optind; j < argc; j++) {
1956 k = read_config_file(argv[j], false);
1957 if (k < 0 && r == 0)
1962 _cleanup_strv_free_ char **files = NULL;
1965 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1967 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1971 STRV_FOREACH(f, files) {
1972 k = read_config_file(*f, true);
1973 if (k < 0 && r == 0)
1978 HASHMAP_FOREACH(a, globs, iterator) {
1979 k = process_item_array(a);
1980 if (k < 0 && r == 0)
1984 HASHMAP_FOREACH(a, items, iterator) {
1985 k = process_item_array(a);
1986 if (k < 0 && r == 0)
1991 while ((a = hashmap_steal_first(items)))
1994 while ((a = hashmap_steal_first(globs)))
1997 hashmap_free(items);
1998 hashmap_free(globs);
2000 free(arg_include_prefixes);
2001 free(arg_exclude_prefixes);
2004 set_free_free(unix_sockets);
2006 mac_selinux_finish();
2008 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;