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/>.
38 #include <sys/xattr.h>
45 #include "path-util.h"
49 #include "conf-files.h"
50 #include "capability.h"
51 #include "specifier.h"
54 #include "selinux-util.h"
55 #include "btrfs-util.h"
58 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
59 * them in the file system. This is intended to be used to create
60 * properly owned directories beneath /tmp, /var/tmp, /run, which are
61 * volatile and hence need to be recreated on bootup. */
63 typedef enum ItemType {
64 /* These ones take file names */
67 CREATE_DIRECTORY = 'd',
68 TRUNCATE_DIRECTORY = 'D',
69 CREATE_SUBVOLUME = 'v',
72 CREATE_CHAR_DEVICE = 'c',
73 CREATE_BLOCK_DEVICE = 'b',
76 /* These ones take globs */
78 RECURSIVE_SET_XATTR = 'T',
80 RECURSIVE_SET_ACL = 'A',
83 IGNORE_DIRECTORY_PATH = 'X',
85 RECURSIVE_REMOVE_PATH = 'R',
86 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
88 RECURSIVE_RELABEL_PATH = 'Z',
114 bool keep_first_level:1;
121 typedef struct ItemArray {
127 static bool arg_create = false;
128 static bool arg_clean = false;
129 static bool arg_remove = false;
130 static bool arg_boot = false;
132 static char **arg_include_prefixes = NULL;
133 static char **arg_exclude_prefixes = NULL;
134 static char *arg_root = NULL;
136 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
138 #define MAX_DEPTH 256
140 static Hashmap *items = NULL, *globs = NULL;
141 static Set *unix_sockets = NULL;
143 static bool needs_glob(ItemType t) {
147 IGNORE_DIRECTORY_PATH,
149 RECURSIVE_REMOVE_PATH,
152 RECURSIVE_RELABEL_PATH,
159 static bool takes_ownership(ItemType t) {
174 IGNORE_DIRECTORY_PATH,
176 RECURSIVE_REMOVE_PATH);
179 static struct Item* find_glob(Hashmap *h, const char *match) {
183 HASHMAP_FOREACH(j, h, i) {
186 for (n = 0; n < j->count; n++) {
187 Item *item = j->items + n;
189 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
197 static void load_unix_sockets(void) {
198 _cleanup_fclose_ FILE *f = NULL;
204 /* We maintain a cache of the sockets we found in
205 * /proc/net/unix to speed things up a little. */
207 unix_sockets = set_new(&string_hash_ops);
211 f = fopen("/proc/net/unix", "re");
216 if (!fgets(line, sizeof(line), f))
223 if (!fgets(line, sizeof(line), f))
228 p = strchr(line, ':');
236 p += strspn(p, WHITESPACE);
237 p += strcspn(p, WHITESPACE); /* skip one more word */
238 p += strspn(p, WHITESPACE);
247 path_kill_slashes(s);
249 k = set_consume(unix_sockets, s);
250 if (k < 0 && k != -EEXIST)
257 set_free_free(unix_sockets);
261 static bool unix_socket_alive(const char *fn) {
267 return !!set_get(unix_sockets, (char*) fn);
269 /* We don't know, so assume yes */
273 static int dir_is_mount_point(DIR *d, const char *subdir) {
275 union file_handle_union h = FILE_HANDLE_INIT;
276 int mount_id_parent, mount_id;
279 r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
283 h.handle.handle_bytes = MAX_HANDLE_SZ;
284 r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
288 /* got no handle; make no assumptions, return error */
289 if (r_p < 0 && r < 0)
292 /* got both handles; if they differ, it is a mount point */
293 if (r_p >= 0 && r >= 0)
294 return mount_id_parent != mount_id;
296 /* got only one handle; assume different mount points if one
297 * of both queries was not supported by the filesystem */
298 if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
307 static DIR* xopendirat_nomod(int dirfd, const char *path) {
310 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
312 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
313 dirfd == AT_FDCWD ? "" : "sub", path);
314 if (errno == EPERM) {
315 dir = xopendirat(dirfd, path, O_NOFOLLOW);
317 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
318 dirfd == AT_FDCWD ? "" : "sub", path);
325 static DIR* opendir_nomod(const char *path) {
326 return xopendirat_nomod(AT_FDCWD, path);
329 static int dir_cleanup(
333 const struct stat *ds,
338 bool keep_this_level) {
341 struct timespec times[2];
342 bool deleted = false;
345 while ((dent = readdir(d))) {
348 _cleanup_free_ char *sub_path = NULL;
350 if (STR_IN_SET(dent->d_name, ".", ".."))
353 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
357 /* FUSE, NFS mounts, SELinux might return EACCES */
359 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
361 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
366 /* Stay on the same filesystem */
367 if (s.st_dev != rootdev) {
368 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
372 /* Try to detect bind mounts of the same filesystem instance; they
373 * do not differ in device major/minors. This type of query is not
374 * supported on all kernels or filesystem types though. */
375 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
376 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
381 /* Do not delete read-only files owned by root */
382 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
383 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
387 sub_path = strjoin(p, "/", dent->d_name, NULL);
393 /* Is there an item configured for this path? */
394 if (hashmap_get(items, sub_path)) {
395 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
399 if (find_glob(globs, sub_path)) {
400 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
404 if (S_ISDIR(s.st_mode)) {
407 streq(dent->d_name, "lost+found") &&
409 log_debug("Ignoring \"%s\".", sub_path);
414 log_warning("Reached max depth on \"%s\".", sub_path);
416 _cleanup_closedir_ DIR *sub_dir;
419 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
422 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
427 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
432 /* Note: if you are wondering why we don't
433 * support the sticky bit for excluding
434 * directories from cleaning like we do it for
435 * other file system objects: well, the sticky
436 * bit already has a meaning for directories,
437 * so we don't want to overload that. */
439 if (keep_this_level) {
440 log_debug("Keeping \"%s\".", sub_path);
444 /* Ignore ctime, we change it when deleting */
445 age = timespec_load(&s.st_mtim);
447 char a[FORMAT_TIMESTAMP_MAX];
448 /* Follows spelling in stat(1). */
449 log_debug("Directory \"%s\": modify time %s is too new.",
451 format_timestamp_us(a, sizeof(a), age));
455 age = timespec_load(&s.st_atim);
457 char a[FORMAT_TIMESTAMP_MAX];
458 log_debug("Directory \"%s\": access time %s is too new.",
460 format_timestamp_us(a, sizeof(a), age));
464 log_debug("Removing directory \"%s\".", sub_path);
465 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
466 if (errno != ENOENT && errno != ENOTEMPTY) {
467 log_error_errno(errno, "rmdir(%s): %m", sub_path);
472 /* Skip files for which the sticky bit is
473 * set. These are semantics we define, and are
474 * unknown elsewhere. See XDG_RUNTIME_DIR
475 * specification for details. */
476 if (s.st_mode & S_ISVTX) {
477 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
481 if (mountpoint && S_ISREG(s.st_mode))
482 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
483 streq(dent->d_name, "aquota.user") ||
484 streq(dent->d_name, "aquota.group")) {
485 log_debug("Skipping \"%s\".", sub_path);
489 /* Ignore sockets that are listed in /proc/net/unix */
490 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
491 log_debug("Skipping \"%s\": live socket.", sub_path);
495 /* Ignore device nodes */
496 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
497 log_debug("Skipping \"%s\": a device.", sub_path);
501 /* Keep files on this level around if this is
503 if (keep_this_level) {
504 log_debug("Keeping \"%s\".", sub_path);
508 age = timespec_load(&s.st_mtim);
510 char a[FORMAT_TIMESTAMP_MAX];
511 /* Follows spelling in stat(1). */
512 log_debug("File \"%s\": modify time %s is too new.",
514 format_timestamp_us(a, sizeof(a), age));
518 age = timespec_load(&s.st_atim);
520 char a[FORMAT_TIMESTAMP_MAX];
521 log_debug("File \"%s\": access time %s is too new.",
523 format_timestamp_us(a, sizeof(a), age));
527 age = timespec_load(&s.st_ctim);
529 char a[FORMAT_TIMESTAMP_MAX];
530 log_debug("File \"%s\": change time %s is too new.",
532 format_timestamp_us(a, sizeof(a), age));
536 log_debug("unlink \"%s\"", sub_path);
538 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
540 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
549 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
551 /* Restore original directory timestamps */
552 times[0] = ds->st_atim;
553 times[1] = ds->st_mtim;
555 age1 = timespec_load(&ds->st_atim);
556 age2 = timespec_load(&ds->st_mtim);
557 log_debug("Restoring access and modification time on \"%s\": %s, %s",
559 format_timestamp_us(a, sizeof(a), age1),
560 format_timestamp_us(b, sizeof(b), age2));
561 if (futimens(dirfd(d), times) < 0)
562 log_error_errno(errno, "utimensat(%s): %m", p);
568 static int path_set_perms(Item *i, const char *path) {
575 st_valid = stat(path, &st) == 0;
577 /* not using i->path directly because it may be a glob */
581 if (i->mask_perms && st_valid) {
582 if (!(st.st_mode & 0111))
584 if (!(st.st_mode & 0222))
586 if (!(st.st_mode & 0444))
588 if (!S_ISDIR(st.st_mode))
589 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
592 if (st_valid && m == (st.st_mode & 07777))
593 log_debug("\"%s\" has right mode %o", path, st.st_mode);
595 log_debug("chmod \"%s\" to mode %o", path, m);
596 if (chmod(path, m) < 0)
597 return log_error_errno(errno, "chmod(%s) failed: %m", path);
601 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
602 (i->uid_set || i->gid_set)) {
603 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
605 i->uid_set ? i->uid : UID_INVALID,
606 i->gid_set ? i->gid : GID_INVALID);
608 i->uid_set ? i->uid : UID_INVALID,
609 i->gid_set ? i->gid : GID_INVALID) < 0)
611 return log_error_errno(errno, "chown(%s) failed: %m", path);
614 return label_fix(path, false, false);
617 static int get_xattrs_from_arg(Item *i) {
627 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
628 _cleanup_free_ char *tmp = NULL, *name = NULL,
629 *value = NULL, *value2 = NULL, *_xattr = xattr;
631 r = split_pair(xattr, "=", &name, &value);
633 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
637 if (strempty(name) || strempty(value)) {
638 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
642 tmp = unquote(value, "\"");
646 value2 = cunescape(tmp);
650 if (strv_push_pair(&i->xattrs, name, value2) < 0)
652 name = value2 = NULL;
658 static int path_set_xattrs(Item *i, const char *path) {
659 char **name, **value;
664 STRV_FOREACH_PAIR(name, value, i->xattrs) {
668 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
669 if (lsetxattr(path, *name, *value, n, 0) < 0) {
670 log_error("Setting extended attribute %s=%s on %s failed: %m",
671 *name, *value, path);
678 static int get_acls_from_arg(Item *item) {
684 /* If force (= modify) is set, we will not modify the acl
685 * afterwards, so the mask can be added now if necessary. */
686 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
688 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
691 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
698 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
699 _cleanup_(acl_freep) acl_t dup = NULL;
701 _cleanup_(acl_free_charpp) char *t = NULL;
704 r = acls_for_file(path, type, acl, &dup);
708 r = calc_acl_mask_if_needed(&dup);
716 /* the mask was already added earlier if needed */
719 r = add_base_acls_if_needed(&dup, path);
723 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
724 log_debug("\"%s\": setting %s ACL \"%s\"", path,
725 type == ACL_TYPE_ACCESS ? "access" : "default",
728 r = acl_set_file(path, type, dup);
730 return log_error_errno(-errno,
731 "Setting %s ACL \"%s\" on %s failed: %m",
732 type == ACL_TYPE_ACCESS ? "access" : "default",
738 static int path_set_acls(Item *item, const char *path) {
745 if (item->acl_access) {
746 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
751 if (item->acl_default) {
752 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
761 static int write_one_file(Item *i, const char *path) {
762 _cleanup_close_ int fd = -1;
769 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
770 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
772 RUN_WITH_UMASK(0000) {
773 mac_selinux_create_file_prepare(path, S_IFREG);
774 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
775 mac_selinux_create_file_clear();
779 if (i->type == WRITE_FILE && errno == ENOENT) {
780 log_debug_errno(errno, "Not writing \"%s\": %m", path);
784 log_error_errno(errno, "Failed to create file %s: %m", path);
789 _cleanup_free_ char *unescaped;
791 log_debug("%s to \"%s\".",
792 i->type == CREATE_FILE ? "Appending" : "Writing", path);
794 unescaped = cunescape(i->argument);
798 r = loop_write(fd, unescaped, strlen(unescaped), false);
800 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
802 log_debug("\"%s\" has been created.", path);
806 if (stat(path, &st) < 0)
807 return log_error_errno(errno, "stat(%s) failed: %m", path);
809 if (!S_ISREG(st.st_mode)) {
810 log_error("%s is not a file.", path);
814 r = path_set_perms(i, path);
821 typedef int (*action_t)(Item *, const char *);
823 static int item_do_children(Item *i, const char *path, action_t action) {
824 _cleanup_closedir_ DIR *d;
830 /* This returns the first error we run into, but nevertheless
833 d = opendir_nomod(path);
835 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
838 _cleanup_free_ char *p = NULL;
845 if (errno != 0 && r == 0)
851 if (STR_IN_SET(de->d_name, ".", ".."))
854 p = strjoin(path, "/", de->d_name, NULL);
859 if (q < 0 && q != -ENOENT && r == 0)
862 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
863 q = item_do_children(i, p, action);
872 static int glob_item(Item *i, action_t action, bool recursive) {
873 _cleanup_globfree_ glob_t g = {
874 .gl_closedir = (void (*)(void *)) closedir,
875 .gl_readdir = (struct dirent *(*)(void *)) readdir,
876 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
884 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
885 if (k != 0 && k != GLOB_NOMATCH)
886 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
888 STRV_FOREACH(fn, g.gl_pathv) {
894 k = item_do_children(i, *fn, action);
908 _CREATION_MODE_INVALID = -1
911 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
912 [CREATION_NORMAL] = "Created",
913 [CREATION_EXISTING] = "Found existing",
914 [CREATION_FORCE] = "Created replacement",
917 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
919 static int create_item(Item *i) {
922 CreationMode creation;
926 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
931 case IGNORE_DIRECTORY_PATH:
933 case RECURSIVE_REMOVE_PATH:
938 r = write_one_file(i, i->path);
944 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
945 r = copy_tree(i->argument, i->path, false);
950 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
952 if (stat(i->argument, &a) < 0)
953 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
955 if (stat(i->path, &b) < 0)
956 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
958 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
959 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
964 r = path_set_perms(i, i->path);
971 r = glob_item(i, write_one_file, false);
977 case CREATE_DIRECTORY:
978 case TRUNCATE_DIRECTORY:
979 case CREATE_SUBVOLUME:
982 mkdir_parents_label(i->path, 0755);
984 if (i->type == CREATE_SUBVOLUME)
985 RUN_WITH_UMASK((~i->mode) & 0777) {
986 r = btrfs_subvol_make(i->path);
987 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
992 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
994 r = mkdir_label(i->path, i->mode);
998 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1000 if (stat(i->path, &st) < 0)
1001 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1003 if (!S_ISDIR(st.st_mode)) {
1004 log_debug("\"%s\" already exists and is not a directory.", i->path);
1008 creation = CREATION_EXISTING;
1010 creation = CREATION_NORMAL;
1011 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1013 r = path_set_perms(i, i->path);
1021 RUN_WITH_UMASK(0000) {
1022 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1023 r = mkfifo(i->path, i->mode);
1024 mac_selinux_create_file_clear();
1028 if (errno != EEXIST)
1029 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1031 if (stat(i->path, &st) < 0)
1032 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1034 if (!S_ISFIFO(st.st_mode)) {
1038 RUN_WITH_UMASK(0000) {
1039 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1040 r = mkfifo_atomic(i->path, i->mode);
1041 mac_selinux_create_file_clear();
1045 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1046 creation = CREATION_FORCE;
1048 log_debug("%s is not a fifo.", i->path);
1052 creation = CREATION_EXISTING;
1054 creation = CREATION_NORMAL;
1055 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1057 r = path_set_perms(i, i->path);
1063 case CREATE_SYMLINK:
1065 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1066 r = symlink(i->argument, i->path);
1067 mac_selinux_create_file_clear();
1070 _cleanup_free_ char *x = NULL;
1072 if (errno != EEXIST)
1073 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1075 r = readlink_malloc(i->path, &x);
1076 if (r < 0 || !streq(i->argument, x)) {
1079 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1080 r = symlink_atomic(i->argument, i->path);
1081 mac_selinux_create_file_clear();
1084 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1085 creation = CREATION_FORCE;
1087 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1091 creation = CREATION_EXISTING;
1093 creation = CREATION_NORMAL;
1094 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1098 case CREATE_BLOCK_DEVICE:
1099 case CREATE_CHAR_DEVICE: {
1102 if (have_effective_cap(CAP_MKNOD) == 0) {
1103 /* In a container we lack CAP_MKNOD. We
1104 shouldn't attempt to create the device node in
1105 that case to avoid noise, and we don't support
1106 virtualized devices in containers anyway. */
1108 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1112 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1114 RUN_WITH_UMASK(0000) {
1115 mac_selinux_create_file_prepare(i->path, file_type);
1116 r = mknod(i->path, i->mode | file_type, i->major_minor);
1117 mac_selinux_create_file_clear();
1121 if (errno == EPERM) {
1122 log_debug("We lack permissions, possibly because of cgroup configuration; "
1123 "skipping creation of device node %s.", i->path);
1127 if (errno != EEXIST)
1128 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1130 if (stat(i->path, &st) < 0)
1131 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1133 if ((st.st_mode & S_IFMT) != file_type) {
1137 RUN_WITH_UMASK(0000) {
1138 mac_selinux_create_file_prepare(i->path, file_type);
1139 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1140 mac_selinux_create_file_clear();
1144 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1145 creation = CREATION_FORCE;
1147 log_debug("%s is not a device node.", i->path);
1151 creation = CREATION_EXISTING;
1153 creation = CREATION_NORMAL;
1154 log_debug("%s %s device node \"%s\" %u:%u.",
1155 creation_mode_verb_to_string(creation),
1156 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1157 i->path, major(i->mode), minor(i->mode));
1159 r = path_set_perms(i, i->path);
1168 r = glob_item(i, path_set_perms, false);
1173 case RECURSIVE_RELABEL_PATH:
1174 r = glob_item(i, path_set_perms, true);
1180 r = glob_item(i, path_set_xattrs, false);
1185 case RECURSIVE_SET_XATTR:
1186 r = glob_item(i, path_set_xattrs, true);
1192 r = glob_item(i, path_set_acls, false);
1197 case RECURSIVE_SET_ACL:
1198 r = glob_item(i, path_set_acls, true);
1204 log_debug("%s created successfully.", i->path);
1209 static int remove_item_instance(Item *i, const char *instance) {
1217 if (remove(instance) < 0 && errno != ENOENT)
1218 return log_error_errno(errno, "rm(%s): %m", instance);
1222 case TRUNCATE_DIRECTORY:
1223 case RECURSIVE_REMOVE_PATH:
1224 /* FIXME: we probably should use dir_cleanup() here
1225 * instead of rm_rf() so that 'x' is honoured. */
1226 log_debug("rm -rf \"%s\"", instance);
1227 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1228 if (r < 0 && r != -ENOENT)
1229 return log_error_errno(r, "rm_rf(%s): %m", instance);
1234 assert_not_reached("wut?");
1240 static int remove_item(Item *i) {
1245 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1251 case CREATE_DIRECTORY:
1252 case CREATE_SUBVOLUME:
1254 case CREATE_SYMLINK:
1255 case CREATE_CHAR_DEVICE:
1256 case CREATE_BLOCK_DEVICE:
1258 case IGNORE_DIRECTORY_PATH:
1261 case RECURSIVE_RELABEL_PATH:
1265 case RECURSIVE_SET_XATTR:
1267 case RECURSIVE_SET_ACL:
1271 case TRUNCATE_DIRECTORY:
1272 case RECURSIVE_REMOVE_PATH:
1273 r = glob_item(i, remove_item_instance, false);
1280 static int clean_item_instance(Item *i, const char* instance) {
1281 _cleanup_closedir_ DIR *d = NULL;
1285 char timestamp[FORMAT_TIMESTAMP_MAX];
1292 n = now(CLOCK_REALTIME);
1296 cutoff = n - i->age;
1298 d = opendir_nomod(instance);
1300 if (errno == ENOENT || errno == ENOTDIR) {
1301 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1305 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1309 if (fstat(dirfd(d), &s) < 0)
1310 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1312 if (!S_ISDIR(s.st_mode)) {
1313 log_error("%s is not a directory.", i->path);
1317 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1318 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1320 mountpoint = s.st_dev != ps.st_dev ||
1321 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1323 log_debug("Cleanup threshold for %s \"%s\" is %s",
1324 mountpoint ? "mount point" : "directory",
1326 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1328 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1329 MAX_DEPTH, i->keep_first_level);
1332 static int clean_item(Item *i) {
1337 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1340 case CREATE_DIRECTORY:
1341 case CREATE_SUBVOLUME:
1342 case TRUNCATE_DIRECTORY:
1345 clean_item_instance(i, i->path);
1347 case IGNORE_DIRECTORY_PATH:
1348 r = glob_item(i, clean_item_instance, false);
1357 static int process_item_array(ItemArray *array);
1359 static int process_item(Item *i) {
1361 _cleanup_free_ char *prefix = NULL;
1370 prefix = malloc(strlen(i->path) + 1);
1374 PATH_FOREACH_PREFIX(prefix, i->path) {
1377 j = hashmap_get(items, prefix);
1381 s = process_item_array(j);
1382 if (s < 0 && t == 0)
1387 r = arg_create ? create_item(i) : 0;
1388 q = arg_remove ? remove_item(i) : 0;
1389 p = arg_clean ? clean_item(i) : 0;
1397 static int process_item_array(ItemArray *array) {
1403 for (n = 0; n < array->count; n++) {
1404 k = process_item(array->items + n);
1405 if (k < 0 && r == 0)
1412 static void item_free_contents(Item *i) {
1416 strv_free(i->xattrs);
1419 acl_free(i->acl_access);
1420 acl_free(i->acl_default);
1424 static void item_array_free(ItemArray *a) {
1430 for (n = 0; n < a->count; n++)
1431 item_free_contents(a->items + n);
1436 static bool item_compatible(Item *a, Item *b) {
1439 assert(streq(a->path, b->path));
1441 if (takes_ownership(a->type) && takes_ownership(b->type))
1442 /* check if the items are the same */
1443 return streq_ptr(a->argument, b->argument) &&
1445 a->uid_set == b->uid_set &&
1448 a->gid_set == b->gid_set &&
1451 a->mode_set == b->mode_set &&
1452 a->mode == b->mode &&
1454 a->age_set == b->age_set &&
1457 a->mask_perms == b->mask_perms &&
1459 a->keep_first_level == b->keep_first_level &&
1461 a->major_minor == b->major_minor;
1466 static bool should_include_path(const char *path) {
1469 STRV_FOREACH(prefix, arg_exclude_prefixes)
1470 if (path_startswith(path, *prefix)) {
1471 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1476 STRV_FOREACH(prefix, arg_include_prefixes)
1477 if (path_startswith(path, *prefix)) {
1478 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1482 /* no matches, so we should include this path only if we
1483 * have no whitelist at all */
1484 if (strv_length(arg_include_prefixes) == 0)
1487 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1491 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1493 static const Specifier specifier_table[] = {
1494 { 'm', specifier_machine_id, NULL },
1495 { 'b', specifier_boot_id, NULL },
1496 { 'H', specifier_host_name, NULL },
1497 { 'v', specifier_kernel_release, NULL },
1501 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1502 _cleanup_(item_free_contents) Item i = {};
1503 ItemArray *existing;
1506 bool force = false, boot = false;
1513 "%ms %ms %ms %ms %ms %ms %n",
1522 log_error("[%s:%u] Syntax error.", fname, line);
1526 if (isempty(action)) {
1527 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1531 for (pos = 1; action[pos]; pos++) {
1532 if (action[pos] == '!' && !boot)
1534 else if (action[pos] == '+' && !force)
1537 log_error("[%s:%u] Unknown modifiers in command '%s'",
1538 fname, line, action);
1543 if (boot && !arg_boot) {
1544 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1552 r = specifier_printf(path, specifier_table, NULL, &i.path);
1554 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1559 c += strspn(buffer+c, WHITESPACE);
1560 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1561 i.argument = unquote(buffer+c, "\"");
1571 case CREATE_DIRECTORY:
1572 case CREATE_SUBVOLUME:
1573 case TRUNCATE_DIRECTORY:
1576 case IGNORE_DIRECTORY_PATH:
1578 case RECURSIVE_REMOVE_PATH:
1581 case RECURSIVE_RELABEL_PATH:
1584 case CREATE_SYMLINK:
1586 i.argument = strappend("/usr/share/factory/", i.path);
1594 log_error("[%s:%u] Write file requires argument.", fname, line);
1601 i.argument = strappend("/usr/share/factory/", i.path);
1604 } else if (!path_is_absolute(i.argument)) {
1605 log_error("[%s:%u] Source path is not absolute.", fname, line);
1609 path_kill_slashes(i.argument);
1612 case CREATE_CHAR_DEVICE:
1613 case CREATE_BLOCK_DEVICE: {
1614 unsigned major, minor;
1617 log_error("[%s:%u] Device file requires argument.", fname, line);
1621 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1622 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1626 i.major_minor = makedev(major, minor);
1631 case RECURSIVE_SET_XATTR:
1633 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1636 r = get_xattrs_from_arg(&i);
1642 case RECURSIVE_SET_ACL:
1644 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1647 r = get_acls_from_arg(&i);
1653 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1657 if (!path_is_absolute(i.path)) {
1658 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1662 path_kill_slashes(i.path);
1664 if (!should_include_path(i.path))
1670 p = strappend(arg_root, i.path);
1678 if (user && !streq(user, "-")) {
1679 const char *u = user;
1681 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1683 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1690 if (group && !streq(group, "-")) {
1691 const char *g = group;
1693 r = get_group_creds(&g, &i.gid);
1695 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1702 if (mode && !streq(mode, "-")) {
1703 const char *mm = mode;
1707 i.mask_perms = true;
1711 if (sscanf(mm, "%o", &m) != 1) {
1712 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1719 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1722 if (age && !streq(age, "-")) {
1723 const char *a = age;
1726 i.keep_first_level = true;
1730 if (parse_sec(a, &i.age) < 0) {
1731 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1738 h = needs_glob(i.type) ? globs : items;
1740 existing = hashmap_get(h, i.path);
1744 for (n = 0; n < existing->count; n++) {
1745 if (!item_compatible(existing->items + n, &i))
1746 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1747 fname, line, i.path);
1750 existing = new0(ItemArray, 1);
1751 r = hashmap_put(h, i.path, existing);
1756 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1759 memcpy(existing->items + existing->count++, &i, sizeof(i));
1764 static void help(void) {
1765 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1766 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1767 " -h --help Show this help\n"
1768 " --version Show package version\n"
1769 " --create Create marked files/directories\n"
1770 " --clean Clean up marked directories\n"
1771 " --remove Remove marked files/directories\n"
1772 " --boot Execute actions only safe at boot\n"
1773 " --prefix=PATH Only apply rules with the specified prefix\n"
1774 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1775 " --root=PATH Operate on an alternate filesystem root\n",
1776 program_invocation_short_name);
1779 static int parse_argv(int argc, char *argv[]) {
1782 ARG_VERSION = 0x100,
1792 static const struct option options[] = {
1793 { "help", no_argument, NULL, 'h' },
1794 { "version", no_argument, NULL, ARG_VERSION },
1795 { "create", no_argument, NULL, ARG_CREATE },
1796 { "clean", no_argument, NULL, ARG_CLEAN },
1797 { "remove", no_argument, NULL, ARG_REMOVE },
1798 { "boot", no_argument, NULL, ARG_BOOT },
1799 { "prefix", required_argument, NULL, ARG_PREFIX },
1800 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1801 { "root", required_argument, NULL, ARG_ROOT },
1810 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1819 puts(PACKAGE_STRING);
1820 puts(SYSTEMD_FEATURES);
1840 if (strv_push(&arg_include_prefixes, optarg) < 0)
1844 case ARG_EXCLUDE_PREFIX:
1845 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1851 arg_root = path_make_absolute_cwd(optarg);
1855 path_kill_slashes(arg_root);
1862 assert_not_reached("Unhandled option");
1865 if (!arg_clean && !arg_create && !arg_remove) {
1866 log_error("You need to specify at least one of --clean, --create or --remove.");
1873 static int read_config_file(const char *fn, bool ignore_enoent) {
1874 _cleanup_fclose_ FILE *f = NULL;
1875 char line[LINE_MAX];
1883 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1885 if (ignore_enoent && r == -ENOENT) {
1886 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1890 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1892 log_debug("Reading config file \"%s\".", fn);
1894 FOREACH_LINE(line, f, break) {
1901 if (*l == '#' || *l == 0)
1904 k = parse_line(fn, v, l);
1905 if (k < 0 && r == 0)
1909 /* we have to determine age parameter for each entry of type X */
1910 HASHMAP_FOREACH(i, globs, iterator) {
1912 Item *j, *candidate_item = NULL;
1914 if (i->type != IGNORE_DIRECTORY_PATH)
1917 HASHMAP_FOREACH(j, items, iter) {
1918 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1921 if (path_equal(j->path, i->path)) {
1926 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1927 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1931 if (candidate_item && candidate_item->age_set) {
1932 i->age = candidate_item->age;
1938 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1946 int main(int argc, char *argv[]) {
1951 r = parse_argv(argc, argv);
1955 log_set_target(LOG_TARGET_AUTO);
1956 log_parse_environment();
1961 mac_selinux_init(NULL);
1963 items = hashmap_new(&string_hash_ops);
1964 globs = hashmap_new(&string_hash_ops);
1966 if (!items || !globs) {
1973 if (optind < argc) {
1976 for (j = optind; j < argc; j++) {
1977 k = read_config_file(argv[j], false);
1978 if (k < 0 && r == 0)
1983 _cleanup_strv_free_ char **files = NULL;
1986 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1988 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1992 STRV_FOREACH(f, files) {
1993 k = read_config_file(*f, true);
1994 if (k < 0 && r == 0)
1999 HASHMAP_FOREACH(a, globs, iterator) {
2000 k = process_item_array(a);
2001 if (k < 0 && r == 0)
2005 HASHMAP_FOREACH(a, items, iterator) {
2006 k = process_item_array(a);
2007 if (k < 0 && r == 0)
2012 while ((a = hashmap_steal_first(items)))
2015 while ((a = hashmap_steal_first(globs)))
2018 hashmap_free(items);
2019 hashmap_free(globs);
2021 free(arg_include_prefixes);
2022 free(arg_exclude_prefixes);
2025 set_free_free(unix_sockets);
2027 mac_selinux_finish();
2029 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;