tmpfiles.c revision 657cf7f4f8d376e082db48022d2be193ff647d06
df8bdeb362277e8d95a74d6c097341fe97409948johnz/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
df8bdeb362277e8d95a74d6c097341fe97409948johnz This file is part of systemd.
df8bdeb362277e8d95a74d6c097341fe97409948johnz Copyright 2010 Lennart Poettering, Kay Sievers
df8bdeb362277e8d95a74d6c097341fe97409948johnz Copyright 2015 Zbigniew Jędrzejewski-Szmek
df8bdeb362277e8d95a74d6c097341fe97409948johnz systemd is free software; you can redistribute it and/or modify it
df8bdeb362277e8d95a74d6c097341fe97409948johnz under the terms of the GNU Lesser General Public License as published by
df8bdeb362277e8d95a74d6c097341fe97409948johnz the Free Software Foundation; either version 2.1 of the License, or
df8bdeb362277e8d95a74d6c097341fe97409948johnz (at your option) any later version.
df8bdeb362277e8d95a74d6c097341fe97409948johnz systemd is distributed in the hope that it will be useful, but
df8bdeb362277e8d95a74d6c097341fe97409948johnz WITHOUT ANY WARRANTY; without even the implied warranty of
df8bdeb362277e8d95a74d6c097341fe97409948johnz MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
df8bdeb362277e8d95a74d6c097341fe97409948johnz Lesser General Public License for more details.
df8bdeb362277e8d95a74d6c097341fe97409948johnz You should have received a copy of the GNU Lesser General Public License
df8bdeb362277e8d95a74d6c097341fe97409948johnz along with systemd; If not, see <http://www.gnu.org/licenses/>.
735564919188238196dbd0d320770dda59b38369Anthony Scarpino/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
df8bdeb362277e8d95a74d6c097341fe97409948johnz * them in the file system. This is intended to be used to create
df8bdeb362277e8d95a74d6c097341fe97409948johnz * properly owned directories beneath /tmp, /var/tmp, /run, which are
df8bdeb362277e8d95a74d6c097341fe97409948johnz * volatile and hence need to be recreated on bootup. */
df8bdeb362277e8d95a74d6c097341fe97409948johnztypedef enum ItemType {
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* These ones take file names */
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* These ones take globs */
df8bdeb362277e8d95a74d6c097341fe97409948johnz ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COMtypedef struct Item {
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COMstatic bool arg_create = false;
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic bool arg_clean = false;
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic bool arg_remove = false;
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic bool arg_boot = false;
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COMstatic Hashmap *items = NULL, *globs = NULL;
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic struct Item* find_glob(Hashmap *h, const char *match) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz unsigned n;
df8bdeb362277e8d95a74d6c097341fe97409948johnz for (n = 0; n < j->count; n++) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic void load_unix_sockets(void) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* We maintain a cache of the sockets we found in
df8bdeb362277e8d95a74d6c097341fe97409948johnz * /proc/net/unix to speed things up a little. */
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Skip header */
df8bdeb362277e8d95a74d6c097341fe97409948johnz char *p, *s;
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM p += strcspn(p, WHITESPACE); /* skip one more word */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM if (k < 0 && k != -EEXIST)
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM return !!set_get(unix_sockets, (char*) fn);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* We don't know, so assume yes */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COMstatic int dir_is_mount_point(DIR *d, const char *subdir) {
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM union file_handle_union h = FILE_HANDLE_INIT;
df8bdeb362277e8d95a74d6c097341fe97409948johnz r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
df8bdeb362277e8d95a74d6c097341fe97409948johnz r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* got no handle; make no assumptions, return error */
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (r_p < 0 && r < 0)
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* got both handles; if they differ, it is a mount point */
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (r_p >= 0 && r >= 0)
2225707c7e7edf7c636ed349df2592ef85329cddValerie Bubb Fenwick /* got only one handle; assume different mount points if one
df8bdeb362277e8d95a74d6c097341fe97409948johnz * of both queries was not supported by the filesystem */
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
df8bdeb362277e8d95a74d6c097341fe97409948johnz return true;
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* return error */
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic DIR* xopendirat_nomod(int dirfd, const char *path) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
df8bdeb362277e8d95a74d6c097341fe97409948johnz const char *p,
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM _cleanup_free_ char *sub_path = NULL;
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM if (STR_IN_SET(dent->d_name, ".", ".."))
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* FUSE, NFS mounts, SELinux might return EACCES */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Stay on the same filesystem */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Try to detect bind mounts of the same filesystem instance; they
df8bdeb362277e8d95a74d6c097341fe97409948johnz * do not differ in device major/minors. This type of query is not
df8bdeb362277e8d95a74d6c097341fe97409948johnz * supported on all kernels or filesystem types though. */
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Do not delete read-only files owned by root */
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Is there an item configured for this path? */
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Ignoring \"%s\".", sub_path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_warning("Reached max depth on \"%s\".", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Note: if you are wondering why we don't
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM * support the sticky bit for excluding
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM * directories from cleaning like we do it for
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM * other file system objects: well, the sticky
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM * bit already has a meaning for directories,
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM * so we don't want to overload that. */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Keeping \"%s\".", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Ignore ctime, we change it when deleting */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Follows spelling in stat(1). */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Directory \"%s\": modify time %s is too new.",
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM format_timestamp_us(a, sizeof(a), age));
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Directory \"%s\": access time %s is too new.",
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM format_timestamp_us(a, sizeof(a), age));
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Removing directory \"%s\".", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM if (errno != ENOENT && errno != ENOTEMPTY) {
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_error_errno(errno, "rmdir(%s): %m", sub_path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Skip files for which the sticky bit is
df8bdeb362277e8d95a74d6c097341fe97409948johnz * set. These are semantics we define, and are
df8bdeb362277e8d95a74d6c097341fe97409948johnz * unknown elsewhere. See XDG_RUNTIME_DIR
df8bdeb362277e8d95a74d6c097341fe97409948johnz * specification for details. */
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug("Skipping \"%s\": sticky bit set.", sub_path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Ignore sockets that are listed in /proc/net/unix */
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Ignore device nodes */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Keep files on this level around if this is
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Keeping \"%s\".", sub_path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* Follows spelling in stat(1). */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM r = log_error_errno(errno, "unlink(%s): %m", sub_path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Restore original directory timestamps */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_debug("Restoring access and modification time on \"%s\": %s, %s",
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM format_timestamp_us(a, sizeof(a), age1),
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* not using i->path directly because it may be a glob */
df8bdeb362277e8d95a74d6c097341fe97409948johnz m &= ~0111;
df8bdeb362277e8d95a74d6c097341fe97409948johnz m &= ~0222;
df8bdeb362277e8d95a74d6c097341fe97409948johnz m &= ~0444;
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug("\"%s\" has right mode %o", path, st.st_mode);
df8bdeb362277e8d95a74d6c097341fe97409948johnz return log_error_errno(errno, "chmod(%s) failed: %m", path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
2225707c7e7edf7c636ed349df2592ef85329cddValerie Bubb Fenwick log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM i->gid_set ? i->gid : GID_INVALID) < 0)
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM return log_error_errno(errno, "chown(%s) failed: %m", path);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM return label_fix(path, false, false);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COMstatic int get_xattrs_from_arg(Item *i) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (r < 0) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic int path_set_xattrs(Item *i, const char *path) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_error("Setting extended attribute %s=%s on %s failed: %m",
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* If force (= modify) is set, we will not modify the acl
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM * afterwards, so the mask can be added now if necessary. */
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COMstatic int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM _cleanup_(acl_freep) acl_t dup = NULL;
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM _cleanup_(acl_free_charpp) char *t = NULL;
8bab47abcb471dffa36ddbf409a8ef5303398ddfJohn.Zolnowsky@Sun.COM /* Returns 0 for success, positive error if already warned,
df8bdeb362277e8d95a74d6c097341fe97409948johnz * negative error otherwise. */
df8bdeb362277e8d95a74d6c097341fe97409948johnz /* the mask was already added earlier if needed */
df8bdeb362277e8d95a74d6c097341fe97409948johnz "Setting %s ACL \"%s\" on %s failed: %m",
df8bdeb362277e8d95a74d6c097341fe97409948johnzstatic int path_set_acls(Item *item, const char *path) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
df8bdeb362277e8d95a74d6c097341fe97409948johnz r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
df8bdeb362277e8d95a74d6c097341fe97409948johnz return -r; /* already warned */
df8bdeb362277e8d95a74d6c097341fe97409948johnz else if (r == -ENOTSUP) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug_errno(r, "ACLs not supported by file system at %s", path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz } else if (r < 0)
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz int flags, r = 0;
df8bdeb362277e8d95a74d6c097341fe97409948johnz flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
df8bdeb362277e8d95a74d6c097341fe97409948johnz i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
df8bdeb362277e8d95a74d6c097341fe97409948johnz fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
df8bdeb362277e8d95a74d6c097341fe97409948johnz if (fd < 0) {
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_debug_errno(errno, "Not writing \"%s\": %m", path);
df8bdeb362277e8d95a74d6c097341fe97409948johnz log_error_errno(errno, "Failed to create file %s: %m", path);
if (!unescaped)
return log_oom();
return -EEXIST;
assert(i);
errno = 0;
if (!de) {
if (errno != 0 && r == 0)
r = -errno;
return -ENOMEM;
q = action(i, p);
if (q < 0 && q != -ENOENT && r == 0)
char **fn;
errno = 0;
if (k != 0 && k != GLOB_NOMATCH)
if (recursive) {
} CreationMode;
assert(i);
switch (i->type) {
case IGNORE_PATH:
case IGNORE_DIRECTORY_PATH:
case REMOVE_PATH:
case RECURSIVE_REMOVE_PATH:
case CREATE_FILE:
case TRUNCATE_FILE:
case COPY_FILES:
struct stat a, b;
if (r != -EEXIST)
case WRITE_FILE:
case CREATE_DIRECTORY:
case TRUNCATE_DIRECTORY:
case CREATE_SUBVOLUME:
RUN_WITH_UMASK(0000)
RUN_WITH_UMASK(0000)
if (r != -EEXIST)
case CREATE_FIFO:
RUN_WITH_UMASK(0000) {
if (i->force) {
RUN_WITH_UMASK(0000) {
case CREATE_SYMLINK:
if (i->force) {
case CREATE_BLOCK_DEVICE:
case CREATE_CHAR_DEVICE: {
RUN_WITH_UMASK(0000) {
if (i->force) {
RUN_WITH_UMASK(0000) {
case ADJUST_MODE:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case SET_XATTR:
case RECURSIVE_SET_XATTR:
case SET_ACL:
case RECURSIVE_SET_ACL:
assert(i);
switch (i->type) {
case REMOVE_PATH:
case TRUNCATE_DIRECTORY:
case RECURSIVE_REMOVE_PATH:
if (r < 0 && r != -ENOENT)
assert(i);
switch (i->type) {
case CREATE_FILE:
case TRUNCATE_FILE:
case CREATE_DIRECTORY:
case CREATE_SUBVOLUME:
case CREATE_FIFO:
case CREATE_SYMLINK:
case CREATE_CHAR_DEVICE:
case CREATE_BLOCK_DEVICE:
case IGNORE_PATH:
case IGNORE_DIRECTORY_PATH:
case ADJUST_MODE:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
case COPY_FILES:
case SET_XATTR:
case RECURSIVE_SET_XATTR:
case SET_ACL:
case RECURSIVE_SET_ACL:
case REMOVE_PATH:
case TRUNCATE_DIRECTORY:
case RECURSIVE_REMOVE_PATH:
bool mountpoint;
assert(i);
if (!i->age_set)
if (n < i->age)
return -errno;
return -ENOTDIR;
assert(i);
switch (i->type) {
case CREATE_DIRECTORY:
case CREATE_SUBVOLUME:
case TRUNCATE_DIRECTORY:
case IGNORE_PATH:
case COPY_FILES:
case IGNORE_DIRECTORY_PATH:
assert(i);
if (i->done)
i->done = true;
if (!prefix)
return log_oom();
ItemArray *j;
s = process_item_array(j);
assert(i);
#ifdef HAVE_ACL
for (n = 0; n < a->count; n++)
free(a);
assert(a);
assert(b);
char **prefix;
_cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
Hashmap *h;
int r, pos;
&action,
&path,
&mode,
&user,
&group,
&age,
&i.argument,
NULL);
return -EIO;
return -EINVAL;
boot = true;
force = true;
return -EINVAL;
switch (i.type) {
case CREATE_FILE:
case TRUNCATE_FILE:
case CREATE_DIRECTORY:
case CREATE_SUBVOLUME:
case TRUNCATE_DIRECTORY:
case CREATE_FIFO:
case IGNORE_PATH:
case IGNORE_DIRECTORY_PATH:
case REMOVE_PATH:
case RECURSIVE_REMOVE_PATH:
case ADJUST_MODE:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case CREATE_SYMLINK:
if (!i.argument) {
if (!i.argument)
return log_oom();
case WRITE_FILE:
if (!i.argument) {
return -EBADMSG;
case COPY_FILES:
if (!i.argument) {
if (!i.argument)
return log_oom();
return -EBADMSG;
case CREATE_CHAR_DEVICE:
case CREATE_BLOCK_DEVICE: {
if (!i.argument) {
return -EBADMSG;
return -EBADMSG;
case SET_XATTR:
case RECURSIVE_SET_XATTR:
if (!i.argument) {
return -EBADMSG;
r = get_xattrs_from_arg(&i);
case SET_ACL:
case RECURSIVE_SET_ACL:
if (!i.argument) {
return -EBADMSG;
r = get_acls_from_arg(&i);
return -EBADMSG;
return -EBADMSG;
if (arg_root) {
return log_oom();
i.path = p;
const char *u = user;
i.uid_set = true;
const char *g = group;
i.gid_set = true;
i.mask_perms = true;
mm++;
return -ENOENT;
i.mode = m;
i.mode_set = true;
const char *a = age;
i.keep_first_level = true;
return -EBADMSG;
i.age_set = true;
if (existing) {
return log_oom();
return log_oom();
zero(i);
static void help(void) {
" --create Create marked files/directories\n"
" --remove Remove marked files/directories\n"
help();
case ARG_VERSION:
case ARG_CREATE:
arg_create = true;
case ARG_CLEAN:
arg_clean = true;
case ARG_REMOVE:
arg_remove = true;
case ARG_BOOT:
arg_boot = true;
case ARG_PREFIX:
return log_oom();
case ARG_EXCLUDE_PREFIX:
return log_oom();
case ARG_ROOT:
if (!arg_root)
return log_oom();
return -EINVAL;
return -EINVAL;
Item *i;
candidate_item = j;
(candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
candidate_item = j;
i->age_set = true;
if (ferror(f)) {
r = -EIO;
ItemArray *a;
goto finish;
log_open();
r = log_oom();
goto finish;
goto finish;
k = read_config_file(*f, true);
k = process_item_array(a);
k = process_item_array(a);
item_array_free(a);
item_array_free(a);