[gparted] Query unallocated space for unmounted file systems (#499202)



commit 719e73e3351b01bc7b0cf968b777dd4aeac027d8
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Tue Jan 10 15:19:01 2012 +0000

    Query unallocated space for unmounted file systems (#499202)
    
    Update file system specific implementations to set the size and free
    space, thus allowing the unallocated space in the partition to be
    calculated, for the following unmounted file systems:
        btrfs, ext2, ext3, ext4, fat16, fat32, jfs, nilfs2, ntfs, reiserfs,
        reiser4, xfs
    
    Bug #499202 - gparted does not see the difference if partition size
                  differs from filesystem size

 include/FileSystem.h |    2 +-
 include/btrfs.h      |    3 ++
 src/btrfs.cc         |   59 +++++++++++++++++++++++++++++--------------------
 src/ext2.cc          |   13 +++++++++-
 src/ext3.cc          |   13 +++++++++-
 src/ext4.cc          |   13 +++++++++-
 src/fat16.cc         |   18 ++++++++++++++-
 src/fat32.cc         |   18 ++++++++++++++-
 src/jfs.cc           |   16 +++++++++++--
 src/nilfs2.cc        |   18 ++++++++++++--
 src/ntfs.cc          |   13 +++++++++-
 src/reiser4.cc       |   23 +++++++++++++------
 src/reiserfs.cc      |   15 ++++++++++--
 src/xfs.cc           |   21 +++++++++++++----
 14 files changed, 189 insertions(+), 56 deletions(-)
---
diff --git a/include/FileSystem.h b/include/FileSystem.h
index 2202402..f69e9e4 100644
--- a/include/FileSystem.h
+++ b/include/FileSystem.h
@@ -66,7 +66,7 @@ protected:
 
 	//those are used in several places..
 	Glib::ustring output, error ;
-	Sector N, S ;
+	Sector T, N, S ;  //File system [T]otal num of blocks, [N]um of free (or used) blocks, block [S]ize
 	int exit_status ;
 	unsigned int index ;
 	
diff --git a/include/btrfs.h b/include/btrfs.h
index f1f8fac..4c1ab6f 100644
--- a/include/btrfs.h
+++ b/include/btrfs.h
@@ -43,6 +43,9 @@ public:
 		   const Glib::ustring & dest_part_path,
 		   OperationDetail & operationdetail ) ;
 	bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
+
+private:
+	Sector btrfs_size_to_num( Glib::ustring s ) const ;
 };
 } //GParted
 
diff --git a/src/btrfs.cc b/src/btrfs.cc
index a0265f8..e051314 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -124,31 +124,27 @@ void btrfs::set_used_sectors( Partition & partition )
 		exit_status = Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ;
 	if ( ! exit_status )
 	{
-		Glib::ustring size_label;
-		if ( ((index = output .find( "FS bytes" )) < output .length()) &&
-			  (size_label=Utils::regexp_label(output .substr( index ), "^FS bytes used (.*)B")) .length() > 0)
+		//FIXME: Improve free space calculation for multi-device
+		//  btrfs file systems.  Currently uses the size of the
+		//  btrfs device in this partition (spot on) and the
+		//  file system wide used bytes (wrong for multi-device
+		//  file systems).
+
+		Glib::ustring str ;
+		//Btrfs file system device size
+		Glib::ustring regexp = "devid .* size ([0-9\\.]+.?B) .* path " + partition .get_path() ;
+		if ( ! ( str = Utils::regexp_label( output, regexp ) ) .empty() )
+			T = btrfs_size_to_num( str ) ;
+
+		//Btrfs file system wide used bytes
+		if ( ! ( str = Utils::regexp_label( output, "FS bytes used ([0-9\\.]+.?B)" ) ) .empty() )
+			N = T - btrfs_size_to_num( str ) ;
+
+		if ( T > -1 && N > -1 )
 		{
-			gchar *suffix;
-			gdouble rawN = g_ascii_strtod (size_label.c_str(),&suffix);
-			unsigned long long mult=0;
-			switch(suffix[0]){
-				case 'K':
-					mult=KIBIBYTE;
-					break;
-				case 'M':
-					mult=MEBIBYTE;
-					break;
-				case 'G':
-					mult=GIBIBYTE;
-					break;
-				case 'T':
-					mult=TEBIBYTE;
-					break;
-				default:
-					mult=1;
-					break;
-					}
-			partition .set_used( Utils::round( (rawN * mult)/ double(partition .sector_size) ) ) ;
+			T = Utils::round( T / double(partition .sector_size) ) ;
+			N = Utils::round( N / double(partition .sector_size) ) ;
+			partition .set_sector_usage( T, N );
 		}
 	}
 	else
@@ -308,5 +304,20 @@ void btrfs::read_uuid( Partition & partition )
 	}
 }
 
+Sector btrfs::btrfs_size_to_num( Glib::ustring str ) const
+{
+	gchar * suffix ;
+	gdouble rawN = g_ascii_strtod( str .c_str(), & suffix ) ;
+	unsigned long long mult ;
+	switch ( suffix[0] )
+	{
+		case 'K':	mult = KIBIBYTE ;	break ;
+		case 'M':	mult = MEBIBYTE ;	break ;
+		case 'G':	mult = GIBIBYTE ;	break ;
+		case 'T':	mult = TEBIBYTE ;	break ;
+		default:	mult = 1 ;		break ;
+	}
+	return Utils::round( rawN * mult ) ;
+}
 
 } //GParted
diff --git a/src/ext2.cc b/src/ext2.cc
index 1a899a4..c967983 100644
--- a/src/ext2.cc
+++ b/src/ext2.cc
@@ -66,6 +66,11 @@ void ext2::set_used_sectors( Partition & partition )
 {
 	if ( ! Utils::execute_command( "dumpe2fs -h " + partition .get_path(), output, error, true ) )
 	{
+		index = output .find( "Block count:" ) ;
+		if ( index >= output .length() ||
+		     sscanf( output.substr( index ) .c_str(), "Block count: %Ld", &T ) != 1 )
+			T = -1 ;
+
 		index = output .find( "Free blocks:" ) ;
 		if ( index >= output .length() ||
 		     sscanf( output.substr( index ) .c_str(), "Free blocks: %Ld", &N ) != 1 )   
@@ -76,8 +81,12 @@ void ext2::set_used_sectors( Partition & partition )
 		     sscanf( output.substr( index ) .c_str(), "Block size: %Ld", &S ) != 1 )  
 			S = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/ext3.cc b/src/ext3.cc
index 9a438da..05c1995 100644
--- a/src/ext3.cc
+++ b/src/ext3.cc
@@ -67,6 +67,11 @@ void ext3::set_used_sectors( Partition & partition )
 {
 	if ( ! Utils::execute_command( "dumpe2fs -h " + partition .get_path(), output, error, true ) )
 	{
+		index = output .find( "Block count: " ) ;
+		if ( index >= output .length() ||
+		     sscanf( output .substr( index ) .c_str(), "Block count: %Ld", &T ) != 1 )
+			T = -1 ;
+
 		index = output .find( "Free blocks:" ) ;
 		if ( index >= output .length() ||
 		     sscanf( output.substr( index ) .c_str(), "Free blocks: %Ld", &N ) != 1 )   
@@ -77,8 +82,12 @@ void ext3::set_used_sectors( Partition & partition )
 		     sscanf( output.substr( index ) .c_str(), "Block size: %Ld", &S ) != 1 )  
 			S = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/ext4.cc b/src/ext4.cc
index bdd00cb..4839eb9 100644
--- a/src/ext4.cc
+++ b/src/ext4.cc
@@ -70,6 +70,11 @@ void ext4::set_used_sectors( Partition & partition )
 {
 	if ( ! Utils::execute_command( "dumpe2fs -h " + partition .get_path(), output, error, true ) )
 	{
+		index = output .find( "Block count:" ) ;
+		if ( index >= output .length() ||
+		     sscanf( output.substr( index ) .c_str(), "Block count: %Ld", &T ) != 1 )
+			T = -1 ;
+
 		index = output .find( "Free blocks:" ) ;
 		if ( index >= output .length() ||
 		     sscanf( output.substr( index ) .c_str(), "Free blocks: %Ld", &N ) != 1 )   
@@ -80,8 +85,12 @@ void ext4::set_used_sectors( Partition & partition )
 		     sscanf( output.substr( index ) .c_str(), "Block size: %Ld", &S ) != 1 )  
 			S = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/fat16.cc b/src/fat16.cc
index bd0485b..6bb4512 100644
--- a/src/fat16.cc
+++ b/src/fat16.cc
@@ -106,6 +106,19 @@ void fat16::set_used_sectors( Partition & partition )
 	exit_status = Utils::execute_command( "dosfsck -n -v " + partition .get_path(), output, error, true ) ;
 	if ( exit_status == 0 || exit_status == 1 || exit_status == 256 )
 	{
+		//total file system size in logical sectors
+		index = output .rfind( "\n", output .find( "sectors total" ) ) +1 ;
+		if ( index >= output .length() || sscanf( output .substr( index ) .c_str(), "%Ld", &T ) != 1 )
+			T = -1 ;
+
+		//bytes per logical sector
+		index = output .rfind( "\n", output .find( "bytes per logical sector" ) ) +1 ;
+		if ( index >= output .length() || sscanf( output .substr( index ) .c_str(), "%Ld", &S ) != 1 )
+			S = -1 ;
+
+		if ( T > -1 && S > -1 )
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+
 		//free clusters
 		index = output .find( ",", output .find( partition .get_path() ) + partition .get_path() .length() ) +1 ;
 		if ( index < output .length() && sscanf( output .substr( index ) .c_str(), "%Ld/%Ld", &S, &N ) == 2 ) 
@@ -119,7 +132,10 @@ void fat16::set_used_sectors( Partition & partition )
 			S = -1 ;
 	
 		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+
+		if ( T > -1 && N > -1 )
+			partition .set_sector_usage( T, N ) ;
 	}
 	else
 	{
diff --git a/src/fat32.cc b/src/fat32.cc
index c49ed50..88ca84c 100644
--- a/src/fat32.cc
+++ b/src/fat32.cc
@@ -94,6 +94,19 @@ void fat32::set_used_sectors( Partition & partition )
 	exit_status = Utils::execute_command( "dosfsck -n -v " + partition .get_path(), output, error, true ) ;
 	if ( exit_status == 0 || exit_status == 1 || exit_status == 256 )
 	{
+		//total file system size in logical sectors
+		index = output .rfind( "\n", output .find( "sectors total" ) ) +1 ;
+		if ( index >= output .length() || sscanf( output .substr( index ) .c_str(), "%Ld", &T ) != 1 )
+			T = -1 ;
+
+		//bytes per logical sector
+		index = output .rfind( "\n", output .find( "bytes per logical sector" ) ) +1 ;
+		if ( index >= output .length() || sscanf( output .substr( index ) .c_str(), "%Ld", &S ) != 1 )
+			S = -1 ;
+
+		if ( T > -1 && S > -1 )
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+
 		//free clusters
 		index = output .find( ",", output .find( partition .get_path() ) + partition .get_path() .length() ) +1 ;
 		if ( index < output .length() && sscanf( output .substr( index ) .c_str(), "%Ld/%Ld", &S, &N ) == 2 ) 
@@ -107,7 +120,10 @@ void fat32::set_used_sectors( Partition & partition )
 			S = -1 ;
 	
 		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+
+		if ( T > -1 && N > -1 )
+			partition .set_sector_usage( T, N ) ;
 	}
 	else
 	{
diff --git a/src/jfs.cc b/src/jfs.cc
index fe1ecb5..79cfc50 100644
--- a/src/jfs.cc
+++ b/src/jfs.cc
@@ -75,15 +75,25 @@ void jfs::set_used_sectors( Partition & partition )
 		if ( index >= output .length() || 
 		     sscanf( output .substr( index ) .c_str(), "Block Size: %Ld", &S ) != 1 ) 
 			S = -1 ;
-		
+
+		//total blocks
+		index = output .find( "dn_mapsize:" ) ;
+		if ( index >= output .length() ||
+		     sscanf( output .substr( index ) .c_str(), "dn_mapsize: %Lx", &T ) != 1 )
+			T = -1 ;
+
 		//free blocks
 		index = output .find( "dn_nfree:" ) ;
 		if ( index >= output .length() || 
 		     sscanf( output .substr( index ) .c_str(), "dn_nfree: %Lx", &N ) != 1 ) 
 			N = -1 ;
 
-		if ( S > -1 && N > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/nilfs2.cc b/src/nilfs2.cc
index 72b8005..37a3673 100644
--- a/src/nilfs2.cc
+++ b/src/nilfs2.cc
@@ -66,7 +66,15 @@ void nilfs2::set_used_sectors( Partition & partition )
 {
 	if ( ! Utils::execute_command( "nilfs-tune -l " + partition .get_path(), output, error, true ) )
 	{
-		Glib::ustring::size_type index = output .find( "Free blocks count:" ) ;
+		//File system size in bytes
+		Glib::ustring::size_type index = output .find( "Device size:" ) ;
+		if (   index == Glib::ustring::npos
+		    || sscanf( output.substr( index ) .c_str(), "Device size: %Ld", &T ) != 1
+		   )
+			T = -1 ;
+
+		//Free space in blocks
+		index = output .find( "Free blocks count:" ) ;
 		if (   index == Glib::ustring::npos
 		    || sscanf( output.substr( index ) .c_str(), "Free blocks count: %Ld", &N ) != 1
 		   )
@@ -78,8 +86,12 @@ void nilfs2::set_used_sectors( Partition & partition )
 		   )
 			S = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double( partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T / double(partition .sector_size) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/ntfs.cc b/src/ntfs.cc
index 429dfbe..17b0117 100644
--- a/src/ntfs.cc
+++ b/src/ntfs.cc
@@ -111,13 +111,22 @@ void ntfs::set_used_sectors( Partition & partition )
 	if ( ! Utils::execute_command( 
 		"ntfsresize --info --force --no-progress-bar " + partition .get_path(), output, error, true ) )
 	{
+		index = output .find( "Current volume size:" ) ;
+		if ( index >= output .length() ||
+		     sscanf( output .substr( index ) .c_str(), "Current volume size: %Ld", &T ) != 1 )
+			T = -1 ;
+
 		index = output .find( "resize at" ) ;
 		if ( index >= output .length() ||
 		     sscanf( output .substr( index ) .c_str(), "resize at %Ld", &N ) != 1 )
 			N = -1 ;
 
-		if ( N > -1 )
-			partition .set_used( Utils::round( N / double(partition .sector_size) ) ) ; 
+		if ( T > -1 && N > -1 )
+		{
+			T = Utils::round( T / double(partition .sector_size) ) ;
+			N = Utils::round( N / double(partition .sector_size) ) ;
+			partition .set_sector_usage( T, T - N );
+		}
 	}
 	else
 	{
diff --git a/src/reiser4.cc b/src/reiser4.cc
index b5650b6..fbef099 100644
--- a/src/reiser4.cc
+++ b/src/reiser4.cc
@@ -60,18 +60,27 @@ void reiser4::set_used_sectors( Partition & partition )
 {
 	if ( ! Utils::execute_command( "debugfs.reiser4 " + partition .get_path(), output, error, true ) )
 	{
-		index = output .find( "free blocks" ) ;
+		index = output .find( "\nblocks:" ) ;
 		if ( index >= output .length() ||
-		     sscanf( output.substr( index ) .c_str(), "free blocks: %Ld", &N ) != 1 )   
+		     sscanf( output.substr( index ) .c_str(), "\nblocks: %Ld", &T ) != 1 )
+			T = -1 ;
+
+		index = output .find( "\nfree blocks:" ) ;
+		if ( index >= output .length() ||
+		     sscanf( output.substr( index ) .c_str(), "\nfree blocks: %Ld", &N ) != 1 )
 			N = -1 ;
-	
-		index = output .find( "blksize" ) ;
+
+		index = output .find( "\nblksize:" ) ;
 		if ( index >= output.length() ||
-		     sscanf( output.substr( index ) .c_str(), "blksize: %Ld", &S ) != 1 )  
+		     sscanf( output.substr( index ) .c_str(), "\nblksize: %Ld", &S ) != 1 )
 			S = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/reiserfs.cc b/src/reiserfs.cc
index fc7a564..55d1310 100644
--- a/src/reiserfs.cc
+++ b/src/reiserfs.cc
@@ -71,7 +71,12 @@ void reiserfs::set_used_sectors( Partition & partition )
 {
 	if ( ! Utils::execute_command( "debugreiserfs " + partition .get_path(), output, error, true ) )
 	{
-		index = output .find( "Blocksize" ) ;
+		index = output .find( "Count of blocks on the device:" ) ;
+		if ( index >= output .length() ||
+		     sscanf( output .substr( index ) .c_str(), "Count of blocks on the device: %Ld", &T ) != 1 )
+			T = -1 ;
+
+		index = output .find( "Blocksize:" ) ;
 		if ( index >= output .length() || 
 		     sscanf( output .substr( index ) .c_str(), "Blocksize: %Ld", &S ) != 1 )
 			S = -1 ;
@@ -81,8 +86,12 @@ void reiserfs::set_used_sectors( Partition & partition )
 		     sscanf( output .substr( index ) .c_str(), "%Ld", &N ) != 1 )
 			N = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
 	}
 	else
 	{
diff --git a/src/xfs.cc b/src/xfs.cc
index 6f4e160..fb866f0 100644
--- a/src/xfs.cc
+++ b/src/xfs.cc
@@ -76,7 +76,7 @@ FS xfs::get_filesystem_support()
 void xfs::set_used_sectors( Partition & partition ) 
 {
 	if ( ! Utils::execute_command( 
-			"xfs_db -c 'sb 0' -c 'print blocksize' -c 'print fdblocks' -r " + partition .get_path(),
+			"xfs_db -c 'sb 0' -c 'print blocksize' -c 'print dblocks' -c 'print fdblocks' -r " + partition .get_path(),
 			output,
 			error,
 			true ) )
@@ -85,14 +85,25 @@ void xfs::set_used_sectors( Partition & partition )
 		if ( sscanf( output .c_str(), "blocksize = %Ld", &S ) != 1 )
 			S = -1 ;
 
+		//filesystem blocks
+		index = output .find( "\ndblocks" ) ;
+		if ( index > output .length() ||
+		     sscanf( output .substr( index ) .c_str(), "\ndblocks = %Ld", &T ) != 1 )
+			T = -1 ;
+
 		//free blocks
-		index = output .find( "fdblocks" ) ;
+		index = output .find( "\nfdblocks" ) ;
 		if ( index > output .length() ||
-		     sscanf( output .substr( index ) .c_str(), "fdblocks = %Ld", &N ) != 1 )
+		     sscanf( output .substr( index ) .c_str(), "\nfdblocks = %Ld", &N ) != 1 )
 			N = -1 ;
 
-		if ( N > -1 && S > -1 )
-			partition .Set_Unused( Utils::round( N * ( S / double(partition .sector_size) ) ) ) ;
+		if ( T > -1 && N > -1 && S > -1 )
+		{
+			T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
+			N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
+			partition .set_sector_usage( T, N ) ;
+		}
+
 	}
 	else
 	{



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