]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/tmpfiles/tmpfiles.c
tmpfiles: shortcut path_set_perms() if there's nothing to do
[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 char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
758 _cleanup_close_ int fd = -1;
759 struct stat st;
760
761 assert(i);
762 assert(path);
763
764 if (!i->mode_set && !i->uid_set && !i->gid_set)
765 goto shortcut;
766
767 /* We open the file with O_PATH here, to make the operation
768 * somewhat atomic. Also there's unfortunately no fchmodat()
769 * with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
770 * O_PATH. */
771
772 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
773 if (fd < 0) {
774 int level = LOG_ERR, r = -errno;
775
776 /* Option "e" operates only on existing objects. Do not
777 * print errors about non-existent files or directories */
778 if (i->type == EMPTY_DIRECTORY && errno == ENOENT) {
779 level = LOG_DEBUG;
780 r = 0;
781 }
782
783 log_full_errno(level, errno, "Adjusting owner and mode for %s failed: %m", path);
784 return r;
785 }
786
787 if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
788 return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
789
790 xsprintf(fn, "/proc/self/fd/%i", fd);
791
792 if (i->mode_set) {
793 if (S_ISLNK(st.st_mode))
794 log_debug("Skipping mode fix for symlink %s.", path);
795 else {
796 mode_t m = i->mode;
797
798 if (i->mask_perms) {
799 if (!(st.st_mode & 0111))
800 m &= ~0111;
801 if (!(st.st_mode & 0222))
802 m &= ~0222;
803 if (!(st.st_mode & 0444))
804 m &= ~0444;
805 if (!S_ISDIR(st.st_mode))
806 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
807 }
808
809 if (m == (st.st_mode & 07777))
810 log_debug("\"%s\" has correct mode %o already.", path, st.st_mode);
811 else {
812 log_debug("Changing \"%s\" to mode %o.", path, m);
813
814 if (chmod(fn, m) < 0)
815 return log_error_errno(errno, "chmod() of %s via %s failed: %m", path, fn);
816 }
817 }
818 }
819
820 if ((i->uid != st.st_uid || i->gid != st.st_gid) &&
821 (i->uid_set || i->gid_set)) {
822 log_debug("Changing \"%s\" to owner "UID_FMT":"GID_FMT,
823 path,
824 i->uid_set ? i->uid : UID_INVALID,
825 i->gid_set ? i->gid : GID_INVALID);
826
827 if (chown(fn,
828 i->uid_set ? i->uid : UID_INVALID,
829 i->gid_set ? i->gid : GID_INVALID) < 0)
830 return log_error_errno(errno, "chown() of %s via %s failed: %m", path, fn);
831 }
832
833 fd = safe_close(fd);
834
835 shortcut:
836 return label_fix(path, false, false);
837 }
838
839 static int parse_xattrs_from_arg(Item *i) {
840 const char *p;
841 int r;
842
843 assert(i);
844 assert(i->argument);
845
846 p = i->argument;
847
848 for (;;) {
849 _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL;
850
851 r = extract_first_word(&p, &xattr, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
852 if (r < 0)
853 log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p);
854 if (r <= 0)
855 break;
856
857 r = split_pair(xattr, "=", &name, &value);
858 if (r < 0) {
859 log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr);
860 continue;
861 }
862
863 if (isempty(name) || isempty(value)) {
864 log_warning("Malformed extended attribute found, ignoring: %s", xattr);
865 continue;
866 }
867
868 if (strv_push_pair(&i->xattrs, name, value) < 0)
869 return log_oom();
870
871 name = value = NULL;
872 }
873
874 return 0;
875 }
876
877 static int path_set_xattrs(Item *i, const char *path) {
878 char **name, **value;
879
880 assert(i);
881 assert(path);
882
883 STRV_FOREACH_PAIR(name, value, i->xattrs) {
884 log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
885 if (lsetxattr(path, *name, *value, strlen(*value), 0) < 0)
886 return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m",
887 *name, *value, path);
888 }
889 return 0;
890 }
891
892 static int parse_acls_from_arg(Item *item) {
893 #if HAVE_ACL
894 int r;
895
896 assert(item);
897
898 /* If force (= modify) is set, we will not modify the acl
899 * afterwards, so the mask can be added now if necessary. */
900
901 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
902 if (r < 0)
903 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument);
904 #else
905 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
906 #endif
907
908 return 0;
909 }
910
911 #if HAVE_ACL
912 static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) {
913 _cleanup_(acl_free_charpp) char *t = NULL;
914 _cleanup_(acl_freep) acl_t dup = NULL;
915 int r;
916
917 /* Returns 0 for success, positive error if already warned,
918 * negative error otherwise. */
919
920 if (modify) {
921 r = acls_for_file(path, type, acl, &dup);
922 if (r < 0)
923 return r;
924
925 r = calc_acl_mask_if_needed(&dup);
926 if (r < 0)
927 return r;
928 } else {
929 dup = acl_dup(acl);
930 if (!dup)
931 return -errno;
932
933 /* the mask was already added earlier if needed */
934 }
935
936 r = add_base_acls_if_needed(&dup, path);
937 if (r < 0)
938 return r;
939
940 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
941 log_debug("Setting %s ACL %s on %s.",
942 type == ACL_TYPE_ACCESS ? "access" : "default",
943 strna(t), pretty);
944
945 r = acl_set_file(path, type, dup);
946 if (r < 0)
947 /* Return positive to indicate we already warned */
948 return -log_error_errno(errno,
949 "Setting %s ACL \"%s\" on %s failed: %m",
950 type == ACL_TYPE_ACCESS ? "access" : "default",
951 strna(t), pretty);
952
953 return 0;
954 }
955 #endif
956
957 static int path_set_acls(Item *item, const char *path) {
958 int r = 0;
959 #if HAVE_ACL
960 char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
961 _cleanup_close_ int fd = -1;
962 struct stat st;
963
964 assert(item);
965 assert(path);
966
967 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
968 if (fd < 0)
969 return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
970
971 if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
972 return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
973
974 if (S_ISLNK(st.st_mode)) {
975 log_debug("Skipping ACL fix for symlink %s.", path);
976 return 0;
977 }
978
979 xsprintf(fn, "/proc/self/fd/%i", fd);
980
981 if (item->acl_access)
982 r = path_set_acl(fn, path, ACL_TYPE_ACCESS, item->acl_access, item->force);
983
984 if (r == 0 && item->acl_default)
985 r = path_set_acl(fn, path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
986
987 if (r > 0)
988 return -r; /* already warned */
989 else if (r == -EOPNOTSUPP) {
990 log_debug_errno(r, "ACLs not supported by file system at %s", path);
991 return 0;
992 } else if (r < 0)
993 log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
994 #endif
995 return r;
996 }
997
998 #define ATTRIBUTES_ALL \
999 (FS_NOATIME_FL | \
1000 FS_SYNC_FL | \
1001 FS_DIRSYNC_FL | \
1002 FS_APPEND_FL | \
1003 FS_COMPR_FL | \
1004 FS_NODUMP_FL | \
1005 FS_EXTENT_FL | \
1006 FS_IMMUTABLE_FL | \
1007 FS_JOURNAL_DATA_FL | \
1008 FS_SECRM_FL | \
1009 FS_UNRM_FL | \
1010 FS_NOTAIL_FL | \
1011 FS_TOPDIR_FL | \
1012 FS_NOCOW_FL)
1013
1014 static int parse_attribute_from_arg(Item *item) {
1015
1016 static const struct {
1017 char character;
1018 unsigned value;
1019 } attributes[] = {
1020 { 'A', FS_NOATIME_FL }, /* do not update atime */
1021 { 'S', FS_SYNC_FL }, /* Synchronous updates */
1022 { 'D', FS_DIRSYNC_FL }, /* dirsync behaviour (directories only) */
1023 { 'a', FS_APPEND_FL }, /* writes to file may only append */
1024 { 'c', FS_COMPR_FL }, /* Compress file */
1025 { 'd', FS_NODUMP_FL }, /* do not dump file */
1026 { 'e', FS_EXTENT_FL }, /* Extents */
1027 { 'i', FS_IMMUTABLE_FL }, /* Immutable file */
1028 { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */
1029 { 's', FS_SECRM_FL }, /* Secure deletion */
1030 { 'u', FS_UNRM_FL }, /* Undelete */
1031 { 't', FS_NOTAIL_FL }, /* file tail should not be merged */
1032 { 'T', FS_TOPDIR_FL }, /* Top of directory hierarchies */
1033 { 'C', FS_NOCOW_FL }, /* Do not cow file */
1034 };
1035
1036 enum {
1037 MODE_ADD,
1038 MODE_DEL,
1039 MODE_SET
1040 } mode = MODE_ADD;
1041
1042 unsigned value = 0, mask = 0;
1043 const char *p;
1044
1045 assert(item);
1046
1047 p = item->argument;
1048 if (p) {
1049 if (*p == '+') {
1050 mode = MODE_ADD;
1051 p++;
1052 } else if (*p == '-') {
1053 mode = MODE_DEL;
1054 p++;
1055 } else if (*p == '=') {
1056 mode = MODE_SET;
1057 p++;
1058 }
1059 }
1060
1061 if (isempty(p) && mode != MODE_SET) {
1062 log_error("Setting file attribute on '%s' needs an attribute specification.", item->path);
1063 return -EINVAL;
1064 }
1065
1066 for (; p && *p ; p++) {
1067 unsigned i, v;
1068
1069 for (i = 0; i < ELEMENTSOF(attributes); i++)
1070 if (*p == attributes[i].character)
1071 break;
1072
1073 if (i >= ELEMENTSOF(attributes)) {
1074 log_error("Unknown file attribute '%c' on '%s'.", *p, item->path);
1075 return -EINVAL;
1076 }
1077
1078 v = attributes[i].value;
1079
1080 SET_FLAG(value, v, IN_SET(mode, MODE_ADD, MODE_SET));
1081
1082 mask |= v;
1083 }
1084
1085 if (mode == MODE_SET)
1086 mask |= ATTRIBUTES_ALL;
1087
1088 assert(mask != 0);
1089
1090 item->attribute_mask = mask;
1091 item->attribute_value = value;
1092 item->attribute_set = true;
1093
1094 return 0;
1095 }
1096
1097 static int path_set_attribute(Item *item, const char *path) {
1098 _cleanup_close_ int fd = -1;
1099 struct stat st;
1100 unsigned f;
1101 int r;
1102
1103 if (!item->attribute_set || item->attribute_mask == 0)
1104 return 0;
1105
1106 fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOATIME|O_NOFOLLOW);
1107 if (fd < 0) {
1108 if (errno == ELOOP)
1109 return log_error_errno(errno, "Skipping file attributes adjustment on symlink %s.", path);
1110
1111 return log_error_errno(errno, "Cannot open '%s': %m", path);
1112 }
1113
1114 if (fstat(fd, &st) < 0)
1115 return log_error_errno(errno, "Cannot stat '%s': %m", path);
1116
1117 /* Issuing the file attribute ioctls on device nodes is not
1118 * safe, as that will be delivered to the drivers, not the
1119 * file system containing the device node. */
1120 if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
1121 log_error("Setting file flags is only supported on regular files and directories, cannot set on '%s'.", path);
1122 return -EINVAL;
1123 }
1124
1125 f = item->attribute_value & item->attribute_mask;
1126
1127 /* Mask away directory-specific flags */
1128 if (!S_ISDIR(st.st_mode))
1129 f &= ~FS_DIRSYNC_FL;
1130
1131 r = chattr_fd(fd, f, item->attribute_mask);
1132 if (r < 0)
1133 log_full_errno(IN_SET(r, -ENOTTY, -EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING,
1134 r,
1135 "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m",
1136 path, item->attribute_value, item->attribute_mask);
1137
1138 return 0;
1139 }
1140
1141 static int write_one_file(Item *i, const char *path) {
1142 _cleanup_close_ int fd = -1;
1143 int flags, r = 0;
1144 struct stat st;
1145
1146 assert(i);
1147 assert(path);
1148
1149 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
1150 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
1151
1152 RUN_WITH_UMASK(0000) {
1153 mac_selinux_create_file_prepare(path, S_IFREG);
1154 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
1155 mac_selinux_create_file_clear();
1156 }
1157
1158 if (fd < 0) {
1159 if (i->type == WRITE_FILE && errno == ENOENT) {
1160 log_debug_errno(errno, "Not writing \"%s\": %m", path);
1161 return 0;
1162 }
1163
1164 r = -errno;
1165 if (!i->argument && errno == EROFS && stat(path, &st) == 0 &&
1166 (i->type == CREATE_FILE || st.st_size == 0))
1167 goto check_mode;
1168
1169 return log_error_errno(r, "Failed to create file %s: %m", path);
1170 }
1171
1172 if (i->argument) {
1173 log_debug("%s to \"%s\".", i->type == CREATE_FILE ? "Appending" : "Writing", path);
1174
1175 r = loop_write(fd, i->argument, strlen(i->argument), false);
1176 if (r < 0)
1177 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
1178 } else
1179 log_debug("\"%s\" has been created.", path);
1180
1181 fd = safe_close(fd);
1182
1183 if (stat(path, &st) < 0)
1184 return log_error_errno(errno, "stat(%s) failed: %m", path);
1185
1186 check_mode:
1187 if (!S_ISREG(st.st_mode)) {
1188 log_error("%s is not a file.", path);
1189 return -EEXIST;
1190 }
1191
1192 r = path_set_perms(i, path);
1193 if (r < 0)
1194 return r;
1195
1196 return 0;
1197 }
1198
1199 typedef int (*action_t)(Item *, const char *);
1200
1201 static int item_do_children(Item *i, const char *path, action_t action) {
1202 _cleanup_closedir_ DIR *d;
1203 struct dirent *de;
1204 int r = 0;
1205
1206 assert(i);
1207 assert(path);
1208
1209 /* This returns the first error we run into, but nevertheless
1210 * tries to go on */
1211
1212 d = opendir_nomod(path);
1213 if (!d)
1214 return IN_SET(errno, ENOENT, ENOTDIR, ELOOP) ? 0 : -errno;
1215
1216 FOREACH_DIRENT_ALL(de, d, r = -errno) {
1217 _cleanup_free_ char *p = NULL;
1218 int q;
1219
1220 if (dot_or_dot_dot(de->d_name))
1221 continue;
1222
1223 p = strjoin(path, "/", de->d_name);
1224 if (!p)
1225 return -ENOMEM;
1226
1227 q = action(i, p);
1228 if (q < 0 && q != -ENOENT && r == 0)
1229 r = q;
1230
1231 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
1232 q = item_do_children(i, p, action);
1233 if (q < 0 && r == 0)
1234 r = q;
1235 }
1236 }
1237
1238 return r;
1239 }
1240
1241 static int glob_item(Item *i, action_t action, bool recursive) {
1242 _cleanup_globfree_ glob_t g = {
1243 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
1244 };
1245 int r = 0, k;
1246 char **fn;
1247
1248 k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
1249 if (k < 0 && k != -ENOENT)
1250 return log_error_errno(k, "glob(%s) failed: %m", i->path);
1251
1252 STRV_FOREACH(fn, g.gl_pathv) {
1253 k = action(i, *fn);
1254 if (k < 0 && r == 0)
1255 r = k;
1256
1257 if (recursive) {
1258 k = item_do_children(i, *fn, action);
1259 if (k < 0 && r == 0)
1260 r = k;
1261 }
1262 }
1263
1264 return r;
1265 }
1266
1267 typedef enum {
1268 CREATION_NORMAL,
1269 CREATION_EXISTING,
1270 CREATION_FORCE,
1271 _CREATION_MODE_MAX,
1272 _CREATION_MODE_INVALID = -1
1273 } CreationMode;
1274
1275 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
1276 [CREATION_NORMAL] = "Created",
1277 [CREATION_EXISTING] = "Found existing",
1278 [CREATION_FORCE] = "Created replacement",
1279 };
1280
1281 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
1282
1283 static int create_item(Item *i) {
1284 struct stat st;
1285 int r = 0;
1286 int q = 0;
1287 CreationMode creation;
1288
1289 assert(i);
1290
1291 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
1292
1293 switch (i->type) {
1294
1295 case IGNORE_PATH:
1296 case IGNORE_DIRECTORY_PATH:
1297 case REMOVE_PATH:
1298 case RECURSIVE_REMOVE_PATH:
1299 return 0;
1300
1301 case CREATE_FILE:
1302 case TRUNCATE_FILE:
1303 r = write_one_file(i, i->path);
1304 if (r < 0)
1305 return r;
1306 break;
1307
1308 case COPY_FILES: {
1309 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1310 r = copy_tree(i->argument, i->path, i->uid_set ? i->uid : UID_INVALID, i->gid_set ? i->gid : GID_INVALID, COPY_REFLINK);
1311
1312 if (r == -EROFS && stat(i->path, &st) == 0)
1313 r = -EEXIST;
1314
1315 if (r < 0) {
1316 struct stat a, b;
1317
1318 if (r != -EEXIST)
1319 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1320
1321 if (stat(i->argument, &a) < 0)
1322 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
1323
1324 if (stat(i->path, &b) < 0)
1325 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1326
1327 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
1328 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1329 return 0;
1330 }
1331 }
1332
1333 r = path_set_perms(i, i->path);
1334 if (r < 0)
1335 return r;
1336
1337 break;
1338
1339 case WRITE_FILE:
1340 r = glob_item(i, write_one_file, false);
1341 if (r < 0)
1342 return r;
1343
1344 break;
1345
1346 case CREATE_DIRECTORY:
1347 case TRUNCATE_DIRECTORY:
1348 case CREATE_SUBVOLUME:
1349 case CREATE_SUBVOLUME_INHERIT_QUOTA:
1350 case CREATE_SUBVOLUME_NEW_QUOTA:
1351 RUN_WITH_UMASK(0000)
1352 mkdir_parents_label(i->path, 0755);
1353
1354 if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {
1355
1356 if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)
1357
1358 /* Don't create a subvolume unless the
1359 * root directory is one, too. We do
1360 * this under the assumption that if
1361 * the root directory is just a plain
1362 * directory (i.e. very light-weight),
1363 * we shouldn't try to split it up
1364 * into subvolumes (i.e. more
1365 * heavy-weight). Thus, chroot()
1366 * environments and suchlike will get
1367 * a full brtfs subvolume set up below
1368 * their tree only if they
1369 * specifically set up a btrfs
1370 * subvolume for the root dir too. */
1371
1372 r = -ENOTTY;
1373 else {
1374 RUN_WITH_UMASK((~i->mode) & 0777)
1375 r = btrfs_subvol_make(i->path);
1376 }
1377 } else
1378 r = 0;
1379
1380 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
1381 RUN_WITH_UMASK(0000)
1382 r = mkdir_label(i->path, i->mode);
1383
1384 if (r < 0) {
1385 int k;
1386
1387 if (!IN_SET(r, -EEXIST, -EROFS))
1388 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1389
1390 k = is_dir(i->path, false);
1391 if (k == -ENOENT && r == -EROFS)
1392 return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", i->path);
1393 if (k < 0)
1394 return log_error_errno(k, "Failed to check if %s exists: %m", i->path);
1395 if (!k) {
1396 log_warning("\"%s\" already exists and is not a directory.", i->path);
1397 return 0;
1398 }
1399
1400 creation = CREATION_EXISTING;
1401 } else
1402 creation = CREATION_NORMAL;
1403
1404 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1405
1406 if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
1407 r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
1408 if (r == -ENOTTY)
1409 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path);
1410 else if (r == -EROFS)
1411 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path);
1412 else if (r == -ENOPROTOOPT)
1413 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path);
1414 else if (r < 0)
1415 q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
1416 else if (r > 0)
1417 log_debug("Adjusted quota for subvolume \"%s\".", i->path);
1418 else if (r == 0)
1419 log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
1420 }
1421
1422 _fallthrough_;
1423 case EMPTY_DIRECTORY:
1424 r = path_set_perms(i, i->path);
1425 if (q < 0)
1426 return q;
1427 if (r < 0)
1428 return r;
1429
1430 break;
1431
1432 case CREATE_FIFO:
1433 RUN_WITH_UMASK(0000) {
1434 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1435 r = mkfifo(i->path, i->mode);
1436 mac_selinux_create_file_clear();
1437 }
1438
1439 if (r < 0) {
1440 if (errno != EEXIST)
1441 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1442
1443 if (lstat(i->path, &st) < 0)
1444 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1445
1446 if (!S_ISFIFO(st.st_mode)) {
1447
1448 if (i->force) {
1449 RUN_WITH_UMASK(0000) {
1450 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1451 r = mkfifo_atomic(i->path, i->mode);
1452 mac_selinux_create_file_clear();
1453 }
1454
1455 if (r < 0)
1456 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1457 creation = CREATION_FORCE;
1458 } else {
1459 log_warning("\"%s\" already exists and is not a fifo.", i->path);
1460 return 0;
1461 }
1462 } else
1463 creation = CREATION_EXISTING;
1464 } else
1465 creation = CREATION_NORMAL;
1466 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1467
1468 r = path_set_perms(i, i->path);
1469 if (r < 0)
1470 return r;
1471
1472 break;
1473 }
1474
1475 case CREATE_SYMLINK: {
1476 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1477 r = symlink(i->argument, i->path);
1478 mac_selinux_create_file_clear();
1479
1480 if (r < 0) {
1481 _cleanup_free_ char *x = NULL;
1482
1483 if (errno != EEXIST)
1484 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1485
1486 r = readlink_malloc(i->path, &x);
1487 if (r < 0 || !streq(i->argument, x)) {
1488
1489 if (i->force) {
1490 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1491 r = symlink_atomic(i->argument, i->path);
1492 mac_selinux_create_file_clear();
1493
1494 if (IN_SET(r, -EEXIST, -ENOTEMPTY)) {
1495 r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL);
1496 if (r < 0)
1497 return log_error_errno(r, "rm -fr %s failed: %m", i->path);
1498
1499 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1500 r = symlink(i->argument, i->path) < 0 ? -errno : 0;
1501 mac_selinux_create_file_clear();
1502 }
1503 if (r < 0)
1504 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1505
1506 creation = CREATION_FORCE;
1507 } else {
1508 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1509 return 0;
1510 }
1511 } else
1512 creation = CREATION_EXISTING;
1513 } else
1514
1515 creation = CREATION_NORMAL;
1516 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1517 break;
1518 }
1519
1520 case CREATE_BLOCK_DEVICE:
1521 case CREATE_CHAR_DEVICE: {
1522 mode_t file_type;
1523
1524 if (have_effective_cap(CAP_MKNOD) == 0) {
1525 /* In a container we lack CAP_MKNOD. We
1526 shouldn't attempt to create the device node in
1527 that case to avoid noise, and we don't support
1528 virtualized devices in containers anyway. */
1529
1530 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1531 return 0;
1532 }
1533
1534 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1535
1536 RUN_WITH_UMASK(0000) {
1537 mac_selinux_create_file_prepare(i->path, file_type);
1538 r = mknod(i->path, i->mode | file_type, i->major_minor);
1539 mac_selinux_create_file_clear();
1540 }
1541
1542 if (r < 0) {
1543 if (errno == EPERM) {
1544 log_debug("We lack permissions, possibly because of cgroup configuration; "
1545 "skipping creation of device node %s.", i->path);
1546 return 0;
1547 }
1548
1549 if (errno != EEXIST)
1550 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1551
1552 if (lstat(i->path, &st) < 0)
1553 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1554
1555 if ((st.st_mode & S_IFMT) != file_type) {
1556
1557 if (i->force) {
1558
1559 RUN_WITH_UMASK(0000) {
1560 mac_selinux_create_file_prepare(i->path, file_type);
1561 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1562 mac_selinux_create_file_clear();
1563 }
1564
1565 if (r < 0)
1566 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1567 creation = CREATION_FORCE;
1568 } else {
1569 log_debug("%s is not a device node.", i->path);
1570 return 0;
1571 }
1572 } else
1573 creation = CREATION_EXISTING;
1574 } else
1575 creation = CREATION_NORMAL;
1576
1577 log_debug("%s %s device node \"%s\" %u:%u.",
1578 creation_mode_verb_to_string(creation),
1579 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1580 i->path, major(i->mode), minor(i->mode));
1581
1582 r = path_set_perms(i, i->path);
1583 if (r < 0)
1584 return r;
1585
1586 break;
1587 }
1588
1589 case ADJUST_MODE:
1590 case RELABEL_PATH:
1591 r = glob_item(i, path_set_perms, false);
1592 if (r < 0)
1593 return r;
1594 break;
1595
1596 case RECURSIVE_RELABEL_PATH:
1597 r = glob_item(i, path_set_perms, true);
1598 if (r < 0)
1599 return r;
1600 break;
1601
1602 case SET_XATTR:
1603 r = glob_item(i, path_set_xattrs, false);
1604 if (r < 0)
1605 return r;
1606 break;
1607
1608 case RECURSIVE_SET_XATTR:
1609 r = glob_item(i, path_set_xattrs, true);
1610 if (r < 0)
1611 return r;
1612 break;
1613
1614 case SET_ACL:
1615 r = glob_item(i, path_set_acls, false);
1616 if (r < 0)
1617 return r;
1618 break;
1619
1620 case RECURSIVE_SET_ACL:
1621 r = glob_item(i, path_set_acls, true);
1622 if (r < 0)
1623 return r;
1624 break;
1625
1626 case SET_ATTRIBUTE:
1627 r = glob_item(i, path_set_attribute, false);
1628 if (r < 0)
1629 return r;
1630 break;
1631
1632 case RECURSIVE_SET_ATTRIBUTE:
1633 r = glob_item(i, path_set_attribute, true);
1634 if (r < 0)
1635 return r;
1636 break;
1637 }
1638
1639 return 0;
1640 }
1641
1642 static int remove_item_instance(Item *i, const char *instance) {
1643 int r;
1644
1645 assert(i);
1646
1647 switch (i->type) {
1648
1649 case REMOVE_PATH:
1650 if (remove(instance) < 0 && errno != ENOENT)
1651 return log_error_errno(errno, "rm(%s): %m", instance);
1652
1653 break;
1654
1655 case TRUNCATE_DIRECTORY:
1656 case RECURSIVE_REMOVE_PATH:
1657 /* FIXME: we probably should use dir_cleanup() here
1658 * instead of rm_rf() so that 'x' is honoured. */
1659 log_debug("rm -rf \"%s\"", instance);
1660 r = rm_rf(instance, (i->type == RECURSIVE_REMOVE_PATH ? REMOVE_ROOT|REMOVE_SUBVOLUME : 0) | REMOVE_PHYSICAL);
1661 if (r < 0 && r != -ENOENT)
1662 return log_error_errno(r, "rm_rf(%s): %m", instance);
1663
1664 break;
1665
1666 default:
1667 assert_not_reached("wut?");
1668 }
1669
1670 return 0;
1671 }
1672
1673 static int remove_item(Item *i) {
1674 assert(i);
1675
1676 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1677
1678 switch (i->type) {
1679
1680 case REMOVE_PATH:
1681 case TRUNCATE_DIRECTORY:
1682 case RECURSIVE_REMOVE_PATH:
1683 return glob_item(i, remove_item_instance, false);
1684
1685 default:
1686 return 0;
1687 }
1688 }
1689
1690 static int clean_item_instance(Item *i, const char* instance) {
1691 _cleanup_closedir_ DIR *d = NULL;
1692 struct stat s, ps;
1693 bool mountpoint;
1694 usec_t cutoff, n;
1695 char timestamp[FORMAT_TIMESTAMP_MAX];
1696
1697 assert(i);
1698
1699 if (!i->age_set)
1700 return 0;
1701
1702 n = now(CLOCK_REALTIME);
1703 if (n < i->age)
1704 return 0;
1705
1706 cutoff = n - i->age;
1707
1708 d = opendir_nomod(instance);
1709 if (!d) {
1710 if (IN_SET(errno, ENOENT, ENOTDIR)) {
1711 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1712 return 0;
1713 }
1714
1715 return log_error_errno(errno, "Failed to open directory %s: %m", instance);
1716 }
1717
1718 if (fstat(dirfd(d), &s) < 0)
1719 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1720
1721 if (!S_ISDIR(s.st_mode)) {
1722 log_error("%s is not a directory.", i->path);
1723 return -ENOTDIR;
1724 }
1725
1726 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1727 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1728
1729 mountpoint = s.st_dev != ps.st_dev || s.st_ino == ps.st_ino;
1730
1731 log_debug("Cleanup threshold for %s \"%s\" is %s",
1732 mountpoint ? "mount point" : "directory",
1733 instance,
1734 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1735
1736 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1737 MAX_DEPTH, i->keep_first_level);
1738 }
1739
1740 static int clean_item(Item *i) {
1741 assert(i);
1742
1743 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1744
1745 switch (i->type) {
1746 case CREATE_DIRECTORY:
1747 case CREATE_SUBVOLUME:
1748 case CREATE_SUBVOLUME_INHERIT_QUOTA:
1749 case CREATE_SUBVOLUME_NEW_QUOTA:
1750 case TRUNCATE_DIRECTORY:
1751 case IGNORE_PATH:
1752 case COPY_FILES:
1753 clean_item_instance(i, i->path);
1754 return 0;
1755 case EMPTY_DIRECTORY:
1756 case IGNORE_DIRECTORY_PATH:
1757 return glob_item(i, clean_item_instance, false);
1758 default:
1759 return 0;
1760 }
1761 }
1762
1763 static int process_item_array(ItemArray *array);
1764
1765 static int process_item(Item *i) {
1766 int r, q, p, t = 0;
1767 _cleanup_free_ char *prefix = NULL;
1768
1769 assert(i);
1770
1771 if (i->done)
1772 return 0;
1773
1774 i->done = true;
1775
1776 prefix = malloc(strlen(i->path) + 1);
1777 if (!prefix)
1778 return log_oom();
1779
1780 PATH_FOREACH_PREFIX(prefix, i->path) {
1781 ItemArray *j;
1782
1783 j = ordered_hashmap_get(items, prefix);
1784 if (j) {
1785 int s;
1786
1787 s = process_item_array(j);
1788 if (s < 0 && t == 0)
1789 t = s;
1790 }
1791 }
1792
1793 if (chase_symlinks(i->path, NULL, CHASE_NO_AUTOFS, NULL) == -EREMOTE)
1794 return t;
1795
1796 r = arg_create ? create_item(i) : 0;
1797 q = arg_remove ? remove_item(i) : 0;
1798 p = arg_clean ? clean_item(i) : 0;
1799
1800 return t < 0 ? t :
1801 r < 0 ? r :
1802 q < 0 ? q :
1803 p;
1804 }
1805
1806 static int process_item_array(ItemArray *array) {
1807 unsigned n;
1808 int r = 0, k;
1809
1810 assert(array);
1811
1812 for (n = 0; n < array->count; n++) {
1813 k = process_item(array->items + n);
1814 if (k < 0 && r == 0)
1815 r = k;
1816 }
1817
1818 return r;
1819 }
1820
1821 static void item_free_contents(Item *i) {
1822 assert(i);
1823 free(i->path);
1824 free(i->argument);
1825 strv_free(i->xattrs);
1826
1827 #if HAVE_ACL
1828 acl_free(i->acl_access);
1829 acl_free(i->acl_default);
1830 #endif
1831 }
1832
1833 static void item_array_free(ItemArray *a) {
1834 unsigned n;
1835
1836 if (!a)
1837 return;
1838
1839 for (n = 0; n < a->count; n++)
1840 item_free_contents(a->items + n);
1841 free(a->items);
1842 free(a);
1843 }
1844
1845 static int item_compare(const void *a, const void *b) {
1846 const Item *x = a, *y = b;
1847
1848 /* Make sure that the ownership taking item is put first, so
1849 * that we first create the node, and then can adjust it */
1850
1851 if (takes_ownership(x->type) && !takes_ownership(y->type))
1852 return -1;
1853 if (!takes_ownership(x->type) && takes_ownership(y->type))
1854 return 1;
1855
1856 return (int) x->type - (int) y->type;
1857 }
1858
1859 static bool item_compatible(Item *a, Item *b) {
1860 assert(a);
1861 assert(b);
1862 assert(streq(a->path, b->path));
1863
1864 if (takes_ownership(a->type) && takes_ownership(b->type))
1865 /* check if the items are the same */
1866 return streq_ptr(a->argument, b->argument) &&
1867
1868 a->uid_set == b->uid_set &&
1869 a->uid == b->uid &&
1870
1871 a->gid_set == b->gid_set &&
1872 a->gid == b->gid &&
1873
1874 a->mode_set == b->mode_set &&
1875 a->mode == b->mode &&
1876
1877 a->age_set == b->age_set &&
1878 a->age == b->age &&
1879
1880 a->mask_perms == b->mask_perms &&
1881
1882 a->keep_first_level == b->keep_first_level &&
1883
1884 a->major_minor == b->major_minor;
1885
1886 return true;
1887 }
1888
1889 static bool should_include_path(const char *path) {
1890 char **prefix;
1891
1892 STRV_FOREACH(prefix, arg_exclude_prefixes)
1893 if (path_startswith(path, *prefix)) {
1894 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1895 path, *prefix);
1896 return false;
1897 }
1898
1899 STRV_FOREACH(prefix, arg_include_prefixes)
1900 if (path_startswith(path, *prefix)) {
1901 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1902 return true;
1903 }
1904
1905 /* no matches, so we should include this path only if we
1906 * have no whitelist at all */
1907 if (strv_isempty(arg_include_prefixes))
1908 return true;
1909
1910 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1911 return false;
1912 }
1913
1914 static int specifier_expansion_from_arg(Item *i) {
1915 _cleanup_free_ char *unescaped = NULL, *resolved = NULL;
1916 char **xattr;
1917 int r;
1918
1919 assert(i);
1920
1921 if (i->argument == NULL)
1922 return 0;
1923
1924 switch (i->type) {
1925 case COPY_FILES:
1926 case CREATE_SYMLINK:
1927 case CREATE_FILE:
1928 case TRUNCATE_FILE:
1929 case WRITE_FILE:
1930 r = cunescape(i->argument, 0, &unescaped);
1931 if (r < 0)
1932 return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument);
1933
1934 r = specifier_printf(unescaped, specifier_table, NULL, &resolved);
1935 if (r < 0)
1936 return r;
1937
1938 free_and_replace(i->argument, resolved);
1939 break;
1940
1941 case SET_XATTR:
1942 case RECURSIVE_SET_XATTR:
1943 assert(i->xattrs);
1944
1945 STRV_FOREACH (xattr, i->xattrs) {
1946 r = specifier_printf(*xattr, specifier_table, NULL, &resolved);
1947 if (r < 0)
1948 return r;
1949
1950 free_and_replace(*xattr, resolved);
1951 }
1952 break;
1953
1954 default:
1955 break;
1956 }
1957 return 0;
1958 }
1959
1960 static int parse_line(const char *fname, unsigned line, const char *buffer, bool *invalid_config) {
1961
1962 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1963 _cleanup_(item_free_contents) Item i = {};
1964 ItemArray *existing;
1965 OrderedHashmap *h;
1966 int r, pos;
1967 bool force = false, boot = false;
1968
1969 assert(fname);
1970 assert(line >= 1);
1971 assert(buffer);
1972
1973 r = extract_many_words(
1974 &buffer,
1975 NULL,
1976 EXTRACT_QUOTES,
1977 &action,
1978 &path,
1979 &mode,
1980 &user,
1981 &group,
1982 &age,
1983 NULL);
1984 if (r < 0) {
1985 if (IN_SET(r, -EINVAL, -EBADSLT))
1986 /* invalid quoting and such or an unknown specifier */
1987 *invalid_config = true;
1988 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1989 }
1990
1991 else if (r < 2) {
1992 *invalid_config = true;
1993 log_error("[%s:%u] Syntax error.", fname, line);
1994 return -EIO;
1995 }
1996
1997 if (!isempty(buffer) && !streq(buffer, "-")) {
1998 i.argument = strdup(buffer);
1999 if (!i.argument)
2000 return log_oom();
2001 }
2002
2003 if (isempty(action)) {
2004 *invalid_config = true;
2005 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
2006 return -EINVAL;
2007 }
2008
2009 for (pos = 1; action[pos]; pos++) {
2010 if (action[pos] == '!' && !boot)
2011 boot = true;
2012 else if (action[pos] == '+' && !force)
2013 force = true;
2014 else {
2015 *invalid_config = true;
2016 log_error("[%s:%u] Unknown modifiers in command '%s'",
2017 fname, line, action);
2018 return -EINVAL;
2019 }
2020 }
2021
2022 if (boot && !arg_boot) {
2023 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
2024 action, path);
2025 return 0;
2026 }
2027
2028 i.type = action[0];
2029 i.force = force;
2030
2031 r = specifier_printf(path, specifier_table, NULL, &i.path);
2032 if (r == -ENXIO)
2033 return log_unresolvable_specifier(fname, line);
2034 if (r < 0) {
2035 if (IN_SET(r, -EINVAL, -EBADSLT))
2036 *invalid_config = true;
2037 return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path);
2038 }
2039
2040 switch (i.type) {
2041
2042 case CREATE_DIRECTORY:
2043 case CREATE_SUBVOLUME:
2044 case CREATE_SUBVOLUME_INHERIT_QUOTA:
2045 case CREATE_SUBVOLUME_NEW_QUOTA:
2046 case EMPTY_DIRECTORY:
2047 case TRUNCATE_DIRECTORY:
2048 case CREATE_FIFO:
2049 case IGNORE_PATH:
2050 case IGNORE_DIRECTORY_PATH:
2051 case REMOVE_PATH:
2052 case RECURSIVE_REMOVE_PATH:
2053 case ADJUST_MODE:
2054 case RELABEL_PATH:
2055 case RECURSIVE_RELABEL_PATH:
2056 if (i.argument)
2057 log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type);
2058
2059 break;
2060
2061 case CREATE_FILE:
2062 case TRUNCATE_FILE:
2063 break;
2064
2065 case CREATE_SYMLINK:
2066 if (!i.argument) {
2067 i.argument = strappend("/usr/share/factory/", i.path);
2068 if (!i.argument)
2069 return log_oom();
2070 }
2071 break;
2072
2073 case WRITE_FILE:
2074 if (!i.argument) {
2075 *invalid_config = true;
2076 log_error("[%s:%u] Write file requires argument.", fname, line);
2077 return -EBADMSG;
2078 }
2079 break;
2080
2081 case COPY_FILES:
2082 if (!i.argument) {
2083 i.argument = strappend("/usr/share/factory/", i.path);
2084 if (!i.argument)
2085 return log_oom();
2086 } else if (!path_is_absolute(i.argument)) {
2087 *invalid_config = true;
2088 log_error("[%s:%u] Source path is not absolute.", fname, line);
2089 return -EBADMSG;
2090 }
2091
2092 path_kill_slashes(i.argument);
2093 break;
2094
2095 case CREATE_CHAR_DEVICE:
2096 case CREATE_BLOCK_DEVICE: {
2097 unsigned major, minor;
2098
2099 if (!i.argument) {
2100 *invalid_config = true;
2101 log_error("[%s:%u] Device file requires argument.", fname, line);
2102 return -EBADMSG;
2103 }
2104
2105 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
2106 *invalid_config = true;
2107 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
2108 return -EBADMSG;
2109 }
2110
2111 i.major_minor = makedev(major, minor);
2112 break;
2113 }
2114
2115 case SET_XATTR:
2116 case RECURSIVE_SET_XATTR:
2117 if (!i.argument) {
2118 *invalid_config = true;
2119 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
2120 return -EBADMSG;
2121 }
2122 r = parse_xattrs_from_arg(&i);
2123 if (r < 0)
2124 return r;
2125 break;
2126
2127 case SET_ACL:
2128 case RECURSIVE_SET_ACL:
2129 if (!i.argument) {
2130 *invalid_config = true;
2131 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
2132 return -EBADMSG;
2133 }
2134 r = parse_acls_from_arg(&i);
2135 if (r < 0)
2136 return r;
2137 break;
2138
2139 case SET_ATTRIBUTE:
2140 case RECURSIVE_SET_ATTRIBUTE:
2141 if (!i.argument) {
2142 *invalid_config = true;
2143 log_error("[%s:%u] Set file attribute requires argument.", fname, line);
2144 return -EBADMSG;
2145 }
2146 r = parse_attribute_from_arg(&i);
2147 if (IN_SET(r, -EINVAL, -EBADSLT))
2148 *invalid_config = true;
2149 if (r < 0)
2150 return r;
2151 break;
2152
2153 default:
2154 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
2155 *invalid_config = true;
2156 return -EBADMSG;
2157 }
2158
2159 if (!path_is_absolute(i.path)) {
2160 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
2161 *invalid_config = true;
2162 return -EBADMSG;
2163 }
2164
2165 path_kill_slashes(i.path);
2166
2167 if (!should_include_path(i.path))
2168 return 0;
2169
2170 r = specifier_expansion_from_arg(&i);
2171 if (r == -ENXIO)
2172 return log_unresolvable_specifier(fname, line);
2173 if (r < 0) {
2174 if (IN_SET(r, -EINVAL, -EBADSLT))
2175 *invalid_config = true;
2176 return log_error_errno(r, "[%s:%u] Failed to substitute specifiers in argument: %m",
2177 fname, line);
2178 }
2179
2180 if (arg_root) {
2181 char *p;
2182
2183 p = prefix_root(arg_root, i.path);
2184 if (!p)
2185 return log_oom();
2186
2187 free(i.path);
2188 i.path = p;
2189 }
2190
2191 if (!isempty(user) && !streq(user, "-")) {
2192 const char *u = user;
2193
2194 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
2195 if (r < 0) {
2196 *invalid_config = true;
2197 return log_error_errno(r, "[%s:%u] Unknown user '%s'.", fname, line, user);
2198 }
2199
2200 i.uid_set = true;
2201 }
2202
2203 if (!isempty(group) && !streq(group, "-")) {
2204 const char *g = group;
2205
2206 r = get_group_creds(&g, &i.gid);
2207 if (r < 0) {
2208 *invalid_config = true;
2209 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
2210 return r;
2211 }
2212
2213 i.gid_set = true;
2214 }
2215
2216 if (!isempty(mode) && !streq(mode, "-")) {
2217 const char *mm = mode;
2218 unsigned m;
2219
2220 if (*mm == '~') {
2221 i.mask_perms = true;
2222 mm++;
2223 }
2224
2225 if (parse_mode(mm, &m) < 0) {
2226 *invalid_config = true;
2227 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
2228 return -EBADMSG;
2229 }
2230
2231 i.mode = m;
2232 i.mode_set = true;
2233 } else
2234 i.mode = IN_SET(i.type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA) ? 0755 : 0644;
2235
2236 if (!isempty(age) && !streq(age, "-")) {
2237 const char *a = age;
2238
2239 if (*a == '~') {
2240 i.keep_first_level = true;
2241 a++;
2242 }
2243
2244 if (parse_sec(a, &i.age) < 0) {
2245 *invalid_config = true;
2246 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
2247 return -EBADMSG;
2248 }
2249
2250 i.age_set = true;
2251 }
2252
2253 h = needs_glob(i.type) ? globs : items;
2254
2255 existing = ordered_hashmap_get(h, i.path);
2256 if (existing) {
2257 unsigned n;
2258
2259 for (n = 0; n < existing->count; n++) {
2260 if (!item_compatible(existing->items + n, &i)) {
2261 log_notice("[%s:%u] Duplicate line for path \"%s\", ignoring.",
2262 fname, line, i.path);
2263 return 0;
2264 }
2265 }
2266 } else {
2267 existing = new0(ItemArray, 1);
2268 if (!existing)
2269 return log_oom();
2270
2271 r = ordered_hashmap_put(h, i.path, existing);
2272 if (r < 0)
2273 return log_oom();
2274 }
2275
2276 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
2277 return log_oom();
2278
2279 memcpy(existing->items + existing->count++, &i, sizeof(i));
2280
2281 /* Sort item array, to enforce stable ordering of application */
2282 qsort_safe(existing->items, existing->count, sizeof(Item), item_compare);
2283
2284 zero(i);
2285 return 0;
2286 }
2287
2288 static void help(void) {
2289 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
2290 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
2291 " -h --help Show this help\n"
2292 " --user Execute user configuration\n"
2293 " --version Show package version\n"
2294 " --create Create marked files/directories\n"
2295 " --clean Clean up marked directories\n"
2296 " --remove Remove marked files/directories\n"
2297 " --boot Execute actions only safe at boot\n"
2298 " --prefix=PATH Only apply rules with the specified prefix\n"
2299 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
2300 " --root=PATH Operate on an alternate filesystem root\n"
2301 , program_invocation_short_name);
2302 }
2303
2304 static int parse_argv(int argc, char *argv[]) {
2305
2306 enum {
2307 ARG_VERSION = 0x100,
2308 ARG_USER,
2309 ARG_CREATE,
2310 ARG_CLEAN,
2311 ARG_REMOVE,
2312 ARG_BOOT,
2313 ARG_PREFIX,
2314 ARG_EXCLUDE_PREFIX,
2315 ARG_ROOT,
2316 };
2317
2318 static const struct option options[] = {
2319 { "help", no_argument, NULL, 'h' },
2320 { "user", no_argument, NULL, ARG_USER },
2321 { "version", no_argument, NULL, ARG_VERSION },
2322 { "create", no_argument, NULL, ARG_CREATE },
2323 { "clean", no_argument, NULL, ARG_CLEAN },
2324 { "remove", no_argument, NULL, ARG_REMOVE },
2325 { "boot", no_argument, NULL, ARG_BOOT },
2326 { "prefix", required_argument, NULL, ARG_PREFIX },
2327 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
2328 { "root", required_argument, NULL, ARG_ROOT },
2329 {}
2330 };
2331
2332 int c, r;
2333
2334 assert(argc >= 0);
2335 assert(argv);
2336
2337 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
2338
2339 switch (c) {
2340
2341 case 'h':
2342 help();
2343 return 0;
2344
2345 case ARG_VERSION:
2346 return version();
2347
2348 case ARG_USER:
2349 arg_user = true;
2350 break;
2351
2352 case ARG_CREATE:
2353 arg_create = true;
2354 break;
2355
2356 case ARG_CLEAN:
2357 arg_clean = true;
2358 break;
2359
2360 case ARG_REMOVE:
2361 arg_remove = true;
2362 break;
2363
2364 case ARG_BOOT:
2365 arg_boot = true;
2366 break;
2367
2368 case ARG_PREFIX:
2369 if (strv_push(&arg_include_prefixes, optarg) < 0)
2370 return log_oom();
2371 break;
2372
2373 case ARG_EXCLUDE_PREFIX:
2374 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
2375 return log_oom();
2376 break;
2377
2378 case ARG_ROOT:
2379 r = parse_path_argument_and_warn(optarg, true, &arg_root);
2380 if (r < 0)
2381 return r;
2382 break;
2383
2384 case '?':
2385 return -EINVAL;
2386
2387 default:
2388 assert_not_reached("Unhandled option");
2389 }
2390
2391 if (!arg_clean && !arg_create && !arg_remove) {
2392 log_error("You need to specify at least one of --clean, --create or --remove.");
2393 return -EINVAL;
2394 }
2395
2396 return 1;
2397 }
2398
2399 static int read_config_file(const char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
2400 _cleanup_fclose_ FILE *_f = NULL;
2401 FILE *f;
2402 char line[LINE_MAX];
2403 Iterator iterator;
2404 unsigned v = 0;
2405 Item *i;
2406 int r = 0;
2407
2408 assert(fn);
2409
2410 if (streq(fn, "-")) {
2411 log_debug("Reading config from stdin.");
2412 fn = "<stdin>";
2413 f = stdin;
2414 } else {
2415 r = search_and_fopen(fn, "re", arg_root, config_dirs, &_f);
2416 if (r < 0) {
2417 if (ignore_enoent && r == -ENOENT) {
2418 log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
2419 return 0;
2420 }
2421
2422 return log_error_errno(r, "Failed to open '%s': %m", fn);
2423 }
2424 log_debug("Reading config file \"%s\".", fn);
2425 f = _f;
2426 }
2427
2428 FOREACH_LINE(line, f, break) {
2429 char *l;
2430 int k;
2431 bool invalid_line = false;
2432
2433 v++;
2434
2435 l = strstrip(line);
2436 if (IN_SET(*l, 0, '#'))
2437 continue;
2438
2439 k = parse_line(fn, v, l, &invalid_line);
2440 if (k < 0) {
2441 if (invalid_line)
2442 /* Allow reporting with a special code if the caller requested this */
2443 *invalid_config = true;
2444 else if (r == 0)
2445 /* The first error becomes our return value */
2446 r = k;
2447 }
2448 }
2449
2450 /* we have to determine age parameter for each entry of type X */
2451 ORDERED_HASHMAP_FOREACH(i, globs, iterator) {
2452 Iterator iter;
2453 Item *j, *candidate_item = NULL;
2454
2455 if (i->type != IGNORE_DIRECTORY_PATH)
2456 continue;
2457
2458 ORDERED_HASHMAP_FOREACH(j, items, iter) {
2459 if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
2460 continue;
2461
2462 if (path_equal(j->path, i->path)) {
2463 candidate_item = j;
2464 break;
2465 }
2466
2467 if ((!candidate_item && path_startswith(i->path, j->path)) ||
2468 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
2469 candidate_item = j;
2470 }
2471
2472 if (candidate_item && candidate_item->age_set) {
2473 i->age = candidate_item->age;
2474 i->age_set = true;
2475 }
2476 }
2477
2478 if (ferror(f)) {
2479 log_error_errno(errno, "Failed to read from file %s: %m", fn);
2480 if (r == 0)
2481 r = -EIO;
2482 }
2483
2484 return r;
2485 }
2486
2487 int main(int argc, char *argv[]) {
2488 int r, k;
2489 ItemArray *a;
2490 Iterator iterator;
2491 _cleanup_strv_free_ char **config_dirs = NULL;
2492 bool invalid_config = false;
2493 char **f;
2494
2495 r = parse_argv(argc, argv);
2496 if (r <= 0)
2497 goto finish;
2498
2499 log_set_target(LOG_TARGET_AUTO);
2500 log_parse_environment();
2501 log_open();
2502
2503 umask(0022);
2504
2505 mac_selinux_init();
2506
2507 items = ordered_hashmap_new(&string_hash_ops);
2508 globs = ordered_hashmap_new(&string_hash_ops);
2509
2510 if (!items || !globs) {
2511 r = log_oom();
2512 goto finish;
2513 }
2514
2515 r = 0;
2516
2517 if (arg_user) {
2518 r = user_config_paths(&config_dirs);
2519 if (r < 0) {
2520 log_error_errno(r, "Failed to initialize configuration directory list: %m");
2521 goto finish;
2522 }
2523 } else {
2524 config_dirs = strv_split_nulstr(CONF_PATHS_NULSTR("tmpfiles.d"));
2525 if (!config_dirs) {
2526 r = log_oom();
2527 goto finish;
2528 }
2529 }
2530
2531 if (DEBUG_LOGGING) {
2532 _cleanup_free_ char *t = NULL;
2533
2534 t = strv_join(config_dirs, "\n\t");
2535 if (t)
2536 log_debug("Looking for configuration files in (higher priority first:\n\t%s", t);
2537 }
2538
2539 if (optind < argc) {
2540 int j;
2541
2542 for (j = optind; j < argc; j++) {
2543 k = read_config_file((const char**) config_dirs, argv[j], false, &invalid_config);
2544 if (k < 0 && r == 0)
2545 r = k;
2546 }
2547
2548 } else {
2549 _cleanup_strv_free_ char **files = NULL;
2550
2551 r = conf_files_list_strv(&files, ".conf", arg_root, 0, (const char* const*) config_dirs);
2552 if (r < 0) {
2553 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
2554 goto finish;
2555 }
2556
2557 STRV_FOREACH(f, files) {
2558 k = read_config_file((const char**) config_dirs, *f, true, &invalid_config);
2559 if (k < 0 && r == 0)
2560 r = k;
2561 }
2562 }
2563
2564 /* The non-globbing ones usually create things, hence we apply
2565 * them first */
2566 ORDERED_HASHMAP_FOREACH(a, items, iterator) {
2567 k = process_item_array(a);
2568 if (k < 0 && r == 0)
2569 r = k;
2570 }
2571
2572 /* The globbing ones usually alter things, hence we apply them
2573 * second. */
2574 ORDERED_HASHMAP_FOREACH(a, globs, iterator) {
2575 k = process_item_array(a);
2576 if (k < 0 && r == 0)
2577 r = k;
2578 }
2579
2580 finish:
2581 ordered_hashmap_free_with_destructor(items, item_array_free);
2582 ordered_hashmap_free_with_destructor(globs, item_array_free);
2583
2584 free(arg_include_prefixes);
2585 free(arg_exclude_prefixes);
2586 free(arg_root);
2587
2588 set_free_free(unix_sockets);
2589
2590 mac_selinux_finish();
2591
2592 if (r < 0)
2593 return EXIT_FAILURE;
2594 else if (invalid_config)
2595 return EX_DATAERR;
2596 else
2597 return EXIT_SUCCESS;
2598 }