gparted/src/linux_swap.cc

219 lines
6.9 KiB
C++
Raw Normal View History

/* Copyright (C) 2004 Bart
* Copyright (C) 2008, 2009, 2010 Curtis Gedak
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "../include/linux_swap.h"
#include "../include/BlockSpecial.h"
#include "../include/Partition.h"
#include <cerrno>
namespace GParted
{
const Glib::ustring linux_swap::get_custom_text( CUSTOM_TEXT ttype, int index ) const
{
/*TO TRANSLATORS: these labels will be used in the partition menu */
static const Glib::ustring activate_text = _( "_Swapon" ) ;
static const Glib::ustring deactivate_text = _( "_Swapoff" ) ;
switch ( ttype ) {
case CTEXT_ACTIVATE_FILESYSTEM :
return index == 0 ? activate_text : "" ;
case CTEXT_DEACTIVATE_FILESYSTEM :
return index == 0 ? deactivate_text : "" ;
default :
return "" ;
}
}
FS linux_swap::get_filesystem_support()
{
FS fs( FS_LINUX_SWAP );
fs .busy = FS::GPARTED ;
fs .read = FS::EXTERNAL ;
fs .online_read = FS::EXTERNAL ;
if ( ! Glib::find_program_in_path( "mkswap" ) .empty() )
{
fs .create = GParted::FS::EXTERNAL ;
fs .create_with_label = GParted::FS::EXTERNAL ;
fs .grow = GParted::FS::EXTERNAL ;
fs .shrink = GParted::FS::EXTERNAL ;
fs.copy = FS::EXTERNAL;
fs.move = FS::EXTERNAL;
}
if ( ! Glib::find_program_in_path( "swaplabel" ) .empty() )
{
fs .read_label = FS::EXTERNAL ;
fs .write_label = FS::EXTERNAL ;
fs .read_uuid = FS::EXTERNAL ;
fs .write_uuid = FS::EXTERNAL ;
}
return fs ;
}
void linux_swap::set_used_sectors( Partition & partition )
{
if ( partition .busy )
{
N = -1;
std::string line ;
std::ifstream input( "/proc/swaps" ) ;
if ( input )
{
BlockSpecial bs_path = BlockSpecial( partition.get_path() );
while ( getline( input, line ) )
{
Glib::ustring filename = Utils::regexp_label( line, "^([[:graph:]]+)" );
if ( bs_path == BlockSpecial( filename ) )
{
sscanf( line.c_str(), "%*s %*s %*d %lld", &N );
break ;
}
}
input .close() ;
}
else
{
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( "open(\"/proc/swaps\", O_RDONLY): " + Glib::strerror( errno ) );
}
if ( N > -1 )
{
// Ignore swap space reported size to ignore 1 page format
// overhead. Instead use partition size as sectors_fs_size so
// reported used figure for active swap space starts from 0
// upwards, matching what 'swapon -s' reports.
T = partition.get_sector_length();
N = Utils::round( N * ( KIBIBYTE / double(partition .sector_size) ) ) ;
partition .set_sector_usage( T, T - N ) ;
}
}
else
{
//By definition inactive swap space is 100% free
Sector size = partition .get_sector_length() ;
partition .set_sector_usage( size, size ) ;
}
}
void linux_swap::read_label( Partition & partition )
{
if ( ! Utils::execute_command( "swaplabel " + partition .get_path(), output, error, true ) )
{
partition.set_filesystem_label( Utils::regexp_label( output, "^LABEL:[[:blank:]]*(.*)$" ) );
}
else
{
if ( ! output .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( output );
if ( ! error .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( error );
}
}
bool linux_swap::write_label( const Partition & partition, OperationDetail & operationdetail )
{
return ! execute_command( "swaplabel -L \"" + partition.get_filesystem_label() + "\" " + partition.get_path(),
Time and check nearly all file system action commands (#754684) There has been an undocumented rule that external commands displayed in the operation details, as part of file system manipulations, only get a time and check mark displayed when multiple commands are needed, and not otherwise. (GParted checks whether all commands are successful or not regardless of whether a check mark is displayed in the operation details or not). EXCEPTION 1: btrfs resize Since the following commit [1] from 2013-02-22, GParted stopped displaying the timing for the btrfs resize command in the operation details. It being part of a multi-command sequence to perform the step. This is because FileSystem::execute_command() since the commit can only check the exit status for zero / non-zero while timing and checking the command status but btrfs resize needs to consider some non-zero statuses as successful. [1] 52a2a9b00a32996921ace055e71d0e09fb33c5fe Reduce threading (#685740) EXCEPTION 2: ext2/3/4 move and copy using e2image When use of e2image was added [2] the single command steps were timed and check. [2] 86111fe12a26d23d9fc2a9e2d19281290ecaf985 Use e2image to move/copy ext[234] file systems (#721516) EXCEPTION 3: fat16/32 write label and UUID Uses Utils::execute_command() rather than FileSystem::execute_command() so can be separately changed. See the following commit for resolution of the final commands not yet timed and check mark displayed. CHANGE: Lets make a simpler rule of always displaying the time and a check mark for all external commands displayed in the operation details. However this makes several of the other single command actions need special exit status handling because zero success, non-zero failure is not correct for every case. Specifically affects resizing of reiserfs and check repair of ext2/3/4, fat16/32, jfs and reiserfs. After this change all external commands run as file system actions must follow one of these two patterns of using the EXEC_CHECK_STATUS flag or separately calling FileSystem::set_status() to register success or failure of the command: exit_status = execute_command(cmd, od, EXEC_CHECK_STATUS...); or: exit_status = execute_command(cmd, od, ...); bool success = (exit_status == 0 || exit_status == OTHER_SUCCESS_VALUE...); set_status(od, success ); Bug 754684 - Updates to FileSystem:: and Utils::execute_command() functions
2015-09-05 02:31:16 -06:00
operationdetail, EXEC_CHECK_STATUS );
}
void linux_swap::read_uuid( Partition & partition )
{
if ( ! Utils::execute_command( "swaplabel " + partition .get_path(), output, error, true ) )
{
partition .uuid = Utils::regexp_label( output, "^UUID:[[:blank:]]*(" RFC4122_NONE_NIL_UUID_REGEXP ")" ) ;
}
else
{
if ( ! output .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( output );
if ( ! error .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( error );
}
}
bool linux_swap::write_uuid( const Partition & partition, OperationDetail & operationdetail )
{
Time and check nearly all file system action commands (#754684) There has been an undocumented rule that external commands displayed in the operation details, as part of file system manipulations, only get a time and check mark displayed when multiple commands are needed, and not otherwise. (GParted checks whether all commands are successful or not regardless of whether a check mark is displayed in the operation details or not). EXCEPTION 1: btrfs resize Since the following commit [1] from 2013-02-22, GParted stopped displaying the timing for the btrfs resize command in the operation details. It being part of a multi-command sequence to perform the step. This is because FileSystem::execute_command() since the commit can only check the exit status for zero / non-zero while timing and checking the command status but btrfs resize needs to consider some non-zero statuses as successful. [1] 52a2a9b00a32996921ace055e71d0e09fb33c5fe Reduce threading (#685740) EXCEPTION 2: ext2/3/4 move and copy using e2image When use of e2image was added [2] the single command steps were timed and check. [2] 86111fe12a26d23d9fc2a9e2d19281290ecaf985 Use e2image to move/copy ext[234] file systems (#721516) EXCEPTION 3: fat16/32 write label and UUID Uses Utils::execute_command() rather than FileSystem::execute_command() so can be separately changed. See the following commit for resolution of the final commands not yet timed and check mark displayed. CHANGE: Lets make a simpler rule of always displaying the time and a check mark for all external commands displayed in the operation details. However this makes several of the other single command actions need special exit status handling because zero success, non-zero failure is not correct for every case. Specifically affects resizing of reiserfs and check repair of ext2/3/4, fat16/32, jfs and reiserfs. After this change all external commands run as file system actions must follow one of these two patterns of using the EXEC_CHECK_STATUS flag or separately calling FileSystem::set_status() to register success or failure of the command: exit_status = execute_command(cmd, od, EXEC_CHECK_STATUS...); or: exit_status = execute_command(cmd, od, ...); bool success = (exit_status == 0 || exit_status == OTHER_SUCCESS_VALUE...); set_status(od, success ); Bug 754684 - Updates to FileSystem:: and Utils::execute_command() functions
2015-09-05 02:31:16 -06:00
return ! execute_command( "swaplabel -U \"" + Utils::generate_uuid() + "\" " + partition .get_path(),
operationdetail, EXEC_CHECK_STATUS );
}
bool linux_swap::create( const Partition & new_partition, OperationDetail & operationdetail )
{
return ! execute_command( "mkswap -L \"" + new_partition.get_filesystem_label() + "\" " +
new_partition.get_path(),
Time and check nearly all file system action commands (#754684) There has been an undocumented rule that external commands displayed in the operation details, as part of file system manipulations, only get a time and check mark displayed when multiple commands are needed, and not otherwise. (GParted checks whether all commands are successful or not regardless of whether a check mark is displayed in the operation details or not). EXCEPTION 1: btrfs resize Since the following commit [1] from 2013-02-22, GParted stopped displaying the timing for the btrfs resize command in the operation details. It being part of a multi-command sequence to perform the step. This is because FileSystem::execute_command() since the commit can only check the exit status for zero / non-zero while timing and checking the command status but btrfs resize needs to consider some non-zero statuses as successful. [1] 52a2a9b00a32996921ace055e71d0e09fb33c5fe Reduce threading (#685740) EXCEPTION 2: ext2/3/4 move and copy using e2image When use of e2image was added [2] the single command steps were timed and check. [2] 86111fe12a26d23d9fc2a9e2d19281290ecaf985 Use e2image to move/copy ext[234] file systems (#721516) EXCEPTION 3: fat16/32 write label and UUID Uses Utils::execute_command() rather than FileSystem::execute_command() so can be separately changed. See the following commit for resolution of the final commands not yet timed and check mark displayed. CHANGE: Lets make a simpler rule of always displaying the time and a check mark for all external commands displayed in the operation details. However this makes several of the other single command actions need special exit status handling because zero success, non-zero failure is not correct for every case. Specifically affects resizing of reiserfs and check repair of ext2/3/4, fat16/32, jfs and reiserfs. After this change all external commands run as file system actions must follow one of these two patterns of using the EXEC_CHECK_STATUS flag or separately calling FileSystem::set_status() to register success or failure of the command: exit_status = execute_command(cmd, od, EXEC_CHECK_STATUS...); or: exit_status = execute_command(cmd, od, ...); bool success = (exit_status == 0 || exit_status == OTHER_SUCCESS_VALUE...); set_status(od, success ); Bug 754684 - Updates to FileSystem:: and Utils::execute_command() functions
2015-09-05 02:31:16 -06:00
operationdetail, EXEC_CHECK_STATUS );
}
bool linux_swap::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
{
//Maintain label and uuid when recreating swap
Glib::ustring command = "mkswap -L \"" + partition_new.get_filesystem_label() + "\" ";
if ( ! partition_new .uuid .empty() )
command += " -U \"" + partition_new .uuid + "\" " ;
command += partition_new .get_path() ;
Refactor linux-swap recreation (#775932) Linux-swap is recreated as part of copy, resize and move operations and the code was special cased to implement that by calling the linux-swap specific resize method. However the displayed text always said "growing file system" and then proceeded to recreate linux swap. Example operation: Copy /dev/sdb1 to /dev/sdb2 ... + copy file system from /dev/sdb1 to /dev/sdb2 Partition copy action skipped because linux-swap file system does not contain data + grow file system to fill the partition + create new linux-swap file system + mkswap -L"" -U "77d939ef-54d6-427a-a2bf-a053da7eed4c" /dev/sdb2 Setting up swapspace version 1, size = 262140 KiB LABEL=, UUID=77d939ef-54d6-427a-a2bf-a053da7eed4c Fix by writing recreate_linux_swap_filesystem() method with better messaging and use everywhere maximise_filesystem() was previously used to recreate linux-swap. Also as this is a create step, erase the partition first to prevent the possibility of any other file system signatures being found afterwards. Now the operation steps are more reflective of what is actually being performed. Copy /dev/sdb1 to /dev/sdb2 ... + copy file system from /dev/sdb1 to /dev/sdb2 Partition copy action skipped because linux-swap file system does not contain data + clear old file system signatures in /dev/sdb2 + create new linux-swap file system + mkswap -L"" -U "77d939ef-54d6-427a-a2bf-a053da7eed4c" /dev/sdb2 Setting up swapspace version 1, size = 262140 KiB LABEL=, UUID=77d939ef-54d6-427a-a2bf-a053da7eed4c Bug 775932 - Refactor mostly applying of operations
2016-11-19 16:48:22 -07:00
return ! execute_command( command, operationdetail, EXEC_CHECK_STATUS );
}
bool linux_swap::move( const Partition & partition_new
, const Partition & partition_old
, OperationDetail & operationdetail
)
{
//Since linux-swap does not contain data, do not actually move the partition
operationdetail .add_child(
OperationDetail(
/* TO TRANSLATORS: looks like Partition move action skipped because linux-swap file system does not contain data */
String::ucompose( _("Partition move action skipped because %1 file system does not contain data")
, Utils::get_filesystem_string( FS_LINUX_SWAP )
)
, STATUS_NONE
, FONT_ITALIC
)
) ;
return true ;
}
bool linux_swap::copy( const Partition & src_part,
Partition & dest_part,
OperationDetail & operationdetail )
{
//Since linux-swap does not contain data, do not actually copy the partition
operationdetail .add_child(
OperationDetail(
/* TO TRANSLATORS: looks like Partition copy action skipped because linux-swap file system does not contain data */
String::ucompose( _("Partition copy action skipped because %1 file system does not contain data")
, Utils::get_filesystem_string( FS_LINUX_SWAP )
)
, STATUS_NONE
, FONT_ITALIC
)
) ;
return true ;
}
} //GParted