mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 06:25:37 +03:00
Merge pull request #25591 from poettering/dissect-probe-offset
dissect-image: probe file system via main block device fd/image file fd
This commit is contained in:
commit
ef6636fd18
@ -74,9 +74,15 @@
|
||||
/* how many times to wait for the device nodes to appear */
|
||||
#define N_DEVICE_NODE_LIST_ATTEMPTS 10
|
||||
|
||||
int probe_filesystem_full(int fd, const char *path, char **ret_fstype) {
|
||||
int probe_filesystem_full(
|
||||
int fd,
|
||||
const char *path,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
char **ret_fstype) {
|
||||
|
||||
/* Try to find device content type and return it in *ret_fstype. If nothing is found,
|
||||
* 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and an
|
||||
* 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and a
|
||||
* different error otherwise. */
|
||||
|
||||
#if HAVE_BLKID
|
||||
@ -105,12 +111,19 @@ int probe_filesystem_full(int fd, const char *path, char **ret_fstype) {
|
||||
path = path_by_fd;
|
||||
}
|
||||
|
||||
if (size == 0) /* empty size? nothing found! */
|
||||
goto not_found;
|
||||
|
||||
b = blkid_new_probe();
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
errno = 0;
|
||||
r = blkid_probe_set_device(b, fd, 0, 0);
|
||||
r = blkid_probe_set_device(
|
||||
b,
|
||||
fd,
|
||||
offset,
|
||||
size == UINT64_MAX ? 0 : size); /* when blkid sees size=0 it understands "everything". We prefer using UINT64_MAX for that */
|
||||
if (r != 0)
|
||||
return errno_or_else(ENOMEM);
|
||||
|
||||
@ -154,7 +167,7 @@ not_found:
|
||||
}
|
||||
|
||||
#if HAVE_BLKID
|
||||
static int dissected_image_probe_filesystem(DissectedImage *m) {
|
||||
static int dissected_image_probe_filesystems(DissectedImage *m, int fd) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -167,9 +180,14 @@ static int dissected_image_probe_filesystem(DissectedImage *m) {
|
||||
if (!p->found)
|
||||
continue;
|
||||
|
||||
if (!p->fstype && p->mount_node_fd >= 0 && !p->decrypted_node) {
|
||||
r = probe_filesystem_full(p->mount_node_fd, p->node, &p->fstype);
|
||||
if (r < 0 && r != -EUCLEAN)
|
||||
if (!p->fstype) {
|
||||
/* If we have an fd referring to the partition block device, use that. Otherwise go
|
||||
* via the whole block device or backing regular file, and read via offset. */
|
||||
if (p->mount_node_fd >= 0)
|
||||
r = probe_filesystem_full(p->mount_node_fd, p->node, 0, UINT64_MAX, &p->fstype);
|
||||
else
|
||||
r = probe_filesystem_full(fd, p->node, p->offset, p->size, &p->fstype);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1117,6 +1135,10 @@ static int dissect_image(
|
||||
}
|
||||
}
|
||||
|
||||
r = dissected_image_probe_filesystems(m, fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -2240,7 +2262,7 @@ int dissected_image_decrypt(
|
||||
}
|
||||
|
||||
if (!p->decrypted_fstype && p->mount_node_fd >= 0 && p->decrypted_node) {
|
||||
r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, &p->decrypted_fstype);
|
||||
r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, 0, UINT64_MAX, &p->decrypted_fstype);
|
||||
if (r < 0 && r != -EUCLEAN)
|
||||
return r;
|
||||
}
|
||||
@ -2952,10 +2974,6 @@ int dissect_loop_device(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dissected_image_probe_filesystem(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
#else
|
||||
|
@ -133,9 +133,9 @@ MountOptions* mount_options_free_all(MountOptions *options);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
|
||||
const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
|
||||
|
||||
int probe_filesystem_full(int fd, const char *path, char **ret_fstype);
|
||||
int probe_filesystem_full(int fd, const char *path, uint64_t offset, uint64_t size, char **ret_fstype);
|
||||
static inline int probe_filesystem(const char *path, char **ret_fstype) {
|
||||
return probe_filesystem_full(-1, path, ret_fstype);
|
||||
return probe_filesystem_full(-1, path, 0, UINT64_MAX, ret_fstype);
|
||||
}
|
||||
int dissect_image_file(
|
||||
const char *path,
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <linux/loop.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "capability-util.h"
|
||||
@ -44,6 +46,15 @@ static void verify_dissected_image(DissectedImage *dissected) {
|
||||
assert_se(dissected->partitions[PARTITION_HOME].node);
|
||||
}
|
||||
|
||||
static void verify_dissected_image_harder(DissectedImage *dissected) {
|
||||
verify_dissected_image(dissected);
|
||||
|
||||
assert_se(streq(dissected->partitions[PARTITION_ESP].fstype, "vfat"));
|
||||
assert_se(streq(dissected->partitions[PARTITION_XBOOTLDR].fstype, "vfat"));
|
||||
assert_se(streq(dissected->partitions[PARTITION_ROOT].fstype, "ext4"));
|
||||
assert_se(streq(dissected->partitions[PARTITION_HOME].fstype, "ext4"));
|
||||
}
|
||||
|
||||
static void* thread_func(void *ptr) {
|
||||
int fd = PTR_TO_FD(ptr);
|
||||
int r;
|
||||
@ -246,8 +257,23 @@ static int run(int argc, char *argv[]) {
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true) >= 0);
|
||||
|
||||
dissected = dissected_image_unref(dissected);
|
||||
|
||||
/* We created the file systems now via the per-partition block devices. But the dissection code might
|
||||
* probe them via the whole block device. These block devices have separate buffer caches though,
|
||||
* hence what was written via the partition device might not appear on the whole block device
|
||||
* yet. Let's hence explicitly flush the whole block device, so that the read-back definitely
|
||||
* works. */
|
||||
assert_se(ioctl(loop->fd, BLKFLSBUF, 0) >= 0);
|
||||
|
||||
/* Try to read once, without pinning or adding partitions, i.e. by only accessing the whole block
|
||||
* device. */
|
||||
assert_se(dissect_loop_device(loop, NULL, NULL, 0, &dissected) >= 0);
|
||||
verify_dissected_image_harder(dissected);
|
||||
dissected = dissected_image_unref(dissected);
|
||||
|
||||
/* Now go via the loopback device after all, but this time add/pin, because now we want to mount it. */
|
||||
assert_se(dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
|
||||
verify_dissected_image(dissected);
|
||||
verify_dissected_image_harder(dissected);
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user