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) {
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");
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",
742 static int path_set_acls(Item *item, const char *path) {
749 if (item->acl_access) {
750 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
755 if (item->acl_default) {
756 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
765 static int write_one_file(Item *i, const char *path) {
766 _cleanup_close_ int fd = -1;
773 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
774 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
776 RUN_WITH_UMASK(0000) {
777 mac_selinux_create_file_prepare(path, S_IFREG);
778 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
779 mac_selinux_create_file_clear();
783 if (i->type == WRITE_FILE && errno == ENOENT) {
784 log_debug_errno(errno, "Not writing \"%s\": %m", path);
788 log_error_errno(errno, "Failed to create file %s: %m", path);
793 _cleanup_free_ char *unescaped;
795 log_debug("%s to \"%s\".",
796 i->type == CREATE_FILE ? "Appending" : "Writing", path);
798 unescaped = cunescape(i->argument);
802 r = loop_write(fd, unescaped, strlen(unescaped), false);
804 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
806 log_debug("\"%s\" has been created.", path);
810 if (stat(path, &st) < 0)
811 return log_error_errno(errno, "stat(%s) failed: %m", path);
813 if (!S_ISREG(st.st_mode)) {
814 log_error("%s is not a file.", path);
818 r = path_set_perms(i, path);
825 typedef int (*action_t)(Item *, const char *);
827 static int item_do_children(Item *i, const char *path, action_t action) {
828 _cleanup_closedir_ DIR *d;
834 /* This returns the first error we run into, but nevertheless
837 d = opendir_nomod(path);
839 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
842 _cleanup_free_ char *p = NULL;
849 if (errno != 0 && r == 0)
855 if (STR_IN_SET(de->d_name, ".", ".."))
858 p = strjoin(path, "/", de->d_name, NULL);
863 if (q < 0 && q != -ENOENT && r == 0)
866 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
867 q = item_do_children(i, p, action);
876 static int glob_item(Item *i, action_t action, bool recursive) {
877 _cleanup_globfree_ glob_t g = {
878 .gl_closedir = (void (*)(void *)) closedir,
879 .gl_readdir = (struct dirent *(*)(void *)) readdir,
880 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
888 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
889 if (k != 0 && k != GLOB_NOMATCH)
890 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
892 STRV_FOREACH(fn, g.gl_pathv) {
898 k = item_do_children(i, *fn, action);
912 _CREATION_MODE_INVALID = -1
915 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
916 [CREATION_NORMAL] = "Created",
917 [CREATION_EXISTING] = "Found existing",
918 [CREATION_FORCE] = "Created replacement",
921 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
923 static int create_item(Item *i) {
926 CreationMode creation;
930 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
935 case IGNORE_DIRECTORY_PATH:
937 case RECURSIVE_REMOVE_PATH:
942 r = write_one_file(i, i->path);
948 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
949 r = copy_tree(i->argument, i->path, false);
954 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
956 if (stat(i->argument, &a) < 0)
957 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
959 if (stat(i->path, &b) < 0)
960 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
962 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
963 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
968 r = path_set_perms(i, i->path);
975 r = glob_item(i, write_one_file, false);
981 case CREATE_DIRECTORY:
982 case TRUNCATE_DIRECTORY:
983 case CREATE_SUBVOLUME:
986 mkdir_parents_label(i->path, 0755);
988 if (i->type == CREATE_SUBVOLUME)
989 RUN_WITH_UMASK((~i->mode) & 0777) {
990 r = btrfs_subvol_make(i->path);
991 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
996 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
998 r = mkdir_label(i->path, i->mode);
1002 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1004 if (stat(i->path, &st) < 0)
1005 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1007 if (!S_ISDIR(st.st_mode)) {
1008 log_debug("\"%s\" already exists and is not a directory.", i->path);
1012 creation = CREATION_EXISTING;
1014 creation = CREATION_NORMAL;
1015 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1017 r = path_set_perms(i, i->path);
1025 RUN_WITH_UMASK(0000) {
1026 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1027 r = mkfifo(i->path, i->mode);
1028 mac_selinux_create_file_clear();
1032 if (errno != EEXIST)
1033 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1035 if (stat(i->path, &st) < 0)
1036 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1038 if (!S_ISFIFO(st.st_mode)) {
1042 RUN_WITH_UMASK(0000) {
1043 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1044 r = mkfifo_atomic(i->path, i->mode);
1045 mac_selinux_create_file_clear();
1049 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1050 creation = CREATION_FORCE;
1052 log_debug("%s is not a fifo.", i->path);
1056 creation = CREATION_EXISTING;
1058 creation = CREATION_NORMAL;
1059 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1061 r = path_set_perms(i, i->path);
1067 case CREATE_SYMLINK:
1069 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1070 r = symlink(i->argument, i->path);
1071 mac_selinux_create_file_clear();
1074 _cleanup_free_ char *x = NULL;
1076 if (errno != EEXIST)
1077 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1079 r = readlink_malloc(i->path, &x);
1080 if (r < 0 || !streq(i->argument, x)) {
1083 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1084 r = symlink_atomic(i->argument, i->path);
1085 mac_selinux_create_file_clear();
1088 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1089 creation = CREATION_FORCE;
1091 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1095 creation = CREATION_EXISTING;
1097 creation = CREATION_NORMAL;
1098 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1102 case CREATE_BLOCK_DEVICE:
1103 case CREATE_CHAR_DEVICE: {
1106 if (have_effective_cap(CAP_MKNOD) == 0) {
1107 /* In a container we lack CAP_MKNOD. We
1108 shouldn't attempt to create the device node in
1109 that case to avoid noise, and we don't support
1110 virtualized devices in containers anyway. */
1112 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1116 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1118 RUN_WITH_UMASK(0000) {
1119 mac_selinux_create_file_prepare(i->path, file_type);
1120 r = mknod(i->path, i->mode | file_type, i->major_minor);
1121 mac_selinux_create_file_clear();
1125 if (errno == EPERM) {
1126 log_debug("We lack permissions, possibly because of cgroup configuration; "
1127 "skipping creation of device node %s.", i->path);
1131 if (errno != EEXIST)
1132 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1134 if (stat(i->path, &st) < 0)
1135 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1137 if ((st.st_mode & S_IFMT) != file_type) {
1141 RUN_WITH_UMASK(0000) {
1142 mac_selinux_create_file_prepare(i->path, file_type);
1143 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1144 mac_selinux_create_file_clear();
1148 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1149 creation = CREATION_FORCE;
1151 log_debug("%s is not a device node.", i->path);
1155 creation = CREATION_EXISTING;
1157 creation = CREATION_NORMAL;
1158 log_debug("%s %s device node \"%s\" %u:%u.",
1159 creation_mode_verb_to_string(creation),
1160 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1161 i->path, major(i->mode), minor(i->mode));
1163 r = path_set_perms(i, i->path);
1172 r = glob_item(i, path_set_perms, false);
1177 case RECURSIVE_RELABEL_PATH:
1178 r = glob_item(i, path_set_perms, true);
1184 r = glob_item(i, path_set_xattrs, false);
1189 case RECURSIVE_SET_XATTR:
1190 r = glob_item(i, path_set_xattrs, true);
1196 r = glob_item(i, path_set_acls, false);
1201 case RECURSIVE_SET_ACL:
1202 r = glob_item(i, path_set_acls, true);
1208 log_debug("%s created successfully.", i->path);
1213 static int remove_item_instance(Item *i, const char *instance) {
1221 if (remove(instance) < 0 && errno != ENOENT)
1222 return log_error_errno(errno, "rm(%s): %m", instance);
1226 case TRUNCATE_DIRECTORY:
1227 case RECURSIVE_REMOVE_PATH:
1228 /* FIXME: we probably should use dir_cleanup() here
1229 * instead of rm_rf() so that 'x' is honoured. */
1230 log_debug("rm -rf \"%s\"", instance);
1231 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1232 if (r < 0 && r != -ENOENT)
1233 return log_error_errno(r, "rm_rf(%s): %m", instance);
1238 assert_not_reached("wut?");
1244 static int remove_item(Item *i) {
1249 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1255 case CREATE_DIRECTORY:
1256 case CREATE_SUBVOLUME:
1258 case CREATE_SYMLINK:
1259 case CREATE_CHAR_DEVICE:
1260 case CREATE_BLOCK_DEVICE:
1262 case IGNORE_DIRECTORY_PATH:
1265 case RECURSIVE_RELABEL_PATH:
1269 case RECURSIVE_SET_XATTR:
1271 case RECURSIVE_SET_ACL:
1275 case TRUNCATE_DIRECTORY:
1276 case RECURSIVE_REMOVE_PATH:
1277 r = glob_item(i, remove_item_instance, false);
1284 static int clean_item_instance(Item *i, const char* instance) {
1285 _cleanup_closedir_ DIR *d = NULL;
1289 char timestamp[FORMAT_TIMESTAMP_MAX];
1296 n = now(CLOCK_REALTIME);
1300 cutoff = n - i->age;
1302 d = opendir_nomod(instance);
1304 if (errno == ENOENT || errno == ENOTDIR) {
1305 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1309 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1313 if (fstat(dirfd(d), &s) < 0)
1314 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1316 if (!S_ISDIR(s.st_mode)) {
1317 log_error("%s is not a directory.", i->path);
1321 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1322 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1324 mountpoint = s.st_dev != ps.st_dev ||
1325 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1327 log_debug("Cleanup threshold for %s \"%s\" is %s",
1328 mountpoint ? "mount point" : "directory",
1330 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1332 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1333 MAX_DEPTH, i->keep_first_level);
1336 static int clean_item(Item *i) {
1341 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1344 case CREATE_DIRECTORY:
1345 case CREATE_SUBVOLUME:
1346 case TRUNCATE_DIRECTORY:
1349 clean_item_instance(i, i->path);
1351 case IGNORE_DIRECTORY_PATH:
1352 r = glob_item(i, clean_item_instance, false);
1361 static int process_item_array(ItemArray *array);
1363 static int process_item(Item *i) {
1365 _cleanup_free_ char *prefix = NULL;
1374 prefix = malloc(strlen(i->path) + 1);
1378 PATH_FOREACH_PREFIX(prefix, i->path) {
1381 j = hashmap_get(items, prefix);
1385 s = process_item_array(j);
1386 if (s < 0 && t == 0)
1391 r = arg_create ? create_item(i) : 0;
1392 q = arg_remove ? remove_item(i) : 0;
1393 p = arg_clean ? clean_item(i) : 0;
1401 static int process_item_array(ItemArray *array) {
1407 for (n = 0; n < array->count; n++) {
1408 k = process_item(array->items + n);
1409 if (k < 0 && r == 0)
1416 static void item_free_contents(Item *i) {
1420 strv_free(i->xattrs);
1423 acl_free(i->acl_access);
1424 acl_free(i->acl_default);
1428 static void item_array_free(ItemArray *a) {
1434 for (n = 0; n < a->count; n++)
1435 item_free_contents(a->items + n);
1440 static bool item_compatible(Item *a, Item *b) {
1443 assert(streq(a->path, b->path));
1445 if (takes_ownership(a->type) && takes_ownership(b->type))
1446 /* check if the items are the same */
1447 return streq_ptr(a->argument, b->argument) &&
1449 a->uid_set == b->uid_set &&
1452 a->gid_set == b->gid_set &&
1455 a->mode_set == b->mode_set &&
1456 a->mode == b->mode &&
1458 a->age_set == b->age_set &&
1461 a->mask_perms == b->mask_perms &&
1463 a->keep_first_level == b->keep_first_level &&
1465 a->major_minor == b->major_minor;
1470 static bool should_include_path(const char *path) {
1473 STRV_FOREACH(prefix, arg_exclude_prefixes)
1474 if (path_startswith(path, *prefix)) {
1475 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1480 STRV_FOREACH(prefix, arg_include_prefixes)
1481 if (path_startswith(path, *prefix)) {
1482 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1486 /* no matches, so we should include this path only if we
1487 * have no whitelist at all */
1488 if (strv_length(arg_include_prefixes) == 0)
1491 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1495 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1497 static const Specifier specifier_table[] = {
1498 { 'm', specifier_machine_id, NULL },
1499 { 'b', specifier_boot_id, NULL },
1500 { 'H', specifier_host_name, NULL },
1501 { 'v', specifier_kernel_release, NULL },
1505 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1506 _cleanup_(item_free_contents) Item i = {};
1507 ItemArray *existing;
1510 bool force = false, boot = false;
1517 "%ms %ms %ms %ms %ms %ms %n",
1526 log_error("[%s:%u] Syntax error.", fname, line);
1530 if (isempty(action)) {
1531 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1535 for (pos = 1; action[pos]; pos++) {
1536 if (action[pos] == '!' && !boot)
1538 else if (action[pos] == '+' && !force)
1541 log_error("[%s:%u] Unknown modifiers in command '%s'",
1542 fname, line, action);
1547 if (boot && !arg_boot) {
1548 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1556 r = specifier_printf(path, specifier_table, NULL, &i.path);
1558 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1563 c += strspn(buffer+c, WHITESPACE);
1564 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1565 i.argument = unquote(buffer+c, "\"");
1575 case CREATE_DIRECTORY:
1576 case CREATE_SUBVOLUME:
1577 case TRUNCATE_DIRECTORY:
1580 case IGNORE_DIRECTORY_PATH:
1582 case RECURSIVE_REMOVE_PATH:
1585 case RECURSIVE_RELABEL_PATH:
1588 case CREATE_SYMLINK:
1590 i.argument = strappend("/usr/share/factory/", i.path);
1598 log_error("[%s:%u] Write file requires argument.", fname, line);
1605 i.argument = strappend("/usr/share/factory/", i.path);
1608 } else if (!path_is_absolute(i.argument)) {
1609 log_error("[%s:%u] Source path is not absolute.", fname, line);
1613 path_kill_slashes(i.argument);
1616 case CREATE_CHAR_DEVICE:
1617 case CREATE_BLOCK_DEVICE: {
1618 unsigned major, minor;
1621 log_error("[%s:%u] Device file requires argument.", fname, line);
1625 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1626 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1630 i.major_minor = makedev(major, minor);
1635 case RECURSIVE_SET_XATTR:
1637 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1640 r = get_xattrs_from_arg(&i);
1646 case RECURSIVE_SET_ACL:
1648 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1651 r = get_acls_from_arg(&i);
1657 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1661 if (!path_is_absolute(i.path)) {
1662 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1666 path_kill_slashes(i.path);
1668 if (!should_include_path(i.path))
1674 p = strappend(arg_root, i.path);
1682 if (user && !streq(user, "-")) {
1683 const char *u = user;
1685 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1687 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1694 if (group && !streq(group, "-")) {
1695 const char *g = group;
1697 r = get_group_creds(&g, &i.gid);
1699 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1706 if (mode && !streq(mode, "-")) {
1707 const char *mm = mode;
1711 i.mask_perms = true;
1715 if (sscanf(mm, "%o", &m) != 1) {
1716 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1723 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1726 if (age && !streq(age, "-")) {
1727 const char *a = age;
1730 i.keep_first_level = true;
1734 if (parse_sec(a, &i.age) < 0) {
1735 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1742 h = needs_glob(i.type) ? globs : items;
1744 existing = hashmap_get(h, i.path);
1748 for (n = 0; n < existing->count; n++) {
1749 if (!item_compatible(existing->items + n, &i))
1750 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1751 fname, line, i.path);
1754 existing = new0(ItemArray, 1);
1755 r = hashmap_put(h, i.path, existing);
1760 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1763 memcpy(existing->items + existing->count++, &i, sizeof(i));
1768 static void help(void) {
1769 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1770 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1771 " -h --help Show this help\n"
1772 " --version Show package version\n"
1773 " --create Create marked files/directories\n"
1774 " --clean Clean up marked directories\n"
1775 " --remove Remove marked files/directories\n"
1776 " --boot Execute actions only safe at boot\n"
1777 " --prefix=PATH Only apply rules with the specified prefix\n"
1778 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1779 " --root=PATH Operate on an alternate filesystem root\n",
1780 program_invocation_short_name);
1783 static int parse_argv(int argc, char *argv[]) {
1786 ARG_VERSION = 0x100,
1796 static const struct option options[] = {
1797 { "help", no_argument, NULL, 'h' },
1798 { "version", no_argument, NULL, ARG_VERSION },
1799 { "create", no_argument, NULL, ARG_CREATE },
1800 { "clean", no_argument, NULL, ARG_CLEAN },
1801 { "remove", no_argument, NULL, ARG_REMOVE },
1802 { "boot", no_argument, NULL, ARG_BOOT },
1803 { "prefix", required_argument, NULL, ARG_PREFIX },
1804 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1805 { "root", required_argument, NULL, ARG_ROOT },
1814 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1823 puts(PACKAGE_STRING);
1824 puts(SYSTEMD_FEATURES);
1844 if (strv_push(&arg_include_prefixes, optarg) < 0)
1848 case ARG_EXCLUDE_PREFIX:
1849 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1855 arg_root = path_make_absolute_cwd(optarg);
1859 path_kill_slashes(arg_root);
1866 assert_not_reached("Unhandled option");
1869 if (!arg_clean && !arg_create && !arg_remove) {
1870 log_error("You need to specify at least one of --clean, --create or --remove.");
1877 static int read_config_file(const char *fn, bool ignore_enoent) {
1878 _cleanup_fclose_ FILE *f = NULL;
1879 char line[LINE_MAX];
1887 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1889 if (ignore_enoent && r == -ENOENT) {
1890 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1894 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1896 log_debug("Reading config file \"%s\".", fn);
1898 FOREACH_LINE(line, f, break) {
1905 if (*l == '#' || *l == 0)
1908 k = parse_line(fn, v, l);
1909 if (k < 0 && r == 0)
1913 /* we have to determine age parameter for each entry of type X */
1914 HASHMAP_FOREACH(i, globs, iterator) {
1916 Item *j, *candidate_item = NULL;
1918 if (i->type != IGNORE_DIRECTORY_PATH)
1921 HASHMAP_FOREACH(j, items, iter) {
1922 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1925 if (path_equal(j->path, i->path)) {
1930 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1931 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1935 if (candidate_item && candidate_item->age_set) {
1936 i->age = candidate_item->age;
1942 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1950 int main(int argc, char *argv[]) {
1955 r = parse_argv(argc, argv);
1959 log_set_target(LOG_TARGET_AUTO);
1960 log_parse_environment();
1965 mac_selinux_init(NULL);
1967 items = hashmap_new(&string_hash_ops);
1968 globs = hashmap_new(&string_hash_ops);
1970 if (!items || !globs) {
1977 if (optind < argc) {
1980 for (j = optind; j < argc; j++) {
1981 k = read_config_file(argv[j], false);
1982 if (k < 0 && r == 0)
1987 _cleanup_strv_free_ char **files = NULL;
1990 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1992 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1996 STRV_FOREACH(f, files) {
1997 k = read_config_file(*f, true);
1998 if (k < 0 && r == 0)
2003 HASHMAP_FOREACH(a, globs, iterator) {
2004 k = process_item_array(a);
2005 if (k < 0 && r == 0)
2009 HASHMAP_FOREACH(a, items, iterator) {
2010 k = process_item_array(a);
2011 if (k < 0 && r == 0)
2016 while ((a = hashmap_steal_first(items)))
2019 while ((a = hashmap_steal_first(globs)))
2022 hashmap_free(items);
2023 hashmap_free(globs);
2025 free(arg_include_prefixes);
2026 free(arg_exclude_prefixes);
2029 set_free_free(unix_sockets);
2031 mac_selinux_finish();
2033 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;