From 4e18b61870a6ba5814d7e9007b2c9b313545d127 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 10 Apr 2008 19:24:21 +0000 Subject: [PATCH] - Don't interactively ask to fix an AlternateGPT's location when not at the end of the disk; this is so that disk images written to a usb-key can work reasonably. --- parted-1.8.8-nofixgpt.patch | 322 ++++++++++++++++++++++++++++++++++++ parted.spec | 9 +- 2 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 parted-1.8.8-nofixgpt.patch diff --git a/parted-1.8.8-nofixgpt.patch b/parted-1.8.8-nofixgpt.patch new file mode 100644 index 0000000..d225257 --- /dev/null +++ b/parted-1.8.8-nofixgpt.patch @@ -0,0 +1,322 @@ +diff -up parted-1.8.8/libparted/labels/gpt.c.nofixgpt parted-1.8.8/libparted/labels/gpt.c +--- parted-1.8.8/libparted/labels/gpt.c.nofixgpt 2007-07-31 13:36:57.000000000 -0400 ++++ parted-1.8.8/libparted/labels/gpt.c 2008-04-10 14:20:05.000000000 -0400 +@@ -233,6 +233,7 @@ struct __attribute__ ((packed)) _LegacyM + /* uses libparted's disk_specific field in PedDisk, to store our info */ + struct __attribute__ ((packed)) _GPTDiskData { + PedGeometry data_area; ++ PedSector agpt_location; + int entry_count; + efi_guid_t uuid; + }; +@@ -542,6 +543,7 @@ gpt_alloc (const PedDevice * dev) + ped_geometry_init (&gpt_disk_data->data_area, dev, data_start, + data_end - data_start + 1); + gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES; ++ gpt_disk_data->agpt_location = disk->dev->length - 1; + uuid_generate ((unsigned char*) &gpt_disk_data->uuid); + swap_uuid_and_efi_guid((unsigned char*)(&gpt_disk_data->uuid)); + return disk; +@@ -571,6 +573,7 @@ gpt_duplicate (const PedDisk* disk) + old_disk_data->data_area.length); + new_disk_data->entry_count = old_disk_data->entry_count; + new_disk_data->uuid = old_disk_data->uuid; ++ new_disk_data->agpt_location = old_disk_data->agpt_location; + return new_disk; + } + +@@ -632,12 +635,13 @@ _read_header (const PedDevice* dev, Guid + + static int + _parse_header (PedDisk* disk, GuidPartitionTableHeader_t* gpt, +- int *update_needed) ++ int *update_needed, int alternate, PedSector agpt_location) + { + GPTDiskData* gpt_disk_data = disk->disk_specific; + PedSector first_usable; + PedSector last_usable; + PedSector last_usable_if_grown, last_usable_min_default; ++ PedSector last_within_agpt; + static int asked_already; + + PED_ASSERT (_header_is_valid (disk->dev, gpt), return 0); +@@ -670,26 +674,28 @@ _parse_header (PedDisk* disk, GuidPartit + parted invocation. + */ + +- last_usable_if_grown +- = PED_CPU_TO_LE64 (disk->dev->length - 2 - ++ last_within_agpt = PED_LE64_TO_CPU ( gpt->AlternateLBA ) - 1; ++ if (alternate) ++ last_within_agpt = agpt_location - 1; ++ PED_ASSERT (last_within_agpt <= disk->dev->length - 2, return 0); ++ ++ last_usable_if_grown = PED_CPU_TO_LE64 ( last_within_agpt - + ((PedSector)(PED_LE32_TO_CPU(gpt->NumberOfPartitionEntries)) * + (PedSector)(PED_LE32_TO_CPU(gpt->SizeOfPartitionEntry)) / + disk->dev->sector_size)); + +- last_usable_min_default = disk->dev->length - 2 - ++ last_usable_min_default = last_within_agpt - + GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / disk->dev->sector_size; + +- if ( last_usable_if_grown > last_usable_min_default ) { +- ++ if ( last_usable_if_grown > last_usable_min_default ) + last_usable_if_grown = last_usable_min_default; +- } +- + + PED_ASSERT (last_usable > first_usable, return 0); +- PED_ASSERT (last_usable <= disk->dev->length, return 0); ++ PED_ASSERT (last_within_agpt <= disk->dev->length - 2, return 0); ++ PED_ASSERT (last_usable <= disk->dev->length - 2, return 0); + + PED_ASSERT (last_usable_if_grown > first_usable, return 0); +- PED_ASSERT (last_usable_if_grown <= disk->dev->length, return 0); ++ PED_ASSERT (last_usable_if_grown <= disk->dev->length - 2, return 0); + + if ( !asked_already && last_usable < last_usable_if_grown ) { + +@@ -719,7 +725,7 @@ _parse_header (PedDisk* disk, GuidPartit + ped_geometry_init (&gpt_disk_data->data_area, disk->dev, + first_usable, last_usable - first_usable + 1); + +- ++ gpt_disk_data->agpt_location = PED_LE64_TO_CPU(gpt->AlternateLBA); + gpt_disk_data->entry_count + = PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries); + PED_ASSERT (gpt_disk_data->entry_count > 0, return 0); +@@ -794,18 +800,23 @@ _parse_part_entry (PedDisk* disk, GuidPa + * for users to use Parted to "fix up" their disk if they + * really want it to be considered GPT. + ************************************************************/ ++/************************************************************ ++ * Right now, we have no infrastructure for per-disklabel ++ * commands, so we can't really directly offer to fix this ++ * interactively. I'm leaving the code around anyway in ++ * hopes it'll become useful someday. -- pjones ++ ************************************************************/ ++#if 0 + static int +-gpt_read (PedDisk * disk) ++gpt_is_small(PedDisk * disk) + { +- GPTDiskData *gpt_disk_data = disk->disk_specific; + GuidPartitionTableHeader_t* gpt; +- GuidPartitionEntry_t* ptes; +- int ptes_size; +- int i; ++ int ret = 0; ++ + #ifndef DISCOVER_ONLY +- int write_back = 0; ++ int write_back; + #endif +- ++ + ped_disk_delete_all (disk); + + /* +@@ -813,78 +824,131 @@ gpt_read (PedDisk * disk) + * ped_disk_probe(), they probably didn't get a choice... + */ + if (!gpt_probe (disk->dev)) +- goto error; ++ return 0; + + if (_read_header (disk->dev, &gpt, 1)) { + PED_ASSERT ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) + <= disk->dev->length - 1, goto error_free_gpt); + if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) + < disk->dev->length - 1) { +- char* zeros = ped_malloc (pth_get_size (disk->dev)); + +-#ifndef DISCOVER_ONLY ++#ifdef DISCOVER_ONLY ++ if (ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_CANCEL, ++ _("The backup GPT table is not at the end of the disk, as it " ++ "should be. This might means that operating systems may " ++ "believe the disk is of a smaller size.")) ++ == PED_EXCEPTION_CANCEL) ++ goto error_free_gpt; ++#else + if (ped_exception_throw ( + PED_EXCEPTION_ERROR, + PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, + _("The backup GPT table is not at the end of the disk, as it " +- "should be. This might mean that another operating system " +- "believes the disk is smaller. Fix, by moving the backup " +- "to the end (and removing the old backup)?")) ++ "should be. This might means that operating systems may " ++ "believe the disk is of a smaller size. Fix, by moving the " ++ "backup to the end?")) + == PED_EXCEPTION_CANCEL) + goto error_free_gpt; + ++ gpt->AlternateLBA = ++ PED_CPU_TO_LE64(disk->dev->length - 1); + write_back = 1; +- memset (zeros, 0, disk->dev->sector_size); +- ped_device_write (disk->dev, zeros, +- PED_LE64_TO_CPU (gpt->AlternateLBA), +- 1); +-#endif /* !DISCOVER_ONLY */ ++#endif + } +- } else { /* primary GPT *not* ok */ +- int alternate_ok = 0; ++ } ++ ++ if (write_back) ++ ped_disk_commit_to_dev (disk); ++ ++ ret = 1; ++ ++error_delete_all: ++ ped_disk_delete_all (disk); ++error_free_gpt: ++ pth_free (gpt); ++ return ret; ++} ++#endif ++ ++static int ++gpt_read (PedDisk * disk) ++{ ++ GPTDiskData *gpt_disk_data = disk->disk_specific; ++ GuidPartitionTableHeader_t* pgpt = NULL; ++ GuidPartitionTableHeader_t* agpt = NULL; ++ GuidPartitionEntry_t* ptes; ++ PedSector agpt_location = 0; ++ int ptes_size; ++ int i; ++ int primary_ok = 0; ++ int alternate_ok = 0; + + #ifndef DISCOVER_ONLY +- write_back = 1; ++ int write_back = 0; + #endif + +- if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) +- < disk->dev->length - 1) { +- alternate_ok = _read_header (disk->dev, &gpt, +- PED_LE64_TO_CPU(gpt->AlternateLBA)); +- } +- if (!alternate_ok) { +- alternate_ok = _read_header (disk->dev, &gpt, +- disk->dev->length - 1); +- } ++ ped_disk_delete_all (disk); + +- if (alternate_ok) { +- if (ped_exception_throw ( +- PED_EXCEPTION_ERROR, +- PED_EXCEPTION_OK_CANCEL, +- _("The primary GPT table is corrupt, but the " +- "backup appears OK, so that will be used.")) +- == PED_EXCEPTION_CANCEL) +- goto error_free_gpt; +- } else { +- ped_exception_throw ( +- PED_EXCEPTION_ERROR, +- PED_EXCEPTION_CANCEL, +- _("Both the primary and backup GPT tables " +- "are corrupt. Try making a fresh table, " +- "and using Parted's rescue feature to " +- "recover partitions.")); +- goto error; ++ if (!gpt_probe (disk->dev)) ++ return 0; ++ ++ if (_read_header (disk->dev, &pgpt, 1)) { ++ primary_ok = 1; ++ if ((PedSector) PED_LE64_TO_CPU (pgpt->AlternateLBA) ++ <= disk->dev->length - 1) { ++ agpt_location = PED_LE64_TO_CPU (pgpt->AlternateLBA); ++ alternate_ok = _read_header (disk->dev, &agpt, ++ agpt_location); + } + } + +- if (!_parse_header (disk, gpt, &write_back)) +- goto error_free_gpt; ++ if (!alternate_ok) { ++ agpt_location = disk->dev->length - 1; ++ alternate_ok = _read_header (disk->dev, &agpt, ++ disk->dev->length - 1); ++ } ++ ++ if (alternate_ok && !_parse_header (disk, agpt, &write_back, 1, ++ agpt_location)) ++ alternate_ok = 0; + ++ if (primary_ok && !_parse_header (disk, pgpt, &write_back, 0, 0)) ++ primary_ok = 0; ++ ++#ifndef DISCOVER_ONLY ++ if (!primary_ok || !alternate_ok) ++ write_back = 1; ++#endif ++ ++ if (!primary_ok && !alternate_ok) { ++ ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_CANCEL, ++ _("Both the primary and backup GPT tables " ++ "are corrupt. Try making a fresh table, " ++ "and using Parted's rescue feature to " ++ "recover partitions.")); ++ goto error_free_gpts; ++ } ++ ++ if (!primary_ok) { ++ if (pgpt) ++ pth_free (pgpt); ++ pgpt = agpt; ++ agpt = NULL; ++ ++ pgpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1); ++ } ++ ++ if (!alternate_ok && agpt) ++ pth_free (agpt); + + ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count; + ptes = (GuidPartitionEntry_t*) ped_malloc (ptes_size); + if (!ped_device_read (disk->dev, ptes, +- PED_LE64_TO_CPU(gpt->PartitionEntryLBA), ++ PED_LE64_TO_CPU(pgpt->PartitionEntryLBA), + ptes_size / disk->dev->sector_size)) + goto error_free_ptes; + +@@ -922,9 +986,12 @@ error_delete_all: + ped_disk_delete_all (disk); + error_free_ptes: + ped_free (ptes); +-error_free_gpt: +- pth_free (gpt); +-error: ++error_free_gpts: ++ if (pgpt) ++ pth_free (pgpt); ++ if (agpt) ++ pth_free (agpt); ++ + return 0; + } + +@@ -980,7 +1047,9 @@ _generate_header (const PedDisk* disk, i + = PED_CPU_TO_LE64 (disk->dev->length - 1 - ptes_size); + } else { + gpt->MyLBA = PED_CPU_TO_LE64 (1); +- gpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1); ++ gpt->AlternateLBA = gpt_disk_data->agpt_location ++ ? PED_CPU_TO_LE64 (gpt_disk_data->agpt_location) ++ : PED_CPU_TO_LE64 (disk->dev->length - 1); + gpt->PartitionEntryLBA = PED_CPU_TO_LE64 (2); + } + diff --git a/parted.spec b/parted.spec index 2a96a62..3ea8bc1 100644 --- a/parted.spec +++ b/parted.spec @@ -4,7 +4,7 @@ Summary: The GNU disk partition manipulation program Name: parted Version: 1.8.8 -Release: 3%{?dist} +Release: 4%{?dist} License: GPLv3+ Group: Applications/System URL: http://www.gnu.org/software/parted @@ -15,6 +15,7 @@ Patch1: %{name}-1.8.8-devmapper-header.patch Patch2: %{name}-1.8.8-noinst-headers.patch Patch3: %{name}-1.8.8-manpage.patch Patch4: %{name}-1.8.8-gcc-4.3.patch +Patch5: %{name}-1.8.8-nofixgpt.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: e2fsprogs-devel @@ -56,6 +57,7 @@ Parted library, you need to install this package. %patch2 -p1 -b .noinst %patch3 -p1 -b .manpage %patch4 -p1 -b .gcc43 +%patch5 -p1 -b .nofixgpt %build %configure --enable-device-mapper --enable-selinux --disable-static @@ -113,6 +115,11 @@ fi %{_exec_prefix}/%{_lib}/pkgconfig/libparted.pc %changelog +* Thu Apr 10 2008 Peter Jones - 1.8.8-4 +- Don't interactively ask to fix an AlternateGPT's location when not + at the end of the disk; this is so that disk images written to a + usb-key can work reasonably. + * Mon Feb 04 2008 David Cantrell - 1.8.8-3 - Fixes so parted compiles with gcc-4.3 (#431397)