Snap partition boundaries before dialogs update FS usage (#48)
Move snap_to_*() method calls from the point when all operations are added to the list, to earlier when Resize/Move, Paste (into new) and Create New dialogs are composing the new partition objects. In particular for the Resize/Move operation, to just before updating the file system usage. This change finally resolves this bug. Because of the dialog call chains into Dialog_Base_Partition, snap_to_alignment() must be added into: * Dialog_Base_Partition::prepare_new_partition() for the Resize/Move and Paste (into new) dialogs; and * Dialog_Partition_New::Get_New_Partition() for the Create New dialog. Closes #48 - Error when moving locked LUKS-encrypted partition
This commit is contained in:
parent
3222c8dd1a
commit
7c94b7d920
|
@ -59,6 +59,9 @@ protected:
|
|||
};
|
||||
|
||||
void prepare_new_partition();
|
||||
static void snap_to_alignment(const Device& device, Partition& partition);
|
||||
static void snap_to_cylinder(const Device& device, Partition& partition);
|
||||
static void snap_to_mebibyte(const Device& device, Partition& partition);
|
||||
|
||||
void Set_Confirm_Button( CONFIRMBUTTON button_type ) ;
|
||||
void Set_MinMax_Text( Sector min, Sector max ) ;
|
||||
|
|
|
@ -51,9 +51,6 @@ public:
|
|||
void set_devices_thread( std::vector<Device> * pdevices );
|
||||
void guess_partition_table(const Device & device, Glib::ustring &buff);
|
||||
|
||||
void snap_to_cylinder(const Device& device, Partition& partition);
|
||||
void snap_to_mebibyte(const Device& device, Partition& partition);
|
||||
void snap_to_alignment(const Device& device, Partition& partition);
|
||||
bool valid_partition(const Device& device, Partition& partition, Glib::ustring& error);
|
||||
bool apply_operation_to_disk( Operation * operation );
|
||||
|
||||
|
|
|
@ -200,8 +200,7 @@ void Dialog_Base_Partition::prepare_new_partition()
|
|||
// If partition size is not an integer multiple of MiB or
|
||||
// the start or end sectors are not MiB aligned, and space
|
||||
// is available, then add 1 MiB to partition so requested
|
||||
// size is kept after GParted_Core::snap_to_mebibyte
|
||||
// method rounding.
|
||||
// size is kept after snap_to_mebibyte() method rounding.
|
||||
Sector partition_size = new_partition->sector_end - new_partition->sector_start + 1;
|
||||
Sector sectors_in_mib = MEBIBYTE / new_partition->sector_size;
|
||||
if ( ( ( partition_size % sectors_in_mib > 0 )
|
||||
|
@ -228,6 +227,8 @@ void Dialog_Base_Partition::prepare_new_partition()
|
|||
if ( ORIG_BEFORE == spinbutton_before .get_value_as_int() )
|
||||
new_partition->strict_start = TRUE;
|
||||
|
||||
snap_to_alignment(m_device, *new_partition);
|
||||
|
||||
//update partition usage
|
||||
if ( new_partition->sector_usage_known() )
|
||||
{
|
||||
|
@ -250,6 +251,222 @@ void Dialog_Base_Partition::prepare_new_partition()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Dialog_Base_Partition::snap_to_alignment(const Device& device, Partition& partition)
|
||||
{
|
||||
if (partition.alignment == ALIGN_CYLINDER)
|
||||
snap_to_cylinder(device, partition);
|
||||
else if (partition.alignment == ALIGN_MEBIBYTE)
|
||||
snap_to_mebibyte(device, partition);
|
||||
}
|
||||
|
||||
|
||||
void Dialog_Base_Partition::snap_to_cylinder(const Device& device, Partition& partition)
|
||||
{
|
||||
Sector diff = 0;
|
||||
|
||||
//Determine if partition size is less than half a disk cylinder
|
||||
bool less_than_half_cylinder = false;
|
||||
if ( ( partition .sector_end - partition .sector_start ) < ( device .cylsize / 2 ) )
|
||||
less_than_half_cylinder = true;
|
||||
|
||||
if ( partition.type == TYPE_LOGICAL ||
|
||||
partition.sector_start == device .sectors
|
||||
)
|
||||
{
|
||||
//Must account the relative offset between:
|
||||
// (A) the Extended Boot Record sector and the next track of the
|
||||
// logical partition (usually 63 sectors), and
|
||||
// (B) the Master Boot Record sector and the next track of the first
|
||||
// primary partition
|
||||
diff = (partition .sector_start - device .sectors) % device .cylsize ;
|
||||
}
|
||||
else if ( partition.sector_start == 34 )
|
||||
{
|
||||
// (C) the GUID Partition Table (GPT) and the start of the data
|
||||
// partition at sector 34
|
||||
diff = (partition .sector_start - 34 ) % device .cylsize ;
|
||||
}
|
||||
else
|
||||
{
|
||||
diff = partition .sector_start % device .cylsize ;
|
||||
}
|
||||
if ( diff && ! partition .strict_start )
|
||||
{
|
||||
if ( diff < ( device .cylsize / 2 ) || less_than_half_cylinder )
|
||||
partition .sector_start -= diff ;
|
||||
else
|
||||
partition .sector_start += (device .cylsize - diff ) ;
|
||||
}
|
||||
|
||||
diff = (partition .sector_end +1) % device .cylsize ;
|
||||
if ( diff )
|
||||
{
|
||||
if ( diff < ( device .cylsize / 2 ) && ! less_than_half_cylinder )
|
||||
partition .sector_end -= diff ;
|
||||
else
|
||||
partition .sector_end += (device .cylsize - diff ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dialog_Base_Partition::snap_to_mebibyte(const Device& device, Partition& partition)
|
||||
{
|
||||
Sector diff = 0;
|
||||
if ( partition .sector_start < 2 || partition .type == TYPE_LOGICAL )
|
||||
{
|
||||
//Must account the relative offset between:
|
||||
// (A) the Master Boot Record sector and the first primary/extended partition, and
|
||||
// (B) the Extended Boot Record sector and the logical partition
|
||||
|
||||
//If strict_start is set then do not adjust sector start.
|
||||
//If this partition is not simply queued for a reformat then
|
||||
// add space minimum to force alignment to next mebibyte.
|
||||
if ( (! partition .strict_start)
|
||||
&& (partition .free_space_before == 0)
|
||||
&& ( partition .status != STAT_FORMATTED)
|
||||
)
|
||||
{
|
||||
//Unless specifically told otherwise, the Linux kernel considers extended
|
||||
// boot records to be two sectors long, in order to "leave room for LILO".
|
||||
partition .sector_start += 2 ;
|
||||
}
|
||||
}
|
||||
|
||||
//Calculate difference offset from Mebibyte boundary
|
||||
diff = Sector(partition .sector_start % ( MEBIBYTE / partition .sector_size ));
|
||||
|
||||
//Align start sector only if permitted to change start sector
|
||||
if ( diff && ( (! partition .strict_start)
|
||||
|| ( partition .strict_start
|
||||
&& ( partition .status == STAT_NEW
|
||||
|| partition .status == STAT_COPY
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
partition .sector_start += ( (MEBIBYTE / partition .sector_size) - diff) ;
|
||||
|
||||
//If this is an extended partition then check to see if sufficient space is
|
||||
// available for any following logical partition Extended Boot Record
|
||||
if ( partition .type == TYPE_EXTENDED )
|
||||
{
|
||||
//If there is logical partition that starts less than 2 sectors
|
||||
// from the start of this partition, then reserve a mebibyte for the EBR.
|
||||
int index_extended = find_extended_partition( device.partitions );
|
||||
if ( index_extended >= 0 )
|
||||
{
|
||||
for ( unsigned int t = 0; t < device .partitions[ index_extended ] .logicals .size(); t++ )
|
||||
{
|
||||
if ( ( device .partitions[ index_extended ] .logicals[ t ] .type == TYPE_LOGICAL )
|
||||
&& ( ( ( device .partitions[ index_extended ] .logicals[ t ] .sector_start )
|
||||
- ( partition .sector_start )
|
||||
)
|
||||
//Unless specifically told otherwise, the Linux kernel considers extended
|
||||
// boot records to be two sectors long, in order to "leave room for LILO".
|
||||
< 2
|
||||
)
|
||||
)
|
||||
{
|
||||
partition .sector_start -= (MEBIBYTE / partition .sector_size) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Align end sector
|
||||
diff = (partition .sector_end + 1) % ( MEBIBYTE / partition .sector_size);
|
||||
if ( diff )
|
||||
partition .sector_end -= diff ;
|
||||
|
||||
//If this is a logical partition not at end of drive then check to see if space is
|
||||
// required for a following logical partition Extended Boot Record
|
||||
if ( partition .type == TYPE_LOGICAL )
|
||||
{
|
||||
//If there is a following logical partition that starts less than 2 sectors from
|
||||
// the end of this partition, then reserve at least a mebibyte for the EBR.
|
||||
int index_extended = find_extended_partition( device.partitions );
|
||||
if ( index_extended >= 0 )
|
||||
{
|
||||
for ( unsigned int t = 0; t < device .partitions[ index_extended ] .logicals .size(); t++ )
|
||||
{
|
||||
if ( ( device .partitions[ index_extended ] .logicals[ t ] .type == TYPE_LOGICAL )
|
||||
&& ( device .partitions[ index_extended ] .logicals[ t ] .sector_start > partition .sector_end )
|
||||
&& ( ( device .partitions[ index_extended ] .logicals[ t ] .sector_start - partition .sector_end )
|
||||
//Unless specifically told otherwise, the Linux kernel considers extended
|
||||
// boot records to be two sectors long, in order to "leave room for LILO".
|
||||
< 2
|
||||
)
|
||||
)
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size ) ;
|
||||
}
|
||||
}
|
||||
|
||||
//If the logical partition end is beyond the end of the extended partition
|
||||
// then reduce logical partition end by a mebibyte to address the overlap.
|
||||
if ( ( index_extended != -1 )
|
||||
&& ( partition .sector_end > device .partitions[ index_extended ] .sector_end )
|
||||
)
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size ) ;
|
||||
}
|
||||
|
||||
//If this is a primary or an extended partition and the partition overlaps
|
||||
// the start of the next primary or extended partition then subtract a
|
||||
// mebibyte from the end of the partition to address the overlap.
|
||||
if ( partition .type == TYPE_PRIMARY || partition .type == TYPE_EXTENDED )
|
||||
{
|
||||
for ( unsigned int t = 0 ; t < device .partitions .size() ; t++ )
|
||||
{
|
||||
if ( ( device .partitions[ t ] .type == TYPE_PRIMARY
|
||||
|| device .partitions[ t ] .type == TYPE_EXTENDED
|
||||
)
|
||||
&& ( //For a change to an existing partition, (e.g., move or resize)
|
||||
// skip comparing to original partition and
|
||||
// only compare to other existing partitions
|
||||
partition .status == STAT_REAL
|
||||
&& partition .partition_number != device. partitions[ t ] .partition_number
|
||||
)
|
||||
&& ( device .partitions[ t ] .sector_start > partition .sector_start )
|
||||
&& ( device .partitions[ t ] .sector_start <= partition .sector_end )
|
||||
)
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size );
|
||||
}
|
||||
}
|
||||
|
||||
//If this is an extended partition then check to see if the end of the
|
||||
// extended partition encompasses the end of the last logical partition.
|
||||
if ( partition .type == TYPE_EXTENDED )
|
||||
{
|
||||
//If there is logical partition that has an end sector beyond the
|
||||
// end of the extended partition, then set the extended partition
|
||||
// end sector to be the same as the end of the logical partition.
|
||||
for ( unsigned int t = 0; t < partition .logicals .size(); t++ )
|
||||
{
|
||||
if ( ( partition .logicals[ t ] .type == TYPE_LOGICAL )
|
||||
&& ( ( partition .logicals[ t ] .sector_end )
|
||||
> ( partition .sector_end )
|
||||
)
|
||||
)
|
||||
{
|
||||
partition .sector_end = partition .logicals[ t ] .sector_end ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If this is a GPT partition table and the partition ends less than 34 sectors
|
||||
// from the end of the device, then reserve at least a mebibyte for the
|
||||
// backup partition table
|
||||
if ( device .disktype == "gpt"
|
||||
&& ( ( device .length - partition .sector_end ) < 34 )
|
||||
)
|
||||
{
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dialog_Base_Partition::Set_Confirm_Button( CONFIRMBUTTON button_type )
|
||||
{
|
||||
switch( button_type )
|
||||
|
|
|
@ -319,6 +319,8 @@ const Partition & Dialog_Partition_New::Get_New_Partition()
|
|||
new_partition->logicals.push_back_adopt( unallocated );
|
||||
}
|
||||
|
||||
Dialog_Base_Partition::snap_to_alignment(m_device, *new_partition);
|
||||
|
||||
return *new_partition;
|
||||
}
|
||||
|
||||
|
|
|
@ -329,225 +329,8 @@ Glib::ustring GParted_Core::get_thread_status_message( )
|
|||
}
|
||||
|
||||
|
||||
void GParted_Core::snap_to_cylinder(const Device& device, Partition& partition)
|
||||
{
|
||||
Sector diff = 0;
|
||||
|
||||
//Determine if partition size is less than half a disk cylinder
|
||||
bool less_than_half_cylinder = false;
|
||||
if ( ( partition .sector_end - partition .sector_start ) < ( device .cylsize / 2 ) )
|
||||
less_than_half_cylinder = true;
|
||||
|
||||
if ( partition.type == TYPE_LOGICAL ||
|
||||
partition.sector_start == device .sectors
|
||||
)
|
||||
{
|
||||
//Must account the relative offset between:
|
||||
// (A) the Extended Boot Record sector and the next track of the
|
||||
// logical partition (usually 63 sectors), and
|
||||
// (B) the Master Boot Record sector and the next track of the first
|
||||
// primary partition
|
||||
diff = (partition .sector_start - device .sectors) % device .cylsize ;
|
||||
}
|
||||
else if ( partition.sector_start == 34 )
|
||||
{
|
||||
// (C) the GUID Partition Table (GPT) and the start of the data
|
||||
// partition at sector 34
|
||||
diff = (partition .sector_start - 34 ) % device .cylsize ;
|
||||
}
|
||||
else
|
||||
{
|
||||
diff = partition .sector_start % device .cylsize ;
|
||||
}
|
||||
if ( diff && ! partition .strict_start )
|
||||
{
|
||||
if ( diff < ( device .cylsize / 2 ) || less_than_half_cylinder )
|
||||
partition .sector_start -= diff ;
|
||||
else
|
||||
partition .sector_start += (device .cylsize - diff ) ;
|
||||
}
|
||||
|
||||
diff = (partition .sector_end +1) % device .cylsize ;
|
||||
if ( diff )
|
||||
{
|
||||
if ( diff < ( device .cylsize / 2 ) && ! less_than_half_cylinder )
|
||||
partition .sector_end -= diff ;
|
||||
else
|
||||
partition .sector_end += (device .cylsize - diff ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GParted_Core::snap_to_mebibyte(const Device& device, Partition& partition)
|
||||
{
|
||||
Sector diff = 0;
|
||||
if ( partition .sector_start < 2 || partition .type == TYPE_LOGICAL )
|
||||
{
|
||||
//Must account the relative offset between:
|
||||
// (A) the Master Boot Record sector and the first primary/extended partition, and
|
||||
// (B) the Extended Boot Record sector and the logical partition
|
||||
|
||||
//If strict_start is set then do not adjust sector start.
|
||||
//If this partition is not simply queued for a reformat then
|
||||
// add space minimum to force alignment to next mebibyte.
|
||||
if ( (! partition .strict_start)
|
||||
&& (partition .free_space_before == 0)
|
||||
&& ( partition .status != STAT_FORMATTED)
|
||||
)
|
||||
{
|
||||
//Unless specifically told otherwise, the Linux kernel considers extended
|
||||
// boot records to be two sectors long, in order to "leave room for LILO".
|
||||
partition .sector_start += 2 ;
|
||||
}
|
||||
}
|
||||
|
||||
//Calculate difference offset from Mebibyte boundary
|
||||
diff = Sector(partition .sector_start % ( MEBIBYTE / partition .sector_size ));
|
||||
|
||||
//Align start sector only if permitted to change start sector
|
||||
if ( diff && ( (! partition .strict_start)
|
||||
|| ( partition .strict_start
|
||||
&& ( partition .status == STAT_NEW
|
||||
|| partition .status == STAT_COPY
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
partition .sector_start += ( (MEBIBYTE / partition .sector_size) - diff) ;
|
||||
|
||||
//If this is an extended partition then check to see if sufficient space is
|
||||
// available for any following logical partition Extended Boot Record
|
||||
if ( partition .type == TYPE_EXTENDED )
|
||||
{
|
||||
//If there is logical partition that starts less than 2 sectors
|
||||
// from the start of this partition, then reserve a mebibyte for the EBR.
|
||||
int index_extended = find_extended_partition( device.partitions );
|
||||
if ( index_extended >= 0 )
|
||||
{
|
||||
for ( unsigned int t = 0; t < device .partitions[ index_extended ] .logicals .size(); t++ )
|
||||
{
|
||||
if ( ( device .partitions[ index_extended ] .logicals[ t ] .type == TYPE_LOGICAL )
|
||||
&& ( ( ( device .partitions[ index_extended ] .logicals[ t ] .sector_start )
|
||||
- ( partition .sector_start )
|
||||
)
|
||||
//Unless specifically told otherwise, the Linux kernel considers extended
|
||||
// boot records to be two sectors long, in order to "leave room for LILO".
|
||||
< 2
|
||||
)
|
||||
)
|
||||
{
|
||||
partition .sector_start -= (MEBIBYTE / partition .sector_size) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Align end sector
|
||||
diff = (partition .sector_end + 1) % ( MEBIBYTE / partition .sector_size);
|
||||
if ( diff )
|
||||
partition .sector_end -= diff ;
|
||||
|
||||
//If this is a logical partition not at end of drive then check to see if space is
|
||||
// required for a following logical partition Extended Boot Record
|
||||
if ( partition .type == TYPE_LOGICAL )
|
||||
{
|
||||
//If there is a following logical partition that starts less than 2 sectors from
|
||||
// the end of this partition, then reserve at least a mebibyte for the EBR.
|
||||
int index_extended = find_extended_partition( device.partitions );
|
||||
if ( index_extended >= 0 )
|
||||
{
|
||||
for ( unsigned int t = 0; t < device .partitions[ index_extended ] .logicals .size(); t++ )
|
||||
{
|
||||
if ( ( device .partitions[ index_extended ] .logicals[ t ] .type == TYPE_LOGICAL )
|
||||
&& ( device .partitions[ index_extended ] .logicals[ t ] .sector_start > partition .sector_end )
|
||||
&& ( ( device .partitions[ index_extended ] .logicals[ t ] .sector_start - partition .sector_end )
|
||||
//Unless specifically told otherwise, the Linux kernel considers extended
|
||||
// boot records to be two sectors long, in order to "leave room for LILO".
|
||||
< 2
|
||||
)
|
||||
)
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size ) ;
|
||||
}
|
||||
}
|
||||
|
||||
//If the logical partition end is beyond the end of the extended partition
|
||||
// then reduce logical partition end by a mebibyte to address the overlap.
|
||||
if ( ( index_extended != -1 )
|
||||
&& ( partition .sector_end > device .partitions[ index_extended ] .sector_end )
|
||||
)
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size ) ;
|
||||
}
|
||||
|
||||
//If this is a primary or an extended partition and the partition overlaps
|
||||
// the start of the next primary or extended partition then subtract a
|
||||
// mebibyte from the end of the partition to address the overlap.
|
||||
if ( partition .type == TYPE_PRIMARY || partition .type == TYPE_EXTENDED )
|
||||
{
|
||||
for ( unsigned int t = 0 ; t < device .partitions .size() ; t++ )
|
||||
{
|
||||
if ( ( device .partitions[ t ] .type == TYPE_PRIMARY
|
||||
|| device .partitions[ t ] .type == TYPE_EXTENDED
|
||||
)
|
||||
&& ( //For a change to an existing partition, (e.g., move or resize)
|
||||
// skip comparing to original partition and
|
||||
// only compare to other existing partitions
|
||||
partition .status == STAT_REAL
|
||||
&& partition .partition_number != device. partitions[ t ] .partition_number
|
||||
)
|
||||
&& ( device .partitions[ t ] .sector_start > partition .sector_start )
|
||||
&& ( device .partitions[ t ] .sector_start <= partition .sector_end )
|
||||
)
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size );
|
||||
}
|
||||
}
|
||||
|
||||
//If this is an extended partition then check to see if the end of the
|
||||
// extended partition encompasses the end of the last logical partition.
|
||||
if ( partition .type == TYPE_EXTENDED )
|
||||
{
|
||||
//If there is logical partition that has an end sector beyond the
|
||||
// end of the extended partition, then set the extended partition
|
||||
// end sector to be the same as the end of the logical partition.
|
||||
for ( unsigned int t = 0; t < partition .logicals .size(); t++ )
|
||||
{
|
||||
if ( ( partition .logicals[ t ] .type == TYPE_LOGICAL )
|
||||
&& ( ( partition .logicals[ t ] .sector_end )
|
||||
> ( partition .sector_end )
|
||||
)
|
||||
)
|
||||
{
|
||||
partition .sector_end = partition .logicals[ t ] .sector_end ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If this is a GPT partition table and the partition ends less than 34 sectors
|
||||
// from the end of the device, then reserve at least a mebibyte for the
|
||||
// backup partition table
|
||||
if ( device .disktype == "gpt"
|
||||
&& ( ( device .length - partition .sector_end ) < 34 )
|
||||
)
|
||||
{
|
||||
partition .sector_end -= ( MEBIBYTE / partition .sector_size ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GParted_Core::snap_to_alignment(const Device& device, Partition& partition)
|
||||
{
|
||||
if ( partition .alignment == ALIGN_CYLINDER )
|
||||
snap_to_cylinder(device, partition);
|
||||
else if ( partition .alignment == ALIGN_MEBIBYTE )
|
||||
snap_to_mebibyte(device, partition);
|
||||
}
|
||||
|
||||
|
||||
bool GParted_Core::valid_partition(const Device& device, Partition& partition, Glib::ustring& error)
|
||||
{
|
||||
snap_to_alignment(device, partition);
|
||||
|
||||
//Ensure that partition start and end are not beyond the ends of the disk device
|
||||
if ( partition .sector_start < 0 )
|
||||
partition .sector_start = 0 ;
|
||||
|
|
Loading…
Reference in New Issue