mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
parent
02d0848df3
commit
de4144cfc3
@ -20,6 +20,7 @@
|
||||
#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"
|
||||
@ -552,6 +553,47 @@ Instance* resource_find_instance(Resource *rr, const char *version) {
|
||||
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,
|
||||
@ -571,8 +613,6 @@ int resource_resolve_path(
|
||||
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
|
||||
@ -596,12 +636,18 @@ int resource_resolve_path(
|
||||
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 */
|
||||
@ -643,7 +689,9 @@ int resource_resolve_path(
|
||||
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;
|
||||
@ -682,9 +730,6 @@ int resource_resolve_path(
|
||||
} 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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user