[gparted] Add helper functions for mounted file system resizing operations



commit 4ab3fe0ee75ed35d049ba349628fb8ea9f6c9d15
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Tue Dec 27 11:05:11 2011 +0000

    Add helper functions for mounted file system resizing operations
    
    There is a lot of commonality and code repetition for resizing of file
    systems which can only be resized while mounted.  Resizing of btrfs, jfs
    and xfs all follow the pattern: mkdir, mount, resize, umount and rmdir.
    Copying an xfs file system also uses a similar pattern, but for the
    source and destination xfs file systems simultaneously.
    
    Add three helper functions to the FileSystem class which implement
    common tasks, allowing mounted file system resizing to be implemented
    more simply.
    
    Also add a function to the Utils class which checks whether the kernel
    supports a file system.  It handles the case of non-loaded modules,
    which currently leads to reporting the growing of jfs and xfs as
    unsupported.

 include/FileSystem.h |    5 +++
 include/Utils.h      |    1 +
 src/FileSystem.cc    |   91 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/Utils.cc         |   44 ++++++++++++++++++++++++
 4 files changed, 141 insertions(+), 0 deletions(-)
---
diff --git a/include/FileSystem.h b/include/FileSystem.h
index 9d26294..589eb14 100644
--- a/include/FileSystem.h
+++ b/include/FileSystem.h
@@ -53,6 +53,11 @@ public:
 	
 protected:
 	int execute_command( const Glib::ustring & command, OperationDetail & operationdetail ) ;
+	int execute_command_timed( const Glib::ustring & command
+	                         , OperationDetail & operationdetail
+	                         , bool check_status = true ) ;
+	Glib::ustring mk_temp_dir( const Glib::ustring & infix, OperationDetail & operationdetail ) ;
+	void rm_temp_dir( const Glib::ustring dir_name, OperationDetail & operationdetail ) ;
 
 	//those are used in several places..
 	Glib::ustring output, error ;
diff --git a/include/Utils.h b/include/Utils.h
index 27023bc..5416f26 100644
--- a/include/Utils.h
+++ b/include/Utils.h
@@ -140,6 +140,7 @@ public:
 	static Glib::RefPtr<Gdk::Pixbuf> get_color_as_pixbuf( FILESYSTEM filesystem, int width, int height ) ;
 	static Glib::ustring get_filesystem_string( FILESYSTEM filesystem ) ;
 	static Glib::ustring get_filesystem_software( FILESYSTEM filesystem ) ;
+	static bool kernel_supports_fs( const Glib::ustring & fs ) ;
 	static Glib::ustring format_size( Sector sectors, Byte_Value sector_size ) ;
 	static Glib::ustring format_time( std::time_t seconds ) ;
 	static double sector_to_unit( Sector sectors, Byte_Value sector_size, SIZE_UNIT size_unit ) ;
diff --git a/src/FileSystem.cc b/src/FileSystem.cc
index 6269424..9ed19ea 100644
--- a/src/FileSystem.cc
+++ b/src/FileSystem.cc
@@ -18,6 +18,8 @@
  
 #include "../include/FileSystem.h"
 
+#include <cerrno>
+
 namespace GParted
 {
 	
@@ -40,4 +42,93 @@ int FileSystem::execute_command( const Glib::ustring & command, OperationDetail
 	return exit_status ;
 }
 
+//Time command, add results to operation detail and by default set success or failure
+int FileSystem::execute_command_timed( const Glib::ustring & command
+                                     , OperationDetail & operationdetail
+                                     , bool check_status )
+{
+	operationdetail .add_child( OperationDetail( command, STATUS_EXECUTE, FONT_BOLD_ITALIC ) ) ;
+
+	int exit_status = Utils::execute_command( "nice -n 19 " + command, output, error ) ;
+	if ( check_status )
+	{
+		if ( ! exit_status )
+			operationdetail .get_last_child() .set_status( STATUS_SUCCES ) ;
+		else
+			operationdetail .get_last_child() .set_status( STATUS_ERROR ) ;
+	}
+
+	if ( ! output .empty() )
+		operationdetail .get_last_child() .add_child( OperationDetail( output, STATUS_NONE, FONT_ITALIC ) ) ;
+
+	if ( ! error .empty() )
+		operationdetail .get_last_child() .add_child( OperationDetail( error, STATUS_NONE, FONT_ITALIC ) ) ;
+
+	return exit_status ;
+}
+
+//Create uniquely named temporary directory and add results to operation detail
+Glib::ustring FileSystem::mk_temp_dir( const Glib::ustring & infix, OperationDetail & operationdetail )
+{
+	// Construct template like "$TMPDIR/gparted-XXXXXX" or "$TMPDIR/gparted-INFIX-XXXXXX"
+	Glib::ustring dir_template = Glib::get_tmp_dir() + "/gparted-" ;
+	if ( ! infix .empty() )
+		dir_template += infix + "-" ;
+	dir_template += "XXXXXX" ;
+	//Secure Programming for Linux and Unix HOWTO, Chapter 6. Avoid Buffer Overflow
+	//  http://tldp.org/HOWTO/Secure-Programs-HOWTO/library-c.html
+	char dir_buf[4096+1];
+	sprintf( dir_buf, "%.*s", sizeof(dir_buf)-1, dir_template .c_str() ) ;
+
+	//Looks like "mkdir -v" command was run to the user
+	operationdetail .add_child( OperationDetail(
+			Glib::ustring( "mkdir -v " ) + dir_buf, STATUS_EXECUTE, FONT_BOLD_ITALIC ) ) ;
+	const char * dir_name = mkdtemp( dir_buf ) ;
+	if ( NULL == dir_name )
+	{
+		int e = errno ;
+		operationdetail .get_last_child() .set_status( STATUS_ERROR ) ;
+		operationdetail .get_last_child() .add_child( OperationDetail(
+				String::ucompose( "mkdtemp(%1): %2", dir_buf, Glib::strerror( e ) ), STATUS_NONE ) ) ;
+		dir_name = "" ;
+	}
+	else
+	{
+		//Update command with actually created temporary directory
+		operationdetail .get_last_child() .set_description(
+				Glib::ustring( "mkdir -v " ) + dir_name, FONT_BOLD_ITALIC ) ;
+		operationdetail .get_last_child() .set_status( STATUS_SUCCES ) ;
+		operationdetail .get_last_child() .add_child( OperationDetail(
+				/*TO TRANSLATORS: looks like   Created directory /tmp/gparted-CEzvSp */
+				String::ucompose( _("Created directory %1"), dir_name ), STATUS_NONE ) ) ;
+	}
+
+	return Glib::ustring( dir_name ) ;
+}
+
+//Remove directory and add results to operation detail
+void FileSystem::rm_temp_dir( const Glib::ustring dir_name, OperationDetail & operationdetail )
+{
+	//Looks like "rmdir -v" command was run to the user
+	operationdetail .add_child( OperationDetail( Glib::ustring( "rmdir -v " ) + dir_name,
+	                                             STATUS_EXECUTE, FONT_BOLD_ITALIC ) ) ;
+	if ( rmdir( dir_name .c_str() ) )
+	{
+		//Don't mark operation as errored just because rmdir
+		//  failed.  Set to Warning (N/A) instead.
+		int e = errno ;
+		operationdetail .get_last_child() .set_status( STATUS_SUCCES ) ;  //Stop timer
+		operationdetail .get_last_child() .set_status( STATUS_N_A ) ;
+		operationdetail .get_last_child() .add_child( OperationDetail(
+				String::ucompose( "rmdir(%1): ", dir_name ) + Glib::strerror( e ), STATUS_NONE ) ) ;
+	}
+	else
+	{
+		operationdetail .get_last_child() .set_status( STATUS_SUCCES ) ;
+		operationdetail .get_last_child() .add_child( OperationDetail(
+				/*TO TRANSLATORS: looks like   Removed directory /tmp/gparted-CEzvSp */
+				String::ucompose( _("Removed directory %1"), dir_name ), STATUS_NONE ) ) ;
+	}
+}
+
 } //GParted
diff --git a/src/Utils.cc b/src/Utils.cc
index c257f73..598b121 100644
--- a/src/Utils.cc
+++ b/src/Utils.cc
@@ -19,6 +19,7 @@
 #include "../include/Utils.h"
 
 #include <sstream>
+#include <fstream>
 #include <iomanip>
 #include <glibmm/regex.h>
 #include <locale.h>
@@ -190,6 +191,49 @@ Glib::ustring Utils::get_filesystem_software( FILESYSTEM filesystem )
 	}
 }
 
+//Report whether or not the kernel supports a particular file system
+bool Utils::kernel_supports_fs( const Glib::ustring & fs )
+{
+	bool fs_supported = false ;
+
+	//Read /proc/filesystems and check for the file system name.
+	//  Will succeed for compiled in drivers and already loaded
+	//  moduler drivers.  If not found, try loading the driver
+	//  as a module and re-checking /proc/filesystems.
+	std::ifstream input ;
+	std::string line ;
+	input .open( "/proc/filesystems" ) ;
+	if ( input )
+	{
+		while ( input >> line )
+			if ( line == fs )
+			{
+				fs_supported = true ;
+				break ;
+			}
+		input .close() ;
+	}
+	if ( fs_supported )
+		return true ;
+
+	Glib::ustring output, error ;
+	execute_command( "modprobe " + fs, output, error, true ) ;
+
+	input .open( "/proc/filesystems" ) ;
+	if ( input )
+	{
+		while ( input >> line )
+			if ( line == fs )
+			{
+				fs_supported = true ;
+				break ;
+			}
+		input .close() ;
+	}
+
+	return fs_supported ;
+}
+
 Glib::ustring Utils::format_size( Sector sectors, Byte_Value sector_size )
 {
 	std::stringstream ss ;



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