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>
46 #include "path-util.h"
50 #include "conf-files.h"
51 #include "capability.h"
52 #include "specifier.h"
55 #include "selinux-util.h"
56 #include "btrfs-util.h"
59 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
60 * them in the file system. This is intended to be used to create
61 * properly owned directories beneath /tmp, /var/tmp, /run, which are
62 * volatile and hence need to be recreated on bootup. */
64 typedef enum ItemType {
65 /* These ones take file names */
68 CREATE_DIRECTORY = 'd',
69 TRUNCATE_DIRECTORY = 'D',
70 CREATE_SUBVOLUME = 'v',
73 CREATE_CHAR_DEVICE = 'c',
74 CREATE_BLOCK_DEVICE = 'b',
77 /* These ones take globs */
79 RECURSIVE_SET_XATTR = 'T',
81 RECURSIVE_SET_ACL = 'A',
84 IGNORE_DIRECTORY_PATH = 'X',
86 RECURSIVE_REMOVE_PATH = 'R',
87 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
89 RECURSIVE_RELABEL_PATH = 'Z',
91 RECURSIVE_SET_ATTRIB = 'H',
110 unsigned long attrib_value;
111 unsigned long attrib_mask;
120 bool keep_first_level:1;
127 typedef struct ItemArray {
133 static bool arg_create = false;
134 static bool arg_clean = false;
135 static bool arg_remove = false;
136 static bool arg_boot = false;
138 static char **arg_include_prefixes = NULL;
139 static char **arg_exclude_prefixes = NULL;
140 static char *arg_root = NULL;
142 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
144 #define MAX_DEPTH 256
146 static Hashmap *items = NULL, *globs = NULL;
147 static Set *unix_sockets = NULL;
149 static bool needs_glob(ItemType t) {
153 IGNORE_DIRECTORY_PATH,
155 RECURSIVE_REMOVE_PATH,
158 RECURSIVE_RELABEL_PATH,
165 static bool takes_ownership(ItemType t) {
179 IGNORE_DIRECTORY_PATH,
181 RECURSIVE_REMOVE_PATH);
184 static struct Item* find_glob(Hashmap *h, const char *match) {
188 HASHMAP_FOREACH(j, h, i) {
191 for (n = 0; n < j->count; n++) {
192 Item *item = j->items + n;
194 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
202 static void load_unix_sockets(void) {
203 _cleanup_fclose_ FILE *f = NULL;
209 /* We maintain a cache of the sockets we found in
210 * /proc/net/unix to speed things up a little. */
212 unix_sockets = set_new(&string_hash_ops);
216 f = fopen("/proc/net/unix", "re");
221 if (!fgets(line, sizeof(line), f))
228 if (!fgets(line, sizeof(line), f))
233 p = strchr(line, ':');
241 p += strspn(p, WHITESPACE);
242 p += strcspn(p, WHITESPACE); /* skip one more word */
243 p += strspn(p, WHITESPACE);
252 path_kill_slashes(s);
254 k = set_consume(unix_sockets, s);
255 if (k < 0 && k != -EEXIST)
262 set_free_free(unix_sockets);
266 static bool unix_socket_alive(const char *fn) {
272 return !!set_get(unix_sockets, (char*) fn);
274 /* We don't know, so assume yes */
278 static int dir_is_mount_point(DIR *d, const char *subdir) {
280 union file_handle_union h = FILE_HANDLE_INIT;
281 int mount_id_parent, mount_id;
284 r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
288 h.handle.handle_bytes = MAX_HANDLE_SZ;
289 r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
293 /* got no handle; make no assumptions, return error */
294 if (r_p < 0 && r < 0)
297 /* got both handles; if they differ, it is a mount point */
298 if (r_p >= 0 && r >= 0)
299 return mount_id_parent != mount_id;
301 /* got only one handle; assume different mount points if one
302 * of both queries was not supported by the filesystem */
303 if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
312 static DIR* xopendirat_nomod(int dirfd, const char *path) {
315 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
319 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
323 dir = xopendirat(dirfd, path, O_NOFOLLOW);
325 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
330 static DIR* opendir_nomod(const char *path) {
331 return xopendirat_nomod(AT_FDCWD, path);
334 static int dir_cleanup(
338 const struct stat *ds,
343 bool keep_this_level) {
346 struct timespec times[2];
347 bool deleted = false;
350 while ((dent = readdir(d))) {
353 _cleanup_free_ char *sub_path = NULL;
355 if (STR_IN_SET(dent->d_name, ".", ".."))
358 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
362 /* FUSE, NFS mounts, SELinux might return EACCES */
364 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
366 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
371 /* Stay on the same filesystem */
372 if (s.st_dev != rootdev) {
373 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
377 /* Try to detect bind mounts of the same filesystem instance; they
378 * do not differ in device major/minors. This type of query is not
379 * supported on all kernels or filesystem types though. */
380 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
381 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
386 /* Do not delete read-only files owned by root */
387 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
388 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
392 sub_path = strjoin(p, "/", dent->d_name, NULL);
398 /* Is there an item configured for this path? */
399 if (hashmap_get(items, sub_path)) {
400 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
404 if (find_glob(globs, sub_path)) {
405 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
409 if (S_ISDIR(s.st_mode)) {
412 streq(dent->d_name, "lost+found") &&
414 log_debug("Ignoring \"%s\".", sub_path);
419 log_warning("Reached max depth on \"%s\".", sub_path);
421 _cleanup_closedir_ DIR *sub_dir;
424 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
427 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
432 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
437 /* Note: if you are wondering why we don't
438 * support the sticky bit for excluding
439 * directories from cleaning like we do it for
440 * other file system objects: well, the sticky
441 * bit already has a meaning for directories,
442 * so we don't want to overload that. */
444 if (keep_this_level) {
445 log_debug("Keeping \"%s\".", sub_path);
449 /* Ignore ctime, we change it when deleting */
450 age = timespec_load(&s.st_mtim);
452 char a[FORMAT_TIMESTAMP_MAX];
453 /* Follows spelling in stat(1). */
454 log_debug("Directory \"%s\": modify time %s is too new.",
456 format_timestamp_us(a, sizeof(a), age));
460 age = timespec_load(&s.st_atim);
462 char a[FORMAT_TIMESTAMP_MAX];
463 log_debug("Directory \"%s\": access time %s is too new.",
465 format_timestamp_us(a, sizeof(a), age));
469 log_debug("Removing directory \"%s\".", sub_path);
470 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
471 if (errno != ENOENT && errno != ENOTEMPTY) {
472 log_error_errno(errno, "rmdir(%s): %m", sub_path);
477 /* Skip files for which the sticky bit is
478 * set. These are semantics we define, and are
479 * unknown elsewhere. See XDG_RUNTIME_DIR
480 * specification for details. */
481 if (s.st_mode & S_ISVTX) {
482 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
486 if (mountpoint && S_ISREG(s.st_mode))
487 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
488 streq(dent->d_name, "aquota.user") ||
489 streq(dent->d_name, "aquota.group")) {
490 log_debug("Skipping \"%s\".", sub_path);
494 /* Ignore sockets that are listed in /proc/net/unix */
495 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
496 log_debug("Skipping \"%s\": live socket.", sub_path);
500 /* Ignore device nodes */
501 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
502 log_debug("Skipping \"%s\": a device.", sub_path);
506 /* Keep files on this level around if this is
508 if (keep_this_level) {
509 log_debug("Keeping \"%s\".", sub_path);
513 age = timespec_load(&s.st_mtim);
515 char a[FORMAT_TIMESTAMP_MAX];
516 /* Follows spelling in stat(1). */
517 log_debug("File \"%s\": modify time %s is too new.",
519 format_timestamp_us(a, sizeof(a), age));
523 age = timespec_load(&s.st_atim);
525 char a[FORMAT_TIMESTAMP_MAX];
526 log_debug("File \"%s\": access time %s is too new.",
528 format_timestamp_us(a, sizeof(a), age));
532 age = timespec_load(&s.st_ctim);
534 char a[FORMAT_TIMESTAMP_MAX];
535 log_debug("File \"%s\": change time %s is too new.",
537 format_timestamp_us(a, sizeof(a), age));
541 log_debug("unlink \"%s\"", sub_path);
543 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
545 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
554 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
556 /* Restore original directory timestamps */
557 times[0] = ds->st_atim;
558 times[1] = ds->st_mtim;
560 age1 = timespec_load(&ds->st_atim);
561 age2 = timespec_load(&ds->st_mtim);
562 log_debug("Restoring access and modification time on \"%s\": %s, %s",
564 format_timestamp_us(a, sizeof(a), age1),
565 format_timestamp_us(b, sizeof(b), age2));
566 if (futimens(dirfd(d), times) < 0)
567 log_error_errno(errno, "utimensat(%s): %m", p);
573 static int path_set_perms(Item *i, const char *path) {
580 st_valid = stat(path, &st) == 0;
582 /* not using i->path directly because it may be a glob */
586 if (i->mask_perms && st_valid) {
587 if (!(st.st_mode & 0111))
589 if (!(st.st_mode & 0222))
591 if (!(st.st_mode & 0444))
593 if (!S_ISDIR(st.st_mode))
594 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
597 if (st_valid && m == (st.st_mode & 07777))
598 log_debug("\"%s\" has right mode %o", path, st.st_mode);
600 log_debug("chmod \"%s\" to mode %o", path, m);
601 if (chmod(path, m) < 0)
602 return log_error_errno(errno, "chmod(%s) failed: %m", path);
606 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
607 (i->uid_set || i->gid_set)) {
608 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
610 i->uid_set ? i->uid : UID_INVALID,
611 i->gid_set ? i->gid : GID_INVALID);
613 i->uid_set ? i->uid : UID_INVALID,
614 i->gid_set ? i->gid : GID_INVALID) < 0)
616 return log_error_errno(errno, "chown(%s) failed: %m", path);
619 return label_fix(path, false, false);
622 static int get_xattrs_from_arg(Item *i) {
632 _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL;
634 r = unquote_first_word(&p, &xattr, UNQUOTE_CUNESCAPE);
636 log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", p);
640 r = split_pair(xattr, "=", &name, &value);
642 log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr);
646 if (isempty(name) || isempty(value)) {
647 log_warning("Malformed xattr found, ignoring: %s", xattr);
651 if (strv_push_pair(&i->xattrs, name, value) < 0)
660 static int path_set_xattrs(Item *i, const char *path) {
661 char **name, **value;
666 STRV_FOREACH_PAIR(name, value, i->xattrs) {
670 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
671 if (lsetxattr(path, *name, *value, n, 0) < 0) {
672 log_error("Setting extended attribute %s=%s on %s failed: %m",
673 *name, *value, path);
680 static int get_acls_from_arg(Item *item) {
686 /* If force (= modify) is set, we will not modify the acl
687 * afterwards, so the mask can be added now if necessary. */
688 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
690 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument);
692 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
699 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
700 _cleanup_(acl_freep) acl_t dup = NULL;
702 _cleanup_(acl_free_charpp) char *t = NULL;
704 /* Returns 0 for success, positive error if already warned,
705 * negative error otherwise. */
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",
743 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);
752 if (r == 0 && item->acl_default)
753 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
756 return -r; /* already warned */
757 else if (r == -EOPNOTSUPP) {
758 log_debug_errno(r, "ACLs not supported by file system at %s", path);
761 log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
766 #define ALL_ATTRIBS \
775 FS_JOURNAL_DATA_FL | \
782 static int get_attrib_from_arg(Item *item) {
783 static const unsigned attributes[] = {
784 [(uint8_t)'A'] = FS_NOATIME_FL, /* do not update atime */
785 [(uint8_t)'S'] = FS_SYNC_FL, /* Synchronous updates */
786 [(uint8_t)'D'] = FS_DIRSYNC_FL, /* dirsync behaviour (directories only) */
787 [(uint8_t)'a'] = FS_APPEND_FL, /* writes to file may only append */
788 [(uint8_t)'c'] = FS_COMPR_FL, /* Compress file */
789 [(uint8_t)'d'] = FS_NODUMP_FL, /* do not dump file */
790 [(uint8_t)'e'] = FS_EXTENT_FL, /* Top of directory hierarchies*/
791 [(uint8_t)'i'] = FS_IMMUTABLE_FL, /* Immutable file */
792 [(uint8_t)'j'] = FS_JOURNAL_DATA_FL, /* Reserved for ext3 */
793 [(uint8_t)'s'] = FS_SECRM_FL, /* Secure deletion */
794 [(uint8_t)'u'] = FS_UNRM_FL, /* Undelete */
795 [(uint8_t)'t'] = FS_NOTAIL_FL, /* file tail should not be merged */
796 [(uint8_t)'T'] = FS_TOPDIR_FL, /* Top of directory hierarchies*/
797 [(uint8_t)'C'] = FS_NOCOW_FL, /* Do not cow file */
799 char *p = item->argument;
805 unsigned long value = 0, mask = 0;
808 log_error("\"%s\": setting ATTR need an argument", item->path);
815 } else if (*p == '-') {
818 } else if (*p == '=') {
823 if (!*p && mode != MODE_SET) {
824 log_error("\"%s\": setting ATTR: argument is empty", item->path);
828 if ((uint8_t)*p >= ELEMENTSOF(attributes) || attributes[(uint8_t)*p] == 0) {
829 log_error("\"%s\": setting ATTR: unknown attr '%c'", item->path, *p);
832 if (mode == MODE_ADD || mode == MODE_SET)
833 value |= attributes[(uint8_t)*p];
835 value &= ~attributes[(uint8_t)*p];
836 mask |= attributes[(uint8_t)*p];
839 if (mode == MODE_SET)
844 item->attrib_mask = mask;
845 item->attrib_value = value;
846 item->attrib_set = true;
852 static int path_set_attrib(Item *item, const char *path) {
853 _cleanup_close_ int fd = -1;
859 if (item->attrib_mask == 0 || !item->attrib_set)
862 * It is OK to ignore an lstat() error, because the error
863 * will be catch by the open() below anyway
865 if (lstat(path, &st) == 0 &&
866 !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
870 fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
873 return log_error_errno(errno, "Cannot open \"%s\": %m", path);
875 f = item->attrib_value & item->attrib_mask;
876 if (!S_ISDIR(st.st_mode))
878 r = change_attr_fd(fd, f, item->attrib_mask);
880 return log_error_errno(errno,
881 "Cannot set attrib for \"%s\", value=0x%08lx, mask=0x%08lx: %m",
882 path, item->attrib_value, item->attrib_mask);
887 static int write_one_file(Item *i, const char *path) {
888 _cleanup_close_ int fd = -1;
895 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
896 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
898 RUN_WITH_UMASK(0000) {
899 mac_selinux_create_file_prepare(path, S_IFREG);
900 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
901 mac_selinux_create_file_clear();
905 if (i->type == WRITE_FILE && errno == ENOENT) {
906 log_debug_errno(errno, "Not writing \"%s\": %m", path);
910 log_error_errno(errno, "Failed to create file %s: %m", path);
915 _cleanup_free_ char *unescaped;
917 log_debug("%s to \"%s\".", i->type == CREATE_FILE ? "Appending" : "Writing", path);
919 unescaped = cunescape(i->argument);
923 r = loop_write(fd, unescaped, strlen(unescaped), false);
925 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
927 log_debug("\"%s\" has been created.", path);
931 if (stat(path, &st) < 0)
932 return log_error_errno(errno, "stat(%s) failed: %m", path);
934 if (!S_ISREG(st.st_mode)) {
935 log_error("%s is not a file.", path);
939 r = path_set_perms(i, path);
946 typedef int (*action_t)(Item *, const char *);
948 static int item_do_children(Item *i, const char *path, action_t action) {
949 _cleanup_closedir_ DIR *d;
955 /* This returns the first error we run into, but nevertheless
958 d = opendir_nomod(path);
960 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
963 _cleanup_free_ char *p = NULL;
970 if (errno != 0 && r == 0)
976 if (STR_IN_SET(de->d_name, ".", ".."))
979 p = strjoin(path, "/", de->d_name, NULL);
984 if (q < 0 && q != -ENOENT && r == 0)
987 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
988 q = item_do_children(i, p, action);
997 static int glob_item(Item *i, action_t action, bool recursive) {
998 _cleanup_globfree_ glob_t g = {
999 .gl_closedir = (void (*)(void *)) closedir,
1000 .gl_readdir = (struct dirent *(*)(void *)) readdir,
1001 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
1009 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
1010 if (k != 0 && k != GLOB_NOMATCH)
1011 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
1013 STRV_FOREACH(fn, g.gl_pathv) {
1015 if (k < 0 && r == 0)
1019 k = item_do_children(i, *fn, action);
1020 if (k < 0 && r == 0)
1033 _CREATION_MODE_INVALID = -1
1036 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
1037 [CREATION_NORMAL] = "Created",
1038 [CREATION_EXISTING] = "Found existing",
1039 [CREATION_FORCE] = "Created replacement",
1042 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
1044 static int create_item(Item *i) {
1047 CreationMode creation;
1051 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
1056 case IGNORE_DIRECTORY_PATH:
1058 case RECURSIVE_REMOVE_PATH:
1063 r = write_one_file(i, i->path);
1069 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1070 r = copy_tree(i->argument, i->path, false);
1075 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1077 if (stat(i->argument, &a) < 0)
1078 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
1080 if (stat(i->path, &b) < 0)
1081 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1083 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
1084 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1089 r = path_set_perms(i, i->path);
1096 r = glob_item(i, write_one_file, false);
1102 case CREATE_DIRECTORY:
1103 case TRUNCATE_DIRECTORY:
1104 case CREATE_SUBVOLUME:
1106 RUN_WITH_UMASK(0000)
1107 mkdir_parents_label(i->path, 0755);
1109 if (i->type == CREATE_SUBVOLUME)
1110 RUN_WITH_UMASK((~i->mode) & 0777) {
1111 r = btrfs_subvol_make(i->path);
1112 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
1117 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
1118 RUN_WITH_UMASK(0000)
1119 r = mkdir_label(i->path, i->mode);
1123 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1125 if (stat(i->path, &st) < 0)
1126 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1128 if (!S_ISDIR(st.st_mode)) {
1129 log_debug("\"%s\" already exists and is not a directory.", i->path);
1133 creation = CREATION_EXISTING;
1135 creation = CREATION_NORMAL;
1136 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1138 r = path_set_perms(i, i->path);
1146 RUN_WITH_UMASK(0000) {
1147 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1148 r = mkfifo(i->path, i->mode);
1149 mac_selinux_create_file_clear();
1153 if (errno != EEXIST)
1154 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1156 if (stat(i->path, &st) < 0)
1157 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1159 if (!S_ISFIFO(st.st_mode)) {
1163 RUN_WITH_UMASK(0000) {
1164 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1165 r = mkfifo_atomic(i->path, i->mode);
1166 mac_selinux_create_file_clear();
1170 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1171 creation = CREATION_FORCE;
1173 log_debug("%s is not a fifo.", i->path);
1177 creation = CREATION_EXISTING;
1179 creation = CREATION_NORMAL;
1180 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1182 r = path_set_perms(i, i->path);
1188 case CREATE_SYMLINK:
1190 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1191 r = symlink(i->argument, i->path);
1192 mac_selinux_create_file_clear();
1195 _cleanup_free_ char *x = NULL;
1197 if (errno != EEXIST)
1198 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1200 r = readlink_malloc(i->path, &x);
1201 if (r < 0 || !streq(i->argument, x)) {
1204 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1205 r = symlink_atomic(i->argument, i->path);
1206 mac_selinux_create_file_clear();
1209 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1210 creation = CREATION_FORCE;
1212 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1216 creation = CREATION_EXISTING;
1218 creation = CREATION_NORMAL;
1219 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1223 case CREATE_BLOCK_DEVICE:
1224 case CREATE_CHAR_DEVICE: {
1227 if (have_effective_cap(CAP_MKNOD) == 0) {
1228 /* In a container we lack CAP_MKNOD. We
1229 shouldn't attempt to create the device node in
1230 that case to avoid noise, and we don't support
1231 virtualized devices in containers anyway. */
1233 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1237 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1239 RUN_WITH_UMASK(0000) {
1240 mac_selinux_create_file_prepare(i->path, file_type);
1241 r = mknod(i->path, i->mode | file_type, i->major_minor);
1242 mac_selinux_create_file_clear();
1246 if (errno == EPERM) {
1247 log_debug("We lack permissions, possibly because of cgroup configuration; "
1248 "skipping creation of device node %s.", i->path);
1252 if (errno != EEXIST)
1253 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1255 if (stat(i->path, &st) < 0)
1256 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1258 if ((st.st_mode & S_IFMT) != file_type) {
1262 RUN_WITH_UMASK(0000) {
1263 mac_selinux_create_file_prepare(i->path, file_type);
1264 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1265 mac_selinux_create_file_clear();
1269 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1270 creation = CREATION_FORCE;
1272 log_debug("%s is not a device node.", i->path);
1276 creation = CREATION_EXISTING;
1278 creation = CREATION_NORMAL;
1279 log_debug("%s %s device node \"%s\" %u:%u.",
1280 creation_mode_verb_to_string(creation),
1281 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1282 i->path, major(i->mode), minor(i->mode));
1284 r = path_set_perms(i, i->path);
1293 r = glob_item(i, path_set_perms, false);
1298 case RECURSIVE_RELABEL_PATH:
1299 r = glob_item(i, path_set_perms, true);
1305 r = glob_item(i, path_set_xattrs, false);
1310 case RECURSIVE_SET_XATTR:
1311 r = glob_item(i, path_set_xattrs, true);
1317 r = glob_item(i, path_set_acls, false);
1322 case RECURSIVE_SET_ACL:
1323 r = glob_item(i, path_set_acls, true);
1329 r = glob_item(i, path_set_attrib, false);
1334 case RECURSIVE_SET_ATTRIB:
1335 r = glob_item(i, path_set_attrib, true);
1344 static int remove_item_instance(Item *i, const char *instance) {
1352 if (remove(instance) < 0 && errno != ENOENT)
1353 return log_error_errno(errno, "rm(%s): %m", instance);
1357 case TRUNCATE_DIRECTORY:
1358 case RECURSIVE_REMOVE_PATH:
1359 /* FIXME: we probably should use dir_cleanup() here
1360 * instead of rm_rf() so that 'x' is honoured. */
1361 log_debug("rm -rf \"%s\"", instance);
1362 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1363 if (r < 0 && r != -ENOENT)
1364 return log_error_errno(r, "rm_rf(%s): %m", instance);
1369 assert_not_reached("wut?");
1375 static int remove_item(Item *i) {
1380 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1386 case CREATE_DIRECTORY:
1387 case CREATE_SUBVOLUME:
1389 case CREATE_SYMLINK:
1390 case CREATE_CHAR_DEVICE:
1391 case CREATE_BLOCK_DEVICE:
1393 case IGNORE_DIRECTORY_PATH:
1396 case RECURSIVE_RELABEL_PATH:
1400 case RECURSIVE_SET_XATTR:
1402 case RECURSIVE_SET_ACL:
1404 case RECURSIVE_SET_ATTRIB:
1408 case TRUNCATE_DIRECTORY:
1409 case RECURSIVE_REMOVE_PATH:
1410 r = glob_item(i, remove_item_instance, false);
1417 static int clean_item_instance(Item *i, const char* instance) {
1418 _cleanup_closedir_ DIR *d = NULL;
1422 char timestamp[FORMAT_TIMESTAMP_MAX];
1429 n = now(CLOCK_REALTIME);
1433 cutoff = n - i->age;
1435 d = opendir_nomod(instance);
1437 if (errno == ENOENT || errno == ENOTDIR) {
1438 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1442 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1446 if (fstat(dirfd(d), &s) < 0)
1447 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1449 if (!S_ISDIR(s.st_mode)) {
1450 log_error("%s is not a directory.", i->path);
1454 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1455 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1457 mountpoint = s.st_dev != ps.st_dev ||
1458 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1460 log_debug("Cleanup threshold for %s \"%s\" is %s",
1461 mountpoint ? "mount point" : "directory",
1463 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1465 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1466 MAX_DEPTH, i->keep_first_level);
1469 static int clean_item(Item *i) {
1474 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1477 case CREATE_DIRECTORY:
1478 case CREATE_SUBVOLUME:
1479 case TRUNCATE_DIRECTORY:
1482 clean_item_instance(i, i->path);
1484 case IGNORE_DIRECTORY_PATH:
1485 r = glob_item(i, clean_item_instance, false);
1494 static int process_item_array(ItemArray *array);
1496 static int process_item(Item *i) {
1498 _cleanup_free_ char *prefix = NULL;
1507 prefix = malloc(strlen(i->path) + 1);
1511 PATH_FOREACH_PREFIX(prefix, i->path) {
1514 j = hashmap_get(items, prefix);
1518 s = process_item_array(j);
1519 if (s < 0 && t == 0)
1524 r = arg_create ? create_item(i) : 0;
1525 q = arg_remove ? remove_item(i) : 0;
1526 p = arg_clean ? clean_item(i) : 0;
1534 static int process_item_array(ItemArray *array) {
1540 for (n = 0; n < array->count; n++) {
1541 k = process_item(array->items + n);
1542 if (k < 0 && r == 0)
1549 static void item_free_contents(Item *i) {
1553 strv_free(i->xattrs);
1556 acl_free(i->acl_access);
1557 acl_free(i->acl_default);
1561 static void item_array_free(ItemArray *a) {
1567 for (n = 0; n < a->count; n++)
1568 item_free_contents(a->items + n);
1573 static bool item_compatible(Item *a, Item *b) {
1576 assert(streq(a->path, b->path));
1578 if (takes_ownership(a->type) && takes_ownership(b->type))
1579 /* check if the items are the same */
1580 return streq_ptr(a->argument, b->argument) &&
1582 a->uid_set == b->uid_set &&
1585 a->gid_set == b->gid_set &&
1588 a->mode_set == b->mode_set &&
1589 a->mode == b->mode &&
1591 a->age_set == b->age_set &&
1594 a->mask_perms == b->mask_perms &&
1596 a->keep_first_level == b->keep_first_level &&
1598 a->major_minor == b->major_minor;
1603 static bool should_include_path(const char *path) {
1606 STRV_FOREACH(prefix, arg_exclude_prefixes)
1607 if (path_startswith(path, *prefix)) {
1608 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1613 STRV_FOREACH(prefix, arg_include_prefixes)
1614 if (path_startswith(path, *prefix)) {
1615 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1619 /* no matches, so we should include this path only if we
1620 * have no whitelist at all */
1621 if (strv_length(arg_include_prefixes) == 0)
1624 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1628 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1630 static const Specifier specifier_table[] = {
1631 { 'm', specifier_machine_id, NULL },
1632 { 'b', specifier_boot_id, NULL },
1633 { 'H', specifier_host_name, NULL },
1634 { 'v', specifier_kernel_release, NULL },
1638 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1639 _cleanup_(item_free_contents) Item i = {};
1640 ItemArray *existing;
1643 bool force = false, boot = false;
1649 r = unquote_many_words(
1660 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1662 log_error("[%s:%u] Syntax error.", fname, line);
1666 if (!isempty(buffer)) {
1667 i.argument = strdup(buffer);
1672 if (isempty(action)) {
1673 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1677 for (pos = 1; action[pos]; pos++) {
1678 if (action[pos] == '!' && !boot)
1680 else if (action[pos] == '+' && !force)
1683 log_error("[%s:%u] Unknown modifiers in command '%s'",
1684 fname, line, action);
1689 if (boot && !arg_boot) {
1690 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1698 r = specifier_printf(path, specifier_table, NULL, &i.path);
1700 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1708 case CREATE_DIRECTORY:
1709 case CREATE_SUBVOLUME:
1710 case TRUNCATE_DIRECTORY:
1713 case IGNORE_DIRECTORY_PATH:
1715 case RECURSIVE_REMOVE_PATH:
1718 case RECURSIVE_RELABEL_PATH:
1721 case CREATE_SYMLINK:
1723 i.argument = strappend("/usr/share/factory/", i.path);
1731 log_error("[%s:%u] Write file requires argument.", fname, line);
1738 i.argument = strappend("/usr/share/factory/", i.path);
1741 } else if (!path_is_absolute(i.argument)) {
1742 log_error("[%s:%u] Source path is not absolute.", fname, line);
1746 path_kill_slashes(i.argument);
1749 case CREATE_CHAR_DEVICE:
1750 case CREATE_BLOCK_DEVICE: {
1751 unsigned major, minor;
1754 log_error("[%s:%u] Device file requires argument.", fname, line);
1758 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1759 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1763 i.major_minor = makedev(major, minor);
1768 case RECURSIVE_SET_XATTR:
1770 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1773 r = get_xattrs_from_arg(&i);
1779 case RECURSIVE_SET_ACL:
1781 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1784 r = get_acls_from_arg(&i);
1790 case RECURSIVE_SET_ATTRIB:
1792 log_error("[%s:%u] Set attrib requires argument.", fname, line);
1795 r = get_attrib_from_arg(&i);
1801 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1805 if (!path_is_absolute(i.path)) {
1806 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1810 path_kill_slashes(i.path);
1812 if (!should_include_path(i.path))
1818 p = strappend(arg_root, i.path);
1826 if (user && !streq(user, "-")) {
1827 const char *u = user;
1829 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1831 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1838 if (group && !streq(group, "-")) {
1839 const char *g = group;
1841 r = get_group_creds(&g, &i.gid);
1843 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1850 if (mode && !streq(mode, "-")) {
1851 const char *mm = mode;
1855 i.mask_perms = true;
1859 if (sscanf(mm, "%o", &m) != 1) {
1860 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1867 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1870 if (age && !streq(age, "-")) {
1871 const char *a = age;
1874 i.keep_first_level = true;
1878 if (parse_sec(a, &i.age) < 0) {
1879 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1886 h = needs_glob(i.type) ? globs : items;
1888 existing = hashmap_get(h, i.path);
1892 for (n = 0; n < existing->count; n++) {
1893 if (!item_compatible(existing->items + n, &i)) {
1894 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1895 fname, line, i.path);
1900 existing = new0(ItemArray, 1);
1901 r = hashmap_put(h, i.path, existing);
1906 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1909 memcpy(existing->items + existing->count++, &i, sizeof(i));
1914 static void help(void) {
1915 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1916 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1917 " -h --help Show this help\n"
1918 " --version Show package version\n"
1919 " --create Create marked files/directories\n"
1920 " --clean Clean up marked directories\n"
1921 " --remove Remove marked files/directories\n"
1922 " --boot Execute actions only safe at boot\n"
1923 " --prefix=PATH Only apply rules with the specified prefix\n"
1924 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1925 " --root=PATH Operate on an alternate filesystem root\n",
1926 program_invocation_short_name);
1929 static int parse_argv(int argc, char *argv[]) {
1932 ARG_VERSION = 0x100,
1942 static const struct option options[] = {
1943 { "help", no_argument, NULL, 'h' },
1944 { "version", no_argument, NULL, ARG_VERSION },
1945 { "create", no_argument, NULL, ARG_CREATE },
1946 { "clean", no_argument, NULL, ARG_CLEAN },
1947 { "remove", no_argument, NULL, ARG_REMOVE },
1948 { "boot", no_argument, NULL, ARG_BOOT },
1949 { "prefix", required_argument, NULL, ARG_PREFIX },
1950 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1951 { "root", required_argument, NULL, ARG_ROOT },
1960 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1969 puts(PACKAGE_STRING);
1970 puts(SYSTEMD_FEATURES);
1990 if (strv_push(&arg_include_prefixes, optarg) < 0)
1994 case ARG_EXCLUDE_PREFIX:
1995 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
2001 arg_root = path_make_absolute_cwd(optarg);
2005 path_kill_slashes(arg_root);
2012 assert_not_reached("Unhandled option");
2015 if (!arg_clean && !arg_create && !arg_remove) {
2016 log_error("You need to specify at least one of --clean, --create or --remove.");
2023 static int read_config_file(const char *fn, bool ignore_enoent) {
2024 _cleanup_fclose_ FILE *f = NULL;
2025 char line[LINE_MAX];
2033 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
2035 if (ignore_enoent && r == -ENOENT) {
2036 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
2040 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
2042 log_debug("Reading config file \"%s\".", fn);
2044 FOREACH_LINE(line, f, break) {
2051 if (*l == '#' || *l == 0)
2054 k = parse_line(fn, v, l);
2055 if (k < 0 && r == 0)
2059 /* we have to determine age parameter for each entry of type X */
2060 HASHMAP_FOREACH(i, globs, iterator) {
2062 Item *j, *candidate_item = NULL;
2064 if (i->type != IGNORE_DIRECTORY_PATH)
2067 HASHMAP_FOREACH(j, items, iter) {
2068 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
2071 if (path_equal(j->path, i->path)) {
2076 if ((!candidate_item && path_startswith(i->path, j->path)) ||
2077 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
2081 if (candidate_item && candidate_item->age_set) {
2082 i->age = candidate_item->age;
2088 log_error_errno(errno, "Failed to read from file %s: %m", fn);
2096 int main(int argc, char *argv[]) {
2101 r = parse_argv(argc, argv);
2105 log_set_target(LOG_TARGET_AUTO);
2106 log_parse_environment();
2111 mac_selinux_init(NULL);
2113 items = hashmap_new(&string_hash_ops);
2114 globs = hashmap_new(&string_hash_ops);
2116 if (!items || !globs) {
2123 if (optind < argc) {
2126 for (j = optind; j < argc; j++) {
2127 k = read_config_file(argv[j], false);
2128 if (k < 0 && r == 0)
2133 _cleanup_strv_free_ char **files = NULL;
2136 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
2138 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
2142 STRV_FOREACH(f, files) {
2143 k = read_config_file(*f, true);
2144 if (k < 0 && r == 0)
2149 HASHMAP_FOREACH(a, globs, iterator) {
2150 k = process_item_array(a);
2151 if (k < 0 && r == 0)
2155 HASHMAP_FOREACH(a, items, iterator) {
2156 k = process_item_array(a);
2157 if (k < 0 && r == 0)
2162 while ((a = hashmap_steal_first(items)))
2165 while ((a = hashmap_steal_first(globs)))
2168 hashmap_free(items);
2169 hashmap_free(globs);
2171 free(arg_include_prefixes);
2172 free(arg_exclude_prefixes);
2175 set_free_free(unix_sockets);
2177 mac_selinux_finish();
2179 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;