[gparted] Snap partition boundaries before dialogs update FS usage (#48)



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]