From fa815ad05db248d78ef214ea79a78c22772a9ffe Mon Sep 17 00:00:00 2001 From: Phillip Susi Date: Sat, 5 Jan 2013 20:53:29 -0500 Subject: [PATCH 60/89] libparted: allow some common errors to be ignored 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 | 6 ++ libparted/cs/geom.c | 8 +-- libparted/disk.c | 89 +++++++----------------- tests/Makefile.am | 1 + tests/t0283-overlap-partitions.sh | 143 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+), 71 deletions(-) create mode 100644 tests/t0283-overlap-partitions.sh diff --git a/NEWS b/NEWS index 3f73434..a05be02 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ GNU parted NEWS -*- outline -*- * Noteworthy changes in release ?.? (????-??-??) [?] +** New Features + + 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. + ** Bug Fixes libparted: fix gpt end of disk handling. Previously if the backup 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..ce71bfc 100644 --- a/libparted/disk.c +++ b/libparted/disk.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "architecture.h" #include "labels/pt-tools.h" @@ -404,6 +405,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 +919,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 +1775,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 +1801,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 +1809,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 +1895,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 +1965,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 eaf44a5..16ec5d2 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..2a53407 --- /dev/null +++ b/tests/t0283-overlap-partitions.sh @@ -0,0 +1,143 @@ +#!/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 . + +. "${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 < out 2>&1 || fail=1 +print +ignore +rm +ignore +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 < 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 +Error: Can't have overlapping partitions. +Ignore/Cancel? ignore +Partition number? 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 < out 2>&1 || fail=1 +print +ignore +rm +ignore +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 < 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 +Error: Can't have a partition outside the disk! +Ignore/Cancel? ignore +Partition number? 1 +(parted) +EOF +compare exp out || fail=1 + +Exit $fail -- 1.8.5.3