]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/tmpfiles/tmpfiles.c
tmpfiles: in dir_cleanup() take benefit that log_error_errno() returns the error...
[thirdparty/systemd.git] / src / tmpfiles / tmpfiles.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering, Kay Sievers
6 Copyright 2015 Zbigniew Jędrzejewski-Szmek
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <fnmatch.h>
25 #include <getopt.h>
26 #include <glob.h>
27 #include <limits.h>
28 #include <linux/fs.h>
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <sys/xattr.h>
36 #include <sysexits.h>
37 #include <time.h>
38 #include <unistd.h>
39
40 #include "sd-path.h"
41
42 #include "acl-util.h"
43 #include "alloc-util.h"
44 #include "btrfs-util.h"
45 #include "capability-util.h"
46 #include "chattr-util.h"
47 #include "conf-files.h"
48 #include "copy.h"
49 #include "def.h"
50 #include "dirent-util.h"
51 #include "escape.h"
52 #include "fd-util.h"
53 #include "fileio.h"
54 #include "format-util.h"
55 #include "fs-util.h"
56 #include "glob-util.h"
57 #include "io-util.h"
58 #include "label.h"
59 #include "log.h"
60 #include "macro.h"
61 #include "missing.h"
62 #include "mkdir.h"
63 #include "mount-util.h"
64 #include "parse-util.h"
65 #include "path-lookup.h"
66 #include "path-util.h"
67 #include "rm-rf.h"
68 #include "selinux-util.h"
69 #include "set.h"
70 #include "specifier.h"
71 #include "stat-util.h"
72 #include "stdio-util.h"
73 #include "string-table.h"
74 #include "string-util.h"
75 #include "strv.h"
76 #include "umask-util.h"
77 #include "user-util.h"
78 #include "util.h"
79
80 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
81 * them in the file system. This is intended to be used to create
82 * properly owned directories beneath /tmp, /var/tmp, /run, which are
83 * volatile and hence need to be recreated on bootup. */
84
85 typedef enum ItemType {
86 /* These ones take file names */
87 CREATE_FILE = 'f',
88 TRUNCATE_FILE = 'F',
89 CREATE_DIRECTORY = 'd',
90 TRUNCATE_DIRECTORY = 'D',
91 CREATE_SUBVOLUME = 'v',
92 CREATE_SUBVOLUME_INHERIT_QUOTA = 'q',
93 CREATE_SUBVOLUME_NEW_QUOTA = 'Q',
94 CREATE_FIFO = 'p',
95 CREATE_SYMLINK = 'L',
96 CREATE_CHAR_DEVICE = 'c',
97 CREATE_BLOCK_DEVICE = 'b',
98 COPY_FILES = 'C',
99
100 /* These ones take globs */
101 WRITE_FILE = 'w',
102 EMPTY_DIRECTORY = 'e',
103 SET_XATTR = 't',
104 RECURSIVE_SET_XATTR = 'T',
105 SET_ACL = 'a',
106 RECURSIVE_SET_ACL = 'A',
107 SET_ATTRIBUTE = 'h',
108 RECURSIVE_SET_ATTRIBUTE = 'H',
109 IGNORE_PATH = 'x',
110 IGNORE_DIRECTORY_PATH = 'X',
111 REMOVE_PATH = 'r',
112 RECURSIVE_REMOVE_PATH = 'R',
113 RELABEL_PATH = 'z',
114 RECURSIVE_RELABEL_PATH = 'Z',
115 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
116 } ItemType;
117
118 typedef struct Item {
119 ItemType type;
120
121 char *path;
122 char *argument;
123 char **xattrs;
124 #if HAVE_ACL
125 acl_t acl_access;
126 acl_t acl_default;
127 #endif
128 uid_t uid;
129 gid_t gid;
130 mode_t mode;
131 usec_t age;
132
133 dev_t major_minor;
134 unsigned attribute_value;
135 unsigned attribute_mask;
136
137 bool uid_set:1;
138 bool gid_set:1;
139 bool mode_set:1;
140 bool age_set:1;
141 bool mask_perms:1;
142 bool attribute_set:1;
143
144 bool keep_first_level:1;
145
146 bool force:1;
147
148 bool done:1;
149 } Item;
150
151 typedef struct ItemArray {
152 Item *items;
153 size_t count;
154 size_t size;
155 } ItemArray;
156
157 typedef enum DirectoryType {
158 DIRECTORY_RUNTIME = 0,
159 DIRECTORY_STATE,
160 DIRECTORY_CACHE,
161 DIRECTORY_LOGS,
162 _DIRECTORY_TYPE_MAX,
163 } DirectoryType;
164
165 static bool arg_user = false;
166 static bool arg_create = false;
167 static bool arg_clean = false;
168 static bool arg_remove = false;
169 static bool arg_boot = false;
170
171 static char **arg_include_prefixes = NULL;
172 static char **arg_exclude_prefixes = NULL;
173 static char *arg_root = NULL;
174
175 #define MAX_DEPTH 256
176
177 static OrderedHashmap *items = NULL, *globs = NULL;
178 static Set *unix_sockets = NULL;
179
180 static int specifier_machine_id_safe(char specifier, void *data, void *userdata, char **ret);
181 static int specifier_directory(char specifier, void *data, void *userdata, char **ret);
182
183 static const Specifier specifier_table[] = {
184 { 'm', specifier_machine_id_safe, NULL },
185 { 'b', specifier_boot_id, NULL },
186 { 'H', specifier_host_name, NULL },
187 { 'v', specifier_kernel_release, NULL },
188
189 { 'U', specifier_user_id, NULL },
190 { 'u', specifier_user_name, NULL },
191 { 'h', specifier_user_home, NULL },
192 { 't', specifier_directory, UINT_TO_PTR(DIRECTORY_RUNTIME) },
193 { 'S', specifier_directory, UINT_TO_PTR(DIRECTORY_STATE) },
194 { 'C', specifier_directory, UINT_TO_PTR(DIRECTORY_CACHE) },
195 { 'L', specifier_directory, UINT_TO_PTR(DIRECTORY_LOGS) },
196 {}
197 };
198
199 static int specifier_machine_id_safe(char specifier, void *data, void *userdata, char **ret) {
200 int r;
201
202 /* If /etc/machine_id is missing or empty (e.g. in a chroot environment)
203 * return a recognizable error so that the caller can skip the rule
204 * gracefully. */
205
206 r = specifier_machine_id(specifier, data, userdata, ret);
207 if (IN_SET(r, -ENOENT, -ENOMEDIUM))
208 return -ENXIO;
209
210 return r;
211 }
212
213 static int specifier_directory(char specifier, void *data, void *userdata, char **ret) {
214 struct table_entry {
215 uint64_t type;
216 const char *suffix;
217 };
218
219 static const struct table_entry paths_system[] = {
220 [DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME },
221 [DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE },
222 [DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE },
223 [DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS },
224 };
225
226 static const struct table_entry paths_user[] = {
227 [DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME },
228 [DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION },
229 [DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE },
230 [DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" },
231 };
232
233 unsigned i;
234 const struct table_entry *paths;
235
236 assert_cc(ELEMENTSOF(paths_system) == ELEMENTSOF(paths_user));
237 paths = arg_user ? paths_user : paths_system;
238
239 i = PTR_TO_UINT(data);
240 assert(i < ELEMENTSOF(paths_system));
241
242 return sd_path_home(paths[i].type, paths[i].suffix, ret);
243 }
244
245 static int log_unresolvable_specifier(const char *filename, unsigned line) {
246 static bool notified = false;
247
248 /* In system mode, this is called when /etc is not fully initialized (e.g.
249 * in a chroot environment) where some specifiers are unresolvable. In user
250 * mode, this is called when some variables are not defined. These cases are
251 * not considered as an error so log at LOG_NOTICE only for the first time
252 * and then downgrade this to LOG_DEBUG for the rest. */
253
254 log_full(notified ? LOG_DEBUG : LOG_NOTICE,
255 "[%s:%u] Failed to resolve specifier: %s, skipping",
256 filename, line,
257 arg_user ? "Required $XDG_... variable not defined" : "uninitialized /etc detected");
258
259 if (!notified)
260 log_notice("All rules containing unresolvable specifiers will be skipped.");
261
262 notified = true;
263 return 0;
264 }
265
266 static int user_config_paths(char*** ret) {
267 _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
268 _cleanup_free_ char *persistent_config = NULL, *runtime_config = NULL, *data_home = NULL;
269 _cleanup_strv_free_ char **res = NULL;
270 int r;
271
272 r = xdg_user_dirs(&config_dirs, &data_dirs);
273 if (r < 0)
274 return r;
275
276 r = xdg_user_config_dir(&persistent_config, "/user-tmpfiles.d");
277 if (r < 0 && r != -ENXIO)
278 return r;
279
280 r = xdg_user_runtime_dir(&runtime_config, "/user-tmpfiles.d");
281 if (r < 0 && r != -ENXIO)
282 return r;
283
284 r = xdg_user_data_dir(&data_home, "/user-tmpfiles.d");
285 if (r < 0 && r != -ENXIO)
286 return r;
287
288 r = strv_extend_strv_concat(&res, config_dirs, "/user-tmpfiles.d");
289 if (r < 0)
290 return r;
291
292 r = strv_extend(&res, persistent_config);
293 if (r < 0)
294 return r;
295
296 r = strv_extend(&res, runtime_config);
297 if (r < 0)
298 return r;
299
300 r = strv_extend(&res, data_home);
301 if (r < 0)
302 return r;
303
304 r = strv_extend_strv_concat(&res, data_dirs, "/user-tmpfiles.d");
305 if (r < 0)
306 return r;
307
308 r = path_strv_make_absolute_cwd(res);
309 if (r < 0)
310 return r;
311
312 *ret = res;
313 res = NULL;
314 return 0;
315 }
316
317 static bool needs_glob(ItemType t) {
318 return IN_SET(t,
319 WRITE_FILE,
320 IGNORE_PATH,
321 IGNORE_DIRECTORY_PATH,
322 REMOVE_PATH,
323 RECURSIVE_REMOVE_PATH,
324 EMPTY_DIRECTORY,
325 ADJUST_MODE,
326 RELABEL_PATH,
327 RECURSIVE_RELABEL_PATH,
328 SET_XATTR,
329 RECURSIVE_SET_XATTR,
330 SET_ACL,
331 RECURSIVE_SET_ACL,
332 SET_ATTRIBUTE,
333 RECURSIVE_SET_ATTRIBUTE);
334 }
335
336 static bool takes_ownership(ItemType t) {
337 return IN_SET(t,
338 CREATE_FILE,
339 TRUNCATE_FILE,
340 CREATE_DIRECTORY,
341 EMPTY_DIRECTORY,
342 TRUNCATE_DIRECTORY,
343 CREATE_SUBVOLUME,
344 CREATE_SUBVOLUME_INHERIT_QUOTA,
345 CREATE_SUBVOLUME_NEW_QUOTA,
346 CREATE_FIFO,
347 CREATE_SYMLINK,
348 CREATE_CHAR_DEVICE,
349 CREATE_BLOCK_DEVICE,
350 COPY_FILES,
351 WRITE_FILE,
352 IGNORE_PATH,
353 IGNORE_DIRECTORY_PATH,
354 REMOVE_PATH,
355 RECURSIVE_REMOVE_PATH);
356 }
357
358 static struct Item* find_glob(OrderedHashmap *h, const char *match) {
359 ItemArray *j;
360 Iterator i;
361
362 ORDERED_HASHMAP_FOREACH(j, h, i) {
363 unsigned n;
364
365 for (n = 0; n < j->count; n++) {
366 Item *item = j->items + n;
367
368 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
369 return item;
370 }
371 }
372
373 return NULL;
374 }
375
376 static void load_unix_sockets(void) {
377 _cleanup_fclose_ FILE *f = NULL;
378 int r;
379
380 if (unix_sockets)
381 return;
382
383 /* We maintain a cache of the sockets we found in /proc/net/unix to speed things up a little. */
384
385 unix_sockets = set_new(&string_hash_ops);
386 if (!unix_sockets)
387 return;
388
389 f = fopen("/proc/net/unix", "re");
390 if (!f) {
391 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
392 "Failed to open /proc/net/unix, ignoring: %m");
393 goto fail;
394 }
395
396 /* Skip header */
397 r = read_line(f, LONG_LINE_MAX, NULL);
398 if (r < 0) {
399 log_warning_errno(r, "Failed to skip /proc/net/unix header line: %m");
400 goto fail;
401 }
402 if (r == 0) {
403 log_warning("Premature end of file reading /proc/net/unix.");
404 goto fail;
405 }
406
407 for (;;) {
408 _cleanup_free_ char *line = NULL;
409 char *p, *s;
410
411 r = read_line(f, LONG_LINE_MAX, &line);
412 if (r < 0) {
413 log_warning_errno(r, "Failed to read /proc/net/unix line, ignoring: %m");
414 goto fail;
415 }
416 if (r == 0) /* EOF */
417 break;
418
419 p = strchr(line, ':');
420 if (!p)
421 continue;
422
423 if (strlen(p) < 37)
424 continue;
425
426 p += 37;
427 p += strspn(p, WHITESPACE);
428 p += strcspn(p, WHITESPACE); /* skip one more word */
429 p += strspn(p, WHITESPACE);
430
431 if (*p != '/')
432 continue;
433
434 s = strdup(p);
435 if (!s) {
436 log_oom();
437 goto fail;
438 }
439
440 path_kill_slashes(s);
441
442 r = set_consume(unix_sockets, s);
443 if (r < 0 && r != -EEXIST) {
444 log_warning_errno(r, "Failed to add AF_UNIX socket to set, ignoring: %m");
445 goto fail;
446 }
447 }
448
449 return;
450
451 fail:
452 unix_sockets = set_free_free(unix_sockets);
453 }
454
455 static bool unix_socket_alive(const char *fn) {
456 assert(fn);
457
458 load_unix_sockets();
459
460 if (unix_sockets)
461 return !!set_get(unix_sockets, (char*) fn);
462
463 /* We don't know, so assume yes */
464 return true;
465 }
466
467 static int dir_is_mount_point(DIR *d, const char *subdir) {
468
469 int mount_id_parent, mount_id;
470 int r_p, r;
471
472 r_p = name_to_handle_at_loop(dirfd(d), ".", NULL, &mount_id_parent, 0);
473 if (r_p < 0)
474 r_p = -errno;
475
476 r = name_to_handle_at_loop(dirfd(d), subdir, NULL, &mount_id, 0);
477 if (r < 0)
478 r = -errno;
479
480 /* got no handle; make no assumptions, return error */
481 if (r_p < 0 && r < 0)
482 return r_p;
483
484 /* got both handles; if they differ, it is a mount point */
485 if (r_p >= 0 && r >= 0)
486 return mount_id_parent != mount_id;
487
488 /* got only one handle; assume different mount points if one
489 * of both queries was not supported by the filesystem */
490 if (IN_SET(r_p, -ENOSYS, -EOPNOTSUPP) || IN_SET(r, -ENOSYS, -EOPNOTSUPP))
491 return true;
492
493 /* return error */
494 if (r_p < 0)
495 return r_p;
496 return r;
497 }
498
499 static DIR* xopendirat_nomod(int dirfd, const char *path) {
500 DIR *dir;
501
502 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
503 if (dir)
504 return dir;
505
506 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
507 if (errno != EPERM)
508 return NULL;
509
510 dir = xopendirat(dirfd, path, O_NOFOLLOW);
511 if (!dir)
512 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
513
514 return dir;
515 }
516
517 static DIR* opendir_nomod(const char *path) {
518 return xopendirat_nomod(AT_FDCWD, path);
519 }
520
521 static int dir_cleanup(
522 Item *i,
523 const char *p,
524 DIR *d,
525 const struct stat *ds,
526 usec_t cutoff,
527 dev_t rootdev,
528 bool mountpoint,
529 int maxdepth,
530 bool keep_this_level) {
531
532 struct dirent *dent;
533 struct timespec times[2];
534 bool deleted = false;
535 int r = 0;
536
537 FOREACH_DIRENT_ALL(dent, d, break) {
538 struct stat s;
539 usec_t age;
540 _cleanup_free_ char *sub_path = NULL;
541
542 if (dot_or_dot_dot(dent->d_name))
543 continue;
544
545 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
546 if (errno == ENOENT)
547 continue;
548
549 /* FUSE, NFS mounts, SELinux might return EACCES */
550 r = log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
551 "stat(%s/%s) failed: %m", p, dent->d_name);
552 continue;
553 }
554
555 /* Stay on the same filesystem */
556 if (s.st_dev != rootdev) {
557 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
558 continue;
559 }
560
561 /* Try to detect bind mounts of the same filesystem instance; they
562 * do not differ in device major/minors. This type of query is not
563 * supported on all kernels or filesystem types though. */
564 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
565 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
566 p, dent->d_name);
567 continue;
568 }
569
570 /* Do not delete read-only files owned by root */
571 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
572 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
573 continue;
574 }
575
576 sub_path = strjoin(p, "/", dent->d_name);
577 if (!sub_path) {
578 r = log_oom();
579 goto finish;
580 }
581
582 /* Is there an item configured for this path? */
583 if (ordered_hashmap_get(items, sub_path)) {
584 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
585 continue;
586 }
587
588 if (find_glob(globs, sub_path)) {
589 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
590 continue;
591 }
592
593 if (S_ISDIR(s.st_mode)) {
594
595 if (mountpoint &&
596 streq(dent->d_name, "lost+found") &&
597 s.st_uid == 0) {
598 log_debug("Ignoring \"%s\".", sub_path);
599 continue;
600 }
601
602 if (maxdepth <= 0)
603 log_warning("Reached max depth on \"%s\".", sub_path);
604 else {
605 _cleanup_closedir_ DIR *sub_dir;
606 int q;
607
608 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
609 if (!sub_dir) {
610 if (errno != ENOENT)
611 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
612
613 continue;
614 }
615
616 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
617 if (q < 0)
618 r = q;
619 }
620
621 /* Note: if you are wondering why we don't
622 * support the sticky bit for excluding
623 * directories from cleaning like we do it for
624 * other file system objects: well, the sticky
625 * bit already has a meaning for directories,
626 * so we don't want to overload that. */
627
628 if (keep_this_level) {
629 log_debug("Keeping \"%s\".", sub_path);
630 continue;
631 }
632
633 /* Ignore ctime, we change it when deleting */
634 age = timespec_load(&s.st_mtim);
635 if (age >= cutoff) {
636 char a[FORMAT_TIMESTAMP_MAX];
637 /* Follows spelling in stat(1). */
638 log_debug("Directory \"%s\": modify time %s is too new.",
639 sub_path,
640 format_timestamp_us(a, sizeof(a), age));
641 continue;
642 }
643
644 age = timespec_load(&s.st_atim);
645 if (age >= cutoff) {
646 char a[FORMAT_TIMESTAMP_MAX];
647 log_debug("Directory \"%s\": access time %s is too new.",
648 sub_path,
649 format_timestamp_us(a, sizeof(a), age));
650 continue;
651 }
652
653 log_debug("Removing directory \"%s\".", sub_path);
654 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
655 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
656 r = log_error_errno(errno, "rmdir(%s): %m", sub_path);
657
658 } else {
659 /* Skip files for which the sticky bit is
660 * set. These are semantics we define, and are
661 * unknown elsewhere. See XDG_RUNTIME_DIR
662 * specification for details. */
663 if (s.st_mode & S_ISVTX) {
664 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
665 continue;
666 }
667
668 if (mountpoint && S_ISREG(s.st_mode))
669 if (s.st_uid == 0 && STR_IN_SET(dent->d_name,
670 ".journal",
671 "aquota.user",
672 "aquota.group")) {
673 log_debug("Skipping \"%s\".", sub_path);
674 continue;
675 }
676
677 /* Ignore sockets that are listed in /proc/net/unix */
678 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
679 log_debug("Skipping \"%s\": live socket.", sub_path);
680 continue;
681 }
682
683 /* Ignore device nodes */
684 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
685 log_debug("Skipping \"%s\": a device.", sub_path);
686 continue;
687 }
688
689 /* Keep files on this level around if this is
690 * requested */
691 if (keep_this_level) {
692 log_debug("Keeping \"%s\".", sub_path);
693 continue;
694 }
695
696 age = timespec_load(&s.st_mtim);
697 if (age >= cutoff) {
698 char a[FORMAT_TIMESTAMP_MAX];
699 /* Follows spelling in stat(1). */
700 log_debug("File \"%s\": modify time %s is too new.",
701 sub_path,
702 format_timestamp_us(a, sizeof(a), age));
703 continue;
704 }
705
706 age = timespec_load(&s.st_atim);
707 if (age >= cutoff) {
708 char a[FORMAT_TIMESTAMP_MAX];
709 log_debug("File \"%s\": access time %s is too new.",
710 sub_path,
711 format_timestamp_us(a, sizeof(a), age));
712 continue;
713 }
714
715 age = timespec_load(&s.st_ctim);
716 if (age >= cutoff) {
717 char a[FORMAT_TIMESTAMP_MAX];
718 log_debug("File \"%s\": change time %s is too new.",
719 sub_path,
720 format_timestamp_us(a, sizeof(a), age));
721 continue;
722 }
723
724 log_debug("unlink \"%s\"", sub_path);
725
726 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
727 if (errno != ENOENT)
728 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
729
730 deleted = true;
731 }
732 }
733
734 finish:
735 if (deleted) {
736 usec_t age1, age2;
737 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
738
739 /* Restore original directory timestamps */
740 times[0] = ds->st_atim;
741 times[1] = ds->st_mtim;
742
743 age1 = timespec_load(&ds->st_atim);
744 age2 = timespec_load(&ds->st_mtim);
745 log_debug("Restoring access and modification time on \"%s\": %s, %s",
746 p,
747 format_timestamp_us(a, sizeof(a), age1),
748 format_timestamp_us(b, sizeof(b), age2));
749 if (futimens(dirfd(d), times) < 0)
750 log_error_errno(errno, "utimensat(%s): %m", p);
751 }
752
753 return r;
754 }
755
756 static int path_set_perms(Item *i, const char *path) {
757 _cleanup_close_ int fd = -1;
758 struct stat st;
759
760 assert(i);
761 assert(path);
762
763 /* We open the file with O_PATH here, to make the operation
764 * somewhat atomic. Also there's unfortunately no fchmodat()
765 * with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
766 * O_PATH. */
767
768 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
769 if (fd < 0) {
770 int level = LOG_ERR, r = -errno;
771
772 /* Option "e" operates only on existing objects. Do not
773 * print errors about non-existent files or directories */
774 if (i->type == EMPTY_DIRECTORY && errno == ENOENT) {
775 level = LOG_DEBUG;
776 r = 0;
777 }
778
779 log_full_errno(level, errno, "Adjusting owner and mode for %s failed: %m", path);
780
781 return r;
782 }
783
784 if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
785 return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
786
787 if (S_ISLNK(st.st_mode))
788 log_debug("Skipping mode and owner fix for symlink %s.", path);
789 else {
790 char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
791 xsprintf(fn, "/proc/self/fd/%i", fd);
792
793 /* not using i->path directly because it may be a glob */
794 if (i->mode_set) {
795 mode_t m = i->mode;
796
797 if (i->mask_perms) {
798 if (!(st.st_mode & 0111))
799 m &= ~0111;
800 if (!(st.st_mode & 0222))
801 m &= ~0222;
802 if (!(st.st_mode & 0444))
803 m &= ~0444;
804 if (!S_ISDIR(st.st_mode))
805 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
806 }
807
808 if (m == (st.st_mode & 07777))
809 log_debug("\"%s\" has right mode %o", path, st.st_mode);
810 else {
811 log_debug("chmod \"%s\" to mode %o", path, m);
812 if (chmod(fn, m) < 0)
813 return log_error_errno(errno, "chmod() of %s via %s failed: %m", path, fn);
814 }
815 }
816
817 if ((i->uid != st.st_uid || i->gid != st.st_gid) &&
818 (i->uid_set || i->gid_set)) {
819 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
820 path,
821 i->uid_set ? i->uid : UID_INVALID,
822 i->gid_set ? i->gid : GID_INVALID);
823 if (chown(fn,
824 i->uid_set ? i->uid : UID_INVALID,
825 i->gid_set ? i->gid : GID_INVALID) < 0)
826 return log_error_errno(errno, "chown() of %s via %s failed: %m", path, fn);
827 }
828 }
829
830 fd = safe_close(fd);
831
832 return label_fix(path, false, false);
833 }
834
835 static int parse_xattrs_from_arg(Item *i) {
836 const char *p;
837 int r;
838
839 assert(i);
840 assert(i->argument);
841
842 p = i->argument;
843
844 for (;;) {
845 _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL;
846
847 r = extract_first_word(&p, &xattr, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
848 if (r < 0)
849 log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p);
850 if (r <= 0)
851 break;
852
853 r = split_pair(xattr, "=", &name, &value);
854 if (r < 0) {
855 log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr);
856 continue;
857 }
858
859 if (isempty(name) || isempty(value)) {
860 log_warning("Malformed extended attribute found, ignoring: %s", xattr);
861 continue;
862 }
863
864 if (strv_push_pair(&i->xattrs, name, value) < 0)
865 return log_oom();
866
867 name = value = NULL;
868 }
869
870 return 0;
871 }
872
873 static int path_set_xattrs(Item *i, const char *path) {
874 char **name, **value;
875
876 assert(i);
877 assert(path);
878
879 STRV_FOREACH_PAIR(name, value, i->xattrs) {
880 int n;
881
882 n = strlen(*value);
883 log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
884 if (lsetxattr(path, *name, *value, n, 0) < 0)
885 return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m",
886 *name, *value, path);
887 }
888 return 0;
889 }
890
891 static int parse_acls_from_arg(Item *item) {
892 #if HAVE_ACL
893 int r;
894
895 assert(item);
896
897 /* If force (= modify) is set, we will not modify the acl
898 * afterwards, so the mask can be added now if necessary. */
899
900 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
901 if (r < 0)
902 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument);
903 #else
904 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
905 #endif
906
907 return 0;
908 }
909
910 #if HAVE_ACL
911 static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) {
912 _cleanup_(acl_free_charpp) char *t = NULL;
913 _cleanup_(acl_freep) acl_t dup = NULL;
914 int r;
915
916 /* Returns 0 for success, positive error if already warned,
917 * negative error otherwise. */
918
919 if (modify) {
920 r = acls_for_file(path, type, acl, &dup);
921 if (r < 0)
922 return r;
923
924 r = calc_acl_mask_if_needed(&dup);
925 if (r < 0)
926 return r;
927 } else {
928 dup = acl_dup(acl);
929 if (!dup)
930 return -errno;
931
932 /* the mask was already added earlier if needed */
933 }
934
935 r = add_base_acls_if_needed(&dup, path);
936 if (r < 0)
937 return r;
938
939 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
940 log_debug("Setting %s ACL %s on %s.",
941 type == ACL_TYPE_ACCESS ? "access" : "default",
942 strna(t), pretty);
943
944 r = acl_set_file(path, type, dup);
945 if (r < 0)
946 /* Return positive to indicate we already warned */
947 return -log_error_errno(errno,
948 "Setting %s ACL \"%s\" on %s failed: %m",
949 type == ACL_TYPE_ACCESS ? "access" : "default",
950 strna(t), pretty);
951
952 return 0;
953 }
954 #endif
955
956 static int path_set_acls(Item *item, const char *path) {
957 int r = 0;
958 #if HAVE_ACL
959 char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
960 _cleanup_close_ int fd = -1;
961 struct stat st;
962
963 assert(item);
964 assert(path);
965
966 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
967 if (fd < 0)
968 return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
969
970 if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
971 return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
972
973 if (S_ISLNK(st.st_mode)) {
974 log_debug("Skipping ACL fix for symlink %s.", path);
975 return 0;
976 }
977
978 xsprintf(fn, "/proc/self/fd/%i", fd);
979
980 if (item->acl_access)
981 r = path_set_acl(fn, path, ACL_TYPE_ACCESS, item->acl_access, item->force);
982
983 if (r == 0 && item->acl_default)
984 r = path_set_acl(fn, path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
985
986 if (r > 0)
987 return -r; /* already warned */
988 else if (r == -EOPNOTSUPP) {
989 log_debug_errno(r, "ACLs not supported by file system at %s", path);
990 return 0;
991 } else if (r < 0)
992 log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
993 #endif
994 return r;
995 }
996
997 #define ATTRIBUTES_ALL \
998 (FS_NOATIME_FL | \
999 FS_SYNC_FL | \
1000 FS_DIRSYNC_FL | \
1001 FS_APPEND_FL | \
1002 FS_COMPR_FL | \
1003 FS_NODUMP_FL | \
1004 FS_EXTENT_FL | \
1005 FS_IMMUTABLE_FL | \
1006 FS_JOURNAL_DATA_FL | \
1007 FS_SECRM_FL | \
1008 FS_UNRM_FL | \
1009 FS_NOTAIL_FL | \
1010 FS_TOPDIR_FL | \
1011 FS_NOCOW_FL)
1012
1013 static int parse_attribute_from_arg(Item *item) {
1014
1015 static const struct {
1016 char character;
1017 unsigned value;
1018 } attributes[] = {
1019 { 'A', FS_NOATIME_FL }, /* do not update atime */
1020 { 'S', FS_SYNC_FL }, /* Synchronous updates */
1021 { 'D', FS_DIRSYNC_FL }, /* dirsync behaviour (directories only) */
1022 { 'a', FS_APPEND_FL }, /* writes to file may only append */
1023 { 'c', FS_COMPR_FL }, /* Compress file */
1024 { 'd', FS_NODUMP_FL }, /* do not dump file */
1025 { 'e', FS_EXTENT_FL }, /* Extents */
1026 { 'i', FS_IMMUTABLE_FL }, /* Immutable file */
1027 { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */
1028 { 's', FS_SECRM_FL }, /* Secure deletion */
1029 { 'u', FS_UNRM_FL }, /* Undelete */
1030 { 't', FS_NOTAIL_FL }, /* file tail should not be merged */
1031 { 'T', FS_TOPDIR_FL }, /* Top of directory hierarchies */
1032 { 'C', FS_NOCOW_FL }, /* Do not cow file */
1033 };
1034
1035 enum {
1036 MODE_ADD,
1037 MODE_DEL,
1038 MODE_SET
1039 } mode = MODE_ADD;
1040
1041 unsigned value = 0, mask = 0;
1042 const char *p;
1043
1044 assert(item);
1045
1046 p = item->argument;
1047 if (p) {
1048 if (*p == '+') {
1049 mode = MODE_ADD;
1050 p++;
1051 } else if (*p == '-') {
1052 mode = MODE_DEL;
1053 p++;
1054 } else if (*p == '=') {
1055 mode = MODE_SET;
1056 p++;
1057 }
1058 }
1059
1060 if (isempty(p) && mode != MODE_SET) {
1061 log_error("Setting file attribute on '%s' needs an attribute specification.", item->path);
1062 return -EINVAL;
1063 }
1064
1065 for (; p && *p ; p++) {
1066 unsigned i, v;
1067
1068 for (i = 0; i < ELEMENTSOF(attributes); i++)
1069 if (*p == attributes[i].character)
1070 break;
1071
1072 if (i >= ELEMENTSOF(attributes)) {
1073 log_error("Unknown file attribute '%c' on '%s'.", *p, item->path);
1074 return -EINVAL;
1075 }
1076
1077 v = attributes[i].value;
1078
1079 SET_FLAG(value, v, IN_SET(mode, MODE_ADD, MODE_SET));
1080
1081 mask |= v;
1082 }
1083
1084 if (mode == MODE_SET)
1085 mask |= ATTRIBUTES_ALL;
1086
1087 assert(mask != 0);
1088
1089 item->attribute_mask = mask;
1090 item->attribute_value = value;
1091 item->attribute_set = true;
1092
1093 return 0;
1094 }
1095
1096 static int path_set_attribute(Item *item, const char *path) {
1097 _cleanup_close_ int fd = -1;
1098 struct stat st;
1099 unsigned f;
1100 int r;
1101
1102 if (!item->attribute_set || item->attribute_mask == 0)
1103 return 0;
1104
1105 fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOATIME|O_NOFOLLOW);
1106 if (fd < 0) {
1107 if (errno == ELOOP)
1108 return log_error_errno(errno, "Skipping file attributes adjustment on symlink %s.", path);
1109
1110 return log_error_errno(errno, "Cannot open '%s': %m", path);
1111 }
1112
1113 if (fstat(fd, &st) < 0)
1114 return log_error_errno(errno, "Cannot stat '%s': %m", path);
1115
1116 /* Issuing the file attribute ioctls on device nodes is not
1117 * safe, as that will be delivered to the drivers, not the
1118 * file system containing the device node. */
1119 if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
1120 log_error("Setting file flags is only supported on regular files and directories, cannot set on '%s'.", path);
1121 return -EINVAL;
1122 }
1123
1124 f = item->attribute_value & item->attribute_mask;
1125
1126 /* Mask away directory-specific flags */
1127 if (!S_ISDIR(st.st_mode))
1128 f &= ~FS_DIRSYNC_FL;
1129
1130 r = chattr_fd(fd, f, item->attribute_mask);
1131 if (r < 0)
1132 log_full_errno(IN_SET(r, -ENOTTY, -EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING,
1133 r,
1134 "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m",
1135 path, item->attribute_value, item->attribute_mask);
1136
1137 return 0;
1138 }
1139
1140 static int write_one_file(Item *i, const char *path) {
1141 _cleanup_close_ int fd = -1;
1142 int flags, r = 0;
1143 struct stat st;
1144
1145 assert(i);
1146 assert(path);
1147
1148 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
1149 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
1150
1151 RUN_WITH_UMASK(0000) {
1152 mac_selinux_create_file_prepare(path, S_IFREG);
1153 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
1154 mac_selinux_create_file_clear();
1155 }
1156
1157 if (fd < 0) {
1158 if (i->type == WRITE_FILE && errno == ENOENT) {
1159 log_debug_errno(errno, "Not writing \"%s\": %m", path);
1160 return 0;
1161 }
1162
1163 r = -errno;
1164 if (!i->argument && errno == EROFS && stat(path, &st) == 0 &&
1165 (i->type == CREATE_FILE || st.st_size == 0))
1166 goto check_mode;
1167
1168 return log_error_errno(r, "Failed to create file %s: %m", path);
1169 }
1170
1171 if (i->argument) {
1172 log_debug("%s to \"%s\".", i->type == CREATE_FILE ? "Appending" : "Writing", path);
1173
1174 r = loop_write(fd, i->argument, strlen(i->argument), false);
1175 if (r < 0)
1176 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
1177 } else
1178 log_debug("\"%s\" has been created.", path);
1179
1180 fd = safe_close(fd);
1181
1182 if (stat(path, &st) < 0)
1183 return log_error_errno(errno, "stat(%s) failed: %m", path);
1184
1185 check_mode:
1186 if (!S_ISREG(st.st_mode)) {
1187 log_error("%s is not a file.", path);
1188 return -EEXIST;
1189 }
1190
1191 r = path_set_perms(i, path);
1192 if (r < 0)
1193 return r;
1194
1195 return 0;
1196 }
1197
1198 typedef int (*action_t)(Item *, const char *);
1199
1200 static int item_do_children(Item *i, const char *path, action_t action) {
1201 _cleanup_closedir_ DIR *d;
1202 struct dirent *de;
1203 int r = 0;
1204
1205 assert(i);
1206 assert(path);
1207
1208 /* This returns the first error we run into, but nevertheless
1209 * tries to go on */
1210
1211 d = opendir_nomod(path);
1212 if (!d)
1213 return IN_SET(errno, ENOENT, ENOTDIR, ELOOP) ? 0 : -errno;
1214
1215 FOREACH_DIRENT_ALL(de, d, r = -errno) {
1216 _cleanup_free_ char *p = NULL;
1217 int q;
1218
1219 if (dot_or_dot_dot(de->d_name))
1220 continue;
1221
1222 p = strjoin(path, "/", de->d_name);
1223 if (!p)
1224 return -ENOMEM;
1225
1226 q = action(i, p);
1227 if (q < 0 && q != -ENOENT && r == 0)
1228 r = q;
1229
1230 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
1231 q = item_do_children(i, p, action);
1232 if (q < 0 && r == 0)
1233 r = q;
1234 }
1235 }
1236
1237 return r;
1238 }
1239
1240 static int glob_item(Item *i, action_t action, bool recursive) {
1241 _cleanup_globfree_ glob_t g = {
1242 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
1243 };
1244 int r = 0, k;
1245 char **fn;
1246
1247 k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
1248 if (k < 0 && k != -ENOENT)
1249 return log_error_errno(k, "glob(%s) failed: %m", i->path);
1250
1251 STRV_FOREACH(fn, g.gl_pathv) {
1252 k = action(i, *fn);
1253 if (k < 0 && r == 0)
1254 r = k;
1255
1256 if (recursive) {
1257 k = item_do_children(i, *fn, action);
1258 if (k < 0 && r == 0)
1259 r = k;
1260 }
1261 }
1262
1263 return r;
1264 }
1265
1266 typedef enum {
1267 CREATION_NORMAL,
1268 CREATION_EXISTING,
1269 CREATION_FORCE,
1270 _CREATION_MODE_MAX,
1271 _CREATION_MODE_INVALID = -1
1272 } CreationMode;
1273
1274 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
1275 [CREATION_NORMAL] = "Created",
1276 [CREATION_EXISTING] = "Found existing",
1277 [CREATION_FORCE] = "Created replacement",
1278 };
1279
1280 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
1281
1282 static int create_item(Item *i) {
1283 struct stat st;
1284 int r = 0;
1285 int q = 0;
1286 CreationMode creation;
1287
1288 assert(i);
1289
1290 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
1291
1292 switch (i->type) {
1293
1294 case IGNORE_PATH:
1295 case IGNORE_DIRECTORY_PATH:
1296 case REMOVE_PATH:
1297 case RECURSIVE_REMOVE_PATH:
1298 return 0;
1299
1300 case CREATE_FILE:
1301 case TRUNCATE_FILE:
1302 r = write_one_file(i, i->path);
1303 if (r < 0)
1304 return r;
1305 break;
1306
1307 case COPY_FILES: {
1308 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1309 r = copy_tree(i->argument, i->path, i->uid_set ? i->uid : UID_INVALID, i->gid_set ? i->gid : GID_INVALID, COPY_REFLINK);
1310
1311 if (r == -EROFS && stat(i->path, &st) == 0)
1312 r = -EEXIST;
1313
1314 if (r < 0) {
1315 struct stat a, b;
1316
1317 if (r != -EEXIST)
1318 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1319
1320 if (stat(i->argument, &a) < 0)
1321 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
1322
1323 if (stat(i->path, &b) < 0)
1324 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1325
1326 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
1327 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1328 return 0;
1329 }
1330 }
1331
1332 r = path_set_perms(i, i->path);
1333 if (r < 0)
1334 return r;
1335
1336 break;
1337
1338 case WRITE_FILE:
1339 r = glob_item(i, write_one_file, false);
1340 if (r < 0)
1341 return r;
1342
1343 break;
1344
1345 case CREATE_DIRECTORY:
1346 case TRUNCATE_DIRECTORY:
1347 case CREATE_SUBVOLUME:
1348 case CREATE_SUBVOLUME_INHERIT_QUOTA:
1349 case CREATE_SUBVOLUME_NEW_QUOTA:
1350 RUN_WITH_UMASK(0000)
1351 mkdir_parents_label(i->path, 0755);
1352
1353 if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {
1354
1355 if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)
1356
1357 /* Don't create a subvolume unless the
1358 * root directory is one, too. We do
1359 * this under the assumption that if
1360 * the root directory is just a plain
1361 * directory (i.e. very light-weight),
1362 * we shouldn't try to split it up
1363 * into subvolumes (i.e. more
1364 * heavy-weight). Thus, chroot()
1365 * environments and suchlike will get
1366 * a full brtfs subvolume set up below
1367 * their tree only if they
1368 * specifically set up a btrfs
1369 * subvolume for the root dir too. */
1370
1371 r = -ENOTTY;
1372 else {
1373 RUN_WITH_UMASK((~i->mode) & 0777)
1374 r = btrfs_subvol_make(i->path);
1375 }
1376 } else
1377 r = 0;
1378
1379 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
1380 RUN_WITH_UMASK(0000)
1381 r = mkdir_label(i->path, i->mode);
1382
1383 if (r < 0) {
1384 int k;
1385
1386 if (!IN_SET(r, -EEXIST, -EROFS))
1387 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1388
1389 k = is_dir(i->path, false);
1390 if (k == -ENOENT && r == -EROFS)
1391 return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", i->path);
1392 if (k < 0)
1393 return log_error_errno(k, "Failed to check if %s exists: %m", i->path);
1394 if (!k) {
1395 log_warning("\"%s\" already exists and is not a directory.", i->path);
1396 return 0;
1397 }
1398
1399 creation = CREATION_EXISTING;
1400 } else
1401 creation = CREATION_NORMAL;
1402
1403 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1404
1405 if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
1406 r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
1407 if (r == -ENOTTY)
1408 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path);
1409 else if (r == -EROFS)
1410 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path);
1411 else if (r == -ENOPROTOOPT)
1412 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path);
1413 else if (r < 0)
1414 q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
1415 else if (r > 0)
1416 log_debug("Adjusted quota for subvolume \"%s\".", i->path);
1417 else if (r == 0)
1418 log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
1419 }
1420
1421 _fallthrough_;
1422 case EMPTY_DIRECTORY:
1423 r = path_set_perms(i, i->path);
1424 if (q < 0)
1425 return q;
1426 if (r < 0)
1427 return r;
1428
1429 break;
1430
1431 case CREATE_FIFO:
1432 RUN_WITH_UMASK(0000) {
1433 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1434 r = mkfifo(i->path, i->mode);
1435 mac_selinux_create_file_clear();
1436 }
1437
1438 if (r < 0) {
1439 if (errno != EEXIST)
1440 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1441
1442 if (lstat(i->path, &st) < 0)
1443 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1444
1445 if (!S_ISFIFO(st.st_mode)) {
1446
1447 if (i->force) {
1448 RUN_WITH_UMASK(0000) {
1449 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1450 r = mkfifo_atomic(i->path, i->mode);
1451 mac_selinux_create_file_clear();
1452 }
1453
1454 if (r < 0)
1455 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1456 creation = CREATION_FORCE;
1457 } else {
1458 log_warning("\"%s\" already exists and is not a fifo.", i->path);
1459 return 0;
1460 }
1461 } else
1462 creation = CREATION_EXISTING;
1463 } else
1464 creation = CREATION_NORMAL;
1465 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1466
1467 r = path_set_perms(i, i->path);
1468 if (r < 0)
1469 return r;
1470
1471 break;
1472 }
1473
1474 case CREATE_SYMLINK: {
1475 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1476 r = symlink(i->argument, i->path);
1477 mac_selinux_create_file_clear();
1478
1479 if (r < 0) {
1480 _cleanup_free_ char *x = NULL;
1481
1482 if (errno != EEXIST)
1483 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1484
1485 r = readlink_malloc(i->path, &x);
1486 if (r < 0 || !streq(i->argument, x)) {
1487
1488 if (i->force) {
1489 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1490 r = symlink_atomic(i->argument, i->path);
1491 mac_selinux_create_file_clear();
1492
1493 if (IN_SET(r, -EEXIST, -ENOTEMPTY)) {
1494 r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL);
1495 if (r < 0)
1496 return log_error_errno(r, "rm -fr %s failed: %m", i->path);
1497
1498 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1499 r = symlink(i->argument, i->path) < 0 ? -errno : 0;
1500 mac_selinux_create_file_clear();
1501 }
1502 if (r < 0)
1503 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1504
1505 creation = CREATION_FORCE;
1506 } else {
1507 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1508 return 0;
1509 }
1510 } else
1511 creation = CREATION_EXISTING;
1512 } else
1513
1514 creation = CREATION_NORMAL;
1515 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1516 break;
1517 }
1518
1519 case CREATE_BLOCK_DEVICE:
1520 case CREATE_CHAR_DEVICE: {
1521 mode_t file_type;
1522
1523 if (have_effective_cap(CAP_MKNOD) == 0) {
1524 /* In a container we lack CAP_MKNOD. We
1525 shouldn't attempt to create the device node in
1526 that case to avoid noise, and we don't support
1527 virtualized devices in containers anyway. */
1528
1529 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1530 return 0;
1531 }
1532
1533 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1534
1535 RUN_WITH_UMASK(0000) {
1536 mac_selinux_create_file_prepare(i->path, file_type);
1537 r = mknod(i->path, i->mode | file_type, i->major_minor);
1538 mac_selinux_create_file_clear();
1539 }
1540
1541 if (r < 0) {
1542 if (errno == EPERM) {
1543 log_debug("We lack permissions, possibly because of cgroup configuration; "
1544 "skipping creation of device node %s.", i->path);
1545 return 0;
1546 }
1547
1548 if (errno != EEXIST)
1549 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1550
1551 if (lstat(i->path, &st) < 0)
1552 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1553
1554 if ((st.st_mode & S_IFMT) != file_type) {
1555
1556 if (i->force) {
1557
1558 RUN_WITH_UMASK(0000) {
1559 mac_selinux_create_file_prepare(i->path, file_type);
1560 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1561 mac_selinux_create_file_clear();
1562 }
1563
1564 if (r < 0)
1565 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1566 creation = CREATION_FORCE;
1567 } else {
1568 log_debug("%s is not a device node.", i->path);
1569 return 0;
1570 }
1571 } else
1572 creation = CREATION_EXISTING;
1573 } else
1574 creation = CREATION_NORMAL;
1575
1576 log_debug("%s %s device node \"%s\" %u:%u.",
1577 creation_mode_verb_to_string(creation),
1578 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1579 i->path, major(i->mode), minor(i->mode));
1580
1581 r = path_set_perms(i, i->path);
1582 if (r < 0)
1583 return r;
1584
1585 break;
1586 }
1587
1588 case ADJUST_MODE:
1589 case RELABEL_PATH:
1590 r = glob_item(i, path_set_perms, false);
1591 if (r < 0)
1592 return r;
1593 break;
1594
1595 case RECURSIVE_RELABEL_PATH:
1596 r = glob_item(i, path_set_perms, true);
1597 if (r < 0)
1598 return r;
1599 break;
1600
1601 case SET_XATTR:
1602 r = glob_item(i, path_set_xattrs, false);
1603 if (r < 0)
1604 return r;
1605 break;
1606
1607 case RECURSIVE_SET_XATTR:
1608 r = glob_item(i, path_set_xattrs, true);
1609 if (r < 0)
1610 return r;
1611 break;
1612
1613 case SET_ACL:
1614 r = glob_item(i, path_set_acls, false);
1615 if (r < 0)
1616 return r;
1617 break;
1618
1619 case RECURSIVE_SET_ACL:
1620 r = glob_item(i, path_set_acls, true);
1621 if (r < 0)
1622 return r;
1623 break;
1624
1625 case SET_ATTRIBUTE:
1626 r = glob_item(i, path_set_attribute, false);
1627 if (r < 0)
1628 return r;
1629 break;
1630
1631 case RECURSIVE_SET_ATTRIBUTE:
1632 r = glob_item(i, path_set_attribute, true);
1633 if (r < 0)
1634 return r;
1635 break;
1636 }
1637
1638 return 0;
1639 }
1640
1641 static int remove_item_instance(Item *i, const char *instance) {
1642 int r;
1643
1644 assert(i);
1645
1646 switch (i->type) {
1647
1648 case REMOVE_PATH:
1649 if (remove(instance) < 0 && errno != ENOENT)
1650 return log_error_errno(errno, "rm(%s): %m", instance);
1651
1652 break;
1653
1654 case TRUNCATE_DIRECTORY:
1655 case RECURSIVE_REMOVE_PATH:
1656 /* FIXME: we probably should use dir_cleanup() here
1657 * instead of rm_rf() so that 'x' is honoured. */
1658 log_debug("rm -rf \"%s\"", instance);
1659 r = rm_rf(instance, (i->type == RECURSIVE_REMOVE_PATH ? REMOVE_ROOT|REMOVE_SUBVOLUME : 0) | REMOVE_PHYSICAL);
1660 if (r < 0 && r != -ENOENT)
1661 return log_error_errno(r, "rm_rf(%s): %m", instance);
1662
1663 break;
1664
1665 default:
1666 assert_not_reached("wut?");
1667 }
1668
1669 return 0;
1670 }
1671
1672 static int remove_item(Item *i) {
1673 assert(i);
1674
1675 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1676
1677 switch (i->type) {
1678
1679 case REMOVE_PATH:
1680 case TRUNCATE_DIRECTORY:
1681 case RECURSIVE_REMOVE_PATH:
1682 return glob_item(i, remove_item_instance, false);
1683
1684 default:
1685 return 0;
1686 }
1687 }
1688
1689 static int clean_item_instance(Item *i, const char* instance) {
1690 _cleanup_closedir_ DIR *d = NULL;
1691 struct stat s, ps;
1692 bool mountpoint;
1693 usec_t cutoff, n;
1694 char timestamp[FORMAT_TIMESTAMP_MAX];
1695
1696 assert(i);
1697
1698 if (!i->age_set)
1699 return 0;
1700
1701 n = now(CLOCK_REALTIME);
1702 if (n < i->age)
1703 return 0;
1704
1705 cutoff = n - i->age;
1706
1707 d = opendir_nomod(instance);
1708 if (!d) {
1709 if (IN_SET(errno, ENOENT, ENOTDIR)) {
1710 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1711 return 0;
1712 }
1713
1714 return log_error_errno(errno, "Failed to open directory %s: %m", instance);
1715 }
1716
1717 if (fstat(dirfd(d), &s) < 0)
1718 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1719
1720 if (!S_ISDIR(s.st_mode)) {
1721 log_error("%s is not a directory.", i->path);
1722 return -ENOTDIR;
1723 }
1724
1725 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1726 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1727
1728 mountpoint = s.st_dev != ps.st_dev || s.st_ino == ps.st_ino;
1729
1730 log_debug("Cleanup threshold for %s \"%s\" is %s",
1731 mountpoint ? "mount point" : "directory",
1732 instance,
1733 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1734
1735 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1736 MAX_DEPTH, i->keep_first_level);
1737 }
1738
1739 static int clean_item(Item *i) {
1740 assert(i);
1741
1742 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1743
1744 switch (i->type) {
1745 case CREATE_DIRECTORY:
1746 case CREATE_SUBVOLUME:
1747 case CREATE_SUBVOLUME_INHERIT_QUOTA:
1748 case CREATE_SUBVOLUME_NEW_QUOTA:
1749 case TRUNCATE_DIRECTORY:
1750 case IGNORE_PATH:
1751 case COPY_FILES:
1752 clean_item_instance(i, i->path);
1753 return 0;
1754 case EMPTY_DIRECTORY:
1755 case IGNORE_DIRECTORY_PATH:
1756 return glob_item(i, clean_item_instance, false);
1757 default:
1758 return 0;
1759 }
1760 }
1761
1762 static int process_item_array(ItemArray *array);
1763
1764 static int process_item(Item *i) {
1765 int r, q, p, t = 0;
1766 _cleanup_free_ char *prefix = NULL;
1767
1768 assert(i);
1769
1770 if (i->done)
1771 return 0;
1772
1773 i->done = true;
1774
1775 prefix = malloc(strlen(i->path) + 1);
1776 if (!prefix)
1777 return log_oom();
1778
1779 PATH_FOREACH_PREFIX(prefix, i->path) {
1780 ItemArray *j;
1781
1782 j = ordered_hashmap_get(items, prefix);
1783 if (j) {
1784 int s;
1785
1786 s = process_item_array(j);
1787 if (s < 0 && t == 0)
1788 t = s;
1789 }
1790 }
1791
1792 if (chase_symlinks(i->path, NULL, CHASE_NO_AUTOFS, NULL) == -EREMOTE)
1793 return t;
1794
1795 r = arg_create ? create_item(i) : 0;
1796 q = arg_remove ? remove_item(i) : 0;
1797 p = arg_clean ? clean_item(i) : 0;
1798
1799 return t < 0 ? t :
1800 r < 0 ? r :
1801 q < 0 ? q :
1802 p;
1803 }
1804
1805 static int process_item_array(ItemArray *array) {
1806 unsigned n;
1807 int r = 0, k;
1808
1809 assert(array);
1810
1811 for (n = 0; n < array->count; n++) {
1812 k = process_item(array->items + n);
1813 if (k < 0 && r == 0)
1814 r = k;
1815 }
1816
1817 return r;
1818 }
1819
1820 static void item_free_contents(Item *i) {
1821 assert(i);
1822 free(i->path);
1823 free(i->argument);
1824 strv_free(i->xattrs);
1825
1826 #if HAVE_ACL
1827 acl_free(i->acl_access);
1828 acl_free(i->acl_default);
1829 #endif
1830 }
1831
1832 static void item_array_free(ItemArray *a) {
1833 unsigned n;
1834
1835 if (!a)
1836 return;
1837
1838 for (n = 0; n < a->count; n++)
1839 item_free_contents(a->items + n);
1840 free(a->items);
1841 free(a);
1842 }
1843
1844 static int item_compare(const void *a, const void *b) {
1845 const Item *x = a, *y = b;
1846
1847 /* Make sure that the ownership taking item is put first, so
1848 * that we first create the node, and then can adjust it */
1849
1850 if (takes_ownership(x->type) && !takes_ownership(y->type))
1851 return -1;
1852 if (!takes_ownership(x->type) && takes_ownership(y->type))
1853 return 1;
1854
1855 return (int) x->type - (int) y->type;
1856 }
1857
1858 static bool item_compatible(Item *a, Item *b) {
1859 assert(a);
1860 assert(b);
1861 assert(streq(a->path, b->path));
1862
1863 if (takes_ownership(a->type) && takes_ownership(b->type))
1864 /* check if the items are the same */
1865 return streq_ptr(a->argument, b->argument) &&
1866
1867 a->uid_set == b->uid_set &&
1868 a->uid == b->uid &&
1869
1870 a->gid_set == b->gid_set &&
1871 a->gid == b->gid &&
1872
1873 a->mode_set == b->mode_set &&
1874 a->mode == b->mode &&
1875
1876 a->age_set == b->age_set &&
1877 a->age == b->age &&
1878
1879 a->mask_perms == b->mask_perms &&
1880
1881 a->keep_first_level == b->keep_first_level &&
1882
1883 a->major_minor == b->major_minor;
1884
1885 return true;
1886 }
1887
1888 static bool should_include_path(const char *path) {
1889 char **prefix;
1890
1891 STRV_FOREACH(prefix, arg_exclude_prefixes)
1892 if (path_startswith(path, *prefix)) {
1893 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1894 path, *prefix);
1895 return false;
1896 }
1897
1898 STRV_FOREACH(prefix, arg_include_prefixes)
1899 if (path_startswith(path, *prefix)) {
1900 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1901 return true;
1902 }
1903
1904 /* no matches, so we should include this path only if we
1905 * have no whitelist at all */
1906 if (strv_isempty(arg_include_prefixes))
1907 return true;
1908
1909 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1910 return false;
1911 }
1912
1913 static int specifier_expansion_from_arg(Item *i) {
1914 _cleanup_free_ char *unescaped = NULL, *resolved = NULL;
1915 char **xattr;
1916 int r;
1917
1918 assert(i);
1919
1920 if (i->argument == NULL)
1921 return 0;
1922
1923 switch (i->type) {
1924 case COPY_FILES:
1925 case CREATE_SYMLINK:
1926 case CREATE_FILE:
1927 case TRUNCATE_FILE:
1928 case WRITE_FILE:
1929 r = cunescape(i->argument, 0, &unescaped);
1930 if (r < 0)
1931 return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument);
1932
1933 r = specifier_printf(unescaped, specifier_table, NULL, &resolved);
1934 if (r < 0)
1935 return r;
1936
1937 free_and_replace(i->argument, resolved);
1938 break;
1939
1940 case SET_XATTR:
1941 case RECURSIVE_SET_XATTR:
1942 assert(i->xattrs);
1943
1944 STRV_FOREACH (xattr, i->xattrs) {
1945 r = specifier_printf(*xattr, specifier_table, NULL, &resolved);
1946 if (r < 0)
1947 return r;
1948
1949 free_and_replace(*xattr, resolved);
1950 }
1951 break;
1952
1953 default:
1954 break;
1955 }
1956 return 0;
1957 }
1958
1959 static int parse_line(const char *fname, unsigned line, const char *buffer, bool *invalid_config) {
1960
1961 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1962 _cleanup_(item_free_contents) Item i = {};
1963 ItemArray *existing;
1964 OrderedHashmap *h;
1965 int r, pos;
1966 bool force = false, boot = false;
1967
1968 assert(fname);
1969 assert(line >= 1);
1970 assert(buffer);
1971
1972 r = extract_many_words(
1973 &buffer,
1974 NULL,
1975 EXTRACT_QUOTES,
1976 &action,
1977 &path,
1978 &mode,
1979 &user,
1980 &group,
1981 &age,
1982 NULL);
1983 if (r < 0) {
1984 if (IN_SET(r, -EINVAL, -EBADSLT))
1985 /* invalid quoting and such or an unknown specifier */
1986 *invalid_config = true;
1987 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1988 }
1989
1990 else if (r < 2) {
1991 *invalid_config = true;
1992 log_error("[%s:%u] Syntax error.", fname, line);
1993 return -EIO;
1994 }
1995
1996 if (!isempty(buffer) && !streq(buffer, "-")) {
1997 i.argument = strdup(buffer);
1998 if (!i.argument)
1999 return log_oom();
2000 }
2001
2002 if (isempty(action)) {
2003 *invalid_config = true;
2004 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
2005 return -EINVAL;
2006 }
2007
2008 for (pos = 1; action[pos]; pos++) {
2009 if (action[pos] == '!' && !boot)
2010 boot = true;
2011 else if (action[pos] == '+' && !force)
2012 force = true;
2013 else {
2014 *invalid_config = true;
2015 log_error("[%s:%u] Unknown modifiers in command '%s'",
2016 fname, line, action);
2017 return -EINVAL;
2018 }
2019 }
2020
2021 if (boot && !arg_boot) {
2022 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
2023 action, path);
2024 return 0;
2025 }
2026
2027 i.type = action[0];
2028 i.force = force;
2029
2030 r = specifier_printf(path, specifier_table, NULL, &i.path);
2031 if (r == -ENXIO)
2032 return log_unresolvable_specifier(fname, line);
2033 if (r < 0) {
2034 if (IN_SET(r, -EINVAL, -EBADSLT))
2035 *invalid_config = true;
2036 return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path);
2037 }
2038
2039 switch (i.type) {
2040
2041 case CREATE_DIRECTORY:
2042 case CREATE_SUBVOLUME:
2043 case CREATE_SUBVOLUME_INHERIT_QUOTA:
2044 case CREATE_SUBVOLUME_NEW_QUOTA:
2045 case EMPTY_DIRECTORY:
2046 case TRUNCATE_DIRECTORY:
2047 case CREATE_FIFO:
2048 case IGNORE_PATH:
2049 case IGNORE_DIRECTORY_PATH:
2050 case REMOVE_PATH:
2051 case RECURSIVE_REMOVE_PATH:
2052 case ADJUST_MODE:
2053 case RELABEL_PATH:
2054 case RECURSIVE_RELABEL_PATH:
2055 if (i.argument)
2056 log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type);
2057
2058 break;
2059
2060 case CREATE_FILE:
2061 case TRUNCATE_FILE:
2062 break;
2063
2064 case CREATE_SYMLINK:
2065 if (!i.argument) {
2066 i.argument = strappend("/usr/share/factory/", i.path);
2067 if (!i.argument)
2068 return log_oom();
2069 }
2070 break;
2071
2072 case WRITE_FILE:
2073 if (!i.argument) {
2074 *invalid_config = true;
2075 log_error("[%s:%u] Write file requires argument.", fname, line);
2076 return -EBADMSG;
2077 }
2078 break;
2079
2080 case COPY_FILES:
2081 if (!i.argument) {
2082 i.argument = strappend("/usr/share/factory/", i.path);
2083 if (!i.argument)
2084 return log_oom();
2085 } else if (!path_is_absolute(i.argument)) {
2086 *invalid_config = true;
2087 log_error("[%s:%u] Source path is not absolute.", fname, line);
2088 return -EBADMSG;
2089 }
2090
2091 path_kill_slashes(i.argument);
2092 break;
2093
2094 case CREATE_CHAR_DEVICE:
2095 case CREATE_BLOCK_DEVICE: {
2096 unsigned major, minor;
2097
2098 if (!i.argument) {
2099 *invalid_config = true;
2100 log_error("[%s:%u] Device file requires argument.", fname, line);
2101 return -EBADMSG;
2102 }
2103
2104 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
2105 *invalid_config = true;
2106 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
2107 return -EBADMSG;
2108 }
2109
2110 i.major_minor = makedev(major, minor);
2111 break;
2112 }
2113
2114 case SET_XATTR:
2115 case RECURSIVE_SET_XATTR:
2116 if (!i.argument) {
2117 *invalid_config = true;
2118 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
2119 return -EBADMSG;
2120 }
2121 r = parse_xattrs_from_arg(&i);
2122 if (r < 0)
2123 return r;
2124 break;
2125
2126 case SET_ACL:
2127 case RECURSIVE_SET_ACL:
2128 if (!i.argument) {
2129 *invalid_config = true;
2130 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
2131 return -EBADMSG;
2132 }
2133 r = parse_acls_from_arg(&i);
2134 if (r < 0)
2135 return r;
2136 break;
2137
2138 case SET_ATTRIBUTE:
2139 case RECURSIVE_SET_ATTRIBUTE:
2140 if (!i.argument) {
2141 *invalid_config = true;
2142 log_error("[%s:%u] Set file attribute requires argument.", fname, line);
2143 return -EBADMSG;
2144 }
2145 r = parse_attribute_from_arg(&i);
2146 if (IN_SET(r, -EINVAL, -EBADSLT))
2147 *invalid_config = true;
2148 if (r < 0)
2149 return r;
2150 break;
2151
2152 default:
2153 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
2154 *invalid_config = true;
2155 return -EBADMSG;
2156 }
2157
2158 if (!path_is_absolute(i.path)) {
2159 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
2160 *invalid_config = true;
2161 return -EBADMSG;
2162 }
2163
2164 path_kill_slashes(i.path);
2165
2166 if (!should_include_path(i.path))
2167 return 0;
2168
2169 r = specifier_expansion_from_arg(&i);
2170 if (r == -ENXIO)
2171 return log_unresolvable_specifier(fname, line);
2172 if (r < 0) {
2173 if (IN_SET(r, -EINVAL, -EBADSLT))
2174 *invalid_config = true;
2175 return log_error_errno(r, "[%s:%u] Failed to substitute specifiers in argument: %m",
2176 fname, line);
2177 }
2178
2179 if (arg_root) {
2180 char *p;
2181
2182 p = prefix_root(arg_root, i.path);
2183 if (!p)
2184 return log_oom();
2185
2186 free(i.path);
2187 i.path = p;
2188 }
2189
2190 if (!isempty(user) && !streq(user, "-")) {
2191 const char *u = user;
2192
2193 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
2194 if (r < 0) {
2195 *invalid_config = true;
2196 return log_error_errno(r, "[%s:%u] Unknown user '%s'.", fname, line, user);
2197 }
2198
2199 i.uid_set = true;
2200 }
2201
2202 if (!isempty(group) && !streq(group, "-")) {
2203 const char *g = group;
2204
2205 r = get_group_creds(&g, &i.gid);
2206 if (r < 0) {
2207 *invalid_config = true;
2208 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
2209 return r;
2210 }
2211
2212 i.gid_set = true;
2213 }
2214
2215 if (!isempty(mode) && !streq(mode, "-")) {
2216 const char *mm = mode;
2217 unsigned m;
2218
2219 if (*mm == '~') {
2220 i.mask_perms = true;
2221 mm++;
2222 }
2223
2224 if (parse_mode(mm, &m) < 0) {
2225 *invalid_config = true;
2226 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
2227 return -EBADMSG;
2228 }
2229
2230 i.mode = m;
2231 i.mode_set = true;
2232 } else
2233 i.mode = IN_SET(i.type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA) ? 0755 : 0644;
2234
2235 if (!isempty(age) && !streq(age, "-")) {
2236 const char *a = age;
2237
2238 if (*a == '~') {
2239 i.keep_first_level = true;
2240 a++;
2241 }
2242
2243 if (parse_sec(a, &i.age) < 0) {
2244 *invalid_config = true;
2245 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
2246 return -EBADMSG;
2247 }
2248
2249 i.age_set = true;
2250 }
2251
2252 h = needs_glob(i.type) ? globs : items;
2253
2254 existing = ordered_hashmap_get(h, i.path);
2255 if (existing) {
2256 unsigned n;
2257
2258 for (n = 0; n < existing->count; n++) {
2259 if (!item_compatible(existing->items + n, &i)) {
2260 log_notice("[%s:%u] Duplicate line for path \"%s\", ignoring.",
2261 fname, line, i.path);
2262 return 0;
2263 }
2264 }
2265 } else {
2266 existing = new0(ItemArray, 1);
2267 r = ordered_hashmap_put(h, i.path, existing);
2268 if (r < 0)
2269 return log_oom();
2270 }
2271
2272 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
2273 return log_oom();
2274
2275 memcpy(existing->items + existing->count++, &i, sizeof(i));
2276
2277 /* Sort item array, to enforce stable ordering of application */
2278 qsort_safe(existing->items, existing->count, sizeof(Item), item_compare);
2279
2280 zero(i);
2281 return 0;
2282 }
2283
2284 static void help(void) {
2285 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
2286 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
2287 " -h --help Show this help\n"
2288 " --user Execute user configuration\n"
2289 " --version Show package version\n"
2290 " --create Create marked files/directories\n"
2291 " --clean Clean up marked directories\n"
2292 " --remove Remove marked files/directories\n"
2293 " --boot Execute actions only safe at boot\n"
2294 " --prefix=PATH Only apply rules with the specified prefix\n"
2295 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
2296 " --root=PATH Operate on an alternate filesystem root\n"
2297 , program_invocation_short_name);
2298 }
2299
2300 static int parse_argv(int argc, char *argv[]) {
2301
2302 enum {
2303 ARG_VERSION = 0x100,
2304 ARG_USER,
2305 ARG_CREATE,
2306 ARG_CLEAN,
2307 ARG_REMOVE,
2308 ARG_BOOT,
2309 ARG_PREFIX,
2310 ARG_EXCLUDE_PREFIX,
2311 ARG_ROOT,
2312 };
2313
2314 static const struct option options[] = {
2315 { "help", no_argument, NULL, 'h' },
2316 { "user", no_argument, NULL, ARG_USER },
2317 { "version", no_argument, NULL, ARG_VERSION },
2318 { "create", no_argument, NULL, ARG_CREATE },
2319 { "clean", no_argument, NULL, ARG_CLEAN },
2320 { "remove", no_argument, NULL, ARG_REMOVE },
2321 { "boot", no_argument, NULL, ARG_BOOT },
2322 { "prefix", required_argument, NULL, ARG_PREFIX },
2323 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
2324 { "root", required_argument, NULL, ARG_ROOT },
2325 {}
2326 };
2327
2328 int c, r;
2329
2330 assert(argc >= 0);
2331 assert(argv);
2332
2333 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
2334
2335 switch (c) {
2336
2337 case 'h':
2338 help();
2339 return 0;
2340
2341 case ARG_VERSION:
2342 return version();
2343
2344 case ARG_USER:
2345 arg_user = true;
2346 break;
2347
2348 case ARG_CREATE:
2349 arg_create = true;
2350 break;
2351
2352 case ARG_CLEAN:
2353 arg_clean = true;
2354 break;
2355
2356 case ARG_REMOVE:
2357 arg_remove = true;
2358 break;
2359
2360 case ARG_BOOT:
2361 arg_boot = true;
2362 break;
2363
2364 case ARG_PREFIX:
2365 if (strv_push(&arg_include_prefixes, optarg) < 0)
2366 return log_oom();
2367 break;
2368
2369 case ARG_EXCLUDE_PREFIX:
2370 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
2371 return log_oom();
2372 break;
2373
2374 case ARG_ROOT:
2375 r = parse_path_argument_and_warn(optarg, true, &arg_root);
2376 if (r < 0)
2377 return r;
2378 break;
2379
2380 case '?':
2381 return -EINVAL;
2382
2383 default:
2384 assert_not_reached("Unhandled option");
2385 }
2386
2387 if (!arg_clean && !arg_create && !arg_remove) {
2388 log_error("You need to specify at least one of --clean, --create or --remove.");
2389 return -EINVAL;
2390 }
2391
2392 return 1;
2393 }
2394
2395 static int read_config_file(const char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
2396 _cleanup_fclose_ FILE *_f = NULL;
2397 FILE *f;
2398 char line[LINE_MAX];
2399 Iterator iterator;
2400 unsigned v = 0;
2401 Item *i;
2402 int r = 0;
2403
2404 assert(fn);
2405
2406 if (streq(fn, "-")) {
2407 log_debug("Reading config from stdin.");
2408 fn = "<stdin>";
2409 f = stdin;
2410 } else {
2411 r = search_and_fopen(fn, "re", arg_root, config_dirs, &_f);
2412 if (r < 0) {
2413 if (ignore_enoent && r == -ENOENT) {
2414 log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
2415 return 0;
2416 }
2417
2418 return log_error_errno(r, "Failed to open '%s': %m", fn);
2419 }
2420 log_debug("Reading config file \"%s\".", fn);
2421 f = _f;
2422 }
2423
2424 FOREACH_LINE(line, f, break) {
2425 char *l;
2426 int k;
2427 bool invalid_line = false;
2428
2429 v++;
2430
2431 l = strstrip(line);
2432 if (IN_SET(*l, 0, '#'))
2433 continue;
2434
2435 k = parse_line(fn, v, l, &invalid_line);
2436 if (k < 0) {
2437 if (invalid_line)
2438 /* Allow reporting with a special code if the caller requested this */
2439 *invalid_config = true;
2440 else if (r == 0)
2441 /* The first error becomes our return value */
2442 r = k;
2443 }
2444 }
2445
2446 /* we have to determine age parameter for each entry of type X */
2447 ORDERED_HASHMAP_FOREACH(i, globs, iterator) {
2448 Iterator iter;
2449 Item *j, *candidate_item = NULL;
2450
2451 if (i->type != IGNORE_DIRECTORY_PATH)
2452 continue;
2453
2454 ORDERED_HASHMAP_FOREACH(j, items, iter) {
2455 if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
2456 continue;
2457
2458 if (path_equal(j->path, i->path)) {
2459 candidate_item = j;
2460 break;
2461 }
2462
2463 if ((!candidate_item && path_startswith(i->path, j->path)) ||
2464 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
2465 candidate_item = j;
2466 }
2467
2468 if (candidate_item && candidate_item->age_set) {
2469 i->age = candidate_item->age;
2470 i->age_set = true;
2471 }
2472 }
2473
2474 if (ferror(f)) {
2475 log_error_errno(errno, "Failed to read from file %s: %m", fn);
2476 if (r == 0)
2477 r = -EIO;
2478 }
2479
2480 return r;
2481 }
2482
2483 int main(int argc, char *argv[]) {
2484 int r, k;
2485 ItemArray *a;
2486 Iterator iterator;
2487 _cleanup_strv_free_ char **config_dirs = NULL;
2488 bool invalid_config = false;
2489 char **f;
2490
2491 r = parse_argv(argc, argv);
2492 if (r <= 0)
2493 goto finish;
2494
2495 log_set_target(LOG_TARGET_AUTO);
2496 log_parse_environment();
2497 log_open();
2498
2499 umask(0022);
2500
2501 mac_selinux_init();
2502
2503 items = ordered_hashmap_new(&string_hash_ops);
2504 globs = ordered_hashmap_new(&string_hash_ops);
2505
2506 if (!items || !globs) {
2507 r = log_oom();
2508 goto finish;
2509 }
2510
2511 r = 0;
2512
2513 if (arg_user) {
2514 r = user_config_paths(&config_dirs);
2515 if (r < 0) {
2516 log_error_errno(r, "Failed to initialize configuration directory list: %m");
2517 goto finish;
2518 }
2519 } else {
2520 config_dirs = strv_split_nulstr(CONF_PATHS_NULSTR("tmpfiles.d"));
2521 if (!config_dirs) {
2522 r = log_oom();
2523 goto finish;
2524 }
2525 }
2526
2527 {
2528 _cleanup_free_ char *t = NULL;
2529
2530 t = strv_join(config_dirs, "\n\t");
2531 if (t)
2532 log_debug("Looking for configuration files in (higher priority first:\n\t%s", t);
2533 }
2534
2535 if (optind < argc) {
2536 int j;
2537
2538 for (j = optind; j < argc; j++) {
2539 k = read_config_file((const char**) config_dirs, argv[j], false, &invalid_config);
2540 if (k < 0 && r == 0)
2541 r = k;
2542 }
2543
2544 } else {
2545 _cleanup_strv_free_ char **files = NULL;
2546
2547 r = conf_files_list_strv(&files, ".conf", arg_root, 0, (const char* const*) config_dirs);
2548 if (r < 0) {
2549 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
2550 goto finish;
2551 }
2552
2553 STRV_FOREACH(f, files) {
2554 k = read_config_file((const char**) config_dirs, *f, true, &invalid_config);
2555 if (k < 0 && r == 0)
2556 r = k;
2557 }
2558 }
2559
2560 /* The non-globbing ones usually create things, hence we apply
2561 * them first */
2562 ORDERED_HASHMAP_FOREACH(a, items, iterator) {
2563 k = process_item_array(a);
2564 if (k < 0 && r == 0)
2565 r = k;
2566 }
2567
2568 /* The globbing ones usually alter things, hence we apply them
2569 * second. */
2570 ORDERED_HASHMAP_FOREACH(a, globs, iterator) {
2571 k = process_item_array(a);
2572 if (k < 0 && r == 0)
2573 r = k;
2574 }
2575
2576 finish:
2577 ordered_hashmap_free_with_destructor(items, item_array_free);
2578 ordered_hashmap_free_with_destructor(globs, item_array_free);
2579
2580 free(arg_include_prefixes);
2581 free(arg_exclude_prefixes);
2582 free(arg_root);
2583
2584 set_free_free(unix_sockets);
2585
2586 mac_selinux_finish();
2587
2588 if (r < 0)
2589 return EXIT_FAILURE;
2590 else if (invalid_config)
2591 return EX_DATAERR;
2592 else
2593 return EXIT_SUCCESS;
2594 }