static int create_item(Item *i) {
        struct stat st;
        int r = 0;
        int q = 0;
        CreationMode creation;

        assert(i);

        log_debug("Running create action for entry %c %s", (char) i->type, i->path);

        switch (i->type) {

        case IGNORE_PATH:
        case IGNORE_DIRECTORY_PATH:
        case REMOVE_PATH:
        case RECURSIVE_REMOVE_PATH:
                return 0;

        case CREATE_FILE:
        case TRUNCATE_FILE:
                r = write_one_file(i, i->path);
                if (r < 0)
                        return r;
                break;

        case COPY_FILES: {
                log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
                r = copy_tree(i->argument, i->path, i->uid_set ? i->uid : UID_INVALID, i->gid_set ? i->gid : GID_INVALID, COPY_REFLINK);

                if (r == -EROFS && stat(i->path, &st) == 0)
                        r = -EEXIST;

                if (r < 0) {
                        struct stat a, b;

                        if (r != -EEXIST)
                                return log_error_errno(r, "Failed to copy files to %s: %m", i->path);

                        if (stat(i->argument, &a) < 0)
                                return log_error_errno(errno, "stat(%s) failed: %m", i->argument);

                        if (stat(i->path, &b) < 0)
                                return log_error_errno(errno, "stat(%s) failed: %m", i->path);

                        if ((a.st_mode ^ b.st_mode) & S_IFMT) {
                                log_debug("Can't copy to %s, file exists already and is of different type", i->path);
                                return 0;
                        }
                }

                r = path_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;

        case WRITE_FILE:
                r = glob_item(i, write_one_file, false);
                if (r < 0)
                        return r;

                break;

        case CREATE_DIRECTORY:
        case TRUNCATE_DIRECTORY:
        case CREATE_SUBVOLUME:
        case CREATE_SUBVOLUME_INHERIT_QUOTA:
        case CREATE_SUBVOLUME_NEW_QUOTA:
                RUN_WITH_UMASK(0000)
                        mkdir_parents_label(i->path, 0755);

                if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {

                        if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)

                                /* Don't create a subvolume unless the
                                 * root directory is one, too. We do
                                 * this under the assumption that if
                                 * the root directory is just a plain
                                 * directory (i.e. very light-weight),
                                 * we shouldn't try to split it up
                                 * into subvolumes (i.e. more
                                 * heavy-weight). Thus, chroot()
                                 * environments and suchlike will get
                                 * a full brtfs subvolume set up below
                                 * their tree only if they
                                 * specifically set up a btrfs
                                 * subvolume for the root dir too. */

                                r = -ENOTTY;
                        else {
                                RUN_WITH_UMASK((~i->mode) & 0777)
                                        r = btrfs_subvol_make(i->path);
                        }
                } else
                        r = 0;

                if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
                        RUN_WITH_UMASK(0000)
                                r = mkdir_label(i->path, i->mode);

                if (r < 0) {
                        int k;

                        if (!IN_SET(r, -EEXIST, -EROFS))
                                return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);

                        k = is_dir(i->path, false);
                        if (k == -ENOENT && r == -EROFS)
                                return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", i->path);
                        if (k < 0)
                                return log_error_errno(k, "Failed to check if %s exists: %m", i->path);
                        if (!k) {
                                log_warning("\"%s\" already exists and is not a directory.", i->path);
                                return 0;
                        }

                        creation = CREATION_EXISTING;
                } else
                        creation = CREATION_NORMAL;

                log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);

                if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
                        r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
                        if (r == -ENOTTY)
                                log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path);
                        else if (r == -EROFS)
                                log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path);
                        else if (r == -ENOPROTOOPT)
                                log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path);
                        else if (r < 0)
                                q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
                        else if (r > 0)
                                log_debug("Adjusted quota for subvolume \"%s\".", i->path);
                        else if (r == 0)
                                log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
                }

                _fallthrough_;
        case EMPTY_DIRECTORY:
                r = path_set_perms(i, i->path);
                if (q < 0)
                        return q;
                if (r < 0)
                        return r;

                break;

        case CREATE_FIFO:
                RUN_WITH_UMASK(0000) {
                        mac_selinux_create_file_prepare(i->path, S_IFIFO);
                        r = mkfifo(i->path, i->mode);
                        mac_selinux_create_file_clear();
                }

                if (r < 0) {
                        if (errno != EEXIST)
                                return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);

                        if (lstat(i->path, &st) < 0)
                                return log_error_errno(errno, "stat(%s) failed: %m", i->path);

                        if (!S_ISFIFO(st.st_mode)) {

                                if (i->force) {
                                        RUN_WITH_UMASK(0000) {
                                                mac_selinux_create_file_prepare(i->path, S_IFIFO);
                                                r = mkfifo_atomic(i->path, i->mode);
                                                mac_selinux_create_file_clear();
                                        }

                                        if (r < 0)
                                                return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
                                        creation = CREATION_FORCE;
                                } else {
                                        log_warning("\"%s\" already exists and is not a fifo.", i->path);
                                        return 0;
                                }
                        } else
                                creation = CREATION_EXISTING;
                } else
                        creation = CREATION_NORMAL;
                log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);

                r = path_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;
        }

        case CREATE_SYMLINK: {
                mac_selinux_create_file_prepare(i->path, S_IFLNK);
                r = symlink(i->argument, i->path);
                mac_selinux_create_file_clear();

                if (r < 0) {
                        _cleanup_free_ char *x = NULL;

                        if (errno != EEXIST)
                                return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);

                        r = readlink_malloc(i->path, &x);
                        if (r < 0 || !streq(i->argument, x)) {

                                if (i->force) {
                                        mac_selinux_create_file_prepare(i->path, S_IFLNK);
                                        r = symlink_atomic(i->argument, i->path);
                                        mac_selinux_create_file_clear();

                                        if (IN_SET(r, -EEXIST, -ENOTEMPTY)) {
                                                r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL);
                                                if (r < 0)
                                                        return log_error_errno(r, "rm -fr %s failed: %m", i->path);

                                                mac_selinux_create_file_prepare(i->path, S_IFLNK);
                                                r = symlink(i->argument, i->path) < 0 ? -errno : 0;
                                                mac_selinux_create_file_clear();
                                        }
                                        if (r < 0)
                                                return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);

                                        creation = CREATION_FORCE;
                                } else {
                                        log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
                                        return 0;
                                }
                        } else
                                creation = CREATION_EXISTING;
                } else

                        creation = CREATION_NORMAL;
                log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
                break;
        }

        case CREATE_BLOCK_DEVICE:
        case CREATE_CHAR_DEVICE: {
                mode_t file_type;

                if (have_effective_cap(CAP_MKNOD) == 0) {
                        /* In a container we lack CAP_MKNOD. We
                        shouldn't attempt to create the device node in
                        that case to avoid noise, and we don't support
                        virtualized devices in containers anyway. */

                        log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
                        return 0;
                }

                file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;

                RUN_WITH_UMASK(0000) {
                        mac_selinux_create_file_prepare(i->path, file_type);
                        r = mknod(i->path, i->mode | file_type, i->major_minor);
                        mac_selinux_create_file_clear();
                }

                if (r < 0) {
                        if (errno == EPERM) {
                                log_debug("We lack permissions, possibly because of cgroup configuration; "
                                          "skipping creation of device node %s.", i->path);
                                return 0;
                        }

                        if (errno != EEXIST)
                                return log_error_errno(errno, "Failed to create device node %s: %m", i->path);

                        if (lstat(i->path, &st) < 0)
                                return log_error_errno(errno, "stat(%s) failed: %m", i->path);

                        if ((st.st_mode & S_IFMT) != file_type) {

                                if (i->force) {

                                        RUN_WITH_UMASK(0000) {
                                                mac_selinux_create_file_prepare(i->path, file_type);
                                                r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
                                                mac_selinux_create_file_clear();
                                        }

                                        if (r < 0)
                                                return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
                                        creation = CREATION_FORCE;
                                } else {
                                        log_debug("%s is not a device node.", i->path);
                                        return 0;
                                }
                        } else
                                creation = CREATION_EXISTING;
                } else
                        creation = CREATION_NORMAL;

                log_debug("%s %s device node \"%s\" %u:%u.",
                          creation_mode_verb_to_string(creation),
                          i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
                          i->path, major(i->mode), minor(i->mode));

                r = path_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;
        }

        case ADJUST_MODE:
        case RELABEL_PATH:
                r = glob_item(i, path_set_perms, false);
                if (r < 0)
                        return r;
                break;

        case RECURSIVE_RELABEL_PATH:
                r = glob_item(i, path_set_perms, true);
                if (r < 0)
                        return r;
                break;

        case SET_XATTR:
                r = glob_item(i, path_set_xattrs, false);
                if (r < 0)
                        return r;
                break;

        case RECURSIVE_SET_XATTR:
                r = glob_item(i, path_set_xattrs, true);
                if (r < 0)
                        return r;
                break;

        case SET_ACL:
                r = glob_item(i, path_set_acls, false);
                if (r < 0)
                        return r;
                break;

        case RECURSIVE_SET_ACL:
                r = glob_item(i, path_set_acls, true);
                if (r < 0)
                        return r;
                break;

        case SET_ATTRIBUTE:
                r = glob_item(i, path_set_attribute, false);
                if (r < 0)
                        return r;
                break;

        case RECURSIVE_SET_ATTRIBUTE:
                r = glob_item(i, path_set_attribute, true);
                if (r < 0)
                        return r;
                break;
        }

        return 0;
}