[parted-devel] bug: parted gets partitions wrong
Colin Watson
cjwatson at ubuntu.com
Wed May 28 11:12:51 UTC 2008
On Fri, May 23, 2008 at 10:35:36PM +0200, Jim Meyering wrote:
> Jim Meyering <jim at meyering.net> wrote:
> > "xerces8" <xerces8 at butn.net> wrote:
> >>> The first 4 sectors are attached.
> >
> > Thanks!
> > I'll take a look by Friday.
>
> Thanks.
> I did reproduce the failure (fdisk sees 2 partitions, parted sees just
> one), using your MBR on a 0-extended loopback device.
> However, that's not fair, since loopback doesn't work with partitions.
> Then I put the boot sector on a USB key. fdisk still sees two:
>
> $ fdisk -l /dev/sdc
>
> Disk /dev/sdc: 65 MB, 65986560 bytes
> 64 heads, 32 sectors/track, 62 cylinders
> Units = cylinders of 2048 * 512 = 1048576 bytes
> Disk identifier: 0x00000000
>
> Device Boot Start End Blocks Id System
> /dev/sdc1 * 1 716 733168 6 FAT16
> /dev/sdc2 717 979 269312 6 FAT16
>
> but parted fails:
>
> $ ./parted -m -s /dev/sdc p
> Error: /dev/sdc: unrecognised disk label
> [Exit 1]
>
> I suspect that the above merely shows that parted
> looks farther than the partition table, and attempts
> to do some minimal verification. When (at least in my case)
> it doesn't find anything sane beyond the partition table, it fails.
> I'll investigate further next week.
I investigated this independently today; the reporter didn't say that
he'd taken it here, so I didn't know about this thread until I went and
looked.
The problem appears to be (and this is conjecture) that the disk
originally simply had a FAT file system on it, with no partition table.
When it was given a partition table, its boot sector wasn't replaced,
and so it still has the FAT signature.
It would be more reliable to do what the Linux kernel does: namely,
check whether the boot indicator on each partition is 0 or 0x80, and
otherwise assume the disk is a FAT file system. Here's the Linux code
for comparison:
/*
* Now that the 55aa signature is present, this is probably
* either the boot sector of a FAT filesystem or a DOS-type
* partition table. Reject this in case the boot indicator
* is not 0 or 0x80.
*/
p = (struct partition *) (data + 0x1be);
for (slot = 1; slot <= 4; slot++, p++) {
if (p->boot_ind != 0 && p->boot_ind != 0x80) {
put_dev_sector(sect);
return 0;
}
}
util-linux's fdisk has a similar check in the is_garbage_table function:
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
if (p->boot_ind != 0 && p->boot_ind != 0x80)
return 1;
}
return 0;
Please consider the following patch, which does basically the same
thing. I think it's sufficiently trivial (and obvious based on other
implementations) to be non-copyrightable, but I can do assignment
paperwork if you feel you need it.
With this patch, the supplied boot sector prints as follows:
$ LD_LIBRARY_PATH=`pwd`/libparted/.libs parted/.libs/parted ~/parted-test
WARNING: You are not superuser. Watch out for permissions.
GNU Parted 1.8.8.1.30-c31f
Using /home/cjwatson/parted-test
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: (file)
Disk /home/cjwatson/parted-test: 1573MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 16.4kB 751MB 751MB primary boot
2 751MB 1027MB 276MB primary
Signed-off-by: Colin Watson <cjwatson at canonical.com>
---
dos.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c
index e513a05..81d8600 100644
--- a/libparted/labels/dos.c
+++ b/libparted/labels/dos.c
@@ -192,14 +192,16 @@ msdos_probe (const PedDevice *dev)
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 this is a FAT fs, fail here. Checking for the FAT signature
+ * has some false positives; instead, do what the Linux kernel does
+ * and ensure that each partition has a boot indicator that is
+ * either 0 or 0x80.
*/
- 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;
+ for (i = 0; i < 4; i++) {
+ if (part_table->partitions[i].boot_ind != 0
+ && part_table->partitions[i].boot_ind != 0x80)
+ goto probe_fail;
+ }
/* If this is a GPT disk, fail here */
for (i = 0; i < 4; i++) {
--
Colin Watson [cjwatson at ubuntu.com]
More information about the parted-devel
mailing list