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
This commit is contained in:
Mike Fleetwood 2012-01-10 15:19:01 +00:00 committed by Curtis Gedak
parent 8ffd68b012
commit 719e73e335
14 changed files with 190 additions and 57 deletions

View File

@ -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 ;

View File

@ -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

View File

@ -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

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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 ;
//free blocks
index = output .find( "fdblocks" ) ;
//filesystem blocks
index = output .find( "\ndblocks" ) ;
if ( index > output .length() ||
sscanf( output .substr( index ) .c_str(), "fdblocks = %Ld", &N ) != 1 )
sscanf( output .substr( index ) .c_str(), "\ndblocks = %Ld", &T ) != 1 )
T = -1 ;
//free blocks
index = output .find( "\nfdblocks" ) ;
if ( index > output .length() ||
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
{