From 719e73e3351b01bc7b0cf968b777dd4aeac027d8 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Tue, 10 Jan 2012 15:19:01 +0000 Subject: [PATCH] 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 | 23 ++++++++++++----- 14 files changed, 190 insertions(+), 57 deletions(-) diff --git a/include/FileSystem.h b/include/FileSystem.h index 2202402c..f69e9e45 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 f1f8fac5..4c1ab6ff 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 a0265f8b..e0513141 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 1a899a42..c9679837 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 9a438dac..05c1995e 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 bdd00cb3..4839eb9a 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 bd0485bd..6bb4512f 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 c49ed50c..88ca84c0 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 fe1ecb5b..79cfc507 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 72b8005d..37a3673a 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 429dfbe3..17b01175 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 b5650b6c..fbef0996 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 fc7a5644..55d13101 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 6f4e1604..fb866f09 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 ; - //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 {