]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/tmpfiles/tmpfiles.c
Merge pull request #17549 from yuwata/tiny-fixes
[thirdparty/systemd.git] / src / tmpfiles / tmpfiles.c
index 7ab655cd6f40223a308180c331b0d1c4daaf8a06..eb63bc38073a8ff35571ead10d8c2d0c02843777 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <errno.h>
 #include <fcntl.h>
@@ -375,9 +375,8 @@ static bool takes_ownership(ItemType t) {
 
 static struct Item* find_glob(OrderedHashmap *h, const char *match) {
         ItemArray *j;
-        Iterator i;
 
-        ORDERED_HASHMAP_FOREACH(j, h, i) {
+        ORDERED_HASHMAP_FOREACH(j, h) {
                 size_t n;
 
                 for (n = 0; n < j->n_items; n++) {
@@ -517,7 +516,6 @@ static int dir_cleanup(
                 int maxdepth,
                 bool keep_this_level) {
 
-        static bool use_statx = true;
         bool deleted = false;
         struct dirent *dent;
         int r = 0;
@@ -525,115 +523,73 @@ static int dir_cleanup(
         FOREACH_DIRENT_ALL(dent, d, break) {
                 _cleanup_free_ char *sub_path = NULL;
                 nsec_t atime_nsec, mtime_nsec, ctime_nsec, btime_nsec;
-                mode_t mode;
-                uid_t uid;
 
                 if (dot_or_dot_dot(dent->d_name))
                         continue;
 
-                if (use_statx) {
-                        /* If statx() is supported, use it. It's preferable over fstatat() since it tells us
-                         * explicitly where we are looking at a mount point, for free as side
-                         * information. Determing the same information without statx() is hard, see the
-                         * complexity of path_is_mount_point(), and also much slower as it requires a numbre
-                         * of syscalls instead of just one. Hence, when we have modern statx() we use it
-                         * instead of fstat() and do proper mount point checks, while on older kernels's well
-                         * do traditional st_dev based detection of mount points.
-                         *
-                         * Using statx() for detecting mount points also has the benfit that we handle weird
-                         * file systems such as overlayfs better where each file is originating from a
-                         * different st_dev. */
-
-                        struct statx sx
-#if HAS_FEATURE_MEMORY_SANITIZER
-                                = {}
-#  warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this."
-#endif
-                                ;
-
-                        if (statx(dirfd(d), dent->d_name,
-                                  AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
-                                  STATX_TYPE|STATX_MODE|STATX_UID|STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_BTIME,
-                                  &sx) < 0) {
-
-                                if (errno == ENOENT)
-                                        continue;
-                                if (ERRNO_IS_NOT_SUPPORTED(errno) || errno == EPERM)
-                                        use_statx = false; /* Not supported or blocked by seccomp or so */
-                                else {
-                                        /* FUSE, NFS mounts, SELinux might return EACCES */
-                                        r = log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
-                                                           "statx(%s/%s) failed: %m", p, dent->d_name);
-                                        continue;
-                                }
-                        } else {
-                                if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) {
-                                        /* Yay, we have the mount point API, use it */
-                                        if (FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT)) {
-                                                log_debug("Ignoring \"%s/%s\": different mount points.", p, dent->d_name);
-                                                continue;
-                                        }
-                                } else {
-                                        /* So we have statx() but the STATX_ATTR_MOUNT_ROOT flag is not
-                                         * supported, fall back to traditional stx_dev checking. */
-                                        if (sx.stx_dev_major != rootdev_major ||
-                                            sx.stx_dev_minor != rootdev_minor) {
-                                                log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
-                                                continue;
-                                        }
-                                }
-
-                                mode = sx.stx_mode;
-                                uid = sx.stx_uid;
-                                atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? load_statx_timestamp_nsec(&sx.stx_atime) : 0;
-                                mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? load_statx_timestamp_nsec(&sx.stx_mtime) : 0;
-                                ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? load_statx_timestamp_nsec(&sx.stx_ctime) : 0;
-                                btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? load_statx_timestamp_nsec(&sx.stx_btime) : 0;
-                        }
+                /* If statx() is supported, use it. It's preferable over fstatat() since it tells us
+                 * explicitly where we are looking at a mount point, for free as side information. Determining
+                 * the same information without statx() is hard, see the complexity of path_is_mount_point(),
+                 * and also much slower as it requires a number of syscalls instead of just one. Hence, when
+                 * we have modern statx() we use it instead of fstat() and do proper mount point checks,
+                 * while on older kernels's well do traditional st_dev based detection of mount points.
+                 *
+                 * Using statx() for detecting mount points also has the benfit that we handle weird file
+                 * systems such as overlayfs better where each file is originating from a different
+                 * st_dev. */
+
+                STRUCT_STATX_DEFINE(sx);
+
+                r = statx_fallback(
+                                dirfd(d), dent->d_name,
+                                AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
+                                STATX_TYPE|STATX_MODE|STATX_UID|STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_BTIME,
+                                &sx);
+                if (r == -ENOENT)
+                        continue;
+                if (r < 0) {
+                        /* FUSE, NFS mounts, SELinux might return EACCES */
+                        r = log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+                                           "statx(%s/%s) failed: %m", p, dent->d_name);
+                        continue;
                 }
 
-                if (!use_statx) {
-                        struct stat s;
-
-                        if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
-                                if (errno == ENOENT)
-                                        continue;
-
-                                /* FUSE, NFS mounts, SELinux might return EACCES */
-                                r = log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
-                                                   "stat(%s/%s) failed: %m", p, dent->d_name);
+                if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) {
+                        /* Yay, we have the mount point API, use it */
+                        if (FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT)) {
+                                log_debug("Ignoring \"%s/%s\": different mount points.", p, dent->d_name);
                                 continue;
                         }
-
-                        /* Stay on the same filesystem */
-                        if (major(s.st_dev) != rootdev_major || minor(s.st_dev) != rootdev_minor) {
+                } else {
+                        /* So we might have statx() but the STATX_ATTR_MOUNT_ROOT flag is not supported, fall
+                         * back to traditional stx_dev checking. */
+                        if (sx.stx_dev_major != rootdev_major ||
+                            sx.stx_dev_minor != rootdev_minor) {
                                 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
                                 continue;
                         }
 
-                        mode = s.st_mode;
-                        uid = s.st_uid;
-                        atime_nsec = timespec_load_nsec(&s.st_atim);
-                        mtime_nsec = timespec_load_nsec(&s.st_mtim);
-                        ctime_nsec = timespec_load_nsec(&s.st_ctim);
-                        btime_nsec = 0;
-                }
+                        /* Try to detect bind mounts of the same filesystem instance; they do not differ in device
+                         * major/minors. This type of query is not supported on all kernels or filesystem types
+                         * though. */
+                        if (S_ISDIR(sx.stx_mode)) {
+                                int q;
 
-                /* Try to detect bind mounts of the same filesystem instance; they
-                 * do not differ in device major/minors. This type of query is not
-                 * supported on all kernels or filesystem types though. */
-                if (S_ISDIR(mode)) {
-                        int q;
-
-                        q = fd_is_mount_point(dirfd(d), dent->d_name, 0);
-                        if (q < 0)
-                                log_debug_errno(q, "Failed to determine whether \"%s/%s\" is a mount point, ignoring: %m", p, dent->d_name);
-                        else if (q > 0) {
-                                log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, dent->d_name);
-                                continue;
+                                q = fd_is_mount_point(dirfd(d), dent->d_name, 0);
+                                if (q < 0)
+                                        log_debug_errno(q, "Failed to determine whether \"%s/%s\" is a mount point, ignoring: %m", p, dent->d_name);
+                                else if (q > 0) {
+                                        log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, dent->d_name);
+                                        continue;
+                                }
                         }
                 }
 
+                atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? load_statx_timestamp_nsec(&sx.stx_atime) : 0;
+                mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? load_statx_timestamp_nsec(&sx.stx_mtime) : 0;
+                ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? load_statx_timestamp_nsec(&sx.stx_ctime) : 0;
+                btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? load_statx_timestamp_nsec(&sx.stx_btime) : 0;
+
                 sub_path = path_join(p, dent->d_name);
                 if (!sub_path) {
                         r = log_oom();
@@ -651,12 +607,12 @@ static int dir_cleanup(
                         continue;
                 }
 
-                if (S_ISDIR(mode)) {
+                if (S_ISDIR(sx.stx_mode)) {
                         _cleanup_closedir_ DIR *sub_dir = NULL;
 
                         if (mountpoint &&
                             streq(dent->d_name, "lost+found") &&
-                            uid == 0) {
+                            sx.stx_uid == 0) {
                                 log_debug("Ignoring directory \"%s\".", sub_path);
                                 continue;
                         }
@@ -732,14 +688,14 @@ static int dir_cleanup(
                 } else {
                         /* Skip files for which the sticky bit is set. These are semantics we define, and are
                          * unknown elsewhere. See XDG_RUNTIME_DIR specification for details. */
-                        if (mode & S_ISVTX) {
+                        if (sx.stx_mode & S_ISVTX) {
                                 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
                                 continue;
                         }
 
                         if (mountpoint &&
-                            S_ISREG(mode) &&
-                            uid == 0 &&
+                            S_ISREG(sx.stx_mode) &&
+                            sx.stx_uid == 0 &&
                             STR_IN_SET(dent->d_name,
                                        ".journal",
                                        "aquota.user",
@@ -749,13 +705,13 @@ static int dir_cleanup(
                         }
 
                         /* Ignore sockets that are listed in /proc/net/unix */
-                        if (S_ISSOCK(mode) && unix_socket_alive(sub_path)) {
+                        if (S_ISSOCK(sx.stx_mode) && unix_socket_alive(sub_path)) {
                                 log_debug("Skipping \"%s\": live socket.", sub_path);
                                 continue;
                         }
 
                         /* Ignore device nodes */
-                        if (S_ISCHR(mode) || S_ISBLK(mode)) {
+                        if (S_ISCHR(sx.stx_mode) || S_ISBLK(sx.stx_mode)) {
                                 log_debug("Skipping \"%s\": a device.", sub_path);
                                 continue;
                         }
@@ -880,6 +836,7 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
         struct stat stbuf;
         mode_t new_mode;
         bool do_chown;
+        int r;
 
         assert(i);
         assert(fd);
@@ -925,8 +882,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
                                 log_debug("\"%s\" matches temporary mode %o already.", path, m);
                         else {
                                 log_debug("Temporarily changing \"%s\" to mode %o.", path, m);
-                                if (fchmod_opath(fd, m) < 0)
-                                        return log_error_errno(errno, "fchmod() of %s failed: %m", path);
+                                r = fchmod_opath(fd, m);
+                                if (r < 0)
+                                        return log_error_errno(r, "fchmod() of %s failed: %m", path);
                         }
                 }
         }
@@ -957,8 +915,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
                                 log_debug("\"%s\" matches mode %o already.", path, new_mode);
                         else {
                                 log_debug("Changing \"%s\" to mode %o.", path, new_mode);
-                                if (fchmod_opath(fd, new_mode) < 0)
-                                        return log_error_errno(errno, "fchmod() of %s failed: %m", path);
+                                r = fchmod_opath(fd, new_mode);
+                                if (r < 0)
+                                        return log_error_errno(r, "fchmod() of %s failed: %m", path);
                         }
                 }
         }
@@ -1104,7 +1063,7 @@ static int parse_acls_from_arg(Item *item) {
         if (r < 0)
                 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument);
 #else
-        log_warning_errno(SYNTHETIC_ERRNO(ENOSYS), "ACLs are not supported. Ignoring");
+        log_warning("ACLs are not supported. Ignoring.");
 #endif
 
         return 0;
@@ -1145,13 +1104,17 @@ static int path_set_acl(const char *path, const char *pretty, acl_type_t type, a
                   strna(t), pretty);
 
         r = acl_set_file(path, type, dup);
-        if (r < 0)
-                /* Return positive to indicate we already warned */
-                return -log_error_errno(errno,
-                                        "Setting %s ACL \"%s\" on %s failed: %m",
-                                        type == ACL_TYPE_ACCESS ? "access" : "default",
-                                        strna(t), pretty);
-
+        if (r < 0) {
+                if (ERRNO_IS_NOT_SUPPORTED(errno))
+                        /* No error if filesystem doesn't support ACLs. Return negative. */
+                        return -errno;
+                else
+                        /* Return positive to indicate we already warned */
+                        return -log_error_errno(errno,
+                                                "Setting %s ACL \"%s\" on %s failed: %m",
+                                                type == ACL_TYPE_ACCESS ? "access" : "default",
+                                                strna(t), pretty);
+        }
         return 0;
 }
 #endif
@@ -1191,6 +1154,11 @@ static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *
         if (r == 0 && item->acl_default && S_ISDIR(st->st_mode))
                 r = path_set_acl(procfs_path, path, ACL_TYPE_DEFAULT, item->acl_default, item->append_or_force);
 
+        if (ERRNO_IS_NOT_SUPPORTED(r)) {
+                log_debug_errno(r, "ACLs not supported by file system at %s", path);
+                return 0;
+        }
+
         if (r > 0)
                 return -r; /* already warned */
 
@@ -1198,10 +1166,6 @@ static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *
         if (r == -ENOENT && proc_mounted() == 0)
                 r = -ENOSYS;
 
-        if (r == -EOPNOTSUPP) {
-                log_debug_errno(r, "ACLs not supported by file system at %s", path);
-                return 0;
-        }
         if (r < 0)
                 return log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
 #endif
@@ -1458,10 +1422,10 @@ static int create_file(Item *i, const char *path) {
                 if (fstat(fd, &stbuf) < 0)
                         return log_error_errno(errno, "stat(%s) failed: %m", path);
 
-                if (!S_ISREG(stbuf.st_mode)) {
-                        log_error("%s exists and is not a regular file.", path);
-                        return -EEXIST;
-                }
+                if (!S_ISREG(stbuf.st_mode))
+                        return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+                                               "%s exists and is not a regular file.",
+                                               path);
 
                 st = &stbuf;
         } else {
@@ -1522,10 +1486,10 @@ static int truncate_file(Item *i, const char *path) {
 
                 fd = openat(dir_fd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH, i->mode);
                 if (fd < 0) {
-                        if (errno == ENOENT) {
-                                log_error("Cannot create file %s on a read-only file system.", path);
-                                return -EROFS;
-                        }
+                        if (errno == ENOENT)
+                                return log_error_errno(SYNTHETIC_ERRNO(EROFS),
+                                                       "Cannot create file %s on a read-only file system.",
+                                                       path);
 
                         return log_error_errno(errno, "Failed to re-open file %s: %m", path);
                 }
@@ -1536,10 +1500,10 @@ static int truncate_file(Item *i, const char *path) {
         if (fstat(fd, &stbuf) < 0)
                 return log_error_errno(errno, "stat(%s) failed: %m", path);
 
-        if (!S_ISREG(stbuf.st_mode)) {
-                log_error("%s exists and is not a regular file.", path);
-                return -EEXIST;
-        }
+        if (!S_ISREG(stbuf.st_mode))
+                return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+                                       "%s exists and is not a regular file.",
+                                       path);
 
         if (stbuf.st_size > 0) {
                 if (ftruncate(fd, 0) < 0) {
@@ -1584,7 +1548,7 @@ static int copy_files(Item *i) {
                          dfd, bn,
                          i->uid_set ? i->uid : UID_INVALID,
                          i->gid_set ? i->gid : GID_INVALID,
-                         COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE);
+                         COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE | COPY_HARDLINKS);
         if (r < 0) {
                 struct stat a, b;
 
@@ -2291,18 +2255,9 @@ static int remove_item(Item *i) {
 static int clean_item_instance(Item *i, const char* instance) {
         char timestamp[FORMAT_TIMESTAMP_MAX];
         _cleanup_closedir_ DIR *d = NULL;
-        uint32_t dev_major, dev_minor;
-        nsec_t atime_nsec, mtime_nsec;
-        int mountpoint = -1;
+        STRUCT_STATX_DEFINE(sx);
+        int mountpoint, r;
         usec_t cutoff, n;
-        uint64_t ino;
-
-        struct statx sx
-#if HAS_FEATURE_MEMORY_SANITIZER
-                = {}
-#  warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this."
-#endif
-                ;
 
         assert(i);
 
@@ -2325,53 +2280,34 @@ static int clean_item_instance(Item *i, const char* instance) {
                 return log_error_errno(errno, "Failed to open directory %s: %m", instance);
         }
 
-        if (statx(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx) < 0) {
-                struct stat s;
-
-                if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
-                        return log_error_errno(errno, "statx(%s) failed: %m", i->path);
-
-                if (fstat(dirfd(d), &s) < 0)
-                        return log_error_errno(errno, "stat(%s) failed: %m", i->path);
-
-                dev_major = major(s.st_dev);
-                dev_minor = minor(s.st_dev);
-                ino = s.st_ino;
-                atime_nsec = timespec_load_nsec(&s.st_atim);
-                mtime_nsec = timespec_load_nsec(&s.st_mtim);
-        } else {
-
-                if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
-                        mountpoint = FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
-
-                dev_major = sx.stx_dev_major;
-                dev_minor = sx.stx_dev_minor;
-                ino = sx.stx_ino;
-                atime_nsec = load_statx_timestamp_nsec(&sx.stx_atime);
-                mtime_nsec = load_statx_timestamp_nsec(&sx.stx_mtime);
-        }
+        r = statx_fallback(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx);
+        if (r < 0)
+                return log_error_errno(r, "statx(%s) failed: %m", instance);
 
-        if (mountpoint < 0) {
+        if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
+                mountpoint = FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
+        else {
                 struct stat ps;
 
                 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
                         return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
 
                 mountpoint =
-                        dev_major != major(ps.st_dev) ||
-                        dev_minor != minor(ps.st_dev) ||
-                        ino != ps.st_ino;
+                        sx.stx_dev_major != major(ps.st_dev) ||
+                        sx.stx_dev_minor != minor(ps.st_dev) ||
+                        sx.stx_ino != ps.st_ino;
         }
 
-
         log_debug("Cleanup threshold for %s \"%s\" is %s",
                   mountpoint ? "mount point" : "directory",
                   instance,
                   format_timestamp_style(timestamp, sizeof(timestamp), cutoff, TIMESTAMP_US));
 
         return dir_cleanup(i, instance, d,
-                           atime_nsec, mtime_nsec, cutoff * NSEC_PER_USEC,
-                           dev_major, dev_minor, mountpoint,
+                           load_statx_timestamp_nsec(&sx.stx_atime),
+                           load_statx_timestamp_nsec(&sx.stx_mtime),
+                           cutoff * NSEC_PER_USEC,
+                           sx.stx_dev_major, sx.stx_dev_minor, mountpoint,
                            MAX_DEPTH, i->keep_first_level);
 }
 
@@ -2443,10 +2379,9 @@ static int process_item_array(ItemArray *array, OperationMask operation) {
 
         /* Clean up all children first */
         if ((operation & (OPERATION_REMOVE|OPERATION_CLEAN)) && !set_isempty(array->children)) {
-                Iterator i;
                 ItemArray *c;
 
-                SET_FOREACH(c, array->children, i) {
+                SET_FOREACH(c, array->children) {
                         int k;
 
                         k = process_item_array(c, operation & (OPERATION_REMOVE|OPERATION_CLEAN));
@@ -3175,11 +3110,15 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_IMAGE:
+#ifdef STANDALONE
+                        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                               "This systemd-tmpfiles version is compiled without support for --image=.");
+#else
                         r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image);
                         if (r < 0)
                                 return r;
-
-                        /* Imply -E here since it makes little sense to create files persistently in the /run mointpoint of a disk image */
+#endif
+                        /* Imply -E here since it makes little sense to create files persistently in the /run mountpoint of a disk image */
                         _fallthrough_;
 
                 case 'E':
@@ -3234,7 +3173,6 @@ static int parse_argv(int argc, char *argv[]) {
 static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
         _cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL;
         _cleanup_fclose_ FILE *_f = NULL;
-        Iterator iterator;
         unsigned v = 0;
         FILE *f;
         Item *i;
@@ -3290,14 +3228,13 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
         }
 
         /* we have to determine age parameter for each entry of type X */
-        ORDERED_HASHMAP_FOREACH(i, globs, iterator) {
-                Iterator iter;
+        ORDERED_HASHMAP_FOREACH(i, globs) {
                 Item *j, *candidate_item = NULL;
 
                 if (i->type != IGNORE_DIRECTORY_PATH)
                         continue;
 
-                ORDERED_HASHMAP_FOREACH(j, items, iter) {
+                ORDERED_HASHMAP_FOREACH(j, items) {
                         if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
                                 continue;
 
@@ -3403,12 +3340,13 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_array_hash_ops, char, string_
                                               ItemArray, item_array_free);
 
 static int run(int argc, char *argv[]) {
+#ifndef STANDALONE
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
         _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
+#endif
         _cleanup_strv_free_ char **config_dirs = NULL;
         bool invalid_config = false;
-        Iterator iterator;
         ItemArray *a;
         enum {
                 PHASE_REMOVE_AND_CLEAN,
@@ -3466,6 +3404,7 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return r;
 
+#ifndef STANDALONE
         if (arg_image) {
                 assert(!arg_root);
 
@@ -3482,6 +3421,9 @@ static int run(int argc, char *argv[]) {
                 if (!arg_root)
                         return log_oom();
         }
+#else
+        assert(!arg_image);
+#endif
 
         items = ordered_hashmap_new(&item_array_hash_ops);
         globs = ordered_hashmap_new(&item_array_hash_ops);
@@ -3502,12 +3444,12 @@ static int run(int argc, char *argv[]) {
                 return r;
 
         /* Let's now link up all child/parent relationships */
-        ORDERED_HASHMAP_FOREACH(a, items, iterator) {
+        ORDERED_HASHMAP_FOREACH(a, items) {
                 r = link_parent(a);
                 if (r < 0)
                         return r;
         }
-        ORDERED_HASHMAP_FOREACH(a, globs, iterator) {
+        ORDERED_HASHMAP_FOREACH(a, globs) {
                 r = link_parent(a);
                 if (r < 0)
                         return r;
@@ -3529,14 +3471,14 @@ static int run(int argc, char *argv[]) {
                         continue;
 
                 /* The non-globbing ones usually create things, hence we apply them first */
-                ORDERED_HASHMAP_FOREACH(a, items, iterator) {
+                ORDERED_HASHMAP_FOREACH(a, items) {
                         k = process_item_array(a, op);
                         if (k < 0 && r >= 0)
                                 r = k;
                 }
 
                 /* The globbing ones usually alter things, hence we apply them second. */
-                ORDERED_HASHMAP_FOREACH(a, globs, iterator) {
+                ORDERED_HASHMAP_FOREACH(a, globs) {
                         k = process_item_array(a, op);
                         if (k < 0 && r >= 0)
                                 r = k;