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: github.com/rwmjones/nbdkit/commits/logical-partitions Rich. -- Richard Jones, Virtualization Group, Red Hat people.redhat.com/~rjones Read my programming and virtualization blog: rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. people.redhat.com/~rjones/virt-top
Possibly Parallel 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.