[gparted] Snap partition boundaries before dialogs update FS usage (#48)
- From: Curtis Gedak <gedakc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gparted] Snap partition boundaries before dialogs update FS usage (#48)
- Date: Tue, 11 Jun 2019 16:22:07 +0000 (UTC)
commit 7c94b7d92060ef7b14be115edb95d6720186f75e
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date: Sun May 19 10:31:55 2019 +0100
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
include/Dialog_Base_Partition.h | 3 +
include/GParted_Core.h | 3 -
src/Dialog_Base_Partition.cc | 221 +++++++++++++++++++++++++++++++++++++++-
src/Dialog_Partition_New.cc | 2 +
src/GParted_Core.cc | 217 ---------------------------------------
5 files changed, 224 insertions(+), 222 deletions(-)
---
diff --git a/include/Dialog_Base_Partition.h b/include/Dialog_Base_Partition.h
index 25a6a5cd..c6ee005b 100644
--- a/include/Dialog_Base_Partition.h
+++ b/include/Dialog_Base_Partition.h
@@ -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 ) ;
diff --git a/include/GParted_Core.h b/include/GParted_Core.h
index 8714e7db..b6274c71 100644
--- a/include/GParted_Core.h
+++ b/include/GParted_Core.h
@@ -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 );
diff --git a/src/Dialog_Base_Partition.cc b/src/Dialog_Base_Partition.cc
index d3a50f52..77d88644 100644
--- a/src/Dialog_Base_Partition.cc
+++ b/src/Dialog_Base_Partition.cc
@@ -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 )
diff --git a/src/Dialog_Partition_New.cc b/src/Dialog_Partition_New.cc
index 92b8aa98..beff15f0 100644
--- a/src/Dialog_Partition_New.cc
+++ b/src/Dialog_Partition_New.cc
@@ -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;
}
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 970c13a9..7afbf977 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -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 ;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]