Use previous unallocated partition when determining 1 MiB reservation in resize/move dialog

The create new and paste into new dialogs are both composing a new
partition into the unallocated selected_partition they are passed.  The
starting sector of this unallocated partition is the first sector the
newly composed partition could possibly have.  To ensure it doesn't
overlay with the partition table or EBR (Extended Boot Records) it calls
MB_Needed_for_Boot_Record() to indicate if the first 1 MiB needs to be
reserved in the dialog or not.

Code:
    Dialog_Partition_New::set_data(..., selected_partition, ...)
        ...
        MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(selected_partition);

    Dialog_Partition_Copy::set_data(selected_partition, ...)
        ...
        MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(selected_partition);

However the resize/move dialog is different.  It is passed the existing
selected_partition object and the vector of partitions from which it
determines if there is a previous unallocated partition object or not.
When there is no previous unallocated partition object, there is no need
to reserve 1 MiB because the selected_partition can't be moved further
to the left.  In the other case when there is a previous unallocated
partition object the start of the existing selected_partition can be
moved to the left.  However the code passes the selected_partition
object to MB_Needed_for_Boot_Record() so doesn't have the first sector
the newly composed partition could possibly have so doesn't reserve the
first 1 MiB to prevent it overlapping with the partition table at the
start of the drive.  These two commits addressed this limitation:
* Ensure 1 MiB reserved when moving extended partition to start of drive
* Ensure 1 MiB reserved when moving partition to start of disk

Code:
    Dialog_Partition_Resize_Move::set_data(selected_partition, ...)
        new_partition = selected_partition.clone();
        if (selected_partition.type == TYPE_EXTENDED)
            Resize_Move_Extended(...);
        else
            Resoze_Move_Normal(...);

    Dialog_Partition_Resize_Move::Resize_Move_Normal(...)
        ...
        if (previous <= 0)
            MIN_SPACE_BEFORE_MB = 0;
        else
        {
            if (START < MEBIBYTE / new_partition->sector_size)
                MIN_SPACE_BEFORE_MB = 1;
            else
                MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*new_partition);
        }

    Dialog_Partition_Resize_Move::Resize_Move_Extended(...)
        ...
        if (previous <= 0)
            MIN_SPACE_BEFORE_MB = 0;
        else
        {
            if (START < MEBIBYTE / new_partition->sector_size)
                MIN_SPACE_BEFORE_MB = 1;
            else
                MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*new_partition);
        }

So instead pass the previous unallocated partition object as that
contains the left most start sector the newly composed partition could
possibly have, therefore the check for overlapping the partition table
in the first 1 MiB of the drive can succeed.
This commit is contained in:
Mike Fleetwood 2021-10-20 22:33:03 +01:00 committed by Curtis Gedak
parent 37689eef9d
commit eaaa5719f7
1 changed files with 17 additions and 20 deletions

View File

@ -118,11 +118,13 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const PartitionVector & p
Sector previous, next ; Sector previous, next ;
previous = next = 0 ; previous = next = 0 ;
const Partition* prev_unalloc_partition = NULL;
//also check the partitions file system ( if this is a 'resize-only' then previous should be 0 ) //also check the partitions file system ( if this is a 'resize-only' then previous should be 0 )
if (t >= 1 && partitions[t-1].type == TYPE_UNALLOCATED && ! this->fixed_start) if (t >= 1 && partitions[t-1].type == TYPE_UNALLOCATED && ! this->fixed_start)
{ {
previous = partitions[t -1] .get_sector_length() ; previous = partitions[t -1] .get_sector_length() ;
START = partitions[t -1] .sector_start ; START = partitions[t -1] .sector_start ;
prev_unalloc_partition = &partitions[t-1];
} }
else else
START = new_partition->sector_start; START = new_partition->sector_start;
@ -152,18 +154,14 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const PartitionVector & p
} }
} }
//Only calculate MIN_SPACE_BEFORE_MB if we have a previous (unallocated) partition. // Only need to use MIN_SPACE_BEFORE_MB to reserve 1 MiB to protect the partition
// Otherwise there will not be enough graphical space to reserve a full 1 MiB for MBR/EBR. // table or EBR if there is a previous unallocated partition allowing the start of
// Since this is an existing partition, if an MBR/EBR was needed then it already exists with enough space. // this selected partition to be resize/moved to the left.
if ( previous <= 0 ) if (prev_unalloc_partition == NULL)
MIN_SPACE_BEFORE_MB = 0 ; MIN_SPACE_BEFORE_MB = 0 ;
else else
{ MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*prev_unalloc_partition);
if (START < MEBIBYTE / new_partition->sector_size)
MIN_SPACE_BEFORE_MB = 1 ;
else
MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record( *new_partition );
}
total_length = previous + new_partition->get_sector_length() + next; total_length = previous + new_partition->get_sector_length() + next;
TOTAL_MB = Utils::round( Utils::sector_to_unit( total_length, new_partition->sector_size, UNIT_MIB ) ); TOTAL_MB = Utils::round( Utils::sector_to_unit( total_length, new_partition->sector_size, UNIT_MIB ) );
@ -245,11 +243,13 @@ void Dialog_Partition_Resize_Move::Resize_Move_Extended( const PartitionVector &
Sector previous, next ; Sector previous, next ;
previous = next = 0 ; previous = next = 0 ;
const Partition* prev_unalloc_partition = NULL;
//calculate length and start of previous //calculate length and start of previous
if (t > 0 && partitions[t-1].type == TYPE_UNALLOCATED) if (t > 0 && partitions[t-1].type == TYPE_UNALLOCATED)
{ {
previous = partitions[t -1] .get_sector_length() ; previous = partitions[t -1] .get_sector_length() ;
START = partitions[t -1] .sector_start ; START = partitions[t -1] .sector_start ;
prev_unalloc_partition = &partitions[t-1];
} }
else else
START = new_partition->sector_start; START = new_partition->sector_start;
@ -259,18 +259,15 @@ void Dialog_Partition_Resize_Move::Resize_Move_Extended( const PartitionVector &
next = partitions[ t +1 ] .get_sector_length() ; next = partitions[ t +1 ] .get_sector_length() ;
//now we have enough data to calculate some important values.. //now we have enough data to calculate some important values..
//Only calculate MIN_SPACE_BEFORE_MB if we have a previous (unallocated) partition.
// Otherwise there will not be enough graphical space to reserve a full 1 MiB for MBR/EBR. // Only need to use MIN_SPACE_BEFORE_MB to reserve 1 MiB to protect the partition
// Since this is an existing partition, if an MBR/EBR was needed then it already exists with enough space. // table or EBR if there is a previous unallocated partition allowing the start of
if ( previous <= 0 ) // this selected partition to be resize/moved to the left.
if (prev_unalloc_partition == NULL)
MIN_SPACE_BEFORE_MB = 0 ; MIN_SPACE_BEFORE_MB = 0 ;
else else
{ MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*prev_unalloc_partition);
if (START < MEBIBYTE / new_partition->sector_size)
MIN_SPACE_BEFORE_MB = 1;
else
MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*new_partition);
}
total_length = previous + new_partition->get_sector_length() + next; total_length = previous + new_partition->get_sector_length() + next;
TOTAL_MB = Utils::round( Utils::sector_to_unit( total_length, new_partition->sector_size, UNIT_MIB ) ); TOTAL_MB = Utils::round( Utils::sector_to_unit( total_length, new_partition->sector_size, UNIT_MIB ) );
MB_PER_PIXEL = TOTAL_MB / 500.00 ; MB_PER_PIXEL = TOTAL_MB / 500.00 ;