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 log_debug("Removing directory \"%s\".", sub_path);
469 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
470 if (errno != ENOENT && errno != ENOTEMPTY) {
471 log_error_errno(errno, "rmdir(%s): %m", sub_path);
476 /* Skip files for which the sticky bit is
477 * set. These are semantics we define, and are
478 * unknown elsewhere. See XDG_RUNTIME_DIR
479 * specification for details. */
480 if (s.st_mode & S_ISVTX) {
481 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
485 if (mountpoint && S_ISREG(s.st_mode))
486 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
487 streq(dent->d_name, "aquota.user") ||
488 streq(dent->d_name, "aquota.group")) {
489 log_debug("Skipping \"%s\".", sub_path);
493 /* Ignore sockets that are listed in /proc/net/unix */
494 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
495 log_debug("Skipping \"%s\": live socket.", sub_path);
499 /* Ignore device nodes */
500 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
501 log_debug("Skipping \"%s\": a device.", sub_path);
505 /* Keep files on this level around if this is
507 if (keep_this_level) {
508 log_debug("Keeping \"%s\".", sub_path);
512 age = timespec_load(&s.st_mtim);
514 char a[FORMAT_TIMESTAMP_MAX];
515 /* Follows spelling in stat(1). */
516 log_debug("File \"%s\": modify time %s is too new.",
518 format_timestamp_us(a, sizeof(a), age));
522 age = timespec_load(&s.st_atim);
524 char a[FORMAT_TIMESTAMP_MAX];
525 log_debug("File \"%s\": access time %s is too new.",
527 format_timestamp_us(a, sizeof(a), age));
531 age = timespec_load(&s.st_ctim);
533 char a[FORMAT_TIMESTAMP_MAX];
534 log_debug("File \"%s\": change time %s is too new.",
536 format_timestamp_us(a, sizeof(a), age));
540 log_debug("unlink \"%s\"", sub_path);
542 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
544 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
553 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
555 /* Restore original directory timestamps */
556 times[0] = ds->st_atim;
557 times[1] = ds->st_mtim;
559 age1 = timespec_load(&ds->st_atim);
560 age2 = timespec_load(&ds->st_mtim);
561 log_debug("Restoring access and modification time on \"%s\": %s, %s",
563 format_timestamp_us(a, sizeof(a), age1),
564 format_timestamp_us(b, sizeof(b), age2));
565 if (futimens(dirfd(d), times) < 0)
566 log_error_errno(errno, "utimensat(%s): %m", p);
572 static int path_set_perms(Item *i, const char *path) {
579 st_valid = stat(path, &st) == 0;
581 /* not using i->path directly because it may be a glob */
585 if (i->mask_perms && st_valid) {
586 if (!(st.st_mode & 0111))
588 if (!(st.st_mode & 0222))
590 if (!(st.st_mode & 0444))
592 if (!S_ISDIR(st.st_mode))
593 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
596 if (st_valid && m == (st.st_mode & 07777))
597 log_debug("\"%s\" has right mode %o", path, st.st_mode);
599 log_debug("chmod \"%s\" to mode %o", path, m);
600 if (chmod(path, m) < 0)
601 return log_error_errno(errno, "chmod(%s) failed: %m", path);
605 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
606 (i->uid_set || i->gid_set)) {
607 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
609 i->uid_set ? i->uid : UID_INVALID,
610 i->gid_set ? i->gid : GID_INVALID);
612 i->uid_set ? i->uid : UID_INVALID,
613 i->gid_set ? i->gid : GID_INVALID) < 0)
615 return log_error_errno(errno, "chown(%s) failed: %m", path);
618 return label_fix(path, false, false);
621 static int get_xattrs_from_arg(Item *i) {
631 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
632 _cleanup_free_ char *tmp = NULL, *name = NULL,
633 *value = NULL, *value2 = NULL;
635 r = split_pair(xattr, "=", &name, &value);
637 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
641 if (strempty(name) || strempty(value)) {
642 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
646 tmp = unquote(value, "\"");
650 value2 = cunescape(tmp);
654 if (strv_push_pair(&i->xattrs, name, value2) < 0)
656 name = value2 = NULL;
662 static int path_set_xattrs(Item *i, const char *path) {
663 char **name, **value;
668 STRV_FOREACH_PAIR(name, value, i->xattrs) {
672 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
673 if (lsetxattr(path, *name, *value, n, 0) < 0) {
674 log_error("Setting extended attribute %s=%s on %s failed: %m",
675 *name, *value, path);
682 static int get_acls_from_arg(Item *item) {
688 /* If force (= modify) is set, we will not modify the acl
689 * afterwards, so the mask can be added now if necessary. */
690 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
692 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
695 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
701 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
702 _cleanup_(acl_freep) acl_t dup = NULL;
704 _cleanup_(acl_free_charpp) char *t = NULL;
707 r = acls_for_file(path, type, acl, &dup);
711 r = calc_acl_mask_if_needed(&dup);
719 /* the mask was already added earlier if needed */
722 r = add_base_acls_if_needed(&dup, path);
726 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
727 log_debug("\"%s\": setting %s ACL \"%s\"", path,
728 type == ACL_TYPE_ACCESS ? "access" : "default",
731 r = acl_set_file(path, type, dup);
733 return log_error_errno(-errno,
734 "Setting %s ACL \"%s\" on %s failed: %m",
735 type == ACL_TYPE_ACCESS ? "access" : "default",
740 static int path_set_acls(Item *item, const char *path) {
747 if (item->acl_access) {
748 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
753 if (item->acl_default) {
754 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
763 static int write_one_file(Item *i, const char *path) {
764 _cleanup_close_ int fd = -1;
771 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
772 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
774 RUN_WITH_UMASK(0000) {
775 mac_selinux_create_file_prepare(path, S_IFREG);
776 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
777 mac_selinux_create_file_clear();
781 if (i->type == WRITE_FILE && errno == ENOENT) {
782 log_debug_errno(errno, "Not writing \"%s\": %m", path);
786 log_error_errno(errno, "Failed to create file %s: %m", path);
791 _cleanup_free_ char *unescaped;
793 log_debug("%s to \"%s\".",
794 i->type == CREATE_FILE ? "Appending" : "Writing", path);
796 unescaped = cunescape(i->argument);
800 r = loop_write(fd, unescaped, strlen(unescaped), false);
802 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
804 log_debug("\"%s\" has been created.", path);
808 if (stat(path, &st) < 0)
809 return log_error_errno(errno, "stat(%s) failed: %m", path);
811 if (!S_ISREG(st.st_mode)) {
812 log_error("%s is not a file.", path);
816 r = path_set_perms(i, path);
823 typedef int (*action_t)(Item *, const char *);
825 static int item_do_children(Item *i, const char *path, action_t action) {
826 _cleanup_closedir_ DIR *d;
832 /* This returns the first error we run into, but nevertheless
835 d = opendir_nomod(path);
837 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
840 _cleanup_free_ char *p = NULL;
847 if (errno != 0 && r == 0)
853 if (STR_IN_SET(de->d_name, ".", ".."))
856 p = strjoin(path, "/", de->d_name, NULL);
861 if (q < 0 && q != -ENOENT && r == 0)
864 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
865 q = item_do_children(i, p, action);
874 static int glob_item(Item *i, action_t action, bool recursive) {
875 _cleanup_globfree_ glob_t g = {
876 .gl_closedir = (void (*)(void *)) closedir,
877 .gl_readdir = (struct dirent *(*)(void *)) readdir,
878 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
886 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
887 if (k != 0 && k != GLOB_NOMATCH)
888 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
890 STRV_FOREACH(fn, g.gl_pathv) {
896 k = item_do_children(i, *fn, action);
910 _CREATION_MODE_INVALID = -1
913 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
914 [CREATION_NORMAL] = "Created",
915 [CREATION_EXISTING] = "Found existing",
916 [CREATION_FORCE] = "Created replacement",
919 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
921 static int create_item(Item *i) {
924 CreationMode creation;
928 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
933 case IGNORE_DIRECTORY_PATH:
935 case RECURSIVE_REMOVE_PATH:
940 r = write_one_file(i, i->path);
946 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
947 r = copy_tree(i->argument, i->path, false);
952 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
954 if (stat(i->argument, &a) < 0)
955 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
957 if (stat(i->path, &b) < 0)
958 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
960 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
961 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
966 r = path_set_perms(i, i->path);
973 r = glob_item(i, write_one_file, false);
979 case CREATE_DIRECTORY:
980 case TRUNCATE_DIRECTORY:
981 case CREATE_SUBVOLUME:
984 mkdir_parents_label(i->path, 0755);
986 if (i->type == CREATE_SUBVOLUME)
987 RUN_WITH_UMASK((~i->mode) & 0777) {
988 r = btrfs_subvol_make(i->path);
989 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
994 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
996 r = mkdir_label(i->path, i->mode);
1000 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1002 if (stat(i->path, &st) < 0)
1003 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1005 if (!S_ISDIR(st.st_mode)) {
1006 log_debug("\"%s\" already exists and is not a directory.", i->path);
1010 creation = CREATION_EXISTING;
1012 creation = CREATION_NORMAL;
1013 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1015 r = path_set_perms(i, i->path);
1023 RUN_WITH_UMASK(0000) {
1024 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1025 r = mkfifo(i->path, i->mode);
1026 mac_selinux_create_file_clear();
1030 if (errno != EEXIST)
1031 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1033 if (stat(i->path, &st) < 0)
1034 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1036 if (!S_ISFIFO(st.st_mode)) {
1040 RUN_WITH_UMASK(0000) {
1041 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1042 r = mkfifo_atomic(i->path, i->mode);
1043 mac_selinux_create_file_clear();
1047 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1048 creation = CREATION_FORCE;
1050 log_debug("%s is not a fifo.", i->path);
1054 creation = CREATION_EXISTING;
1056 creation = CREATION_NORMAL;
1057 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1059 r = path_set_perms(i, i->path);
1065 case CREATE_SYMLINK:
1067 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1068 r = symlink(i->argument, i->path);
1069 mac_selinux_create_file_clear();
1072 _cleanup_free_ char *x = NULL;
1074 if (errno != EEXIST)
1075 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1077 r = readlink_malloc(i->path, &x);
1078 if (r < 0 || !streq(i->argument, x)) {
1081 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1082 r = symlink_atomic(i->argument, i->path);
1083 mac_selinux_create_file_clear();
1086 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1087 creation = CREATION_FORCE;
1089 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1093 creation = CREATION_EXISTING;
1095 creation = CREATION_NORMAL;
1096 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1100 case CREATE_BLOCK_DEVICE:
1101 case CREATE_CHAR_DEVICE: {
1104 if (have_effective_cap(CAP_MKNOD) == 0) {
1105 /* In a container we lack CAP_MKNOD. We
1106 shouldn't attempt to create the device node in
1107 that case to avoid noise, and we don't support
1108 virtualized devices in containers anyway. */
1110 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1114 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1116 RUN_WITH_UMASK(0000) {
1117 mac_selinux_create_file_prepare(i->path, file_type);
1118 r = mknod(i->path, i->mode | file_type, i->major_minor);
1119 mac_selinux_create_file_clear();
1123 if (errno == EPERM) {
1124 log_debug("We lack permissions, possibly because of cgroup configuration; "
1125 "skipping creation of device node %s.", i->path);
1129 if (errno != EEXIST)
1130 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1132 if (stat(i->path, &st) < 0)
1133 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1135 if ((st.st_mode & S_IFMT) != file_type) {
1139 RUN_WITH_UMASK(0000) {
1140 mac_selinux_create_file_prepare(i->path, file_type);
1141 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1142 mac_selinux_create_file_clear();
1146 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1147 creation = CREATION_FORCE;
1149 log_debug("%s is not a device node.", i->path);
1153 creation = CREATION_EXISTING;
1155 creation = CREATION_NORMAL;
1156 log_debug("%s %s device node \"%s\" %u:%u.",
1157 creation_mode_verb_to_string(creation),
1158 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1159 i->path, major(i->mode), minor(i->mode));
1161 r = path_set_perms(i, i->path);
1170 r = glob_item(i, path_set_perms, false);
1175 case RECURSIVE_RELABEL_PATH:
1176 r = glob_item(i, path_set_perms, true);
1182 r = glob_item(i, path_set_xattrs, false);
1187 case RECURSIVE_SET_XATTR:
1188 r = glob_item(i, path_set_xattrs, true);
1194 r = glob_item(i, path_set_acls, false);
1199 case RECURSIVE_SET_ACL:
1200 r = glob_item(i, path_set_acls, true);
1206 log_debug("%s created successfully.", i->path);
1211 static int remove_item_instance(Item *i, const char *instance) {
1219 if (remove(instance) < 0 && errno != ENOENT)
1220 return log_error_errno(errno, "rm(%s): %m", instance);
1224 case TRUNCATE_DIRECTORY:
1225 case RECURSIVE_REMOVE_PATH:
1226 /* FIXME: we probably should use dir_cleanup() here
1227 * instead of rm_rf() so that 'x' is honoured. */
1228 log_debug("rm -rf \"%s\"", instance);
1229 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1230 if (r < 0 && r != -ENOENT)
1231 return log_error_errno(r, "rm_rf(%s): %m", instance);
1236 assert_not_reached("wut?");
1242 static int remove_item(Item *i) {
1247 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1253 case CREATE_DIRECTORY:
1254 case CREATE_SUBVOLUME:
1256 case CREATE_SYMLINK:
1257 case CREATE_CHAR_DEVICE:
1258 case CREATE_BLOCK_DEVICE:
1260 case IGNORE_DIRECTORY_PATH:
1263 case RECURSIVE_RELABEL_PATH:
1267 case RECURSIVE_SET_XATTR:
1269 case RECURSIVE_SET_ACL:
1273 case TRUNCATE_DIRECTORY:
1274 case RECURSIVE_REMOVE_PATH:
1275 r = glob_item(i, remove_item_instance, false);
1282 static int clean_item_instance(Item *i, const char* instance) {
1283 _cleanup_closedir_ DIR *d = NULL;
1287 char timestamp[FORMAT_TIMESTAMP_MAX];
1294 n = now(CLOCK_REALTIME);
1298 cutoff = n - i->age;
1300 d = opendir_nomod(instance);
1302 if (errno == ENOENT || errno == ENOTDIR) {
1303 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1307 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1311 if (fstat(dirfd(d), &s) < 0)
1312 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1314 if (!S_ISDIR(s.st_mode)) {
1315 log_error("%s is not a directory.", i->path);
1319 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1320 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1322 mountpoint = s.st_dev != ps.st_dev ||
1323 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1325 log_debug("Cleanup threshold for %s \"%s\" is %s",
1326 mountpoint ? "mount point" : "directory",
1328 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1330 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1331 MAX_DEPTH, i->keep_first_level);
1334 static int clean_item(Item *i) {
1339 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1342 case CREATE_DIRECTORY:
1343 case CREATE_SUBVOLUME:
1344 case TRUNCATE_DIRECTORY:
1347 clean_item_instance(i, i->path);
1349 case IGNORE_DIRECTORY_PATH:
1350 r = glob_item(i, clean_item_instance, false);
1359 static int process_item_array(ItemArray *array);
1361 static int process_item(Item *i) {
1363 _cleanup_free_ char *prefix = NULL;
1372 prefix = malloc(strlen(i->path) + 1);
1376 PATH_FOREACH_PREFIX(prefix, i->path) {
1379 j = hashmap_get(items, prefix);
1383 s = process_item_array(j);
1384 if (s < 0 && t == 0)
1389 r = arg_create ? create_item(i) : 0;
1390 q = arg_remove ? remove_item(i) : 0;
1391 p = arg_clean ? clean_item(i) : 0;
1399 static int process_item_array(ItemArray *array) {
1405 for (n = 0; n < array->count; n++) {
1406 k = process_item(array->items + n);
1407 if (k < 0 && r == 0)
1414 static void item_free_contents(Item *i) {
1418 strv_free(i->xattrs);
1421 acl_free(i->acl_access);
1422 acl_free(i->acl_default);
1426 static void item_array_free(ItemArray *a) {
1432 for (n = 0; n < a->count; n++)
1433 item_free_contents(a->items + n);
1438 static bool item_compatible(Item *a, Item *b) {
1441 assert(streq(a->path, b->path));
1443 if (takes_ownership(a->type) && takes_ownership(b->type))
1444 /* check if the items are the same */
1445 return streq_ptr(a->argument, b->argument) &&
1447 a->uid_set == b->uid_set &&
1450 a->gid_set == b->gid_set &&
1453 a->mode_set == b->mode_set &&
1454 a->mode == b->mode &&
1456 a->age_set == b->age_set &&
1459 a->mask_perms == b->mask_perms &&
1461 a->keep_first_level == b->keep_first_level &&
1463 a->major_minor == b->major_minor;
1468 static bool should_include_path(const char *path) {
1471 STRV_FOREACH(prefix, arg_exclude_prefixes)
1472 if (path_startswith(path, *prefix)) {
1473 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1478 STRV_FOREACH(prefix, arg_include_prefixes)
1479 if (path_startswith(path, *prefix)) {
1480 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1484 /* no matches, so we should include this path only if we
1485 * have no whitelist at all */
1486 if (strv_length(arg_include_prefixes) == 0)
1489 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1493 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1495 static const Specifier specifier_table[] = {
1496 { 'm', specifier_machine_id, NULL },
1497 { 'b', specifier_boot_id, NULL },
1498 { 'H', specifier_host_name, NULL },
1499 { 'v', specifier_kernel_release, NULL },
1503 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1504 _cleanup_(item_free_contents) Item i = {};
1505 ItemArray *existing;
1508 bool force = false, boot = false;
1515 "%ms %ms %ms %ms %ms %ms %n",
1524 log_error("[%s:%u] Syntax error.", fname, line);
1528 if (isempty(action)) {
1529 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1533 for (pos = 1; action[pos]; pos++) {
1534 if (action[pos] == '!' && !boot)
1536 else if (action[pos] == '+' && !force)
1539 log_error("[%s:%u] Unknown modifiers in command '%s'",
1540 fname, line, action);
1545 if (boot && !arg_boot) {
1546 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1554 r = specifier_printf(path, specifier_table, NULL, &i.path);
1556 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1561 c += strspn(buffer+c, WHITESPACE);
1562 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1563 i.argument = unquote(buffer+c, "\"");
1573 case CREATE_DIRECTORY:
1574 case CREATE_SUBVOLUME:
1575 case TRUNCATE_DIRECTORY:
1578 case IGNORE_DIRECTORY_PATH:
1580 case RECURSIVE_REMOVE_PATH:
1583 case RECURSIVE_RELABEL_PATH:
1586 case CREATE_SYMLINK:
1588 i.argument = strappend("/usr/share/factory/", i.path);
1596 log_error("[%s:%u] Write file requires argument.", fname, line);
1603 i.argument = strappend("/usr/share/factory/", i.path);
1606 } else if (!path_is_absolute(i.argument)) {
1607 log_error("[%s:%u] Source path is not absolute.", fname, line);
1611 path_kill_slashes(i.argument);
1614 case CREATE_CHAR_DEVICE:
1615 case CREATE_BLOCK_DEVICE: {
1616 unsigned major, minor;
1619 log_error("[%s:%u] Device file requires argument.", fname, line);
1623 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1624 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1628 i.major_minor = makedev(major, minor);
1633 case RECURSIVE_SET_XATTR:
1635 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1638 r = get_xattrs_from_arg(&i);
1644 case RECURSIVE_SET_ACL:
1646 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1649 r = get_acls_from_arg(&i);
1655 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1659 if (!path_is_absolute(i.path)) {
1660 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1664 path_kill_slashes(i.path);
1666 if (!should_include_path(i.path))
1672 p = strappend(arg_root, i.path);
1680 if (user && !streq(user, "-")) {
1681 const char *u = user;
1683 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1685 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1692 if (group && !streq(group, "-")) {
1693 const char *g = group;
1695 r = get_group_creds(&g, &i.gid);
1697 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1704 if (mode && !streq(mode, "-")) {
1705 const char *mm = mode;
1709 i.mask_perms = true;
1713 if (sscanf(mm, "%o", &m) != 1) {
1714 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1721 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1724 if (age && !streq(age, "-")) {
1725 const char *a = age;
1728 i.keep_first_level = true;
1732 if (parse_sec(a, &i.age) < 0) {
1733 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1740 h = needs_glob(i.type) ? globs : items;
1742 existing = hashmap_get(h, i.path);
1746 for (n = 0; n < existing->count; n++) {
1747 if (!item_compatible(existing->items + n, &i))
1748 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1749 fname, line, i.path);
1752 existing = new0(ItemArray, 1);
1753 r = hashmap_put(h, i.path, existing);
1758 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1761 memcpy(existing->items + existing->count++, &i, sizeof(i));
1766 static void help(void) {
1767 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1768 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1769 " -h --help Show this help\n"
1770 " --version Show package version\n"
1771 " --create Create marked files/directories\n"
1772 " --clean Clean up marked directories\n"
1773 " --remove Remove marked files/directories\n"
1774 " --boot Execute actions only safe at boot\n"
1775 " --prefix=PATH Only apply rules with the specified prefix\n"
1776 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1777 " --root=PATH Operate on an alternate filesystem root\n",
1778 program_invocation_short_name);
1781 static int parse_argv(int argc, char *argv[]) {
1784 ARG_VERSION = 0x100,
1794 static const struct option options[] = {
1795 { "help", no_argument, NULL, 'h' },
1796 { "version", no_argument, NULL, ARG_VERSION },
1797 { "create", no_argument, NULL, ARG_CREATE },
1798 { "clean", no_argument, NULL, ARG_CLEAN },
1799 { "remove", no_argument, NULL, ARG_REMOVE },
1800 { "boot", no_argument, NULL, ARG_BOOT },
1801 { "prefix", required_argument, NULL, ARG_PREFIX },
1802 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1803 { "root", required_argument, NULL, ARG_ROOT },
1812 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1821 puts(PACKAGE_STRING);
1822 puts(SYSTEMD_FEATURES);
1842 if (strv_push(&arg_include_prefixes, optarg) < 0)
1846 case ARG_EXCLUDE_PREFIX:
1847 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1853 arg_root = path_make_absolute_cwd(optarg);
1857 path_kill_slashes(arg_root);
1864 assert_not_reached("Unhandled option");
1867 if (!arg_clean && !arg_create && !arg_remove) {
1868 log_error("You need to specify at least one of --clean, --create or --remove.");
1875 static int read_config_file(const char *fn, bool ignore_enoent) {
1876 _cleanup_fclose_ FILE *f = NULL;
1877 char line[LINE_MAX];
1885 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1887 if (ignore_enoent && r == -ENOENT) {
1888 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1892 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1894 log_debug("Reading config file \"%s\".", fn);
1896 FOREACH_LINE(line, f, break) {
1903 if (*l == '#' || *l == 0)
1906 k = parse_line(fn, v, l);
1907 if (k < 0 && r == 0)
1911 /* we have to determine age parameter for each entry of type X */
1912 HASHMAP_FOREACH(i, globs, iterator) {
1914 Item *j, *candidate_item = NULL;
1916 if (i->type != IGNORE_DIRECTORY_PATH)
1919 HASHMAP_FOREACH(j, items, iter) {
1920 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1923 if (path_equal(j->path, i->path)) {
1928 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1929 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1933 if (candidate_item && candidate_item->age_set) {
1934 i->age = candidate_item->age;
1940 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1948 int main(int argc, char *argv[]) {
1953 r = parse_argv(argc, argv);
1957 log_set_target(LOG_TARGET_AUTO);
1958 log_parse_environment();
1963 mac_selinux_init(NULL);
1965 items = hashmap_new(&string_hash_ops);
1966 globs = hashmap_new(&string_hash_ops);
1968 if (!items || !globs) {
1975 if (optind < argc) {
1978 for (j = optind; j < argc; j++) {
1979 k = read_config_file(argv[j], false);
1980 if (k < 0 && r == 0)
1985 _cleanup_strv_free_ char **files = NULL;
1988 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1990 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1994 STRV_FOREACH(f, files) {
1995 k = read_config_file(*f, true);
1996 if (k < 0 && r == 0)
2001 HASHMAP_FOREACH(a, globs, iterator) {
2002 k = process_item_array(a);
2003 if (k < 0 && r == 0)
2007 HASHMAP_FOREACH(a, items, iterator) {
2008 k = process_item_array(a);
2009 if (k < 0 && r == 0)
2014 while ((a = hashmap_steal_first(items)))
2017 while ((a = hashmap_steal_first(globs)))
2020 hashmap_free(items);
2021 hashmap_free(globs);
2023 free(arg_include_prefixes);
2024 free(arg_exclude_prefixes);
2027 set_free_free(unix_sockets);
2029 mac_selinux_finish();
2031 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;