return asprintf(ret, "%s%s%i", whole_devname, need_p ? "p" : "", nr);
}
-#endif
-int dissect_image(
+static int dissect_image(
+ DissectedImage *m,
int fd,
const char *devname,
- const char *image_path,
const VeritySettings *verity,
const MountOptions *mount_options,
- DissectImageFlags flags,
- DissectedImage **ret) {
+ DissectImageFlags flags) {
-#if HAVE_BLKID
sd_id128_t root_uuid = SD_ID128_NULL, root_verity_uuid = SD_ID128_NULL;
sd_id128_t usr_uuid = SD_ID128_NULL, usr_verity_uuid = SD_ID128_NULL;
bool is_gpt, is_mbr, multiple_generic = false,
generic_rw = false, /* initialize to appease gcc */
generic_growfs = false;
- _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_(blkid_free_probep) blkid_probe b = NULL;
_cleanup_free_ char *generic_node = NULL;
sd_id128_t generic_uuid = SD_ID128_NULL;
blkid_partlist pl;
int r, generic_nr = -1, n_partitions;
+ assert(m);
assert(fd >= 0);
assert(devname);
- assert(ret);
assert(!verity || verity->designator < 0 || IN_SET(verity->designator, PARTITION_ROOT, PARTITION_USR));
assert(!verity || verity->root_hash || verity->root_hash_size == 0);
assert(!verity || verity->root_hash_sig || verity->root_hash_sig_size == 0);
if (r != 0)
return errno_or_else(EIO);
- r = dissected_image_new(image_path, &m);
- if (r < 0)
- return r;
-
if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
(flags & DISSECT_IMAGE_GENERIC_ROOT)) ||
(flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) {
.size = UINT64_MAX,
};
- *ret = TAKE_PTR(m);
return 0;
}
}
if (verity && verity->data_path)
return -EBADR;
- /* Safety check: refuse block devices that carry a partition table but for which the kernel doesn't
- * do partition scanning. */
- r = blockdev_partscan_enabled(fd);
- if (r < 0)
- return r;
- if (r == 0)
- return -EPROTONOSUPPORT;
+ if (FLAGS_SET(flags, DISSECT_IMAGE_MANAGE_PARTITION_DEVICES)) {
+ /* Safety check: refuse block devices that carry a partition table but for which the kernel doesn't
+ * do partition scanning. */
+ r = blockdev_partscan_enabled(fd);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EPROTONOSUPPORT;
+ }
errno = 0;
pl = blkid_probe_get_partitions(b);
* Kernel returns EBUSY if there's already a partition by that number or an overlapping
* partition already existent. */
- r = block_device_add_partition(fd, node, nr, (uint64_t) start * 512, (uint64_t) size * 512);
- if (r < 0) {
- if (r != -EBUSY)
- return log_debug_errno(r, "BLKPG_ADD_PARTITION failed: %m");
+ if (FLAGS_SET(flags, DISSECT_IMAGE_MANAGE_PARTITION_DEVICES)) {
+ r = block_device_add_partition(fd, node, nr, (uint64_t) start * 512, (uint64_t) size * 512);
+ if (r < 0) {
+ if (r != -EBUSY)
+ return log_debug_errno(r, "BLKPG_ADD_PARTITION failed: %m");
- log_debug_errno(r, "Kernel was quicker than us in adding partition %i.", nr);
- } else
- log_debug("We were quicker than kernel in adding partition %i.", nr);
+ log_debug_errno(r, "Kernel was quicker than us in adding partition %i.", nr);
+ } else
+ log_debug("We were quicker than kernel in adding partition %i.", nr);
+ }
if (is_gpt) {
PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
}
}
- blkid_free_probe(b);
- b = NULL;
+ return 0;
+}
+#endif
- r = dissected_image_probe_filesystem(m);
+int dissect_image_file(
+ const char *path,
+ const VeritySettings *verity,
+ const MountOptions *mount_options,
+ DissectImageFlags flags,
+ DissectedImage **ret) {
+
+#if HAVE_BLKID
+ _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
+ _cleanup_close_ int fd = -1;
+ int r;
+
+ assert(path);
+ assert((flags & DISSECT_IMAGE_BLOCK_DEVICE) == 0);
+ assert(ret);
+
+ fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+ if (fd < 0)
+ return -errno;
+
+ r = fd_verify_regular(fd);
+ if (r < 0)
+ return r;
+
+ r = dissected_image_new(path, &m);
+ if (r < 0)
+ return r;
+
+ r = dissect_image(m, fd, path, verity, mount_options, flags);
if (r < 0)
return r;
DissectImageFlags flags,
DissectedImage **ret) {
+#if HAVE_BLKID
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
int r;
assert(loop);
assert(ret);
- r = dissect_image(loop->fd, loop->node, loop->backing_file ?: loop->node, verity, mount_options, flags, &m);
+ r = dissected_image_new(loop->backing_file ?: loop->node, &m);
if (r < 0)
return r;
m->loop = loop_device_ref(loop);
+ r = dissect_image(m, loop->fd, loop->node, verity, mount_options, flags | DISSECT_IMAGE_BLOCK_DEVICE);
+ if (r < 0)
+ return r;
+
+ r = dissected_image_probe_filesystem(m);
+ if (r < 0)
+ return r;
+
*ret = TAKE_PTR(m);
return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
}
int dissect_loop_device_and_warn(
}
typedef enum DissectImageFlags {
- DISSECT_IMAGE_DEVICE_READ_ONLY = 1 << 0, /* Make device read-only */
- DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */
- DISSECT_IMAGE_DISCARD = 1 << 2, /* Turn on "discard" if file system supports it, on all block devices */
- DISSECT_IMAGE_DISCARD_ON_CRYPTO = 1 << 3, /* Turn on "discard" also on crypto devices */
- DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP |
- DISSECT_IMAGE_DISCARD |
- DISSECT_IMAGE_DISCARD_ON_CRYPTO,
- DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */
- DISSECT_IMAGE_GENERIC_ROOT = 1 << 5, /* If no partition table or only single generic partition, assume it's the root fs */
- DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */
- DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */
- DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */
- DISSECT_IMAGE_VALIDATE_OS_EXT = 1 << 9, /* Refuse mounting images that aren't identifiable as OS extension images */
- DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */
- DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
- DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */
- DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */
- DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */
- DISSECT_IMAGE_USR_NO_ROOT = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */
- DISSECT_IMAGE_REQUIRE_ROOT = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */
- DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */
- DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY |
- DISSECT_IMAGE_MOUNT_READ_ONLY,
- DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
- DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */
+ DISSECT_IMAGE_DEVICE_READ_ONLY = 1 << 0, /* Make device read-only */
+ DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */
+ DISSECT_IMAGE_DISCARD = 1 << 2, /* Turn on "discard" if file system supports it, on all block devices */
+ DISSECT_IMAGE_DISCARD_ON_CRYPTO = 1 << 3, /* Turn on "discard" also on crypto devices */
+ DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP |
+ DISSECT_IMAGE_DISCARD |
+ DISSECT_IMAGE_DISCARD_ON_CRYPTO,
+ DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */
+ DISSECT_IMAGE_GENERIC_ROOT = 1 << 5, /* If no partition table or only single generic partition, assume it's the root fs */
+ DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */
+ DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */
+ DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */
+ DISSECT_IMAGE_VALIDATE_OS_EXT = 1 << 9, /* Refuse mounting images that aren't identifiable as OS extension images */
+ DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */
+ DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
+ DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */
+ DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */
+ DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */
+ DISSECT_IMAGE_USR_NO_ROOT = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */
+ DISSECT_IMAGE_REQUIRE_ROOT = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */
+ DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */
+ DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY |
+ DISSECT_IMAGE_MOUNT_READ_ONLY,
+ DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
+ DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */
+ DISSECT_IMAGE_MANAGE_PARTITION_DEVICES = 1 << 20, /* Manage partition devices, e.g. probe each partition in more detail */
+ DISSECT_IMAGE_BLOCK_DEVICE = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES,
} DissectImageFlags;
struct DissectedImage {
const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
int probe_filesystem(const char *node, char **ret_fstype);
-int dissect_image(
- int fd,
- const char *devname,
- const char *image_path,
+int dissect_image_file(
+ const char *path,
const VeritySettings *verity,
const MountOptions *mount_options,
DissectImageFlags flags,