[parted-devel] [PATCH 09/11] libparted: allow some common errors to be ignored

Phillip Susi psusi at ubuntu.com
Mon Jan 7 04:44:34 UTC 2013


Partitions that overlap or extend beyond the end of the disk are common
errors that usually result in people having to use other tools to correct
because parted refuses to operate when it sees them.  Change these errors
to allow you to ignore them and use parted to correct the problem.
---
 NEWS                              |    4 ++
 libparted/cs/geom.c               |    8 +--
 libparted/disk.c                  |   90 +++++++------------------
 tests/Makefile.am                 |    1 +
 tests/t0283-overlap-partitions.sh |  133 +++++++++++++++++++++++++++++++++++++
 5 files changed, 164 insertions(+), 72 deletions(-)
 create mode 100644 tests/t0283-overlap-partitions.sh

diff --git a/NEWS b/NEWS
index c5fc878..d8205d1 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,10 @@ GNU parted NEWS                                    -*- outline -*-
 
 ** Bug Fixes
 
+  You can now choose to ignore errors about partitions that overlap,
+  or are longer than the disk.  This allows you to use parted to
+  repair the problem.
+
   libparted: previously if you chose to ignore the warning about
   the gpt thinking the disk was smaller than it appears to be on
   on disk, subsequent warnings on other disks would be suppressed.
diff --git a/libparted/cs/geom.c b/libparted/cs/geom.c
index 65c10c5..b8726da 100644
--- a/libparted/cs/geom.c
+++ b/libparted/cs/geom.c
@@ -153,6 +153,7 @@ ped_geometry_set (PedGeometry* geom, PedSector start, PedSector length)
 {
 	PED_ASSERT (geom != NULL);
 	PED_ASSERT (geom->dev != NULL);
+	PED_ASSERT (start >= 0);
 
 	if (length < 1) {
 		ped_exception_throw (
@@ -162,13 +163,6 @@ ped_geometry_set (PedGeometry* geom, PedSector start, PedSector length)
                           " (start sector=%jd length=%jd)"), start, length);
 		return 0;
 	}
-	if (start < 0 || start + length - 1 >= geom->dev->length) {
-		ped_exception_throw (
-			PED_EXCEPTION_ERROR,
-			PED_EXCEPTION_CANCEL,
-			_("Can't have a partition outside the disk!"));
-		return 0;
- 	}
 
 	geom->start = start;
 	geom->length = length;
diff --git a/libparted/disk.c b/libparted/disk.c
index d3cd5bb..6d2058f 100644
--- a/libparted/disk.c
+++ b/libparted/disk.c
@@ -36,6 +36,7 @@
 #include <parted/parted.h>
 #include <parted/debug.h>
 #include <stdbool.h>
+#include <limits.h>
 
 #include "architecture.h"
 #include "labels/pt-tools.h"
@@ -198,7 +199,6 @@ ped_disk_new (PedDevice* dev)
 		goto error_close_dev;
 	if (!type->ops->read (disk))
 		goto error_destroy_disk;
-	disk->needs_clobber = 0;
 	ped_device_close (dev);
 	return disk;
 
@@ -404,6 +404,7 @@ _ped_disk_alloc (const PedDevice* dev, const PedDiskType* disk_type)
 	disk->type = disk_type;
 	disk->update_mode = 1;
 	disk->part_list = NULL;
+	disk->needs_clobber = 0;
 	return disk;
 
 error:
@@ -917,6 +918,8 @@ _partition_align (PedPartition* part, const PedConstraint* constraint)
 	PED_ASSERT (disk_type->ops->partition_align != NULL);
 	PED_ASSERT (part->disk->update_mode);
 
+	if (part->disk->needs_clobber)
+		return 1; /* do not attempt to align partitions while reading them */
 	return disk_type->ops->partition_align (part, constraint);
 }
 
@@ -1771,7 +1774,7 @@ _partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom)
 		walk = ext_part->part_list;
 	} else {
 		min_start = 0;
-		max_end = part->disk->dev->length - 1;
+		max_end = LLONG_MAX - 1;
 		walk = part->disk->part_list;
 	}
 
@@ -1797,48 +1800,6 @@ _partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom)
 	return ped_constraint_new_from_max (&free_space);
 }
 
-/*
- * Returns \c 0 if the partition, \p part overlaps with any partitions on the
- * \p disk.  The geometry of \p part is taken to be \p geom, NOT \p part->geom
- * (the idea here is to check if \p geom is valid, before changing \p part).
- *
- * This is useful for seeing if a resized partitions new geometry is going to
- * fit, without the existing geomtry getting in the way.
- *
- * Note: overlap with an extended partition is also allowed, provided that
- * \p geom lies completely inside the extended partition.
- */
-static int _GL_ATTRIBUTE_PURE
-_disk_check_part_overlaps (PedDisk* disk, PedPartition* part)
-{
-	PedPartition*	walk;
-
-	PED_ASSERT (disk != NULL);
-	PED_ASSERT (part != NULL);
-
-	for (walk = ped_disk_next_partition (disk, NULL); walk;
-	     walk = ped_disk_next_partition (disk, walk)) {
-		if (walk->type & PED_PARTITION_FREESPACE)
-			continue;
-		if (walk == part)
-			continue;
-		if (part->type & PED_PARTITION_EXTENDED
-		    && walk->type & PED_PARTITION_LOGICAL)
-			continue;
-
-		if (ped_geometry_test_overlap (&walk->geom, &part->geom)) {
-			if (walk->type & PED_PARTITION_EXTENDED
-			    && part->type & PED_PARTITION_LOGICAL
-			    && ped_geometry_test_inside (&walk->geom,
-							 &part->geom))
-				continue;
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
 static int
 _partition_check_basic_sanity (PedDisk* disk, PedPartition* part)
 {
@@ -1847,7 +1808,6 @@ _partition_check_basic_sanity (PedDisk* disk, PedPartition* part)
 	PED_ASSERT (part->disk == disk);
 
 	PED_ASSERT (part->geom.start >= 0);
-	PED_ASSERT (part->geom.end < disk->dev->length);
 	PED_ASSERT (part->geom.start <= part->geom.end);
 
 	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
@@ -1934,29 +1894,30 @@ _check_partition (PedDisk* disk, PedPartition* part)
 
 	if (part->type & PED_PARTITION_LOGICAL
 	    && !ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
-		ped_exception_throw (
+		if (ped_exception_throw (
 			PED_EXCEPTION_ERROR,
-			PED_EXCEPTION_CANCEL,
+			PED_EXCEPTION_IGNORE_CANCEL,
 			_("Can't have a logical partition outside of the "
 			  "extended partition on %s."),
-			disk->dev->path);
-		return 0;
-	}
-
-	if (!_disk_check_part_overlaps (disk, part)) {
-		ped_exception_throw (
-			PED_EXCEPTION_ERROR,
-			PED_EXCEPTION_CANCEL,
-			_("Can't have overlapping partitions."));
-		return 0;
+			disk->dev->path) != PED_EXCEPTION_IGNORE)
+			return 0;
 	}
 
 	if (! (part->type & PED_PARTITION_LOGICAL)
 	    && ext_part && ext_part != part
 	    && ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
-		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+		if (ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
 			_("Can't have a primary partition inside an extended "
-			 "partition."));
+			  "partition.")) != PED_EXCEPTION_IGNORE)
+			return 0;
+	}
+
+	if (part->geom.end >= disk->dev->length) {
+		if (ped_exception_throw (
+			PED_EXCEPTION_ERROR,
+			PED_EXCEPTION_IGNORE_CANCEL,
+			_("Can't have a partition outside the disk!"))
+		    != PED_EXCEPTION_IGNORE )
 		return 0;
 	}
 
@@ -2003,16 +1964,15 @@ ped_disk_add_partition (PedDisk* disk, PedPartition* part,
 							constraint);
 
 		if (!constraints && constraint) {
-			ped_exception_throw (
+			if (ped_exception_throw (
 				PED_EXCEPTION_ERROR,
-				PED_EXCEPTION_CANCEL,
-				_("Can't have overlapping partitions."));
+				PED_EXCEPTION_IGNORE_CANCEL,
+				_("Can't have overlapping partitions.")) != PED_EXCEPTION_IGNORE)
 			goto error;
-		}
-
+		} else constraint = constraints;
 		if (!_partition_enumerate (part))
 			goto error;
-		if (!_partition_align (part, constraints))
+		if (!_partition_align (part, constraint))
 			goto error;
 	}
         /* FIXME: when _check_partition fails, we end up leaking PART
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 28cd467..ad3c73a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -30,6 +30,7 @@ TESTS = \
   t0280-gpt-corrupt.sh \
   t0281-gpt-grow.sh \
   t0282-gpt-move-backup.sh \
+  t0283-overlap-partitions.sh \
   t0300-dos-on-gpt.sh \
   t0301-overwrite-gpt-pmbr.sh \
   t0350-mac-PT-increases-sector-size.sh \
diff --git a/tests/t0283-overlap-partitions.sh b/tests/t0283-overlap-partitions.sh
new file mode 100644
index 0000000..547ff9c
--- /dev/null
+++ b/tests/t0283-overlap-partitions.sh
@@ -0,0 +1,133 @@
+#!/bin/sh
+# ensure parted can ignore partitions that overlap or are
+# longer than the disk and remove them
+
+# Copyright (C) 2009-2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../parted
+require_512_byte_sector_size_
+dev=loop-file
+
+truncate -s 10m $dev || fail=1
+
+# write damaged label
+xxd -r - $dev <<EOF
+0000000: fab8 0010 8ed0 bc00 b0b8 0000 8ed8 8ec0  ................
+0000010: fbbe 007c bf00 06b9 0002 f3a4 ea21 0600  ...|.........!..
+0000020: 00be be07 3804 750b 83c6 1081 fefe 0775  ....8.u........u
+0000030: f3eb 16b4 02b0 01bb 007c b280 8a74 018b  .........|...t..
+0000040: 4c02 cd13 ea00 7c00 00eb fe00 0000 0000  L.....|.........
+0000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000100: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000110: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000120: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000150: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000160: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000170: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000180: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+0000190: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00001a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00001b0: 0000 0000 0000 0000 72f5 0000 0000 0000  ........r.......
+00001c0: 0110 8303 204f 0008 0000 0020 0000 0000  .... O..... ....
+00001d0: 0050 8300 0a7a ff27 0000 0a15 0000 0000  .P...z.'........
+00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.
+EOF
+
+# print the empty table
+parted ---pretend-input-tty $dev <<EOF > out 2>&1 || fail=1
+print
+ignore
+rm 2
+EOF
+
+# $PWD contains a symlink-to-dir.  Also, remove the ^M      ...^M bogosity.
+# normalize the actual output
+mv out o2 && sed -e "s,/.*/$dev,DEVICE,;s,
   *
,,g;s, $,," \
+                      -e "s,^.*/lt-parted: ,parted: ," -e "s/^GNU Parted .*$/GNU Parted VERSION/" o2 > out
+
+# check for expected output
+cat <<EOF > exp || fail=1
+GNU Parted VERSION
+Using DEVICE
+Welcome to GNU Parted! Type 'help' to view a list of commands.
+(parted) print
+Error: Can't have overlapping partitions.
+Ignore/Cancel? ignore
+Model:  (file)
+Disk DEVICE: 10.5MB
+Sector size (logical/physical): 512B/512B
+Partition Table: msdos
+Disk Flags:
+
+Number  Start   End     Size    Type     File system  Flags
+ 1      1049kB  5243kB  4194kB  primary
+ 2      5242kB  8000kB  2758kB  primary
+
+(parted) rm 2
+(parted)
+EOF
+compare exp out || fail=1
+
+truncate -s 3m $dev || fail=1
+
+# print the table, verify error, ignore it, and remove the partition
+parted ---pretend-input-tty $dev <<EOF > out 2>&1 || fail=1
+print
+ignore
+rm 1
+EOF
+
+# $PWD contains a symlink-to-dir.  Also, remove the ^M      ...^M bogosity.
+# normalize the actual output
+mv out o2 && sed -e "s,/.*/$dev,DEVICE,;s,
   *
,,g;s, $,," \
+                      -e "s,^.*/lt-parted: ,parted: ," -e "s/^GNU Parted .*$/GNU Parted VERSION/" o2 > out
+
+# check for expected output
+cat <<EOF > exp || fail=1
+GNU Parted VERSION
+Using DEVICE
+Welcome to GNU Parted! Type 'help' to view a list of commands.
+(parted) print
+Error: Can't have a partition outside the disk!
+Ignore/Cancel? ignore
+Model:  (file)
+Disk DEVICE: 3146kB
+Sector size (logical/physical): 512B/512B
+Partition Table: msdos
+Disk Flags:
+
+Number  Start   End     Size    Type     File system  Flags
+ 1      1049kB  5243kB  4194kB  primary
+
+(parted) rm 1
+(parted)
+EOF
+compare exp out || fail=1
+
+Exit $fail
-- 
1.7.10.4




More information about the parted-devel mailing list