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
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
37 #include <sys/types.h>
38 #include <sys/param.h>
45 #include "path-util.h"
49 #include "conf-files.h"
51 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
52 * them in the file system. This is intended to be used to create
53 * properly owned directories beneath /tmp, /var/tmp, /run, which are
54 * volatile and hence need to be recreated on bootup. */
56 typedef enum ItemType {
57 /* These ones take file names */
61 CREATE_DIRECTORY = 'd',
62 TRUNCATE_DIRECTORY = 'D',
65 CREATE_CHAR_DEVICE = 'c',
66 CREATE_BLOCK_DEVICE = 'b',
68 /* These ones take globs */
71 RECURSIVE_REMOVE_PATH = 'R',
73 RECURSIVE_RELABEL_PATH = 'Z'
94 static Hashmap *items = NULL, *globs = NULL;
95 static Set *unix_sockets = NULL;
97 static bool arg_create = false;
98 static bool arg_clean = false;
99 static bool arg_remove = false;
101 static const char *arg_prefix = NULL;
103 static const char *conf_file_dirs[] = {
106 "/usr/local/lib/tmpfiles.d",
107 "/usr/lib/tmpfiles.d",
111 #define MAX_DEPTH 256
113 static bool needs_glob(ItemType t) {
114 return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
117 static struct Item* find_glob(Hashmap *h, const char *match) {
121 HASHMAP_FOREACH(j, h, i)
122 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
128 static void load_unix_sockets(void) {
135 /* We maintain a cache of the sockets we found in
136 * /proc/net/unix to speed things up a little. */
138 unix_sockets = set_new(string_hash_func, string_compare_func);
142 f = fopen("/proc/net/unix", "re");
147 if (!fgets(line, sizeof(line), f))
154 if (!fgets(line, sizeof(line), f))
159 p = strchr(line, ':');
167 p += strspn(p, WHITESPACE);
168 p += strcspn(p, WHITESPACE); /* skip one more word */
169 p += strspn(p, WHITESPACE);
178 path_kill_slashes(s);
180 k = set_put(unix_sockets, s);
193 set_free_free(unix_sockets);
200 static bool unix_socket_alive(const char *fn) {
206 return !!set_get(unix_sockets, (char*) fn);
208 /* We don't know, so assume yes */
212 static int dir_cleanup(
215 const struct stat *ds,
222 struct timespec times[2];
223 bool deleted = false;
224 char *sub_path = NULL;
227 while ((dent = readdir(d))) {
231 if (streq(dent->d_name, ".") ||
232 streq(dent->d_name, ".."))
235 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
237 if (errno != ENOENT) {
238 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
245 /* Stay on the same filesystem */
246 if (s.st_dev != rootdev)
249 /* Do not delete read-only files owned by root */
250 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
256 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
257 log_error("Out of memory");
262 /* Is there an item configured for this path? */
263 if (hashmap_get(items, sub_path))
266 if (find_glob(globs, sub_path))
269 if (S_ISDIR(s.st_mode)) {
272 streq(dent->d_name, "lost+found") &&
277 log_warning("Reached max depth on %s.", sub_path);
282 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
283 if (sub_dir == NULL) {
284 if (errno != ENOENT) {
285 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
292 q = dir_cleanup(sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1);
299 /* Ignore ctime, we change it when deleting */
300 age = MAX(timespec_load(&s.st_mtim),
301 timespec_load(&s.st_atim));
305 log_debug("rmdir '%s'\n", sub_path);
307 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
308 if (errno != ENOENT && errno != ENOTEMPTY) {
309 log_error("rmdir(%s): %m", sub_path);
315 /* Skip files for which the sticky bit is
316 * set. These are semantics we define, and are
317 * unknown elsewhere. See XDG_RUNTIME_DIR
318 * specification for details. */
319 if (s.st_mode & S_ISVTX)
322 if (mountpoint && S_ISREG(s.st_mode)) {
323 if (streq(dent->d_name, ".journal") &&
327 if (streq(dent->d_name, "aquota.user") ||
328 streq(dent->d_name, "aquota.group"))
332 /* Ignore sockets that are listed in /proc/net/unix */
333 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
336 /* Ignore device nodes */
337 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
340 age = MAX3(timespec_load(&s.st_mtim),
341 timespec_load(&s.st_atim),
342 timespec_load(&s.st_ctim));
347 log_debug("unlink '%s'\n", sub_path);
349 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
350 if (errno != ENOENT) {
351 log_error("unlink(%s): %m", sub_path);
362 /* Restore original directory timestamps */
363 times[0] = ds->st_atim;
364 times[1] = ds->st_mtim;
366 if (futimens(dirfd(d), times) < 0)
367 log_error("utimensat(%s): %m", p);
375 static int clean_item(Item *i) {
384 if (i->type != CREATE_DIRECTORY &&
385 i->type != TRUNCATE_DIRECTORY &&
386 i->type != IGNORE_PATH)
389 if (!i->age_set || i->age <= 0)
392 n = now(CLOCK_REALTIME);
398 d = opendir(i->path);
403 log_error("Failed to open directory %s: %m", i->path);
407 if (fstat(dirfd(d), &s) < 0) {
408 log_error("stat(%s) failed: %m", i->path);
413 if (!S_ISDIR(s.st_mode)) {
414 log_error("%s is not a directory.", i->path);
419 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
420 log_error("stat(%s/..) failed: %m", i->path);
425 mountpoint = s.st_dev != ps.st_dev ||
426 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
428 r = dir_cleanup(i->path, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH);
437 static int item_set_perms(Item *i, const char *path) {
438 /* not using i->path directly because it may be a glob */
440 if (chmod(path, i->mode) < 0) {
441 log_error("chmod(%s) failed: %m", path);
445 if (i->uid_set || i->gid_set)
447 i->uid_set ? i->uid : (uid_t) -1,
448 i->gid_set ? i->gid : (gid_t) -1) < 0) {
450 log_error("chown(%s) failed: %m", path);
454 return label_fix(path, false);
457 static int recursive_relabel_children(Item *i, const char *path) {
461 /* This returns the first error we run into, but nevertheless
466 return errno == ENOENT ? 0 : -errno;
469 struct dirent buf, *de;
474 r = readdir_r(d, &buf, &de);
484 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
487 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
493 if (de->d_type == DT_UNKNOWN) {
496 if (lstat(entry_path, &st) < 0) {
497 if (ret == 0 && errno != ENOENT)
503 is_dir = S_ISDIR(st.st_mode);
506 is_dir = de->d_type == DT_DIR;
508 r = item_set_perms(i, entry_path);
510 if (ret == 0 && r != -ENOENT)
517 r = recursive_relabel_children(i, entry_path);
518 if (r < 0 && ret == 0)
530 static int recursive_relabel(Item *i, const char *path) {
534 r = item_set_perms(i, path);
538 if (lstat(path, &st) < 0)
541 if (S_ISDIR(st.st_mode))
542 r = recursive_relabel_children(i, path);
547 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
555 if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
557 if (k != GLOB_NOMATCH) {
561 log_error("glob(%s) failed: %m", i->path);
566 STRV_FOREACH(fn, g.gl_pathv)
567 if ((k = action(i, *fn)) < 0)
574 static int create_item(Item *i) {
585 case RECURSIVE_REMOVE_PATH:
593 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
594 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
597 label_context_set(i->path, S_IFREG);
598 fd = open(i->path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
600 label_context_clear();
605 if (i->type == WRITE_FILE && errno == ENOENT)
608 log_error("Failed to create file %s: %m", i->path);
615 struct iovec iovec[2];
616 static const char new_line = '\n';
618 l = strlen(i->argument);
621 iovec[0].iov_base = i->argument;
622 iovec[0].iov_len = l;
624 iovec[1].iov_base = (void*) &new_line;
625 iovec[1].iov_len = 1;
627 n = writev(fd, iovec, 2);
629 /* It's OK if we don't write the trailing
630 * newline, hence we check for l, instead of
631 * l+1 here. Files in /sys often refuse
632 * writing of the trailing newline. */
633 if (n < 0 || (size_t) n < l) {
634 log_error("Failed to write file %s: %s", i->path, n < 0 ? strerror(-n) : "Short write");
635 close_nointr_nofail(fd);
636 return n < 0 ? n : -EIO;
640 close_nointr_nofail(fd);
642 if (stat(i->path, &st) < 0) {
643 log_error("stat(%s) failed: %m", i->path);
647 if (!S_ISREG(st.st_mode)) {
648 log_error("%s is not a file.", i->path);
652 r = item_set_perms(i, i->path);
659 case TRUNCATE_DIRECTORY:
660 case CREATE_DIRECTORY:
663 mkdir_parents_label(i->path, 0755);
664 r = mkdir(i->path, i->mode);
667 if (r < 0 && errno != EEXIST) {
668 log_error("Failed to create directory %s: %m", i->path);
672 if (stat(i->path, &st) < 0) {
673 log_error("stat(%s) failed: %m", i->path);
677 if (!S_ISDIR(st.st_mode)) {
678 log_error("%s is not a directory.", i->path);
682 r = item_set_perms(i, i->path);
691 r = mkfifo(i->path, i->mode);
694 if (r < 0 && errno != EEXIST) {
695 log_error("Failed to create fifo %s: %m", i->path);
699 if (stat(i->path, &st) < 0) {
700 log_error("stat(%s) failed: %m", i->path);
704 if (!S_ISFIFO(st.st_mode)) {
705 log_error("%s is not a fifo.", i->path);
709 r = item_set_perms(i, i->path);
715 case CREATE_SYMLINK: {
718 label_context_set(i->path, S_IFLNK);
719 r = symlink(i->argument, i->path);
721 label_context_clear();
724 if (r < 0 && errno != EEXIST) {
725 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
729 r = readlink_malloc(i->path, &x);
731 log_error("readlink(%s) failed: %s", i->path, strerror(-r));
735 if (!streq(i->argument, x)) {
737 log_error("%s is not the right symlinks.", i->path);
745 case CREATE_BLOCK_DEVICE:
746 case CREATE_CHAR_DEVICE: {
749 label_context_set(i->path, CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
750 r = mknod(i->path, i->mode | (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR), i->major_minor);
752 label_context_clear();
756 if (r < 0 && errno != EEXIST) {
757 log_error("Failed to create device node %s: %m", i->path);
761 if (stat(i->path, &st) < 0) {
762 log_error("stat(%s) failed: %m", i->path);
766 if (i->type == CREATE_BLOCK_DEVICE ? !S_ISBLK(st.st_mode) : !S_ISCHR(st.st_mode)) {
767 log_error("%s is not a device node.", i->path);
771 r = item_set_perms(i, i->path);
780 r = glob_item(i, item_set_perms);
785 case RECURSIVE_RELABEL_PATH:
787 r = glob_item(i, recursive_relabel);
792 log_debug("%s created successfully.", i->path);
797 static int remove_item_instance(Item *i, const char *instance) {
806 case CREATE_DIRECTORY:
809 case CREATE_BLOCK_DEVICE:
810 case CREATE_CHAR_DEVICE:
813 case RECURSIVE_RELABEL_PATH:
818 if (remove(instance) < 0 && errno != ENOENT) {
819 log_error("remove(%s): %m", instance);
825 case TRUNCATE_DIRECTORY:
826 case RECURSIVE_REMOVE_PATH:
827 r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
828 if (r < 0 && r != -ENOENT) {
829 log_error("rm_rf(%s): %s", instance, strerror(-r));
839 static int remove_item(Item *i) {
848 case CREATE_DIRECTORY:
851 case CREATE_CHAR_DEVICE:
852 case CREATE_BLOCK_DEVICE:
855 case RECURSIVE_RELABEL_PATH:
860 case TRUNCATE_DIRECTORY:
861 case RECURSIVE_REMOVE_PATH:
862 r = glob_item(i, remove_item_instance);
869 static int process_item(Item *i) {
874 r = arg_create ? create_item(i) : 0;
875 q = arg_remove ? remove_item(i) : 0;
876 p = arg_clean ? clean_item(i) : 0;
887 static void item_free(Item *i) {
895 static bool item_equal(Item *a, Item *b) {
899 if (!streq_ptr(a->path, b->path))
902 if (a->type != b->type)
905 if (a->uid_set != b->uid_set ||
906 (a->uid_set && a->uid != b->uid))
909 if (a->gid_set != b->gid_set ||
910 (a->gid_set && a->gid != b->gid))
913 if (a->mode_set != b->mode_set ||
914 (a->mode_set && a->mode != b->mode))
917 if (a->age_set != b->age_set ||
918 (a->age_set && a->age != b->age))
921 if ((a->type == CREATE_FILE ||
922 a->type == TRUNCATE_FILE ||
923 a->type == WRITE_FILE ||
924 a->type == CREATE_SYMLINK) &&
925 !streq_ptr(a->argument, b->argument))
928 if ((a->type == CREATE_CHAR_DEVICE ||
929 a->type == CREATE_BLOCK_DEVICE) &&
930 a->major_minor != b->major_minor)
936 static int parse_line(const char *fname, unsigned line, const char *buffer) {
938 char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
949 log_error("Out of memory");
968 log_error("[%s:%u] Syntax error.", fname, line);
974 n += strspn(buffer+n, WHITESPACE);
975 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
976 i->argument = unquote(buffer+n, "\"");
978 log_error("Out of memory");
988 case CREATE_DIRECTORY:
989 case TRUNCATE_DIRECTORY:
993 case RECURSIVE_REMOVE_PATH:
995 case RECURSIVE_RELABEL_PATH:
1000 log_error("[%s:%u] Symlink file requires argument.", fname, line);
1008 log_error("[%s:%u] Write file requires argument.", fname, line);
1014 case CREATE_CHAR_DEVICE:
1015 case CREATE_BLOCK_DEVICE: {
1016 unsigned major, minor;
1019 log_error("[%s:%u] Device file requires argument.", fname, line);
1024 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1025 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1030 i->major_minor = makedev(major, minor);
1035 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1042 if (!path_is_absolute(i->path)) {
1043 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1048 path_kill_slashes(i->path);
1050 if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
1055 if (user && !streq(user, "-")) {
1056 const char *u = user;
1058 r = get_user_creds(&u, &i->uid, NULL, NULL);
1060 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1067 if (group && !streq(group, "-")) {
1068 const char *g = group;
1070 r = get_group_creds(&g, &i->gid);
1072 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1079 if (mode && !streq(mode, "-")) {
1082 if (sscanf(mode, "%o", &m) != 1) {
1083 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1092 i->type == CREATE_DIRECTORY ||
1093 i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1095 if (age && !streq(age, "-")) {
1096 if (parse_usec(age, &i->age) < 0) {
1097 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1105 h = needs_glob(i->type) ? globs : items;
1107 existing = hashmap_get(h, i->path);
1110 /* Two identical items are fine */
1111 if (!item_equal(existing, i))
1112 log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1118 r = hashmap_put(h, i->path, i);
1120 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1139 static int help(void) {
1141 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1142 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1143 " -h --help Show this help\n"
1144 " --create Create marked files/directories\n"
1145 " --clean Clean up marked directories\n"
1146 " --remove Remove marked files/directories\n"
1147 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
1148 program_invocation_short_name);
1153 static int parse_argv(int argc, char *argv[]) {
1162 static const struct option options[] = {
1163 { "help", no_argument, NULL, 'h' },
1164 { "create", no_argument, NULL, ARG_CREATE },
1165 { "clean", no_argument, NULL, ARG_CLEAN },
1166 { "remove", no_argument, NULL, ARG_REMOVE },
1167 { "prefix", required_argument, NULL, ARG_PREFIX },
1168 { NULL, 0, NULL, 0 }
1176 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1197 arg_prefix = optarg;
1204 log_error("Unknown option code %c", c);
1209 if (!arg_clean && !arg_create && !arg_remove) {
1210 log_error("You need to specify at least one of --clean, --create or --remove.");
1217 static int read_config_file(const char *fn, bool ignore_enoent) {
1224 f = fopen(fn, "re");
1227 if (ignore_enoent && errno == ENOENT)
1230 log_error("Failed to open %s: %m", fn);
1234 log_debug("apply: %s\n", fn);
1236 char line[LINE_MAX], *l;
1239 if (!(fgets(line, sizeof(line), f)))
1245 if (*l == '#' || *l == 0)
1248 if ((k = parse_line(fn, v, l)) < 0)
1254 log_error("Failed to read from file %s: %m", fn);
1264 static char *resolve_fragment(const char *fragment, const char **search_paths) {
1266 char *resolved_path;
1268 if (is_path(fragment))
1269 return strdup(fragment);
1271 STRV_FOREACH(p, search_paths) {
1272 resolved_path = join(*p, "/", fragment, NULL);
1273 if (resolved_path == NULL) {
1274 log_error("Out of memory");
1278 if (access(resolved_path, F_OK) == 0)
1279 return resolved_path;
1281 free(resolved_path);
1288 int main(int argc, char *argv[]) {
1293 r = parse_argv(argc, argv);
1295 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1297 log_set_target(LOG_TARGET_AUTO);
1298 log_parse_environment();
1305 items = hashmap_new(string_hash_func, string_compare_func);
1306 globs = hashmap_new(string_hash_func, string_compare_func);
1308 if (!items || !globs) {
1309 log_error("Out of memory");
1316 if (optind < argc) {
1319 for (j = optind; j < argc; j++) {
1322 fragment = resolve_fragment(argv[j], conf_file_dirs);
1324 log_error("Failed to find a %s file: %m", argv[j]);
1328 if (read_config_file(fragment, false) < 0)
1336 r = conf_files_list_strv(&files, ".conf",
1337 (const char **)conf_file_dirs);
1339 log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1344 STRV_FOREACH(f, files) {
1345 if (read_config_file(*f, true) < 0)
1352 HASHMAP_FOREACH(i, globs, iterator)
1355 HASHMAP_FOREACH(i, items, iterator)
1359 while ((i = hashmap_steal_first(items)))
1362 while ((i = hashmap_steal_first(globs)))
1365 hashmap_free(items);
1366 hashmap_free(globs);
1368 set_free_free(unix_sockets);