Remove requirement for xxd and dd for NTFS move or paste action

Perform direct update of Number of Hidden Sectors in NTFS boot record.
This change removes the need for /usr/bin/xxd and /bin/dd.
Related to GParted bug #574389
This commit is contained in:
Curtis Gedak 2009-05-16 12:15:14 -06:00
parent 9fa7486b7c
commit dd8a57a8fe
4 changed files with 47 additions and 25 deletions

2
README
View File

@ -112,7 +112,7 @@ Optional packages include:
hfsutils hfsutils
hfsprogs hfsprogs
jfsutils jfsutils
ntfsprogs - dd command, and xxd command from vim-common also required ntfsprogs
reiser4progs reiser4progs
reiserfsprogs reiserfsprogs
xfsprogs xfsprogs

View File

@ -2565,15 +2565,21 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition )
bool GParted_Core::update_bootsector( const Partition & partition, OperationDetail & operationdetail ) bool GParted_Core::update_bootsector( const Partition & partition, OperationDetail & operationdetail )
{ {
//only for ntfs atm... //only for ntfs atm...
//FIXME: 1) this should be done without relying on external commands //FIXME: this should probably be done in the fs classes...
// 2) this should probably be done in the fsclasses...
if ( partition .filesystem == FS_NTFS ) if ( partition .filesystem == FS_NTFS )
{ {
//The NTFS file system stores a value in the boot record called the
// Number of Hidden Sectors. This value must match the partition start
// sector number in order for Windows to boot from the file system.
// For more details, refer to the NTFS Volume Boot Record at:
// http://www.geocities.com/thestarman3/asm/mbr/NTFSBR.htm
operationdetail .add_child( OperationDetail( operationdetail .add_child( OperationDetail(
String::ucompose( _("updating boot sector of %1 file system on %2"), String::ucompose( _("update boot sector of %1 file system on %2"),
Utils::get_filesystem_string( partition .filesystem ), Utils::get_filesystem_string( partition .filesystem ),
partition .get_path() ) ) ) ; partition .get_path() ) ) ) ;
//convert start sector to hex string
std::stringstream ss ; std::stringstream ss ;
ss << std::hex << partition .sector_start ; ss << std::hex << partition .sector_start ;
Glib::ustring hex = ss .str() ; Glib::ustring hex = ss .str() ;
@ -2584,18 +2590,41 @@ bool GParted_Core::update_bootsector( const Partition & partition, OperationDeta
for ( int t = 6 ; t >= 0 ; t -=2 ) for ( int t = 6 ; t >= 0 ; t -=2 )
reversed_hex .append( hex .substr( t, 2 ) ) ; reversed_hex .append( hex .substr( t, 2 ) ) ;
Glib::ustring output, error, command ; //convert reversed hex codes into ascii characters
command = char buf[4] ;
"echo " + reversed_hex + " | xxd -r -p | dd conv=notrunc of=" + partition .get_path() + " bs=1 seek=28" ; for ( unsigned int k = 0; (k < 4 && k < (reversed_hex .length() / 2)); k++ )
{
Glib::ustring tmp_hex = "0x" + reversed_hex .substr( k * 2, 2 ) ;
buf[k] = (char)( std::strtol( tmp_hex .c_str(), NULL, 16 ) ) ;
}
operationdetail .get_last_child() .add_child( OperationDetail( command, STATUS_NONE, FONT_BOLD_ITALIC ) ) ; //write new Number of Hidden Sectors value into NTFS boot sector at offset 0x1C
bool succes = ! Utils::execute_command( command, output, error ) ; Glib::ustring error_message = "" ;
std::ofstream dev_file ;
dev_file .open( partition .get_path() .c_str(), std::ios::out | std::ios::binary ) ;
if ( dev_file .is_open() )
{
dev_file .seekp( 0x1C ) ;
if ( dev_file .good() )
{
dev_file .write( buf, 4 ) ;
if ( dev_file .bad() )
error_message = String::ucompose( _("Error trying to write to boot sector in %1"), partition .get_path() ) ;;
}
else
error_message = String::ucompose( _("Error trying to seek to position 0x1c in %1"), partition .get_path() ) ;;
dev_file .close( ) ;
}
else
error_message = String::ucompose( _("Error trying to open %1"), partition .get_path() ) ;
if ( ! output .empty() ) //append error messages if any
operationdetail .get_last_child() .get_last_child() .add_child( OperationDetail( output, STATUS_NONE, FONT_ITALIC ) ) ; bool succes = true ;
if ( ! error_message .empty() )
if ( ! error .empty() ) {
operationdetail .get_last_child() .get_last_child() .add_child( OperationDetail( error, STATUS_NONE, FONT_ITALIC ) ) ; succes = false ;
operationdetail .get_last_child() .add_child( OperationDetail( error_message, STATUS_NONE, FONT_ITALIC ) ) ;
}
operationdetail .get_last_child() .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ; operationdetail .get_last_child() .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ;
return succes ; return succes ;

View File

@ -157,7 +157,7 @@ Glib::ustring Utils::get_filesystem_software( FILESYSTEM filesystem )
case FS_HFSPLUS : return "hfsprogs" ; case FS_HFSPLUS : return "hfsprogs" ;
case FS_JFS : return "jfsutils" ; case FS_JFS : return "jfsutils" ;
case FS_LINUX_SWAP : return "util-linux" ; case FS_LINUX_SWAP : return "util-linux" ;
case FS_NTFS : return "ntfsprogs, xxd, dd" ; case FS_NTFS : return "ntfsprogs" ;
case FS_REISER4 : return "reiser4progs" ; case FS_REISER4 : return "reiser4progs" ;
case FS_REISERFS : return "reiserfsprogs" ; case FS_REISERFS : return "reiserfsprogs" ;
case FS_UFS : return "" ; case FS_UFS : return "" ;

View File

@ -49,18 +49,11 @@ FS ntfs::get_filesystem_support()
fs .shrink = GParted::FS::EXTERNAL ; fs .shrink = GParted::FS::EXTERNAL ;
} }
//Command xxd used with dd to update NTFS boot sector after move or paste.
// See GParted_Core::update_bootsector().
//we need ntfsresize to set correct used/unused after cloning //we need ntfsresize to set correct used/unused after cloning
if ( ! Glib::find_program_in_path( "ntfsclone" ) .empty() && if ( ! Glib::find_program_in_path( "ntfsclone" ) .empty() )
! Glib::find_program_in_path( "xxd" ) .empty() &&
! Glib::find_program_in_path( "dd" ) .empty() )
fs .copy = GParted::FS::EXTERNAL ; fs .copy = GParted::FS::EXTERNAL ;
if ( fs .check && if ( fs .check )
! Glib::find_program_in_path( "xxd" ) .empty() &&
! Glib::find_program_in_path( "dd" ) .empty() )
fs .move = GParted::FS::GPARTED ; fs .move = GParted::FS::GPARTED ;
return fs ; return fs ;