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
This commit is contained in:
Mike Fleetwood 2016-09-16 13:04:21 +01:00 committed by Curtis Gedak
parent 88136c96d7
commit a568e5365a
3 changed files with 82 additions and 40 deletions

View file

@ -631,9 +631,10 @@ bool GParted_Core::apply_operation_to_disk( Operation * operation )
// space earlier in the sequence of operations now being applied. // space earlier in the sequence of operations now being applied.
operation->get_partition_original().set_path( operation->get_partition_new().get_path() ); 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 ) operation->operation_detail )
&& format( operation->get_partition_new(), operation->operation_detail ); && format( operation->get_partition_new().get_filesystem_partition(),
operation->operation_detail );
break; break;
case OPERATION_COPY: case OPERATION_COPY:

View file

@ -74,7 +74,7 @@ void OperationFormat::create_description()
/*TO TRANSLATORS: looks like Format /dev/hda4 as linux-swap */ /*TO TRANSLATORS: looks like Format /dev/hda4 as linux-swap */
description = String::ucompose( _("Format %1 as %2"), description = String::ucompose( _("Format %1 as %2"),
partition_original->get_path(), partition_original->get_path(),
Utils::get_filesystem_string( partition_new->filesystem ) ); partition_new->get_filesystem_string() );
} }
bool OperationFormat::merge_operations( const Operation & candidate ) bool OperationFormat::merge_operations( const Operation & candidate )

View file

@ -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( 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 g_assert( valid_display_partition_ptr( selected_partition_ptr ) ); // Bug: Not pointing at a valid display partition object
// VGNAME from mount mount const Partition & filesystem_ptn = selected_partition_ptr->get_filesystem_partition();
if ( selected_partition_ptr->filesystem == FS_LVM2_PV && ! selected_partition_ptr->get_mountpoint().empty() )
// 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 ) ) if ( ! remove_non_empty_lvm2_pv_dialog( OPERATION_FORMAT ) )
return ; return ;
} }
//check for some limits... // Generate minimum and maximum partition size limits for the new file system.
fs = gparted_core .get_fs( new_fs ) ; 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 ) || if ( ( selected_partition_ptr->get_byte_length() < fs.MIN ) ||
( fs.MAX && selected_partition_ptr->get_byte_length() > fs.MAX ) ) ( fs.MAX && selected_partition_ptr->get_byte_length() > fs.MAX ) )
{ {
Gtk::MessageDialog dialog( *this, Gtk::MessageDialog dialog( *this,
String::ucompose( String::ucompose( /* TO TRANSLATORS: looks like
/* TO TRANSLATORS: looks like * Cannot format this file system to fat16.
* Cannot format this file system to fat16. */
*/ _("Cannot format this file system to %1"),
_( "Cannot format this file system to %1" ), Utils::get_filesystem_string( encrypted, new_fs ) ),
Utils::get_filesystem_string( new_fs ) ) , false,
false, Gtk::MESSAGE_ERROR,
Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
Gtk::BUTTONS_OK, true );
true );
if ( selected_partition_ptr->get_byte_length() < fs.MIN ) if ( selected_partition_ptr->get_byte_length() < fs.MIN )
dialog .set_secondary_text( String::ucompose( 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 fat16 file system requires a partition of at least 16.00 MiB.
*/ */
_( "A %1 file system requires a partition of at least %2."), _( "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 */ ) ) ); Utils::format_size( fs .MIN, 1 /* Byte */ ) ) );
else else
dialog .set_secondary_text( String::ucompose( 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 hfs file system has a maximum size of 2.00 GiB.
*/ */
_( "A partition with a %1 file system has a maximum size of %2."), _( "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 */ ) ) ); Utils::format_size( fs .MAX, 1 /* Byte */ ) ) );
dialog .run() ; dialog .run() ;
return ; return ;
} }
//ok we made it. lets create an fitting partition object // Compose Partition object to represent the format operation.
Partition part_temp ; Partition * temp_ptn;
part_temp.Set( devices[current_device].get_path(), if ( selected_partition_ptr->filesystem == FS_LUKS && ! selected_partition_ptr->busy )
selected_partition_ptr->get_path(), {
selected_partition_ptr->partition_number, // Formatting a closed LUKS encrypted partition will erase the encryption
selected_partition_ptr->type, // replacing it with a non-encrypted file system. Start with a plain
selected_partition_ptr->whole_device, // Partition object instead of cloning the existing PartitionLUKS object
new_fs, // containing a Partition object.
selected_partition_ptr->sector_start, // FIXME:
selected_partition_ptr->sector_end, // Expect to remove this case when creating and removing LUKS encryption
devices[current_device].sector_size, // is added as a separate action when full LUKS read-write support is
selected_partition_ptr->inside_extended, // implemented.
false ); temp_ptn = new Partition;
part_temp.name = selected_partition_ptr->name; }
//Leave sector usage figures to new Partition object defaults of else
// -1, -1, 0 (_used, _unused, _unallocated) representing unknown. {
// Formatting a file system, either a plain file system or one within an
part_temp .status = GParted::STAT_FORMATTED ; // open LUKS encryption mapping. Start with a clone of the existing
// When formatting a partition which already exists on the disk all possible // 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. // operations could be pending so only try merging with the previous operation.
MergeType mergetype = MERGE_LAST_WITH_PREV; 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 // add it again with the new file system
if ( selected_partition_ptr->status == STAT_NEW ) 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 // On a partition which is pending creation only resize/move and format
// operations are possible. These operations are always mergeable with // operations are possible. These operations are always mergeable with
// the pending operation which will create the partition. Hence merge // 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], Operation * operation = new OperationFormat( devices[current_device],
*selected_partition_ptr, *selected_partition_ptr,
part_temp ); *temp_ptn );
operation->icon = render_icon( Gtk::Stock::CONVERT, Gtk::ICON_SIZE_MENU ); operation->icon = render_icon( Gtk::Stock::CONVERT, Gtk::ICON_SIZE_MENU );
delete temp_ptn;
temp_ptn = NULL;
Add_Operation( operation ); Add_Operation( operation );
merge_operations( mergetype ); merge_operations( mergetype );