gparted/include/FileSystem.h

185 lines
7.3 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/>.
*/
#ifndef GPARTED_FILESYSTEM_H
#define GPARTED_FILESYSTEM_H
#include "Operation.h"
#include "Partition.h"
#include "PipeCapture.h"
Create separate file system limits structure and getter method (#787204) PATCH SET OVERVIEW: Currently the supported actions of each file system and their size limits are stored in struct FS objects. These are created by calling file system specific derived implementations of FileSystem::get_filesystem_support(). This happens when GParted is started or when a when a rescan for supported actions is performed. The file system size limits are expressed as a fixed number of bytes. The maximum UDF file system size is specified in terms of file system block size units. Also the file system block size must match the sector size of the underlying device. Typically 2K for optical media and 512 bytes or 4K for hard drives. Therefore GParted can't properly express the true UDF file system size limits because they depend on the block size of an existing UDF file system or the sector size of the device for new UDF file systems. In fact other file systems such as EXT2/3/4 and XFS actually express their maximum file system size in terms of numbers of file system blocks but these tend to always be 4K and don't have to match the sector size of the underlying device, so fixed byte values tend to suffice. To update GParted for this, first separate file system size limits from struct FS into struct FS_Limits and provide new FileSystem::get_filesystem_limits() method to allow the limits to be queried independently of the calls to get_filesystem_support(). Second, pass Partition objects and allow derived get_filesystem_limits() implementations. THIS PATCH: Just creates a separate structure storing fixed value file system minimum and maximum size limits along with getter method get_filesystem_limits(). Bug 787204 - Minimum and maximum size of the UDF partition/disk
2018-01-11 05:30:48 -07:00
#include "Utils.h"
#include <fstream>
#include <sys/stat.h>
#include <sigc++/slot.h>
namespace GParted
{
enum CUSTOM_TEXT
{
CTEXT_NONE,
CTEXT_ACTIVATE_FILESYSTEM, // Activate text ('Mount', 'Swapon', VG 'Activate', ...)
CTEXT_DEACTIVATE_FILESYSTEM, // Deactivate text ('Unmount', 'Swapoff', VG 'Deactivate', ...)
CTEXT_CHANGE_UUID_WARNING, // Warning to print when changing UUIDs
CTEXT_RESIZE_DISALLOWED_WARNING // File system resizing currently disallowed reason
};
// Minimum and maximum file system size limits
struct FS_Limits
{
Byte_Value min_size; // 0 => no limit, +ve => limit defined. (As implemented by)
Byte_Value max_size; // -----------------"----------------- (code using these.)
FS_Limits() : min_size( 0 ) , max_size( 0 ) {};
FS_Limits( Byte_Value min, Byte_Value max ) : min_size( min ), max_size( max ) {};
};
// Struct to store file system support information
struct FS
{
enum Support
{
NONE = 0,
GPARTED = 1,
LIBPARTED = 2,
EXTERNAL = 3
};
FSType fstype;
Support busy; // How to determine if partition/file system is busy
Support read; // Can and how to read sector usage while inactive
Support read_label;
Support write_label;
Support read_uuid;
Support write_uuid;
Support create;
Support create_with_label; // Can and how to format file system with label
Support grow;
Support shrink;
Support move; // start point and endpoint
Support check; // Some check tool available?
Support copy;
Support remove;
Support online_read; // Can and how to read sector usage while active
Support online_grow;
Support online_shrink;
Support online_write_label;
FS(FSType fstype_ = FS_UNSUPPORTED) : fstype(fstype_)
{
busy = read = read_label = write_label = read_uuid = write_uuid = create =
create_with_label = grow = shrink = move = check = copy = remove = online_read =
online_grow = online_shrink = online_write_label = NONE;
}
};
enum ExecFlags
{
EXEC_NONE = 1 << 0,
EXEC_CHECK_STATUS = 1 << 1, // Set the status of the command in the operation
// details based on the exit status being zero or
// non-zero. Must either use this flag when calling
// ::execute_command() or call ::set_status()
// afterwards.
EXEC_CANCEL_SAFE = 1 << 2,
EXEC_PROGRESS_STDOUT = 1 << 3, // Run progress tracking callback after reading new
// data on stdout from command.
Connect timed progress tracking callbacks inside execute_command() (#760709) The timed progress tracking callback for execution of xfs copy follows this pattern: sigc::connection c; ... c = Glib::signal_timeout().connect( ... sigc::mem_fun( *this, &xfs::copy_progress ) ..., 500 /*ms*/ ); ... execute_command( ... ); c.disconnect(); As with output progress tracking callbacks for ext2/3/4 and ntfs file system specific commands, pass the callback slot and a flag into execute_command() and connect the timed callback inside. This simplified the pattern to: ... execute_command( ...|EXEC_PROGRESS_TIMED, static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) ); NOTE: The type of sigc::mem_fun() doesn't allow the compiler to choose between the two overloaded variants of execute_command() with the fourth parameter of either (full types without typedefs of StreamSlot and TimedSlot respectively): sigc::slot<void, OperationDetail *> stream_progress_slot sigc::slot<bool, OperationDetail *> timed_progress_slot Therefore have to cast the result of all callback slots to the relevant type. Hence: static_cast<StreamSlot>( sigc::mem_fun( *this, &{CLASS}::{NAME}_progress ) ) static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) References: * [sigc] Functor not resolving between overloaded methods with different slot types https://mail.gnome.org/archives/libsigc-list/2016-February/msg00000.html * Bug 306705 - Can't overload methods based on different slot<> parameters. https://bugzilla.gnome.org/show_bug.cgi?id=306705 Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific copy methods
2016-02-03 14:17:30 -07:00
EXEC_PROGRESS_STDERR = 1 << 4, // Same but for stderr.
EXEC_PROGRESS_TIMED = 1 << 5 // Run progress tracking callback periodically.
};
inline ExecFlags operator|( ExecFlags lhs, ExecFlags rhs )
{ return static_cast<ExecFlags>( static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs) ); }
inline ExecFlags operator&( ExecFlags lhs, ExecFlags rhs )
{ return static_cast<ExecFlags>( static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs) ); }
class FileSystem
{
public:
FileSystem() ;
virtual ~FileSystem() {}
virtual const Glib::ustring & get_custom_text( CUSTOM_TEXT ttype, int index = 0 ) const;
static const Glib::ustring & get_generic_text( CUSTOM_TEXT ttype, int index = 0 );
virtual FS get_filesystem_support() = 0 ;
virtual FS_Limits get_filesystem_limits( const Partition & partition ) const { return fs_limits; };
virtual bool is_busy( const Glib::ustring & path ) { return false ; } ;
virtual void set_used_sectors( Partition & partition ) {};
virtual void read_label( Partition & partition ) {};
virtual bool write_label( const Partition & partition, OperationDetail & operationdetail ) { return false; };
virtual void read_uuid( Partition & partition ) {};
virtual bool write_uuid( const Partition & partition, OperationDetail & operationdetail ) { return false; };
virtual bool create( const Partition & new_partition, OperationDetail & operationdetail ) { return false; };
virtual bool resize( const Partition & partition_new,
OperationDetail & operationdetail,
bool fill_partition ) { return false; };
virtual bool move( const Partition & partition_new
, const Partition & partition_old
, OperationDetail & operationdetail
) { return false; };
virtual bool copy( const Partition & src_part,
Partition & dest_part,
OperationDetail & operationdetail ) { return false; };
virtual bool check_repair( const Partition & partition, OperationDetail & operationdetail ) { return false; };
virtual bool remove( const Partition & partition, OperationDetail & operationdetail ) { return true; };
protected:
typedef sigc::slot<void, OperationDetail *> StreamSlot;
Connect timed progress tracking callbacks inside execute_command() (#760709) The timed progress tracking callback for execution of xfs copy follows this pattern: sigc::connection c; ... c = Glib::signal_timeout().connect( ... sigc::mem_fun( *this, &xfs::copy_progress ) ..., 500 /*ms*/ ); ... execute_command( ... ); c.disconnect(); As with output progress tracking callbacks for ext2/3/4 and ntfs file system specific commands, pass the callback slot and a flag into execute_command() and connect the timed callback inside. This simplified the pattern to: ... execute_command( ...|EXEC_PROGRESS_TIMED, static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) ); NOTE: The type of sigc::mem_fun() doesn't allow the compiler to choose between the two overloaded variants of execute_command() with the fourth parameter of either (full types without typedefs of StreamSlot and TimedSlot respectively): sigc::slot<void, OperationDetail *> stream_progress_slot sigc::slot<bool, OperationDetail *> timed_progress_slot Therefore have to cast the result of all callback slots to the relevant type. Hence: static_cast<StreamSlot>( sigc::mem_fun( *this, &{CLASS}::{NAME}_progress ) ) static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) References: * [sigc] Functor not resolving between overloaded methods with different slot types https://mail.gnome.org/archives/libsigc-list/2016-February/msg00000.html * Bug 306705 - Can't overload methods based on different slot<> parameters. https://bugzilla.gnome.org/show_bug.cgi?id=306705 Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific copy methods
2016-02-03 14:17:30 -07:00
typedef sigc::slot<bool, OperationDetail *> TimedSlot;
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
Connect timed progress tracking callbacks inside execute_command() (#760709) The timed progress tracking callback for execution of xfs copy follows this pattern: sigc::connection c; ... c = Glib::signal_timeout().connect( ... sigc::mem_fun( *this, &xfs::copy_progress ) ..., 500 /*ms*/ ); ... execute_command( ... ); c.disconnect(); As with output progress tracking callbacks for ext2/3/4 and ntfs file system specific commands, pass the callback slot and a flag into execute_command() and connect the timed callback inside. This simplified the pattern to: ... execute_command( ...|EXEC_PROGRESS_TIMED, static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) ); NOTE: The type of sigc::mem_fun() doesn't allow the compiler to choose between the two overloaded variants of execute_command() with the fourth parameter of either (full types without typedefs of StreamSlot and TimedSlot respectively): sigc::slot<void, OperationDetail *> stream_progress_slot sigc::slot<bool, OperationDetail *> timed_progress_slot Therefore have to cast the result of all callback slots to the relevant type. Hence: static_cast<StreamSlot>( sigc::mem_fun( *this, &{CLASS}::{NAME}_progress ) ) static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) References: * [sigc] Functor not resolving between overloaded methods with different slot types https://mail.gnome.org/archives/libsigc-list/2016-February/msg00000.html * Bug 306705 - Can't overload methods based on different slot<> parameters. https://bugzilla.gnome.org/show_bug.cgi?id=306705 Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific copy methods
2016-02-03 14:17:30 -07:00
ExecFlags flags = EXEC_NONE );
int execute_command(const Glib::ustring& command, const char *input, OperationDetail& operationdetail,
ExecFlags flags = EXEC_NONE);
Connect timed progress tracking callbacks inside execute_command() (#760709) The timed progress tracking callback for execution of xfs copy follows this pattern: sigc::connection c; ... c = Glib::signal_timeout().connect( ... sigc::mem_fun( *this, &xfs::copy_progress ) ..., 500 /*ms*/ ); ... execute_command( ... ); c.disconnect(); As with output progress tracking callbacks for ext2/3/4 and ntfs file system specific commands, pass the callback slot and a flag into execute_command() and connect the timed callback inside. This simplified the pattern to: ... execute_command( ...|EXEC_PROGRESS_TIMED, static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) ); NOTE: The type of sigc::mem_fun() doesn't allow the compiler to choose between the two overloaded variants of execute_command() with the fourth parameter of either (full types without typedefs of StreamSlot and TimedSlot respectively): sigc::slot<void, OperationDetail *> stream_progress_slot sigc::slot<bool, OperationDetail *> timed_progress_slot Therefore have to cast the result of all callback slots to the relevant type. Hence: static_cast<StreamSlot>( sigc::mem_fun( *this, &{CLASS}::{NAME}_progress ) ) static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) References: * [sigc] Functor not resolving between overloaded methods with different slot types https://mail.gnome.org/archives/libsigc-list/2016-February/msg00000.html * Bug 306705 - Can't overload methods based on different slot<> parameters. https://bugzilla.gnome.org/show_bug.cgi?id=306705 Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific copy methods
2016-02-03 14:17:30 -07:00
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot );
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
TimedSlot timed_progress_slot );
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
void set_status( OperationDetail & operationdetail, bool success );
void execute_command_eof();
Glib::ustring mk_temp_dir( const Glib::ustring & infix, OperationDetail & operationdetail ) ;
void rm_temp_dir( const Glib::ustring dir_name, OperationDetail & operationdetail ) ;
FS_Limits fs_limits; // File system minimum and maximum size limits. In derived
// classes either assign fixed values in get_filesystem_support()
// or implement get_filesystem_limits() for dynamic values.
Create separate file system limits structure and getter method (#787204) PATCH SET OVERVIEW: Currently the supported actions of each file system and their size limits are stored in struct FS objects. These are created by calling file system specific derived implementations of FileSystem::get_filesystem_support(). This happens when GParted is started or when a when a rescan for supported actions is performed. The file system size limits are expressed as a fixed number of bytes. The maximum UDF file system size is specified in terms of file system block size units. Also the file system block size must match the sector size of the underlying device. Typically 2K for optical media and 512 bytes or 4K for hard drives. Therefore GParted can't properly express the true UDF file system size limits because they depend on the block size of an existing UDF file system or the sector size of the device for new UDF file systems. In fact other file systems such as EXT2/3/4 and XFS actually express their maximum file system size in terms of numbers of file system blocks but these tend to always be 4K and don't have to match the sector size of the underlying device, so fixed byte values tend to suffice. To update GParted for this, first separate file system size limits from struct FS into struct FS_Limits and provide new FileSystem::get_filesystem_limits() method to allow the limits to be queried independently of the calls to get_filesystem_support(). Second, pass Partition objects and allow derived get_filesystem_limits() implementations. THIS PATCH: Just creates a separate structure storing fixed value file system minimum and maximum size limits along with getter method get_filesystem_limits(). Bug 787204 - Minimum and maximum size of the UDF partition/disk
2018-01-11 05:30:48 -07:00
//those are used in several places..
Glib::ustring output, error ;
int exit_status ;
private:
int execute_command_internal(const Glib::ustring& command, const char *input,
OperationDetail& operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot,
TimedSlot timed_progress_slot);
void store_exit_status( GPid pid, int status );
bool running;
int pipecount;
};
} //GParted
#endif /* GPARTED_FILESYSTEM_H */