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, *_xattr = xattr;
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) {
685 _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
689 /* If force (= modify) is set, we will not modify the acl
690 * afterwards, so the mask can be added now if necessary. */
691 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
693 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
696 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
702 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
703 _cleanup_(acl_freep) acl_t dup = NULL;
705 _cleanup_(acl_free_charpp) char *t = NULL;
708 r = acls_for_file(path, type, acl, &dup);
712 r = calc_acl_mask_if_needed(&dup);
720 /* the mask was already added earlier if needed */
723 r = add_base_acls_if_needed(&dup, path);
727 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
728 log_debug("\"%s\": setting %s ACL \"%s\"", path,
729 type == ACL_TYPE_ACCESS ? "access" : "default",
732 r = acl_set_file(path, type, dup);
734 return log_error_errno(-errno,
735 "Setting %s ACL \"%s\" on %s failed: %m",
736 type == ACL_TYPE_ACCESS ? "access" : "default",
741 static int path_set_acls(Item *item, const char *path) {
748 if (item->acl_access) {
749 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
754 if (item->acl_default) {
755 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
764 static int write_one_file(Item *i, const char *path) {
765 _cleanup_close_ int fd = -1;
772 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
773 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
775 RUN_WITH_UMASK(0000) {
776 mac_selinux_create_file_prepare(path, S_IFREG);
777 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
778 mac_selinux_create_file_clear();
782 if (i->type == WRITE_FILE && errno == ENOENT) {
783 log_debug_errno(errno, "Not writing \"%s\": %m", path);
787 log_error_errno(errno, "Failed to create file %s: %m", path);
792 _cleanup_free_ char *unescaped;
794 log_debug("%s to \"%s\".",
795 i->type == CREATE_FILE ? "Appending" : "Writing", path);
797 unescaped = cunescape(i->argument);
801 r = loop_write(fd, unescaped, strlen(unescaped), false);
803 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
805 log_debug("\"%s\" has been created.", path);
809 if (stat(path, &st) < 0)
810 return log_error_errno(errno, "stat(%s) failed: %m", path);
812 if (!S_ISREG(st.st_mode)) {
813 log_error("%s is not a file.", path);
817 r = path_set_perms(i, path);
824 typedef int (*action_t)(Item *, const char *);
826 static int item_do_children(Item *i, const char *path, action_t action) {
827 _cleanup_closedir_ DIR *d;
833 /* This returns the first error we run into, but nevertheless
836 d = opendir_nomod(path);
838 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
841 _cleanup_free_ char *p = NULL;
848 if (errno != 0 && r == 0)
854 if (STR_IN_SET(de->d_name, ".", ".."))
857 p = strjoin(path, "/", de->d_name, NULL);
862 if (q < 0 && q != -ENOENT && r == 0)
865 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
866 q = item_do_children(i, p, action);
875 static int glob_item(Item *i, action_t action, bool recursive) {
876 _cleanup_globfree_ glob_t g = {
877 .gl_closedir = (void (*)(void *)) closedir,
878 .gl_readdir = (struct dirent *(*)(void *)) readdir,
879 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
887 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
888 if (k != 0 && k != GLOB_NOMATCH)
889 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
891 STRV_FOREACH(fn, g.gl_pathv) {
897 k = item_do_children(i, *fn, action);
912 static const char* creation_verb(CreationMode mode) {
914 case CREATION_NORMAL:
916 case CREATION_EXISTING:
917 return "Found existing";
919 return "Created replacement";
921 assert_not_reached("Bad creation");
924 static int create_item(Item *i) {
927 CreationMode creation;
931 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
936 case IGNORE_DIRECTORY_PATH:
938 case RECURSIVE_REMOVE_PATH:
943 r = write_one_file(i, i->path);
949 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
950 r = copy_tree(i->argument, i->path, false);
955 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
957 if (stat(i->argument, &a) < 0)
958 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
960 if (stat(i->path, &b) < 0)
961 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
963 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
964 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
969 r = path_set_perms(i, i->path);
976 r = glob_item(i, write_one_file, false);
982 case CREATE_DIRECTORY:
983 case TRUNCATE_DIRECTORY:
984 case CREATE_SUBVOLUME:
987 mkdir_parents_label(i->path, 0755);
989 if (i->type == CREATE_SUBVOLUME)
990 RUN_WITH_UMASK((~i->mode) & 0777) {
991 r = btrfs_subvol_make(i->path);
992 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
997 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
999 r = mkdir_label(i->path, i->mode);
1003 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1005 if (stat(i->path, &st) < 0)
1006 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1008 if (!S_ISDIR(st.st_mode)) {
1009 log_debug("\"%s\" already exists and is not a directory.", i->path);
1013 creation = CREATION_EXISTING;
1015 creation = CREATION_NORMAL;
1016 log_debug("%s directory \"%s\".", creation_verb(creation), i->path);
1018 r = path_set_perms(i, i->path);
1026 RUN_WITH_UMASK(0000) {
1027 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1028 r = mkfifo(i->path, i->mode);
1029 mac_selinux_create_file_clear();
1033 if (errno != EEXIST)
1034 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1036 if (stat(i->path, &st) < 0)
1037 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1039 if (!S_ISFIFO(st.st_mode)) {
1043 RUN_WITH_UMASK(0000) {
1044 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1045 r = mkfifo_atomic(i->path, i->mode);
1046 mac_selinux_create_file_clear();
1050 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1051 creation = CREATION_FORCE;
1053 log_debug("%s is not a fifo.", i->path);
1057 creation = CREATION_EXISTING;
1059 creation = CREATION_NORMAL;
1060 log_debug("%s fifo \"%s\".", creation_verb(creation), i->path);
1062 r = path_set_perms(i, i->path);
1068 case CREATE_SYMLINK:
1070 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1071 r = symlink(i->argument, i->path);
1072 mac_selinux_create_file_clear();
1075 _cleanup_free_ char *x = NULL;
1077 if (errno != EEXIST)
1078 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1080 r = readlink_malloc(i->path, &x);
1081 if (r < 0 || !streq(i->argument, x)) {
1084 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1085 r = symlink_atomic(i->argument, i->path);
1086 mac_selinux_create_file_clear();
1089 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1090 creation = CREATION_FORCE;
1092 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1096 creation = CREATION_EXISTING;
1098 creation = CREATION_NORMAL;
1099 log_debug("%s symlink \"%s\".", creation_verb(creation), i->path);
1103 case CREATE_BLOCK_DEVICE:
1104 case CREATE_CHAR_DEVICE: {
1107 if (have_effective_cap(CAP_MKNOD) == 0) {
1108 /* In a container we lack CAP_MKNOD. We
1109 shouldn't attempt to create the device node in
1110 that case to avoid noise, and we don't support
1111 virtualized devices in containers anyway. */
1113 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1117 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1119 RUN_WITH_UMASK(0000) {
1120 mac_selinux_create_file_prepare(i->path, file_type);
1121 r = mknod(i->path, i->mode | file_type, i->major_minor);
1122 mac_selinux_create_file_clear();
1126 if (errno == EPERM) {
1127 log_debug("We lack permissions, possibly because of cgroup configuration; "
1128 "skipping creation of device node %s.", i->path);
1132 if (errno != EEXIST)
1133 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1135 if (stat(i->path, &st) < 0)
1136 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1138 if ((st.st_mode & S_IFMT) != file_type) {
1142 RUN_WITH_UMASK(0000) {
1143 mac_selinux_create_file_prepare(i->path, file_type);
1144 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1145 mac_selinux_create_file_clear();
1149 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1150 creation = CREATION_FORCE;
1152 log_debug("%s is not a device node.", i->path);
1156 creation = CREATION_EXISTING;
1158 creation = CREATION_NORMAL;
1159 log_debug("%s %s device node \"%s\" %u:%u.",
1160 creation_verb(creation),
1161 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1162 i->path, major(i->mode), minor(i->mode));
1164 r = path_set_perms(i, i->path);
1173 r = glob_item(i, path_set_perms, false);
1178 case RECURSIVE_RELABEL_PATH:
1179 r = glob_item(i, path_set_perms, true);
1185 r = glob_item(i, path_set_xattrs, false);
1190 case RECURSIVE_SET_XATTR:
1191 r = glob_item(i, path_set_xattrs, true);
1197 r = glob_item(i, path_set_acls, false);
1202 case RECURSIVE_SET_ACL:
1203 r = glob_item(i, path_set_acls, true);
1209 log_debug("%s created successfully.", i->path);
1214 static int remove_item_instance(Item *i, const char *instance) {
1222 if (remove(instance) < 0 && errno != ENOENT)
1223 return log_error_errno(errno, "rm(%s): %m", instance);
1227 case TRUNCATE_DIRECTORY:
1228 case RECURSIVE_REMOVE_PATH:
1229 /* FIXME: we probably should use dir_cleanup() here
1230 * instead of rm_rf() so that 'x' is honoured. */
1231 log_debug("rm -rf \"%s\"", instance);
1232 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1233 if (r < 0 && r != -ENOENT)
1234 return log_error_errno(r, "rm_rf(%s): %m", instance);
1239 assert_not_reached("wut?");
1245 static int remove_item(Item *i) {
1250 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1256 case CREATE_DIRECTORY:
1257 case CREATE_SUBVOLUME:
1259 case CREATE_SYMLINK:
1260 case CREATE_CHAR_DEVICE:
1261 case CREATE_BLOCK_DEVICE:
1263 case IGNORE_DIRECTORY_PATH:
1266 case RECURSIVE_RELABEL_PATH:
1270 case RECURSIVE_SET_XATTR:
1272 case RECURSIVE_SET_ACL:
1276 case TRUNCATE_DIRECTORY:
1277 case RECURSIVE_REMOVE_PATH:
1278 r = glob_item(i, remove_item_instance, false);
1285 static int clean_item_instance(Item *i, const char* instance) {
1286 _cleanup_closedir_ DIR *d = NULL;
1290 char timestamp[FORMAT_TIMESTAMP_MAX];
1297 n = now(CLOCK_REALTIME);
1301 cutoff = n - i->age;
1303 d = opendir_nomod(instance);
1305 if (errno == ENOENT || errno == ENOTDIR) {
1306 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1310 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1314 if (fstat(dirfd(d), &s) < 0)
1315 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1317 if (!S_ISDIR(s.st_mode)) {
1318 log_error("%s is not a directory.", i->path);
1322 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1323 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1325 mountpoint = s.st_dev != ps.st_dev ||
1326 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1328 log_debug("Cleanup threshold for %s \"%s\" is %s",
1329 mountpoint ? "mount point" : "directory",
1331 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1333 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1334 MAX_DEPTH, i->keep_first_level);
1337 static int clean_item(Item *i) {
1342 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1345 case CREATE_DIRECTORY:
1346 case CREATE_SUBVOLUME:
1347 case TRUNCATE_DIRECTORY:
1350 clean_item_instance(i, i->path);
1352 case IGNORE_DIRECTORY_PATH:
1353 r = glob_item(i, clean_item_instance, false);
1362 static int process_item_array(ItemArray *array);
1364 static int process_item(Item *i) {
1366 _cleanup_free_ char *prefix = NULL;
1375 prefix = malloc(strlen(i->path) + 1);
1379 PATH_FOREACH_PREFIX(prefix, i->path) {
1382 j = hashmap_get(items, prefix);
1386 s = process_item_array(j);
1387 if (s < 0 && t == 0)
1392 r = arg_create ? create_item(i) : 0;
1393 q = arg_remove ? remove_item(i) : 0;
1394 p = arg_clean ? clean_item(i) : 0;
1402 static int process_item_array(ItemArray *array) {
1408 for (n = 0; n < array->count; n++) {
1409 k = process_item(array->items + n);
1410 if (k < 0 && r == 0)
1417 static void item_free_contents(Item *i) {
1421 strv_free(i->xattrs);
1424 acl_free(i->acl_access);
1425 acl_free(i->acl_default);
1429 static void item_array_free(ItemArray *a) {
1435 for (n = 0; n < a->count; n++)
1436 item_free_contents(a->items + n);
1441 static bool item_compatible(Item *a, Item *b) {
1444 assert(streq(a->path, b->path));
1446 if (takes_ownership(a->type) && takes_ownership(b->type))
1447 /* check if the items are the same */
1448 return streq_ptr(a->argument, b->argument) &&
1450 a->uid_set == b->uid_set &&
1453 a->gid_set == b->gid_set &&
1456 a->mode_set == b->mode_set &&
1457 a->mode == b->mode &&
1459 a->age_set == b->age_set &&
1462 a->mask_perms == b->mask_perms &&
1464 a->keep_first_level == b->keep_first_level &&
1466 a->major_minor == b->major_minor;
1471 static bool should_include_path(const char *path) {
1474 STRV_FOREACH(prefix, arg_exclude_prefixes)
1475 if (path_startswith(path, *prefix)) {
1476 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1481 STRV_FOREACH(prefix, arg_include_prefixes)
1482 if (path_startswith(path, *prefix)) {
1483 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1487 /* no matches, so we should include this path only if we
1488 * have no whitelist at all */
1489 if (strv_length(arg_include_prefixes) == 0)
1492 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1496 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1498 static const Specifier specifier_table[] = {
1499 { 'm', specifier_machine_id, NULL },
1500 { 'b', specifier_boot_id, NULL },
1501 { 'H', specifier_host_name, NULL },
1502 { 'v', specifier_kernel_release, NULL },
1506 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1507 _cleanup_(item_free_contents) Item i = {};
1508 ItemArray *existing;
1511 bool force = false, boot = false;
1518 "%ms %ms %ms %ms %ms %ms %n",
1527 log_error("[%s:%u] Syntax error.", fname, line);
1531 if (isempty(action)) {
1532 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1536 for (pos = 1; action[pos]; pos++) {
1537 if (action[pos] == '!' && !boot)
1539 else if (action[pos] == '+' && !force)
1542 log_error("[%s:%u] Unknown modifiers in command '%s'",
1543 fname, line, action);
1548 if (boot && !arg_boot) {
1549 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1557 r = specifier_printf(path, specifier_table, NULL, &i.path);
1559 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1564 c += strspn(buffer+c, WHITESPACE);
1565 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1566 i.argument = unquote(buffer+c, "\"");
1576 case CREATE_DIRECTORY:
1577 case CREATE_SUBVOLUME:
1578 case TRUNCATE_DIRECTORY:
1581 case IGNORE_DIRECTORY_PATH:
1583 case RECURSIVE_REMOVE_PATH:
1586 case RECURSIVE_RELABEL_PATH:
1589 case CREATE_SYMLINK:
1591 i.argument = strappend("/usr/share/factory/", i.path);
1599 log_error("[%s:%u] Write file requires argument.", fname, line);
1606 i.argument = strappend("/usr/share/factory/", i.path);
1609 } else if (!path_is_absolute(i.argument)) {
1610 log_error("[%s:%u] Source path is not absolute.", fname, line);
1614 path_kill_slashes(i.argument);
1617 case CREATE_CHAR_DEVICE:
1618 case CREATE_BLOCK_DEVICE: {
1619 unsigned major, minor;
1622 log_error("[%s:%u] Device file requires argument.", fname, line);
1626 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1627 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1631 i.major_minor = makedev(major, minor);
1636 case RECURSIVE_SET_XATTR:
1638 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1641 r = get_xattrs_from_arg(&i);
1647 case RECURSIVE_SET_ACL:
1649 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1652 r = get_acls_from_arg(&i);
1658 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1662 if (!path_is_absolute(i.path)) {
1663 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1667 path_kill_slashes(i.path);
1669 if (!should_include_path(i.path))
1675 p = strappend(arg_root, i.path);
1683 if (user && !streq(user, "-")) {
1684 const char *u = user;
1686 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1688 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1695 if (group && !streq(group, "-")) {
1696 const char *g = group;
1698 r = get_group_creds(&g, &i.gid);
1700 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1707 if (mode && !streq(mode, "-")) {
1708 const char *mm = mode;
1712 i.mask_perms = true;
1716 if (sscanf(mm, "%o", &m) != 1) {
1717 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1724 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1727 if (age && !streq(age, "-")) {
1728 const char *a = age;
1731 i.keep_first_level = true;
1735 if (parse_sec(a, &i.age) < 0) {
1736 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1743 h = needs_glob(i.type) ? globs : items;
1745 existing = hashmap_get(h, i.path);
1749 for (n = 0; n < existing->count; n++) {
1750 if (!item_compatible(existing->items + n, &i))
1751 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1752 fname, line, i.path);
1755 existing = new0(ItemArray, 1);
1756 r = hashmap_put(h, i.path, existing);
1761 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1764 memcpy(existing->items + existing->count++, &i, sizeof(i));
1769 static void help(void) {
1770 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1771 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1772 " -h --help Show this help\n"
1773 " --version Show package version\n"
1774 " --create Create marked files/directories\n"
1775 " --clean Clean up marked directories\n"
1776 " --remove Remove marked files/directories\n"
1777 " --boot Execute actions only safe at boot\n"
1778 " --prefix=PATH Only apply rules with the specified prefix\n"
1779 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1780 " --root=PATH Operate on an alternate filesystem root\n",
1781 program_invocation_short_name);
1784 static int parse_argv(int argc, char *argv[]) {
1787 ARG_VERSION = 0x100,
1797 static const struct option options[] = {
1798 { "help", no_argument, NULL, 'h' },
1799 { "version", no_argument, NULL, ARG_VERSION },
1800 { "create", no_argument, NULL, ARG_CREATE },
1801 { "clean", no_argument, NULL, ARG_CLEAN },
1802 { "remove", no_argument, NULL, ARG_REMOVE },
1803 { "boot", no_argument, NULL, ARG_BOOT },
1804 { "prefix", required_argument, NULL, ARG_PREFIX },
1805 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1806 { "root", required_argument, NULL, ARG_ROOT },
1815 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1824 puts(PACKAGE_STRING);
1825 puts(SYSTEMD_FEATURES);
1845 if (strv_push(&arg_include_prefixes, optarg) < 0)
1849 case ARG_EXCLUDE_PREFIX:
1850 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1856 arg_root = path_make_absolute_cwd(optarg);
1860 path_kill_slashes(arg_root);
1867 assert_not_reached("Unhandled option");
1870 if (!arg_clean && !arg_create && !arg_remove) {
1871 log_error("You need to specify at least one of --clean, --create or --remove.");
1878 static int read_config_file(const char *fn, bool ignore_enoent) {
1879 _cleanup_fclose_ FILE *f = NULL;
1880 char line[LINE_MAX];
1888 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1890 if (ignore_enoent && r == -ENOENT) {
1891 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1895 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1897 log_debug("Reading config file \"%s\".", fn);
1899 FOREACH_LINE(line, f, break) {
1906 if (*l == '#' || *l == 0)
1909 k = parse_line(fn, v, l);
1910 if (k < 0 && r == 0)
1914 /* we have to determine age parameter for each entry of type X */
1915 HASHMAP_FOREACH(i, globs, iterator) {
1917 Item *j, *candidate_item = NULL;
1919 if (i->type != IGNORE_DIRECTORY_PATH)
1922 HASHMAP_FOREACH(j, items, iter) {
1923 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1926 if (path_equal(j->path, i->path)) {
1931 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1932 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1936 if (candidate_item && candidate_item->age_set) {
1937 i->age = candidate_item->age;
1943 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1951 int main(int argc, char *argv[]) {
1956 r = parse_argv(argc, argv);
1960 log_set_target(LOG_TARGET_AUTO);
1961 log_parse_environment();
1966 mac_selinux_init(NULL);
1968 items = hashmap_new(&string_hash_ops);
1969 globs = hashmap_new(&string_hash_ops);
1971 if (!items || !globs) {
1978 if (optind < argc) {
1981 for (j = optind; j < argc; j++) {
1982 k = read_config_file(argv[j], false);
1983 if (k < 0 && r == 0)
1988 _cleanup_strv_free_ char **files = NULL;
1991 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1993 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1997 STRV_FOREACH(f, files) {
1998 k = read_config_file(*f, true);
1999 if (k < 0 && r == 0)
2004 HASHMAP_FOREACH(a, globs, iterator) {
2005 k = process_item_array(a);
2006 if (k < 0 && r == 0)
2010 HASHMAP_FOREACH(a, items, iterator) {
2011 k = process_item_array(a);
2012 if (k < 0 && r == 0)
2017 while ((a = hashmap_steal_first(items)))
2020 while ((a = hashmap_steal_first(globs)))
2023 hashmap_free(items);
2024 hashmap_free(globs);
2026 free(arg_include_prefixes);
2027 free(arg_exclude_prefixes);
2030 set_free_free(unix_sockets);
2032 mac_selinux_finish();
2034 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;