Skip to content

Commit

Permalink
fdisk: add GPT support
Browse files Browse the repository at this point in the history
This patch allows fdisk to handle GUID partition tables, based on the latest UEFI specifications
version 2.3.1, from June 27th, 2012. The following operations are supported:

  - Probing (detects both protective and hybrid MBRs)
  - Writing to disk
  - Listing used partitions
  - Adding partitions
  - Deleting partitions
  - Data integrity verifications (for both headers and partitions).

A few considerations:
  - Currently we do not fix invalid primary headers -- we just abort!
  - Header checksums are updated upon every change (ie: add/delete partitions), this allows us
    to mathematically verify the changes on-the-fly, and not only when writing to disk, like
    most other related tools do.
  - We are extremly picky when writing to disk, any error aborts the opeartion.
  - When creating a new partition, the following GUIDs are available:
     http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs

For test cases, the gpt.img from libblkid tests, scsi_debug and my own hard drive (/dev/sda) were used.
For the image, all operations were tested successfully, and for /dev/sda all except write, which
was not tested - hey, I'm not suicidal!

[kzak@redhat.com: - add get/set partition type functions
                  - use unified on strings based table for partition types
                  - add partition type to table list function]

Tested-and-reviewed-by: Petr Uzel <petr.uzel@suse.cz>
Signed-off-by: Davidlohr Bueso <dave@gnu.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
  • Loading branch information
Davidlohr Bueso authored and karelzak committed Sep 27, 2012
1 parent 2b1a43c commit 766d515
Show file tree
Hide file tree
Showing 8 changed files with 1,380 additions and 206 deletions.
21 changes: 12 additions & 9 deletions fdisks/Makemodule.am
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@

fdisk_common_sources = \
fdisks/common.h \
fdisks/gpt.c \
fdisks/gpt.h

if !ARCH_M68K

sbin_PROGRAMS += fdisk
Expand All @@ -24,16 +19,24 @@ fdisk_SOURCES = \
fdisks/fdisksunlabel.h \
fdisks/fdiskdoslabel.c \
fdisks/fdiskdoslabel.h \
fdisks/gpt.c \
fdisks/gpt.h \
fdisks/partname.c \
$(fdisk_common_sources)
fdisks/common.h

fdisk_LDADD = $(LDADD) libcommon.la
fdisk_CFLAGS = $(AM_CFLAGS)

if BUILD_LIBBLKID
fdisk_CFLAGS = -I$(ul_libblkid_incdir)
fdisk_CFLAGS += -I$(ul_libblkid_incdir)
fdisk_LDADD += libblkid.la
endif

if BUILD_LIBUUID
fdisk_CFLAGS += -I$(ul_libuuid_incdir)
fdisk_LDADD += libuuid.la
endif

if HAVE_STATIC_FDISK
sbin_PROGRAMS += fdisk.static
fdisk_static_SOURCES = $(fdisk_SOURCES)
Expand All @@ -50,7 +53,7 @@ dist_man_MANS += fdisks/sfdisk.8
sfdisk_SOURCES = \
fdisks/partname.c \
fdisks/sfdisk.c \
$(fdisk_common_sources)
fdisks/common.h
sfdisk_LDADD = $(LDADD) libcommon.la

if HAVE_STATIC_SFDISK
Expand All @@ -64,7 +67,7 @@ endif
if BUILD_CFDISK
sbin_PROGRAMS += cfdisk
dist_man_MANS += fdisks/cfdisk.8
cfdisk_SOURCES = fdisks/cfdisk.c $(fdisk_common_sources)
cfdisk_SOURCES = fdisks/cfdisk.c fdisks/common.h
cfdisk_CFLAGS =
cfdisk_LDADD = $(LDADD) libcommon.la

Expand Down
8 changes: 0 additions & 8 deletions fdisks/cfdisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@
#include "blkdev.h"
#include "strutils.h"
#include "common.h"
#include "gpt.h"
#include "mbsalign.h"
#include "widechar.h"

Expand Down Expand Up @@ -1510,13 +1509,6 @@ fill_p_info(void) {
opentype = O_RDWR;
opened = TRUE;

if (gpt_probe_signature_fd(fd)) {
print_warning(_("Warning!! Unsupported GPT (GUID Partition Table) detected. Use GNU Parted."));
refresh();
getch();
clear_warning();
}

#ifdef BLKFLSBUF
/* Blocks are visible in more than one way:
e.g. as block on /dev/hda and as block on /dev/hda3
Expand Down
33 changes: 14 additions & 19 deletions fdisks/fdisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static const struct menulist_descr menulist[] = {
{'c', N_("toggle the mountable flag"), {SUN_LABEL, 0}},
{'c', N_("select sgi swap partition"), {SGI_LABEL, 0}},
{'c', N_("change number of cylinders"), {0, DOS_LABEL | SUN_LABEL}},
{'d', N_("delete a partition"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}},
{'d', N_("delete a partition"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL | GPT_LABEL, 0}},
{'d', N_("print the raw data in the partition table"), {0, ANY_LABEL}},
{'e', N_("change number of extra sectors per cylinder"), {0, SUN_LABEL}},
{'e', N_("list extended partitions"), {0, DOS_LABEL}},
Expand All @@ -94,9 +94,9 @@ static const struct menulist_descr menulist[] = {
{'i', N_("change interleave factor"), {0, SUN_LABEL}},
{'i', N_("change the disk identifier"), {0, DOS_LABEL}},
{'i', N_("install bootstrap"), {OSF_LABEL, 0}},
{'l', N_("list known partition types"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}},
{'l', N_("list known partition types"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL | GPT_LABEL, 0}},
{'m', N_("print this menu"), {ANY_LABEL, ANY_LABEL}},
{'n', N_("add a new partition"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}},
{'n', N_("add a new partition"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL | GPT_LABEL, 0}},
{'o', N_("create a new empty DOS partition table"), {~OSF_LABEL, 0}},
{'o', N_("change rotation speed (rpm)"), {0, SUN_LABEL}},
{'p', N_("print the partition table"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, DOS_LABEL | SUN_LABEL}},
Expand All @@ -108,7 +108,7 @@ static const struct menulist_descr menulist[] = {
{'t', N_("change a partition's system id"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}},
{'u', N_("change display/entry units"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}},
{'v', N_("verify the partition table"), {DOS_LABEL | SUN_LABEL | SGI_LABEL, DOS_LABEL | SUN_LABEL | SGI_LABEL}},
{'w', N_("write table to disk and exit"), {DOS_LABEL | SUN_LABEL | SGI_LABEL, DOS_LABEL | SUN_LABEL | SGI_LABEL}},
{'w', N_("write table to disk and exit"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | GPT_LABEL, DOS_LABEL | SUN_LABEL | SGI_LABEL}},
{'w', N_("write disklabel to disk"), {OSF_LABEL, 0}},
{'x', N_("extra functionality (experts only)"), {DOS_LABEL | SUN_LABEL | SGI_LABEL, 0}},
#if !defined (__alpha__)
Expand Down Expand Up @@ -740,7 +740,7 @@ get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt) {
i = read_int(cxt, 1, dflt, max, 0, _("Partition number")) - 1;
pe = &ptes[i];

if (warn) {
if (warn && disklabel != GPT_LABEL) {
if ((disklabel != SUN_LABEL && disklabel != SGI_LABEL && !pe->part_table->sys_ind)
|| (disklabel == SUN_LABEL &&
(!sunlabel->partitions[i].num_sectors ||
Expand Down Expand Up @@ -1122,8 +1122,8 @@ fix_partition_table_order(void) {

}

static void
list_table(struct fdisk_context *cxt, int xtra) {
static void list_table(struct fdisk_context *cxt, int xtra)
{
struct partition *p;
int i, w;

Expand All @@ -1139,6 +1139,11 @@ list_table(struct fdisk_context *cxt, int xtra) {

list_disk_geometry(cxt);

if (disklabel == GPT_LABEL) {
gpt_list_table(cxt, xtra);
return;
}

if (disklabel == OSF_LABEL) {
xbsd_print_disklabel(cxt, xtra);
return;
Expand Down Expand Up @@ -1303,7 +1308,8 @@ static void new_partition(struct fdisk_context *cxt)
if (warn_geometry(cxt))
return;

if (disklabel == SUN_LABEL || disklabel == SGI_LABEL)
if (disklabel == SUN_LABEL || disklabel == SGI_LABEL
|| disklabel == GPT_LABEL)
partnum = get_partition(cxt, 0, partitions);

fdisk_add_partition(cxt, partnum, NULL);
Expand Down Expand Up @@ -1549,14 +1555,6 @@ static int is_ide_cdrom_or_tape(char *device)
return ret;
}

static void
gpt_warning(char *dev)
{
if (dev && gpt_probe_signature_devname(dev))
fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
"The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev);
}

/* Print disk geometry and partition table of a specified device (-l option) */
static void print_partition_table_from_option(char *device, unsigned long sector_size)
{
Expand All @@ -1572,7 +1570,6 @@ static void print_partition_table_from_option(char *device, unsigned long sector
if (user_cylinders || user_heads || user_sectors)
fdisk_context_set_user_geometry(cxt, user_cylinders,
user_heads, user_sectors);
gpt_warning(device);

if (!fdisk_dev_has_disklabel(cxt)) {
/*
Expand Down Expand Up @@ -1878,8 +1875,6 @@ int main(int argc, char **argv)
printf(_("Note: sector size is %ld (not %d)\n"),
cxt->sector_size, DEFAULT_SECTOR_SIZE);

gpt_warning(cxt->dev_path);

if (!fdisk_dev_has_disklabel(cxt)) {
fprintf(stderr,
_("Device does not contain a recognized partition table\n"));
Expand Down
2 changes: 2 additions & 0 deletions fdisks/fdisk.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ extern const struct fdisk_label bsd_label;
extern const struct fdisk_label mac_label;
extern const struct fdisk_label sun_label;
extern const struct fdisk_label sgi_label;
extern const struct fdisk_label gpt_label;

extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly);
extern int fdisk_dev_has_topology(struct fdisk_context *cxt);
Expand Down Expand Up @@ -276,6 +277,7 @@ enum fdisk_labeltype {
AIX_LABEL = 8,
OSF_LABEL = 16,
MAC_LABEL = 32,
GPT_LABEL = 64,
ANY_LABEL = -1
};

Expand Down

0 comments on commit 766d515

Please sign in to comment.