Richard W.M. Jones
2019-Jan-20 20:57 UTC
[Libguestfs] [PATCH nbdkit 0/4] partition: Support MBR logical partitions.
This implements support for MBR logical partitions in nbdkit-partition-filter, complementing existing support in the partitioning plugin. Rich.
Richard W.M. Jones
2019-Jan-20 20:57 UTC
[Libguestfs] [PATCH nbdkit 1/4] partition: Move MBR and GPT parsing code to separate files.
Simply code motion, there should be no change to the functionality.
---
filters/partition/partition.h | 48 ++++++++++
filters/partition/partition-gpt.c | 126 ++++++++++++++++++++++++++
filters/partition/partition-mbr.c | 91 +++++++++++++++++++
filters/partition/partition.c | 146 +++---------------------------
filters/partition/Makefile.am | 5 +-
5 files changed, 280 insertions(+), 136 deletions(-)
diff --git a/filters/partition/partition.h b/filters/partition/partition.h
new file mode 100644
index 0000000..f82d845
--- /dev/null
+++ b/filters/partition/partition.h
@@ -0,0 +1,48 @@
+/* nbdkit
+ * Copyright (C) 2018-2019 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef NBDKIT_PARTITION_H
+#define NBDKIT_PARTITION_H
+
+#include <nbdkit-filter.h>
+
+extern int partnum;
+
+extern int find_mbr_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
+ int64_t size, uint8_t *mbr,
+ int64_t *offset_r, int64_t *range_r);
+extern int find_gpt_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
+ int64_t size, uint8_t *header_bytes,
+ int64_t *offset_r, int64_t *range_r);
+
+#endif /* NBDKIT_PARTITION_H */
diff --git a/filters/partition/partition-gpt.c
b/filters/partition/partition-gpt.c
new file mode 100644
index 0000000..feefe7b
--- /dev/null
+++ b/filters/partition/partition-gpt.c
@@ -0,0 +1,126 @@
+/* nbdkit
+ * Copyright (C) 2018-2019 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <nbdkit-filter.h>
+
+#include "byte-swapping.h"
+
+#include "partition.h"
+
+struct gpt_header {
+ uint32_t nr_partitions;
+ uint32_t partition_entry_size;
+};
+
+static void
+get_gpt_header (uint8_t *sector, struct gpt_header *header)
+{
+ memcpy (&header->nr_partitions, §or[0x50], 4);
+ header->nr_partitions = le32toh (header->nr_partitions);
+ memcpy (&header->partition_entry_size, §or[0x54], 4);
+ header->partition_entry_size = le32toh (header->partition_entry_size);
+}
+
+struct gpt_partition {
+ uint8_t partition_type_guid[16];
+ uint64_t first_lba;
+ uint64_t last_lba;
+};
+
+static void
+get_gpt_partition (uint8_t *bytes, struct gpt_partition *part)
+{
+ memcpy (&part->partition_type_guid, &bytes[0], 16);
+ memcpy (&part->first_lba, &bytes[0x20], 8);
+ part->first_lba = le64toh (part->first_lba);
+ memcpy (&part->last_lba, &bytes[0x28], 8);
+ part->last_lba = le64toh (part->last_lba);
+}
+
+int
+find_gpt_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
+ int64_t size, uint8_t *header_bytes,
+ int64_t *offset_r, int64_t *range_r)
+{
+ uint8_t partition_bytes[128];
+ struct gpt_header header;
+ struct gpt_partition partition;
+ int i;
+ int err;
+
+ get_gpt_header (header_bytes, &header);
+ if (partnum > header.nr_partitions) {
+ nbdkit_error ("GPT partition number out of range");
+ return -1;
+ }
+
+ if (header.partition_entry_size < 128) {
+ nbdkit_error ("GPT partition entry size is < 128 bytes");
+ return -1;
+ }
+
+ /* Check the disk is large enough to contain the partition table
+ * array (twice) plus other GPT overheads. Otherwise it is likely
+ * that the GPT header is bogus.
+ */
+ if (size < INT64_C(3*512) +
+ INT64_C(2) * header.nr_partitions * header.partition_entry_size) {
+ nbdkit_error ("GPT partition table is too large for this disk");
+ return -1;
+ }
+
+ for (i = 0; i < header.nr_partitions; ++i) {
+ /* We already checked these are within bounds above. */
+ if (next_ops->pread (nxdata, partition_bytes, sizeof partition_bytes,
+ 2*512 + i*header.partition_entry_size, 0, &err) ==
-1)
+ return -1;
+ get_gpt_partition (partition_bytes, &partition);
+ if (memcmp (partition.partition_type_guid,
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) != 0
&&
+ partnum == i+1) {
+ *offset_r = partition.first_lba * 512;
+ *range_r = (1 + partition.last_lba - partition.first_lba) * 512;
+ return 0;
+ }
+ }
+
+ nbdkit_error ("GPT partition %d not found", partnum);
+ return -1;
+}
diff --git a/filters/partition/partition-mbr.c
b/filters/partition/partition-mbr.c
new file mode 100644
index 0000000..f679db0
--- /dev/null
+++ b/filters/partition/partition-mbr.c
@@ -0,0 +1,91 @@
+/* nbdkit
+ * Copyright (C) 2018-2019 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <nbdkit-filter.h>
+
+#include "byte-swapping.h"
+
+#include "partition.h"
+
+struct mbr_partition {
+ uint8_t part_type_byte;
+ uint32_t start_sector;
+ uint32_t nr_sectors;
+};
+
+static void
+get_mbr_partition (uint8_t *sector, int i, struct mbr_partition *part)
+{
+ int offset = 0x1BE + i*0x10;
+
+ part->part_type_byte = sector[offset+4];
+ memcpy (&part->start_sector, §or[offset+8], 4);
+ part->start_sector = le32toh (part->start_sector);
+ memcpy (&part->nr_sectors, §or[offset+0xC], 4);
+ part->nr_sectors = le32toh (part->nr_sectors);
+}
+
+int
+find_mbr_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
+ int64_t size, uint8_t *mbr,
+ int64_t *offset_r, int64_t *range_r)
+{
+ int i;
+ struct mbr_partition partition;
+
+ if (partnum > 4) {
+ nbdkit_error ("MBR logical partitions are not supported");
+ return -1;
+ }
+
+ for (i = 0; i < 4; ++i) {
+ get_mbr_partition (mbr, i, &partition);
+ if (partition.nr_sectors > 0 &&
+ partition.part_type_byte != 0 &&
+ partnum == i+1) {
+ *offset_r = partition.start_sector * 512;
+ *range_r = partition.nr_sectors * 512;
+ return 0;
+ }
+ }
+
+ nbdkit_error ("MBR partition %d not found", partnum);
+ return -1;
+}
diff --git a/filters/partition/partition.c b/filters/partition/partition.c
index 4d141ef..af103a8 100644
--- a/filters/partition/partition.c
+++ b/filters/partition/partition.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2018 Red Hat Inc.
+ * Copyright (C) 2018-2019 Red Hat Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,9 +43,11 @@
#include "byte-swapping.h"
+#include "partition.h"
+
#define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL
-static int partnum = -1;
+int partnum = -1;
/* Called for each key=value passed on the command line. */
static int
@@ -111,134 +113,6 @@ partition_close (void *handle)
free (h);
}
-/* Inspect the underlying partition table. partition_prepare is
- * called before data processing.
- */
-struct mbr_partition {
- uint8_t part_type_byte;
- uint32_t start_sector;
- uint32_t nr_sectors;
-};
-
-static void
-get_mbr_partition (uint8_t *sector, int i, struct mbr_partition *part)
-{
- int offset = 0x1BE + i*0x10;
-
- part->part_type_byte = sector[offset+4];
- memcpy (&part->start_sector, §or[offset+8], 4);
- part->start_sector = le32toh (part->start_sector);
- memcpy (&part->nr_sectors, §or[offset+0xC], 4);
- part->nr_sectors = le32toh (part->nr_sectors);
-}
-
-static int
-find_mbr_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
- struct handle *h, int64_t size, uint8_t *mbr)
-{
- int i;
- struct mbr_partition partition;
-
- if (partnum > 4) {
- nbdkit_error ("MBR logical partitions are not supported");
- return -1;
- }
-
- for (i = 0; i < 4; ++i) {
- get_mbr_partition (mbr, i, &partition);
- if (partition.nr_sectors > 0 &&
- partition.part_type_byte != 0 &&
- partnum == i+1) {
- h->offset = partition.start_sector * 512;
- h->range = partition.nr_sectors * 512;
- return 0;
- }
- }
-
- nbdkit_error ("MBR partition %d not found", partnum);
- return -1;
-}
-
-struct gpt_header {
- uint32_t nr_partitions;
- uint32_t partition_entry_size;
-};
-
-static void
-get_gpt_header (uint8_t *sector, struct gpt_header *header)
-{
- memcpy (&header->nr_partitions, §or[0x50], 4);
- header->nr_partitions = le32toh (header->nr_partitions);
- memcpy (&header->partition_entry_size, §or[0x54], 4);
- header->partition_entry_size = le32toh (header->partition_entry_size);
-}
-
-struct gpt_partition {
- uint8_t partition_type_guid[16];
- uint64_t first_lba;
- uint64_t last_lba;
-};
-
-static void
-get_gpt_partition (uint8_t *bytes, struct gpt_partition *part)
-{
- memcpy (&part->partition_type_guid, &bytes[0], 16);
- memcpy (&part->first_lba, &bytes[0x20], 8);
- part->first_lba = le64toh (part->first_lba);
- memcpy (&part->last_lba, &bytes[0x28], 8);
- part->last_lba = le64toh (part->last_lba);
-}
-
-static int
-find_gpt_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
- struct handle *h, int64_t size, uint8_t *header_bytes)
-{
- uint8_t partition_bytes[128];
- struct gpt_header header;
- struct gpt_partition partition;
- int i;
- int err;
-
- get_gpt_header (header_bytes, &header);
- if (partnum > header.nr_partitions) {
- nbdkit_error ("GPT partition number out of range");
- return -1;
- }
-
- if (header.partition_entry_size < 128) {
- nbdkit_error ("GPT partition entry size is < 128 bytes");
- return -1;
- }
-
- /* Check the disk is large enough to contain the partition table
- * array (twice) plus other GPT overheads. Otherwise it is likely
- * that the GPT header is bogus.
- */
- if (size < INT64_C(3*512) +
- INT64_C(2) * header.nr_partitions * header.partition_entry_size) {
- nbdkit_error ("GPT partition table is too large for this disk");
- return -1;
- }
-
- for (i = 0; i < header.nr_partitions; ++i) {
- /* We already checked these are within bounds above. */
- if (next_ops->pread (nxdata, partition_bytes, sizeof partition_bytes,
- 2*512 + i*header.partition_entry_size, 0, &err) ==
-1)
- return -1;
- get_gpt_partition (partition_bytes, &partition);
- if (memcmp (partition.partition_type_guid,
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) != 0
&&
- partnum == i+1) {
- h->offset = partition.first_lba * 512;
- h->range = (1 + partition.last_lba - partition.first_lba) * 512;
- return 0;
- }
- }
-
- nbdkit_error ("GPT partition %d not found", partnum);
- return -1;
-}
-
static int
partition_prepare (struct nbdkit_next_ops *next_ops, void *nxdata,
void *handle)
@@ -264,10 +138,12 @@ partition_prepare (struct nbdkit_next_ops *next_ops, void
*nxdata,
/* Is it GPT? */
if (size >= 2 * 34 * 512 && memcmp (&lba01[512], "EFI
PART", 8) == 0)
- r = find_gpt_partition (next_ops, nxdata, h, size, &lba01[512]);
+ r = find_gpt_partition (next_ops, nxdata, size, &lba01[512],
+ &h->offset, &h->range);
/* Is it MBR? */
else if (lba01[0x1fe] == 0x55 && lba01[0x1ff] == 0xAA)
- r = find_mbr_partition (next_ops, nxdata, h, size, lba01);
+ r = find_mbr_partition (next_ops, nxdata, size, lba01,
+ &h->offset, &h->range);
else {
nbdkit_error ("disk does not contain MBR or GPT partition table
signature");
r = -1;
@@ -275,9 +151,9 @@ partition_prepare (struct nbdkit_next_ops *next_ops, void
*nxdata,
if (r == -1)
return -1;
- /* The find_*_partition functions set h->offset & h->range in the
- * handle to point to the partition boundaries. However we
- * additionally check that they are inside the underlying disk.
+ /* The find_*_partition functions set h->offset & h->range to the
+ * partition boundaries. We additionally check that they are inside
+ * the underlying disk.
*/
if (h->offset < 0 || h->range < 0 || h->offset + h->range
> size) {
nbdkit_error ("partition is outside the disk");
diff --git a/filters/partition/Makefile.am b/filters/partition/Makefile.am
index 7e8430a..0932793 100644
--- a/filters/partition/Makefile.am
+++ b/filters/partition/Makefile.am
@@ -1,5 +1,5 @@
# nbdkit
-# Copyright (C) 2018 Red Hat Inc.
+# Copyright (C) 2018-2019 Red Hat Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,9 @@ filter_LTLIBRARIES = nbdkit-partition-filter.la
nbdkit_partition_filter_la_SOURCES = \
partition.c \
+ partition.h \
+ partition-gpt.c \
+ partition-mbr.c \
$(top_srcdir)/include/nbdkit-filter.h
nbdkit_partition_filter_la_CPPFLAGS = \
--
2.20.1
Richard W.M. Jones
2019-Jan-20 20:57 UTC
[Libguestfs] [PATCH nbdkit 2/4] partition: Support MBR logical partitions.
---
filters/partition/nbdkit-partition-filter.pod | 5 -
filters/partition/partition-mbr.c | 108 ++++++++++++++++--
tests/test-partitioning1.sh | 22 +++-
3 files changed, 117 insertions(+), 18 deletions(-)
diff --git a/filters/partition/nbdkit-partition-filter.pod
b/filters/partition/nbdkit-partition-filter.pod
index 4a615b6..ccd1b52 100644
--- a/filters/partition/nbdkit-partition-filter.pod
+++ b/filters/partition/nbdkit-partition-filter.pod
@@ -19,11 +19,6 @@ This works like the C<qemu-nbd -P> option.
The opposite of this filter is L<nbdkit-partitioning-plugin(1)> which
adds a virtual partition table to a file or files.
-=head1 NOTE
-
-Only MBR primary partitions and GPT partition tables are supported.
-MBR logical partitions are B<not> supported.
-
=head1 PARAMETERS
=over 4
diff --git a/filters/partition/partition-mbr.c
b/filters/partition/partition-mbr.c
index f679db0..8e61128 100644
--- a/filters/partition/partition-mbr.c
+++ b/filters/partition/partition-mbr.c
@@ -36,14 +36,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <inttypes.h>
#include <string.h>
+#include <errno.h>
#include <nbdkit-filter.h>
#include "byte-swapping.h"
+#include "isaligned.h"
#include "partition.h"
+/* See also linux.git/block/partitions/msdos.c:is_extended_partition */
+#define is_extended(byte) ((byte) == 0x5 || (byte) == 0xf || (byte) == 0x85)
+
struct mbr_partition {
uint8_t part_type_byte;
uint32_t start_sector;
@@ -69,20 +75,98 @@ find_mbr_partition (struct nbdkit_next_ops *next_ops, void
*nxdata,
{
int i;
struct mbr_partition partition;
+ uint32_t ep_start_sector, ep_nr_sectors;
+ uint64_t ebr, next_ebr;
+ uint8_t sector[512];
- if (partnum > 4) {
- nbdkit_error ("MBR logical partitions are not supported");
+ if (partnum <= 4) { /* Primary partition. */
+ for (i = 0; i < 4; ++i) {
+ get_mbr_partition (mbr, i, &partition);
+ if (partition.nr_sectors > 0 &&
+ partition.part_type_byte != 0 &&
+ !is_extended (partition.part_type_byte) &&
+ partnum == i+1) {
+ *offset_r = partition.start_sector * 512;
+ *range_r = partition.nr_sectors * 512;
+ return 0;
+ }
+ }
+ }
+ else { /* Logical partition. */
+ /* Find the extended partition. */
+ for (i = 0; i < 4; ++i) {
+ get_mbr_partition (mbr, i, &partition);
+ if (partition.nr_sectors > 0 &&
+ is_extended (partition.part_type_byte)) {
+ goto found_extended;
+ }
+ }
+ nbdkit_error ("MBR logical partition %d (>= 5) selected, but there
is no extended partition in the partition table",
+ partnum);
return -1;
- }
-
- for (i = 0; i < 4; ++i) {
- get_mbr_partition (mbr, i, &partition);
- if (partition.nr_sectors > 0 &&
- partition.part_type_byte != 0 &&
- partnum == i+1) {
- *offset_r = partition.start_sector * 512;
- *range_r = partition.nr_sectors * 512;
- return 0;
+
+ found_extended:
+ ep_start_sector = partition.start_sector;
+ ep_nr_sectors = partition.nr_sectors;
+ ebr = ep_start_sector * UINT64_C(512);
+
+ /* This loop will terminate eventually because we only accept
+ * links which strictly increase the EBR pointer.
+ */
+ for (i = 5; ; ++i) {
+ /* Read the EBR sector. */
+ if (next_ops->pread (nxdata, sector, sizeof sector, ebr, 0,
+ &errno) == -1)
+ return -1;
+
+ if (i == partnum) {
+ uint64_t offset, range;
+
+ /* First entry in EBR points to the logical partition. */
+ get_mbr_partition (sector, 0, &partition);
+
+ /* The first entry start sector is relative to the EBR. */
+ offset = ebr + partition.start_sector * UINT64_C(512);
+ range = partition.nr_sectors * UINT64_C(512);
+
+ /* Logical partition cannot be before the corresponding EBR,
+ * and it cannot extend beyond the enclosing extended
+ * partition.
+ */
+ if (offset <= ebr ||
+ offset + range >
+ ((uint64_t)ep_start_sector + ep_nr_sectors) * 512) {
+ nbdkit_error ("logical partition start or size out of range
"
+ "(offset=%" PRIu64 ", range=%"
PRIu64 ", "
+ "ep:startsect=%" PRIu32 ",
ep:nrsects=%" PRIu32 ")",
+ offset, range, ep_start_sector, ep_nr_sectors);
+ return -1;
+ }
+ *offset_r = offset;
+ *range_r = range;
+ return 0;
+ }
+
+ /* Second entry in EBR links to the next EBR. */
+ get_mbr_partition (sector, 1, &partition);
+
+ /* All zeroes means the end of the chain. */
+ if (partition.start_sector == 0 && partition.nr_sectors == 0)
+ break;
+
+ /* The second entry start sector is relative to the start to the
+ * extended partition.
+ */
+ next_ebr = ((uint64_t)ep_start_sector + partition.start_sector) * 512;
+
+ /* Make sure the next EBR > current EBR. */
+ if (next_ebr <= ebr) {
+ nbdkit_error ("invalid EBR chain: "
+ "next EBR %" PRIu64 " <= current EBR
%" PRIu64,
+ next_ebr, ebr);
+ return -1;
+ }
+ ebr = next_ebr;
}
}
diff --git a/tests/test-partitioning1.sh b/tests/test-partitioning1.sh
index 76ab43b..8aa45b9 100755
--- a/tests/test-partitioning1.sh
+++ b/tests/test-partitioning1.sh
@@ -77,7 +77,27 @@ nbdkit -f -v -D partitioning.regions=1 -U - \
# Contents of partitioning1.out should be identical to file-data.
cmp file-data partitioning1.out
-# Same test with GPT and more partitions.
+# Same test with > 4 MBR partitions.
+# Note we select partition 6 because partition 4 is the extended partition.
+nbdkit -f -v -D partitioning.regions=1 -U - \
+ --filter=partition \
+ partitioning \
+ partitioning1-p1 \
+ partitioning1-p2 \
+ partitioning1-p3 \
+ partitioning1-p4 \
+ type-guid=A2A0D0EB-E5B9-3344-87C0-68B6B72699C7 \
+ file-data \
+ type-guid=AF3DC60F-8384-7247-8E79-3D69D8477DE4 \
+ partitioning1-p5 \
+ partitioning1-p6 \
+ partition-type=mbr \
+ partition=6 \
+ --run 'qemu-img convert $nbd partitioning1.out'
+
+cmp file-data partitioning1.out
+
+# Same test with GPT.
nbdkit -f -v -D partitioning.regions=1 -U - \
--filter=partition \
partitioning \
--
2.20.1
Richard W.M. Jones
2019-Jan-20 20:57 UTC
[Libguestfs] [PATCH nbdkit 3/4] tests: Copy test-partitioning4.sh for MBR.
This test is now applicable to MBR too since we started
supporting logical partitions.
---
tests/Makefile.am | 4 +-
tests/test-partitioning4.sh | 2 +-
tests/test-partitioning6.sh | 92 +++++++++++++++++++++++++++++++++++++
3 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 27abbaf..3afa81a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -84,6 +84,7 @@ EXTRA_DIST = \
test-partitioning3.sh \
test-partitioning4.sh \
test-partitioning5.sh \
+ test-partitioning6.sh \
test-pattern.sh \
test-pattern-largest.sh \
test-pattern-largest-for-qemu.sh \
@@ -453,7 +454,8 @@ test_memory_LDADD = libtest.la $(LIBGUESTFS_LIBS)
# partitioning plugin test.
TESTS += \
test-partitioning1.sh \
- test-partitioning4.sh
+ test-partitioning4.sh \
+ test-partitioning6.sh
if HAVE_GUESTFISH
TESTS += \
test-partitioning2.sh \
diff --git a/tests/test-partitioning4.sh b/tests/test-partitioning4.sh
index 4177640..f80c7ae 100755
--- a/tests/test-partitioning4.sh
+++ b/tests/test-partitioning4.sh
@@ -33,7 +33,7 @@
# Test the partitioning plugin.
#
-# Test 4: Test > 128 partitions.
+# Test 4: Test > 128 partitions using GPT.
#
# virtio-scsi (used by libguestfs) doesn't support more than 15
# partitions. In fact the only client which supports this is our own
diff --git a/tests/test-partitioning6.sh b/tests/test-partitioning6.sh
new file mode 100755
index 0000000..ea84854
--- /dev/null
+++ b/tests/test-partitioning6.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright (C) 2018-2019 Red Hat Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# Test the partitioning plugin.
+#
+# Test 4: Test > 128 partitions using MBR.
+#
+# virtio-scsi (used by libguestfs) doesn't support more than 15
+# partitions. In fact the only client which supports this is our own
+# partition filter so we use that for the test.
+
+source ./functions.sh
+set -e
+set -x
+
+# Check if the printf utility is available. This is probably using
+# the bash builtin (not the one from coreutils) which does not
+# understand --flags, so we have to test it using a dummy format
+# string.
+if ! printf ""; then
+ echo "$0: missing or broken printf"
+ exit 77
+fi
+
+# Test that qemu-img works
+if ! qemu-img --help >/dev/null; then
+ echo "$0: missing or broken qemu-img"
+ exit 77
+fi
+
+d=partitioning6.d
+rm -rf $d
+mkdir $d
+cleanup_fn rm -rf $d
+
+# Create the partitions.
+for i in {1..768}; do
+ truncate -s 1 $(printf '%s/part.%04d' $d $i)
+done
+
+# Create partition 250 containing data and truncate it to a whole
+# number of sectors.
+rm $d/part.0250
+for i in {0..1000}; do
+ echo -n "hello " >> $d/part.0250
+done
+truncate -s 6144 $d/part.0250
+
+# Run nbdkit.
+#
+# Note we select partition 251 (not 250) because partition 4 is the
+# extended partition and everything partition following moves up by 1.
+nbdkit -f -v -D partitioning.regions=1 -U - \
+ --filter=partition \
+ partitioning \
+ $d/part.* \
+ partition-type=mbr \
+ partition=251 \
+ --run "qemu-img convert \$nbd $d/out"
+
+# The output should be identical to partition 250.
+cmp $d/part.0250 $d/out
--
2.20.1
Richard W.M. Jones
2019-Jan-20 20:57 UTC
[Libguestfs] [PATCH nbdkit 4/4] tests: Implement a better nbdkit-partition-filter test.
Test the partition filter against real life partition tables created
by sfdisk.
---
tests/test-partition.c | 101 -----------------------------
tests/Makefile.am | 7 +-
tests/test-partition.sh | 140 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+), 106 deletions(-)
diff --git a/tests/test-partition.c b/tests/test-partition.c
deleted file mode 100644
index 3de60d8..0000000
--- a/tests/test-partition.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* nbdkit
- * Copyright (C) 2018 Red Hat Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of Red Hat nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <guestfs.h>
-
-#include "test.h"
-
-int
-main (int argc, char *argv[])
-{
- guestfs_h *g;
- int r;
- char *data;
-
- if (test_start_nbdkit ("-r",
- "--filter", "partition",
- "file", "disk",
- "partition=1",
- NULL) == -1)
- exit (EXIT_FAILURE);
-
- g = guestfs_create ();
- if (g == NULL) {
- perror ("guestfs_create");
- exit (EXIT_FAILURE);
- }
-
- r = guestfs_add_drive_opts (g, "",
- GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
- GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
- -1);
- if (r == -1)
- exit (EXIT_FAILURE);
-
- if (guestfs_launch (g) == -1)
- exit (EXIT_FAILURE);
-
- /* Because we're using the partition filter, the device should
- * appear to be a filesystem directly on a whole disk.
- */
- if (guestfs_mount_ro (g, "/dev/sda", "/") == -1)
- exit (EXIT_FAILURE);
-
- data = guestfs_cat (g, "/hello.txt");
- if (!data)
- exit (EXIT_FAILURE);
-
- if (strcmp (data, "hello,world") != 0) {
- fprintf (stderr,
- "%s FAILED: unexpected content of /hello.txt file "
- "(actual: %s, expected: \"hello,world\")\n",
- program_name, data);
- exit (EXIT_FAILURE);
- }
-
- free (data);
-
- guestfs_close (g);
- exit (EXIT_SUCCESS);
-}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3afa81a..dfc065e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -79,6 +79,7 @@ EXTRA_DIST = \
test-offset2.sh \
test-parallel-file.sh \
test-parallel-nbd.sh \
+ test-partition.sh \
test-partitioning1.sh \
test-partitioning2.sh \
test-partitioning3.sh \
@@ -794,11 +795,7 @@ test_offset_LDADD = libtest.la $(LIBGUESTFS_LIBS)
TESTS += test-offset2.sh
# partition filter test.
-LIBGUESTFS_TESTS += test-partition
-
-test_partition_SOURCES = test-partition.c test.h
-test_partition_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
-test_partition_LDADD = libtest.la $(LIBGUESTFS_LIBS)
+TESTS += test-partition.sh
# truncate filter tests.
TESTS += \
diff --git a/tests/test-partition.sh b/tests/test-partition.sh
new file mode 100755
index 0000000..425cd0f
--- /dev/null
+++ b/tests/test-partition.sh
@@ -0,0 +1,140 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright (C) 2018-2019 Red Hat Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+source ./functions.sh
+set -e
+set -x
+
+d="partition.d"
+rm -rf $d
+cleanup_fn rm -rf $d
+mkdir $d
+
+# Test that sfdisk is available and working.
+if ! sfdisk --help >/dev/null; then
+ echo "$0: missing or broken sfdisk"
+ exit 77
+fi
+
+# Test that qemu-img is available and working.
+if ! qemu-img --help >/dev/null; then
+ echo "$0: missing or broken qemu-img"
+ exit 77
+fi
+
+echo "The quick brown fox jumps over the lazy dog" > $d/rand
+
+test ()
+{
+ label=$1
+ nrparts=$2
+
+ rm -f $d/disk
+ truncate -s 1G $d/disk
+ sfdisk -X $label $d/disk
+
+ # Run nbdkit on each partition, copying data in and out.
+ for ((part=1; part <= $nrparts; ++part)); do
+ if [ $nrparts -le 4 ] || [ $label != "dos" ] || [ $part -ne 4
]; then
+ nbdkit -f -v --filter=partition file $d/disk partition=$part \
+ --run "qemu-img convert -n $d/rand \$nbd"
+ nbdkit -f -v --filter=partition file $d/disk partition=$part \
+ --run "qemu-img convert \$nbd $d/out"
+ truncate -r $d/rand $d/out
+ cmp $d/rand $d/out
+ fi
+ done
+}
+
+test dos 1 <<'EOF'
+2048 1023 L -
+EOF
+
+test dos 2 <<'EOF'
+2048 1023 L -
+4096 4095 L -
+EOF
+
+test dos 3 <<'EOF'
+2048 1023 L -
+4096 4095 L -
+8192 8191 L -
+EOF
+
+test dos 6 <<'EOF'
+2048 2047 L -
+4096 4095 L -
+8192 8191 L -
+16384 16383 E -
+17000 999 L -
+18000 999 L -
+EOF
+
+test gpt 1 <<'EOF'
+2048 1023 L -
+EOF
+
+test gpt 2 <<'EOF'
+2048 1023 L -
+4096 4095 L -
+EOF
+
+test gpt 3 <<'EOF'
+2048 1023 L -
+4096 4095 L -
+8192 8191 L -
+EOF
+
+test gpt 4 <<'EOF'
+2048 1023 L -
+4096 4095 L -
+8192 8191 L -
+16384 16383 L -
+EOF
+
+test gpt 5 <<'EOF'
+2048 2047 L -
+4096 4095 L -
+8192 8191 L -
+16384 16383 L -
+32768 32767 L -
+EOF
+
+test gpt 6 <<'EOF'
+2048 2047 L -
+4096 4095 L -
+8192 8191 L -
+16384 16383 L -
+32768 32767 L -
+65536 65535 L -
+EOF
--
2.20.1
Richard W.M. Jones
2019-Jan-20 20:59 UTC
Re: [Libguestfs] [PATCH nbdkit 0/4] partition: Support MBR logical partitions.
The full series is here: https://github.com/rwmjones/nbdkit/commits/logical-partitions Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
Seemingly Similar Threads
- [PATCH nbdkit v3 0/5] partition filter: Support MBR logical partitions.
- [PATCH nbdkit v2 0/4] Support MBR logical partitions.
- [PATCH nbdkit v3 0/4] Add linuxdisk plugin.
- [PATCH nbdkit v2 0/5] Add linuxdisk plugin.
- [PATCH nbdkit 0/4] New plugin: Add linuxdisk plugin.