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'
93 bool keep_first_level:1;
96 static Hashmap *items = NULL, *globs = NULL;
97 static Set *unix_sockets = NULL;
99 static bool arg_create = false;
100 static bool arg_clean = false;
101 static bool arg_remove = false;
103 static const char *arg_prefix = NULL;
105 static const char * const conf_file_dirs[] = {
108 "/usr/local/lib/tmpfiles.d",
109 "/usr/lib/tmpfiles.d",
113 #define MAX_DEPTH 256
115 static bool needs_glob(ItemType t) {
116 return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
119 static struct Item* find_glob(Hashmap *h, const char *match) {
123 HASHMAP_FOREACH(j, h, i)
124 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
130 static void load_unix_sockets(void) {
137 /* We maintain a cache of the sockets we found in
138 * /proc/net/unix to speed things up a little. */
140 unix_sockets = set_new(string_hash_func, string_compare_func);
144 f = fopen("/proc/net/unix", "re");
149 if (!fgets(line, sizeof(line), f))
156 if (!fgets(line, sizeof(line), f))
161 p = strchr(line, ':');
169 p += strspn(p, WHITESPACE);
170 p += strcspn(p, WHITESPACE); /* skip one more word */
171 p += strspn(p, WHITESPACE);
180 path_kill_slashes(s);
182 k = set_put(unix_sockets, s);
195 set_free_free(unix_sockets);
202 static bool unix_socket_alive(const char *fn) {
208 return !!set_get(unix_sockets, (char*) fn);
210 /* We don't know, so assume yes */
214 static int dir_cleanup(
217 const struct stat *ds,
222 bool keep_this_level)
225 struct timespec times[2];
226 bool deleted = false;
227 char *sub_path = NULL;
230 while ((dent = readdir(d))) {
234 if (streq(dent->d_name, ".") ||
235 streq(dent->d_name, ".."))
238 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
240 if (errno != ENOENT) {
241 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
248 /* Stay on the same filesystem */
249 if (s.st_dev != rootdev)
252 /* Do not delete read-only files owned by root */
253 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
259 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
260 log_error("Out of memory");
265 /* Is there an item configured for this path? */
266 if (hashmap_get(items, sub_path))
269 if (find_glob(globs, sub_path))
272 if (S_ISDIR(s.st_mode)) {
275 streq(dent->d_name, "lost+found") &&
280 log_warning("Reached max depth on %s.", sub_path);
285 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
286 if (sub_dir == NULL) {
287 if (errno != ENOENT) {
288 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
295 q = dir_cleanup(sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
302 /* Note: if you are wondering why we don't
303 * support the sticky bit for excluding
304 * directories from cleaning like we do it for
305 * other file system objects: well, the sticky
306 * bit already has a meaning for directories,
307 * so we don't want to overload that. */
312 /* Ignore ctime, we change it when deleting */
313 age = MAX(timespec_load(&s.st_mtim),
314 timespec_load(&s.st_atim));
318 log_debug("rmdir '%s'\n", sub_path);
320 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
321 if (errno != ENOENT && errno != ENOTEMPTY) {
322 log_error("rmdir(%s): %m", sub_path);
328 /* Skip files for which the sticky bit is
329 * set. These are semantics we define, and are
330 * unknown elsewhere. See XDG_RUNTIME_DIR
331 * specification for details. */
332 if (s.st_mode & S_ISVTX)
335 if (mountpoint && S_ISREG(s.st_mode)) {
336 if (streq(dent->d_name, ".journal") &&
340 if (streq(dent->d_name, "aquota.user") ||
341 streq(dent->d_name, "aquota.group"))
345 /* Ignore sockets that are listed in /proc/net/unix */
346 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
349 /* Ignore device nodes */
350 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
353 /* Keep files on this level around if this is
358 age = MAX3(timespec_load(&s.st_mtim),
359 timespec_load(&s.st_atim),
360 timespec_load(&s.st_ctim));
365 log_debug("unlink '%s'\n", sub_path);
367 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
368 if (errno != ENOENT) {
369 log_error("unlink(%s): %m", sub_path);
380 /* Restore original directory timestamps */
381 times[0] = ds->st_atim;
382 times[1] = ds->st_mtim;
384 if (futimens(dirfd(d), times) < 0)
385 log_error("utimensat(%s): %m", p);
393 static int clean_item(Item *i) {
402 if (i->type != CREATE_DIRECTORY &&
403 i->type != TRUNCATE_DIRECTORY &&
404 i->type != IGNORE_PATH)
407 if (!i->age_set || i->age <= 0)
410 n = now(CLOCK_REALTIME);
416 d = opendir(i->path);
421 log_error("Failed to open directory %s: %m", i->path);
425 if (fstat(dirfd(d), &s) < 0) {
426 log_error("stat(%s) failed: %m", i->path);
431 if (!S_ISDIR(s.st_mode)) {
432 log_error("%s is not a directory.", i->path);
437 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
438 log_error("stat(%s/..) failed: %m", i->path);
443 mountpoint = s.st_dev != ps.st_dev ||
444 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
446 r = dir_cleanup(i->path, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH, i->keep_first_level);
455 static int item_set_perms(Item *i, const char *path) {
456 /* not using i->path directly because it may be a glob */
458 if (chmod(path, i->mode) < 0) {
459 log_error("chmod(%s) failed: %m", path);
463 if (i->uid_set || i->gid_set)
465 i->uid_set ? i->uid : (uid_t) -1,
466 i->gid_set ? i->gid : (gid_t) -1) < 0) {
468 log_error("chown(%s) failed: %m", path);
472 return label_fix(path, false);
475 static int recursive_relabel_children(Item *i, const char *path) {
479 /* This returns the first error we run into, but nevertheless
484 return errno == ENOENT ? 0 : -errno;
487 struct dirent buf, *de;
492 r = readdir_r(d, &buf, &de);
502 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
505 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
511 if (de->d_type == DT_UNKNOWN) {
514 if (lstat(entry_path, &st) < 0) {
515 if (ret == 0 && errno != ENOENT)
521 is_dir = S_ISDIR(st.st_mode);
524 is_dir = de->d_type == DT_DIR;
526 r = item_set_perms(i, entry_path);
528 if (ret == 0 && r != -ENOENT)
535 r = recursive_relabel_children(i, entry_path);
536 if (r < 0 && ret == 0)
548 static int recursive_relabel(Item *i, const char *path) {
552 r = item_set_perms(i, path);
556 if (lstat(path, &st) < 0)
559 if (S_ISDIR(st.st_mode))
560 r = recursive_relabel_children(i, path);
565 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
573 if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
575 if (k != GLOB_NOMATCH) {
579 log_error("glob(%s) failed: %m", i->path);
584 STRV_FOREACH(fn, g.gl_pathv)
585 if ((k = action(i, *fn)) < 0)
592 static int create_item(Item *i) {
603 case RECURSIVE_REMOVE_PATH:
611 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
612 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
615 label_context_set(i->path, S_IFREG);
616 fd = open(i->path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
618 label_context_clear();
623 if (i->type == WRITE_FILE && errno == ENOENT)
626 log_error("Failed to create file %s: %m", i->path);
633 struct iovec iovec[2];
634 static const char new_line = '\n';
636 l = strlen(i->argument);
639 iovec[0].iov_base = i->argument;
640 iovec[0].iov_len = l;
642 iovec[1].iov_base = (void*) &new_line;
643 iovec[1].iov_len = 1;
645 n = writev(fd, iovec, 2);
647 /* It's OK if we don't write the trailing
648 * newline, hence we check for l, instead of
649 * l+1 here. Files in /sys often refuse
650 * writing of the trailing newline. */
651 if (n < 0 || (size_t) n < l) {
652 log_error("Failed to write file %s: %s", i->path, n < 0 ? strerror(-n) : "Short write");
653 close_nointr_nofail(fd);
654 return n < 0 ? n : -EIO;
658 close_nointr_nofail(fd);
660 if (stat(i->path, &st) < 0) {
661 log_error("stat(%s) failed: %m", i->path);
665 if (!S_ISREG(st.st_mode)) {
666 log_error("%s is not a file.", i->path);
670 r = item_set_perms(i, i->path);
677 case TRUNCATE_DIRECTORY:
678 case CREATE_DIRECTORY:
681 mkdir_parents_label(i->path, 0755);
682 r = mkdir(i->path, i->mode);
685 if (r < 0 && errno != EEXIST) {
686 log_error("Failed to create directory %s: %m", i->path);
690 if (stat(i->path, &st) < 0) {
691 log_error("stat(%s) failed: %m", i->path);
695 if (!S_ISDIR(st.st_mode)) {
696 log_error("%s is not a directory.", i->path);
700 r = item_set_perms(i, i->path);
709 r = mkfifo(i->path, i->mode);
712 if (r < 0 && errno != EEXIST) {
713 log_error("Failed to create fifo %s: %m", i->path);
717 if (stat(i->path, &st) < 0) {
718 log_error("stat(%s) failed: %m", i->path);
722 if (!S_ISFIFO(st.st_mode)) {
723 log_error("%s is not a fifo.", i->path);
727 r = item_set_perms(i, i->path);
733 case CREATE_SYMLINK: {
736 label_context_set(i->path, S_IFLNK);
737 r = symlink(i->argument, i->path);
739 label_context_clear();
742 if (r < 0 && errno != EEXIST) {
743 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
747 r = readlink_malloc(i->path, &x);
749 log_error("readlink(%s) failed: %s", i->path, strerror(-r));
753 if (!streq(i->argument, x)) {
755 log_error("%s is not the right symlinks.", i->path);
763 case CREATE_BLOCK_DEVICE:
764 case CREATE_CHAR_DEVICE: {
765 mode_t file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
768 label_context_set(i->path, file_type);
769 r = mknod(i->path, i->mode | file_type, i->major_minor);
771 label_context_clear();
775 if (r < 0 && errno != EEXIST) {
776 log_error("Failed to create device node %s: %m", i->path);
780 if (stat(i->path, &st) < 0) {
781 log_error("stat(%s) failed: %m", i->path);
785 if ((st.st_mode & S_IFMT) != file_type) {
786 log_error("%s is not a device node.", i->path);
790 r = item_set_perms(i, i->path);
799 r = glob_item(i, item_set_perms);
804 case RECURSIVE_RELABEL_PATH:
806 r = glob_item(i, recursive_relabel);
811 log_debug("%s created successfully.", i->path);
816 static int remove_item_instance(Item *i, const char *instance) {
825 case CREATE_DIRECTORY:
828 case CREATE_BLOCK_DEVICE:
829 case CREATE_CHAR_DEVICE:
832 case RECURSIVE_RELABEL_PATH:
837 if (remove(instance) < 0 && errno != ENOENT) {
838 log_error("remove(%s): %m", instance);
844 case TRUNCATE_DIRECTORY:
845 case RECURSIVE_REMOVE_PATH:
846 /* FIXME: we probably should use dir_cleanup() here
847 * instead of rm_rf() so that 'x' is honoured. */
848 r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
849 if (r < 0 && r != -ENOENT) {
850 log_error("rm_rf(%s): %s", instance, strerror(-r));
860 static int remove_item(Item *i) {
869 case CREATE_DIRECTORY:
872 case CREATE_CHAR_DEVICE:
873 case CREATE_BLOCK_DEVICE:
876 case RECURSIVE_RELABEL_PATH:
881 case TRUNCATE_DIRECTORY:
882 case RECURSIVE_REMOVE_PATH:
883 r = glob_item(i, remove_item_instance);
890 static int process_item(Item *i) {
895 r = arg_create ? create_item(i) : 0;
896 q = arg_remove ? remove_item(i) : 0;
897 p = arg_clean ? clean_item(i) : 0;
908 static void item_free(Item *i) {
916 static bool item_equal(Item *a, Item *b) {
920 if (!streq_ptr(a->path, b->path))
923 if (a->type != b->type)
926 if (a->uid_set != b->uid_set ||
927 (a->uid_set && a->uid != b->uid))
930 if (a->gid_set != b->gid_set ||
931 (a->gid_set && a->gid != b->gid))
934 if (a->mode_set != b->mode_set ||
935 (a->mode_set && a->mode != b->mode))
938 if (a->age_set != b->age_set ||
939 (a->age_set && a->age != b->age))
942 if ((a->type == CREATE_FILE ||
943 a->type == TRUNCATE_FILE ||
944 a->type == WRITE_FILE ||
945 a->type == CREATE_SYMLINK) &&
946 !streq_ptr(a->argument, b->argument))
949 if ((a->type == CREATE_CHAR_DEVICE ||
950 a->type == CREATE_BLOCK_DEVICE) &&
951 a->major_minor != b->major_minor)
957 static int parse_line(const char *fname, unsigned line, const char *buffer) {
959 char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
970 log_error("Out of memory");
989 log_error("[%s:%u] Syntax error.", fname, line);
995 n += strspn(buffer+n, WHITESPACE);
996 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
997 i->argument = unquote(buffer+n, "\"");
999 log_error("Out of memory");
1009 case CREATE_DIRECTORY:
1010 case TRUNCATE_DIRECTORY:
1014 case RECURSIVE_REMOVE_PATH:
1016 case RECURSIVE_RELABEL_PATH:
1019 case CREATE_SYMLINK:
1021 log_error("[%s:%u] Symlink file requires argument.", fname, line);
1029 log_error("[%s:%u] Write file requires argument.", fname, line);
1035 case CREATE_CHAR_DEVICE:
1036 case CREATE_BLOCK_DEVICE: {
1037 unsigned major, minor;
1040 log_error("[%s:%u] Device file requires argument.", fname, line);
1045 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1046 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1051 i->major_minor = makedev(major, minor);
1056 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1063 if (!path_is_absolute(i->path)) {
1064 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1069 path_kill_slashes(i->path);
1071 if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
1076 if (user && !streq(user, "-")) {
1077 const char *u = user;
1079 r = get_user_creds(&u, &i->uid, NULL, NULL);
1081 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1088 if (group && !streq(group, "-")) {
1089 const char *g = group;
1091 r = get_group_creds(&g, &i->gid);
1093 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1100 if (mode && !streq(mode, "-")) {
1103 if (sscanf(mode, "%o", &m) != 1) {
1104 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1113 i->type == CREATE_DIRECTORY ||
1114 i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1116 if (age && !streq(age, "-")) {
1117 const char *a = age;
1120 i->keep_first_level = true;
1124 if (parse_usec(a, &i->age) < 0) {
1125 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1133 h = needs_glob(i->type) ? globs : items;
1135 existing = hashmap_get(h, i->path);
1138 /* Two identical items are fine */
1139 if (!item_equal(existing, i))
1140 log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1146 r = hashmap_put(h, i->path, i);
1148 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1167 static int help(void) {
1169 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1170 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1171 " -h --help Show this help\n"
1172 " --create Create marked files/directories\n"
1173 " --clean Clean up marked directories\n"
1174 " --remove Remove marked files/directories\n"
1175 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
1176 program_invocation_short_name);
1181 static int parse_argv(int argc, char *argv[]) {
1190 static const struct option options[] = {
1191 { "help", no_argument, NULL, 'h' },
1192 { "create", no_argument, NULL, ARG_CREATE },
1193 { "clean", no_argument, NULL, ARG_CLEAN },
1194 { "remove", no_argument, NULL, ARG_REMOVE },
1195 { "prefix", required_argument, NULL, ARG_PREFIX },
1196 { NULL, 0, NULL, 0 }
1204 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1225 arg_prefix = optarg;
1232 log_error("Unknown option code %c", c);
1237 if (!arg_clean && !arg_create && !arg_remove) {
1238 log_error("You need to specify at least one of --clean, --create or --remove.");
1245 static int read_config_file(const char *fn, bool ignore_enoent) {
1252 f = fopen(fn, "re");
1255 if (ignore_enoent && errno == ENOENT)
1258 log_error("Failed to open %s: %m", fn);
1262 log_debug("apply: %s\n", fn);
1264 char line[LINE_MAX], *l;
1267 if (!(fgets(line, sizeof(line), f)))
1273 if (*l == '#' || *l == 0)
1276 if ((k = parse_line(fn, v, l)) < 0)
1282 log_error("Failed to read from file %s: %m", fn);
1292 static char *resolve_fragment(const char *fragment, const char **search_paths) {
1294 char *resolved_path;
1296 if (is_path(fragment))
1297 return strdup(fragment);
1299 STRV_FOREACH(p, search_paths) {
1300 resolved_path = join(*p, "/", fragment, NULL);
1301 if (resolved_path == NULL) {
1302 log_error("Out of memory");
1306 if (access(resolved_path, F_OK) == 0)
1307 return resolved_path;
1309 free(resolved_path);
1316 int main(int argc, char *argv[]) {
1321 r = parse_argv(argc, argv);
1323 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1325 log_set_target(LOG_TARGET_AUTO);
1326 log_parse_environment();
1333 items = hashmap_new(string_hash_func, string_compare_func);
1334 globs = hashmap_new(string_hash_func, string_compare_func);
1336 if (!items || !globs) {
1337 log_error("Out of memory");
1344 if (optind < argc) {
1347 for (j = optind; j < argc; j++) {
1350 fragment = resolve_fragment(argv[j], (const char**) conf_file_dirs);
1352 log_error("Failed to find a %s file: %m", argv[j]);
1356 if (read_config_file(fragment, false) < 0)
1364 r = conf_files_list_strv(&files, ".conf",
1365 (const char **) conf_file_dirs);
1367 log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1372 STRV_FOREACH(f, files) {
1373 if (read_config_file(*f, true) < 0)
1380 HASHMAP_FOREACH(i, globs, iterator)
1383 HASHMAP_FOREACH(i, items, iterator)
1387 while ((i = hashmap_steal_first(items)))
1390 while ((i = hashmap_steal_first(globs)))
1393 hashmap_free(items);
1394 hashmap_free(globs);
1396 set_free_free(unix_sockets);