#include "hexdecoct.h"
#include "import-util.h"
#include "macro.h"
+#include "missing_magic.h"
#include "process-util.h"
#include "sort-util.h"
#include "string-table.h"
return *found;
}
+static int get_sysext_overlay_block(const char *p, dev_t *ret) {
+ int r;
+
+ assert(p);
+ assert(ret);
+
+ /* Tries to read the backing device information systemd-sysext puts in the virtual file
+ * /usr/.systemd-sysext/backing */
+
+ _cleanup_free_ char *j = path_join(p, ".systemd-sysext");
+ if (!j)
+ return log_oom_debug();
+
+ _cleanup_close_ int fd = open(j, O_RDONLY|O_DIRECTORY);
+ if (fd < 0)
+ return log_debug_errno(errno, "Failed to open '%s': %m", j);
+
+ r = fd_is_fs_type(fd, OVERLAYFS_SUPER_MAGIC);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to determine backing file system of '%s': %m", j);
+ if (r == 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOTTY), "Backing file system of '%s' is not an overlayfs.", j);
+
+ _cleanup_free_ char *buf = NULL;
+ r = read_one_line_file_at(fd, "backing", &buf);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read contents of '%s/backing': %m", j);
+
+ r = parse_devnum(buf, ret);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse contents of '%s/backing': %m", j);
+
+ if (major(*ret) == 0) { /* not a block device? */
+ *ret = 0;
+ return 0;
+ }
+
+ (void) block_get_originating(*ret, ret);
+ return 1;
+}
+
int resource_resolve_path(
Resource *rr,
const char *root,
path_relative_to_to_string(rr->path_relative_to));
if (rr->path_auto) {
- struct stat orig_root_stats;
-
/* NB: If the root mount has been replaced by some form of volatile file system (overlayfs),
* the original root block device node is symlinked in /run/systemd/volatile-root. Let's
* follow that link here. If that doesn't exist, we check the backing device of "/usr". We
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
"Block device is not allowed when using --root= mode.");
- r = stat("/run/systemd/volatile-root", &orig_root_stats);
+ struct stat orig_root_stats;
+ r = RET_NERRNO(stat("/run/systemd/volatile-root", &orig_root_stats));
if (r < 0) {
- if (errno == ENOENT) /* volatile-root not found */
- r = get_block_device_harder("/usr/", &d);
- else
+ if (r != -ENOENT)
return log_error_errno(r, "Failed to stat /run/systemd/volatile-root: %m");
+
+ /* volatile-root not found */
+ r = get_block_device_harder("/usr/", &d);
+ if (r == 0) /* Not backed by a block device? Let's see if this is a sysext overlayfs instance */
+ r = get_sysext_overlay_block("/usr/", &d);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine block device of file system: %m");
} else if (!S_ISBLK(orig_root_stats.st_mode)) /* symlink was present but not block device */
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "/run/systemd/volatile-root is not linked to a block device.");
else /* symlink was present and a block device */
if (real_fd < 0)
return log_error_errno(real_fd, "Failed to convert O_PATH file descriptor for %s to regular file descriptor: %m", rr->path);
- r = get_block_device_harder_fd(fd, &d);
+ r = get_block_device_harder_fd(real_fd, &d);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine block device of file system: %m");
} else if (RESOURCE_IS_FILESYSTEM(rr->type)) {
_cleanup_free_ char *resolved = NULL, *relative_to = NULL;
} else
return 0; /* Otherwise assume there's nothing to resolve */
- if (r < 0)
- return log_error_errno(r, "Failed to determine block device of file system: %m");
-
r = block_get_whole_disk(d, &d);
if (r < 0)
return log_error_errno(r, "Failed to find whole disk device for partition backing file system: %m");