[gparted] Implement format operation on encrypted file systems (#774818)



commit a568e5365a9872645f4dbac69214c725433d4a72
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Fri Sep 16 13:04:21 2016 +0100

    Implement format operation on encrypted file systems (#774818)
    
    Formatting an existing encrypted partition will format the file system
    within the encrypted mapping.  Formatting over the top of a closed
    encrypted partition will remove the encryption.  (The latter is planned
    to be prevented when creating and removing LUKS encryption is
    implemented as part of full LUKS read-write support).
    
    Composing the format operation inside an open LUKS encryption mapping
    also has to account for the size of that mapping and construct a
    PartitionLUKS object containing the new file system.  Implementing the
    operation itself is as simple as passing the Partition object directly
    containing the file system, instead of the outer PartitionLUKS object.
    
    Bug 774818 - Implement LUKS read-write actions NOT requiring a
                 passphrase

 src/GParted_Core.cc    |    5 +-
 src/OperationFormat.cc |    2 +-
 src/Win_GParted.cc     |  115 ++++++++++++++++++++++++++++++++---------------
 3 files changed, 82 insertions(+), 40 deletions(-)
---
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index bd6dad7..ff84391 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -631,9 +631,10 @@ bool GParted_Core::apply_operation_to_disk( Operation * operation )
                        // space earlier in the sequence of operations now being applied.
                        operation->get_partition_original().set_path( 
operation->get_partition_new().get_path() );
 
-                       success =    remove_filesystem( operation->get_partition_original(),
+                       success =    remove_filesystem( 
operation->get_partition_original().get_filesystem_partition(),
                                                        operation->operation_detail )
-                                 && format( operation->get_partition_new(), operation->operation_detail );
+                                 && format( operation->get_partition_new().get_filesystem_partition(),
+                                            operation->operation_detail );
                        break;
 
                case OPERATION_COPY:
diff --git a/src/OperationFormat.cc b/src/OperationFormat.cc
index efd1d69..a6a4d0e 100644
--- a/src/OperationFormat.cc
+++ b/src/OperationFormat.cc
@@ -74,7 +74,7 @@ void OperationFormat::create_description()
        /*TO TRANSLATORS: looks like  Format /dev/hda4 as linux-swap */
        description = String::ucompose( _("Format %1 as %2"),
                                        partition_original->get_path(),
-                                       Utils::get_filesystem_string( partition_new->filesystem ) );
+                                       partition_new->get_filesystem_string() );
 }
 
 bool OperationFormat::merge_operations( const Operation & candidate )
diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc
index a4bfc8e..028a5ea 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -2131,30 +2131,42 @@ void Win_GParted::activate_format( GParted::FILESYSTEM new_fs )
        g_assert( selected_partition_ptr != NULL );  // Bug: Partition callback without a selected partition
        g_assert( valid_display_partition_ptr( selected_partition_ptr ) );  // Bug: Not pointing at a valid 
display partition object
 
-       // VGNAME from mount mount
-       if ( selected_partition_ptr->filesystem == FS_LVM2_PV && ! 
selected_partition_ptr->get_mountpoint().empty() )
+       const Partition & filesystem_ptn = selected_partition_ptr->get_filesystem_partition();
+
+       // For non-empty LVM2 PV confirm overwrite before continuing.  VGNAME from mount mount.
+       if ( filesystem_ptn.filesystem == FS_LVM2_PV && ! filesystem_ptn.get_mountpoint().empty() )
        {
                if ( ! remove_non_empty_lvm2_pv_dialog( OPERATION_FORMAT ) )
                        return ;
        }
 
-       //check for some limits...
+       // Generate minimum and maximum partition size limits for the new file system.
        fs = gparted_core .get_fs( new_fs ) ;
+       bool encrypted = false;
+       if ( selected_partition_ptr->filesystem == FS_LUKS && selected_partition_ptr->busy )
+       {
+               encrypted = true;
+               Byte_Value encryption_overhead = selected_partition_ptr->get_byte_length() -
+                                                filesystem_ptn.get_byte_length();
+               fs.MIN += encryption_overhead;
+               if ( fs.MAX > 0 )
+                       fs.MAX += encryption_overhead;
+       }
 
+       // Confirm partition is the right size to store the file system before continuing.
        if ( ( selected_partition_ptr->get_byte_length() < fs.MIN )           ||
             ( fs.MAX && selected_partition_ptr->get_byte_length() > fs.MAX )    )
        {
                Gtk::MessageDialog dialog( *this,
-                                          String::ucompose( 
-                                                       /* TO TRANSLATORS: looks like
-                                                       * Cannot format this file system to fat16.
-                                                       */
-                                                       _( "Cannot format this file system to %1" ),
-                                                          Utils::get_filesystem_string( new_fs ) ) ,
-                                          false,
-                                          Gtk::MESSAGE_ERROR,
-                                          Gtk::BUTTONS_OK,
-                                          true );
+                                          String::ucompose( /* TO TRANSLATORS: looks like
+                                                             * Cannot format this file system to fat16.
+                                                             */
+                                                            _("Cannot format this file system to %1"),
+                                                            Utils::get_filesystem_string( encrypted, new_fs 
) ),
+                                          false,
+                                          Gtk::MESSAGE_ERROR,
+                                          Gtk::BUTTONS_OK,
+                                          true );
 
                if ( selected_partition_ptr->get_byte_length() < fs.MIN )
                        dialog .set_secondary_text( String::ucompose(
@@ -2162,7 +2174,7 @@ void Win_GParted::activate_format( GParted::FILESYSTEM new_fs )
                                                 * A fat16 file system requires a partition of at least 16.00 
MiB.
                                                 */
                                                _( "A %1 file system requires a partition of at least %2."),
-                                               Utils::get_filesystem_string( new_fs ),
+                                               Utils::get_filesystem_string( encrypted, new_fs ),
                                                Utils::format_size( fs .MIN, 1 /* Byte */ ) ) );
                else
                        dialog .set_secondary_text( String::ucompose(
@@ -2170,32 +2182,58 @@ void Win_GParted::activate_format( GParted::FILESYSTEM new_fs )
                                                 * A partition with a hfs file system has a maximum size of 
2.00 GiB.
                                                 */
                                                _( "A partition with a %1 file system has a maximum size of 
%2."),
-                                               Utils::get_filesystem_string( new_fs ),
+                                               Utils::get_filesystem_string( encrypted, new_fs ),
                                                Utils::format_size( fs .MAX, 1 /* Byte */ ) ) );
                
                dialog .run() ;
                return ;
        }
-       
-       //ok we made it.  lets create an fitting partition object
-       Partition part_temp ;
-       part_temp.Set( devices[current_device].get_path(),
-                      selected_partition_ptr->get_path(),
-                      selected_partition_ptr->partition_number,
-                      selected_partition_ptr->type,
-                      selected_partition_ptr->whole_device,
-                      new_fs,
-                      selected_partition_ptr->sector_start,
-                      selected_partition_ptr->sector_end,
-                      devices[current_device].sector_size,
-                      selected_partition_ptr->inside_extended,
-                      false );
-       part_temp.name = selected_partition_ptr->name;
-       //Leave sector usage figures to new Partition object defaults of
-       //  -1, -1, 0 (_used, _unused, _unallocated) representing unknown.
-       
-       part_temp .status = GParted::STAT_FORMATTED ;
-       // When formatting a partition which already exists on the disk all possible
+
+       // Compose Partition object to represent the format operation.
+       Partition * temp_ptn;
+       if ( selected_partition_ptr->filesystem == FS_LUKS && ! selected_partition_ptr->busy )
+       {
+               // Formatting a closed LUKS encrypted partition will erase the encryption
+               // replacing it with a non-encrypted file system.  Start with a plain
+               // Partition object instead of cloning the existing PartitionLUKS object
+               // containing a Partition object.
+               // FIXME:
+               // Expect to remove this case when creating and removing LUKS encryption
+               // is added as a separate action when full LUKS read-write support is
+               // implemented.
+               temp_ptn = new Partition;
+       }
+       else
+       {
+               // Formatting a file system, either a plain file system or one within an
+               // open LUKS encryption mapping.  Start with a clone of the existing
+               // Partition object whether it be a plain Partition object or a
+               // PartitionLUKS object containing a Partition object.
+               temp_ptn = selected_partition_ptr->clone();
+       }
+       {
+               // Sub-block so that temp_filesystem_ptn reference goes out of scope
+               // before temp_ptn pointer is deallocated.
+               Partition & temp_filesystem_ptn = temp_ptn->get_filesystem_partition();
+               temp_filesystem_ptn.Reset();
+               temp_filesystem_ptn.Set( filesystem_ptn.device_path,
+                                        filesystem_ptn.get_path(),
+                                        filesystem_ptn.partition_number,
+                                        filesystem_ptn.type,
+                                        filesystem_ptn.whole_device,
+                                        new_fs,
+                                        filesystem_ptn.sector_start,
+                                        filesystem_ptn.sector_end,
+                                        filesystem_ptn.sector_size,
+                                        filesystem_ptn.inside_extended,
+                                        false );
+               // Leave sector usage figures as new Partition object defaults of
+               // -1, -1, 0 (_used, _unused, _unallocated) representing unknown.
+       }
+       temp_ptn->name = selected_partition_ptr->name;
+       temp_ptn->status = STAT_FORMATTED;
+
+       // When formatting a partition which already exists on the disk, all possible
        // operations could be pending so only try merging with the previous operation.
        MergeType mergetype = MERGE_LAST_WITH_PREV;
 
@@ -2203,7 +2241,7 @@ void Win_GParted::activate_format( GParted::FILESYSTEM new_fs )
        // add it again with the new file system
        if ( selected_partition_ptr->status == STAT_NEW )
        {
-               part_temp.status = STAT_NEW;
+               temp_ptn->status = STAT_NEW;
                // On a partition which is pending creation only resize/move and format
                // operations are possible.  These operations are always mergeable with
                // the pending operation which will create the partition.  Hence merge
@@ -2213,9 +2251,12 @@ void Win_GParted::activate_format( GParted::FILESYSTEM new_fs )
 
        Operation * operation = new OperationFormat( devices[current_device],
                                                     *selected_partition_ptr,
-                                                    part_temp );
+                                                    *temp_ptn );
        operation->icon = render_icon( Gtk::Stock::CONVERT, Gtk::ICON_SIZE_MENU );
 
+       delete temp_ptn;
+       temp_ptn = NULL;
+
        Add_Operation( operation );
        merge_operations( mergetype );
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]