[parted-devel] [PATCH] Read an msdos partition table from a device with 2K sectors.

Jim Meyering jim at meyering.net
Wed May 30 21:37:18 UTC 2007


I happened to poke at a CD with an empty msdos partition, and tried
running parted on it.  It wasn't recognized, because read support for
2KB-sectors is still incomplete.  So I taught dos.c about 2KB sectors,
and now parted can print my empty partition table.

I can test with this particular CD, but an automated test would require
a writable device with 2KB sectors, and I don't have one of those.

	Read an msdos partition table from a device with 2K sectors.
	* libparted/labels/dos.c: Include <stdbool.h>.
	(msdos_probe): Don't hard-code 512.
	Use read_sector, not ped_device_read.
	Adapt to changed type of "part_table".
	Now that "label" is malloc'd, be sure to free it before returning.
	(read_table): Likewise.

Signed-off-by: Jim Meyering <jim at meyering.net>
---
 libparted/labels/dos.c |   85 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 59 insertions(+), 26 deletions(-)

diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c
index 50fadfd..76abe35 100644
--- a/libparted/labels/dos.c
+++ b/libparted/labels/dos.c
@@ -21,6 +21,7 @@
 #include <config.h>

 #include <sys/time.h>
+#include <stdbool.h>
 #include <parted/parted.h>
 #include <parted/debug.h>
 #include <parted/endian.h>
@@ -150,46 +151,67 @@ typedef struct {

 static PedDiskType msdos_disk_type;

+/* FIXME: factor out this function: copied from aix.c, with changes to
+   the description, and an added sector number argument.
+   Read sector, SECTOR_NUM (which has length DEV->sector_size) into malloc'd
+   storage.  If the read fails, free the memory and return zero without
+   modifying *BUF.  Otherwise, set *BUF to the new buffer and return 1.  */
+static int
+read_sector (const PedDevice *dev, PedSector sector_num, char **buf)
+{
+	char *b = ped_malloc (dev->sector_size);
+	PED_ASSERT (b != NULL, return 0);
+	if (!ped_device_read (dev, b, sector_num, 1)) {
+		ped_free (b);
+		return 0;
+	}
+	*buf = b;
+	return 1;
+}
+
 static int
 msdos_probe (const PedDevice *dev)
 {
 	PedDiskType*	disk_type;
-	DosRawTable	part_table;
+	DosRawTable*	part_table;
 	int		i;

 	PED_ASSERT (dev != NULL, return 0);

-        if (dev->sector_size != 512)
+        if (dev->sector_size < sizeof *part_table)
                 return 0;

-	if (!ped_device_read (dev, &part_table, 0, 1))
+	char *label;
+	if (!read_sector (dev, 0, &label))
 		return 0;

+        part_table = (DosRawTable *) label;
+
 	/* check magic */
-	if (PED_LE16_TO_CPU (part_table.magic) != MSDOS_MAGIC)
-		return 0;
+	if (PED_LE16_TO_CPU (part_table->magic) != MSDOS_MAGIC)
+		goto probe_fail;

 	/* if this is a FAT fs, fail here.  Note that the Smart Boot Manager
 	 * Loader (SBML) signature indicates a partition table, not a file
 	 * system.
 	 */
-	if ((!strncmp (part_table.boot_code + 0x36, "FAT", 3)
-	    && strncmp (part_table.boot_code + 0x40, "SBML", 4) != 0)
-	    || !strncmp (part_table.boot_code + 0x52, "FAT", 3))
-		return 0;
+	if ((!strncmp (part_table->boot_code + 0x36, "FAT", 3)
+	    && strncmp (part_table->boot_code + 0x40, "SBML", 4) != 0)
+	    || !strncmp (part_table->boot_code + 0x52, "FAT", 3))
+		goto probe_fail;

 	/* If this is a GPT disk, fail here */
 	for (i = 0; i < 4; i++) {
-		if (part_table.partitions[i].type == PARTITION_GPT)
-			return 0;
+		if (part_table->partitions[i].type == PARTITION_GPT)
+			goto probe_fail;
 	}

 	/* If this is an AIX Physical Volume, fail here.  IBMA in EBCDIC */
-	if (part_table.boot_code[0] == (char) 0xc9 && 
-	    part_table.boot_code[1] == (char) 0xc2 &&
-	    part_table.boot_code[2] == (char) 0xd4 && 
-	    part_table.boot_code[3] == (char) 0xc1)
-		return 0;
+	if (part_table->boot_code[0] == (char) 0xc9 &&
+	    part_table->boot_code[1] == (char) 0xc2 &&
+	    part_table->boot_code[2] == (char) 0xd4 &&
+	    part_table->boot_code[3] == (char) 0xc1)
+		goto probe_fail;

 #ifdef ENABLE_PC98
 	/* HACK: it's impossible to tell PC98 and msdos disk labels apart.
@@ -198,10 +220,15 @@ msdos_probe (const PedDevice *dev)
 	 * is more reliable */
 	disk_type = ped_disk_type_get ("pc98");
 	if (disk_type && disk_type->ops->probe (dev))
-		return 0;
+		goto probe_fail;
 #endif /* ENABLE_PC98 */

+	free (label);
 	return 1;
+
+ probe_fail:
+	free (label);
+	return 0;
 }

 static PedDisk*
@@ -802,7 +829,7 @@ static int
 read_table (PedDisk* disk, PedSector sector, int is_extended_table)
 {
 	int			i;
-	DosRawTable		table;
+	DosRawTable*		table;
 	DosRawPartition*	raw_part;
 	PedPartition*		part;
 	PedPartitionType	type;
@@ -812,31 +839,34 @@ read_table (PedDisk* disk, PedSector sector, int is_extended_table)
 	PED_ASSERT (disk != NULL, return 0);
 	PED_ASSERT (disk->dev != NULL, return 0);

-	if (!ped_device_read (disk->dev, (void*) &table, sector, 1))
+	char *label = NULL;
+	if (!read_sector (disk->dev, sector, &label))
 		goto error;

+        table = (DosRawTable *) label;
+
 	/* weird: empty extended partitions are filled with 0xf6 by PM */
 	if (is_extended_table
-	    && PED_LE16_TO_CPU (table.magic) == PARTITION_MAGIC_MAGIC)
-		return 1;
+	    && PED_LE16_TO_CPU (table->magic) == PARTITION_MAGIC_MAGIC)
+		goto read_ok;

 #ifndef DISCOVER_ONLY
-	if (PED_LE16_TO_CPU (table.magic) != MSDOS_MAGIC) {
+	if (PED_LE16_TO_CPU (table->magic) != MSDOS_MAGIC) {
 		if (ped_exception_throw (
 			PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
 			_("Invalid partition table on %s "
 			  "-- wrong signature %x."),
 			disk->dev->path,
-			PED_LE16_TO_CPU (table.magic))
+			PED_LE16_TO_CPU (table->magic))
 				!= PED_EXCEPTION_IGNORE)
 			goto error;
-		return 1;
+		goto read_ok;
 	}
 #endif

 	/* parse the partitions from this table */
 	for (i = 0; i < 4; i++) {
-		raw_part = &table.partitions [i];
+		raw_part = &table->partitions [i];
 		if (raw_part->type == PARTITION_EMPTY || !raw_part->length)
 			continue;

@@ -892,7 +922,7 @@ read_table (PedDisk* disk, PedSector sector, int is_extended_table)
 		for (i = 0; i < 4; i++) {
 			PedSector part_start;

-			raw_part = &table.partitions [i];
+			raw_part = &table->partitions [i];
 			if (!raw_part_is_extended (raw_part))
 				continue;

@@ -910,9 +940,12 @@ read_table (PedDisk* disk, PedSector sector, int is_extended_table)
 		}
 	}

+read_ok:
+	free (label);
 	return 1;

 error:
+	free (label);
 	ped_disk_delete_all (disk);
 	return 0;
 }



More information about the parted-devel mailing list