]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: (gpt) allow to work with hybrid GPT
authorKarel Zak <kzak@redhat.com>
Wed, 23 Oct 2013 14:59:45 +0000 (16:59 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 23 Oct 2013 14:59:45 +0000 (16:59 +0200)
Notes:

 * fdisk don't sync hybrid MBR with GPT
 * hybrid MBR is ignored and not overwritten by PBMR
 * users is informed about expert command 'M' to toggle between MBR
   and GPT mode. It's possible to manually modify hybrid MBR.

Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/fdisk.c
libfdisk/src/dos.c
libfdisk/src/gpt.c
libfdisk/src/libfdisk.h

index ca49606a5d03aa739a8da21001be0ffb7858d019..874f9d138b2f1f8f007f42e3361234fcdb047358 100644 (file)
@@ -546,7 +546,11 @@ int main(int argc, char **argv)
                if (!fdisk_dev_has_disklabel(cxt)) {
                        fdisk_info(cxt, _("Device does not contain a recognized partition table."));
                        fdisk_create_disklabel(cxt, NULL);
-               }
+
+               } else if (fdisk_is_disklabel(cxt, GPT) && fdisk_gpt_is_hybrid(cxt))
+                       fdisk_warnx(cxt, _(
+                                 "The hybrid GPT detected. You have to sync "
+                                 "the hybrid MBR manually (expert command 'M')."));
 
                while (1)
                        process_fdisk_menu(&cxt);
index 11d3c71f4cce88547008fcf31773467606b4a5ef..8b51b8c538d93aa94059b92270892c28d50087e9 100644 (file)
@@ -815,7 +815,11 @@ static int add_partition(struct fdisk_context *cxt, size_t n, struct fdisk_partt
        }
        fill_bounds(cxt, first, last);
        if (n < 4) {
-               start = cxt->first_lba;
+               if (cxt->parent && fdisk_is_disklabel(cxt->parent, GPT))
+                       start = 1;              /* Bad boy modifies hybrid MBR */
+               else
+                       start = cxt->first_lba;
+
                if (fdisk_context_use_cylinders(cxt) || !cxt->total_sectors)
                        limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1;
                else
index 68eddeb80aff5053399de747c67ba8f224368b06..f4c46b94d3428e98bfb3732aea42ae0f9a2c1ad0 100644 (file)
@@ -1476,16 +1476,14 @@ fail:
 static int gpt_write_disklabel(struct fdisk_context *cxt)
 {
        struct fdisk_gpt_label *gpt;
+       int mbr_type;
 
        assert(cxt);
        assert(cxt->label);
        assert(fdisk_is_disklabel(cxt, GPT));
 
        gpt = self_label(cxt);
-
-       /* we do not want to mess up hybrid MBRs by creating a valid pmbr */
-       if (valid_pmbr(cxt) == GPT_MBR_HYBRID)
-               goto err0;
+       mbr_type = valid_pmbr(cxt);
 
        /* check that disk is big enough to handle the backup header */
        if (le64_to_cpu(gpt->pheader->alternative_lba) > cxt->total_sectors)
@@ -1522,7 +1520,11 @@ static int gpt_write_disklabel(struct fdisk_context *cxt)
                goto err1;
        if (gpt_write_header(cxt, gpt->pheader, GPT_PRIMARY_PARTITION_TABLE_LBA) != 0)
                goto err1;
-       if (gpt_write_pmbr(cxt) != 0)
+
+       if (mbr_type == GPT_MBR_HYBRID)
+               fdisk_warnx(cxt, _("The device contains hybrid MBR -- writing GPT only. "
+                                  "You have to sync the MBR manually."));
+       else if (gpt_write_pmbr(cxt) != 0)
                goto err1;
 
        DBG(LABEL, dbgprint("GPT write success"));
@@ -2164,6 +2166,12 @@ int fdisk_gpt_partition_set_name(struct fdisk_context *cxt, size_t i)
        return 0;
 }
 
+int fdisk_gpt_is_hybrid(struct fdisk_context *cxt)
+{
+       assert(cxt);
+       return valid_pmbr(cxt) == GPT_MBR_HYBRID;
+}
+
 static int gpt_toggle_partition_flag(
                struct fdisk_context *cxt,
                size_t i,
index 77892d271fb2a5c6317fc95cf9f625435bd09c15..f653b48b1f0816f3b35c9d778b2ad026a78f121d 100644 (file)
@@ -199,6 +199,7 @@ enum {
 
 extern int fdisk_gpt_partition_set_uuid(struct fdisk_context *cxt, size_t i);
 extern int fdisk_gpt_partition_set_name(struct fdisk_context *cxt, size_t i);
+extern int fdisk_gpt_is_hybrid(struct fdisk_context *cxt);
 
 /* dos.c */
 extern struct dos_partition *fdisk_dos_get_partition(