#if HAVE_BLKID
static int make_partition_devname(
const char *whole_devname,
+ uint64_t diskseq,
int nr,
+ DissectImageFlags flags,
char **ret) {
- bool need_p;
+ _cleanup_free_ char *s = NULL;
+ int r;
assert(whole_devname);
- assert(nr > 0);
+ assert(nr != 0); /* zero is not a valid partition nr */
+ assert(ret);
- /* Given a whole block device node name (e.g. /dev/sda or /dev/loop7) generate a partition device
- * name (e.g. /dev/sda7 or /dev/loop7p5). The rule the kernel uses is simple: if whole block device
- * node name ends in a digit, then suffix a 'p', followed by the partition number. Otherwise, just
- * suffix the partition number without any 'p'. */
+ if (!FLAGS_SET(flags, DISSECT_IMAGE_DISKSEQ_DEVNODE) || diskseq == UINT64_MAX) {
- if (isempty(whole_devname)) /* Make sure there *is* a last char */
- return -EINVAL;
+ /* Given a whole block device node name (e.g. /dev/sda or /dev/loop7) generate a partition
+ * device name (e.g. /dev/sda7 or /dev/loop7p5). The rule the kernel uses is simple: if whole
+ * block device node name ends in a digit, then suffix a 'p', followed by the partition
+ * number. Otherwise, just suffix the partition number without any 'p'. */
+
+ if (nr < 0) { /* whole disk? */
+ s = strdup(whole_devname);
+ if (!s)
+ return -ENOMEM;
+ } else {
+ size_t l = strlen(whole_devname);
+ if (l < 1) /* underflow check for the subtraction below */
+ return -EINVAL;
- need_p = ascii_isdigit(whole_devname[strlen(whole_devname)-1]); /* Last char a digit? */
+ bool need_p = ascii_isdigit(whole_devname[l-1]); /* Last char a digit? */
+
+ if (asprintf(&s, "%s%s%i", whole_devname, need_p ? "p" : "", nr) < 0)
+ return -ENOMEM;
+ }
+ } else {
+ if (nr < 0) /* whole disk? */
+ r = asprintf(&s, "/dev/disk/by-diskseq/%" PRIu64, diskseq);
+ else
+ r = asprintf(&s, "/dev/disk/by-diskseq/%" PRIu64 "-part%i", diskseq, nr);
+ if (r < 0)
+ return -ENOMEM;
+ }
- return asprintf(ret, "%s%s%i", whole_devname, need_p ? "p" : "", nr);
+ *ret = TAKE_PTR(s);
+ return 0;
}
-static int open_partition(const char *node, bool is_partition, const LoopDevice *loop) {
+static int open_partition(
+ const char *node,
+ bool is_partition,
+ const LoopDevice *loop) {
+
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_close_ int fd = -EBADF;
dev_t devnum;
* Returns -ENXIO if we couldn't find any partition suitable as root or /usr partition
* Returns -ENOTUNIQ if we only found multiple generic partitions and thus don't know what to do with that */
+ uint64_t diskseq = m->loop ? m->loop->diskseq : UINT64_MAX;
+
if (verity && verity->root_hash) {
sd_id128_t fsuuid, vuuid;
log_debug_errno(r, "Failed to parse file system UUID '%s', ignoring: %m", suuid);
}
- n = strdup(devname);
- if (!n)
- return -ENOMEM;
+ r = make_partition_devname(devname, diskseq, -1, flags, &n);
+ if (r < 0)
+ return r;
m->single_file_system = true;
m->encrypted = streq_ptr(fstype, "crypto_LUKS");
assert((uint64_t) size < UINT64_MAX/512);
- r = make_partition_devname(devname, nr, &node);
+ /* While probing we need the non-diskseq device node name to access the thing, hence mask off
+ * DISSECT_IMAGE_DISKSEQ_DEVNODE. */
+ r = make_partition_devname(devname, diskseq, nr, flags & ~DISSECT_IMAGE_DISKSEQ_DEVNODE, &node);
if (r < 0)
return r;
}
if (type.designator != _PARTITION_DESIGNATOR_INVALID) {
- _cleanup_free_ char *t = NULL, *o = NULL, *l = NULL;
+ _cleanup_free_ char *t = NULL, *o = NULL, *l = NULL, *n = NULL;
_cleanup_close_ int mount_node_fd = -EBADF;
const char *options = NULL;
return mount_node_fd;
}
+ r = make_partition_devname(devname, diskseq, nr, flags, &n);
+ if (r < 0)
+ return r;
+
if (fstype) {
t = strdup(fstype);
if (!t)
.rw = rw,
.growfs = growfs,
.architecture = type.arch,
- .node = TAKE_PTR(node),
+ .node = TAKE_PTR(n),
.fstype = TAKE_PTR(t),
.label = TAKE_PTR(l),
.uuid = id,
case 0xEA: { /* Boot Loader Spec extended $BOOT partition */
_cleanup_close_ int mount_node_fd = -EBADF;
- _cleanup_free_ char *o = NULL;
+ _cleanup_free_ char *o = NULL, *n = NULL;
sd_id128_t id = SD_ID128_NULL;
const char *options = NULL;
(void) blkid_partition_get_uuid_id128(pp, &id);
+ r = make_partition_devname(devname, diskseq, nr, flags, &n);
+ if (r < 0)
+ return r;
+
options = mount_options_from_designator(mount_options, PARTITION_XBOOTLDR);
if (options) {
o = strdup(options);
.rw = true,
.growfs = false,
.architecture = _ARCHITECTURE_INVALID,
- .node = TAKE_PTR(node),
+ .node = TAKE_PTR(n),
.uuid = id,
.mount_options = TAKE_PTR(o),
.mount_node_fd = TAKE_FD(mount_node_fd),
/* If we didn't find a generic node, then we can't fix this up either */
if (generic_node) {
_cleanup_close_ int mount_node_fd = -EBADF;
- _cleanup_free_ char *o = NULL;
+ _cleanup_free_ char *o = NULL, *n = NULL;
const char *options;
if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
return mount_node_fd;
}
+ r = make_partition_devname(devname, diskseq, generic_nr, flags, &n);
+ if (r < 0)
+ return r;
+
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
if (options) {
o = strdup(options);
.growfs = generic_growfs,
.partno = generic_nr,
.architecture = _ARCHITECTURE_INVALID,
- .node = TAKE_PTR(generic_node),
+ .node = TAKE_PTR(n),
.uuid = generic_uuid,
.mount_options = TAKE_PTR(o),
.mount_node_fd = TAKE_FD(mount_node_fd),