From dd8a57a8fec3abfa8b1b5399a73aa6a5845aed23 Mon Sep 17 00:00:00 2001 From: Curtis Gedak Date: Sat, 16 May 2009 12:15:14 -0600 Subject: [PATCH] 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 --- README | 2 +- src/GParted_Core.cc | 57 ++++++++++++++++++++++++++++++++++----------- src/Utils.cc | 2 +- src/ntfs.cc | 11 ++------- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/README b/README index 82e0ccb2..1be5a297 100644 --- a/README +++ b/README @@ -112,7 +112,7 @@ Optional packages include: hfsutils hfsprogs jfsutils - ntfsprogs - dd command, and xxd command from vim-common also required + ntfsprogs reiser4progs reiserfsprogs xfsprogs diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index dd714f32..c76deb6f 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -2565,37 +2565,66 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition ) bool GParted_Core::update_bootsector( const Partition & partition, OperationDetail & operationdetail ) { //only for ntfs atm... - //FIXME: 1) this should be done without relying on external commands - // 2) this should probably be done in the fsclasses... + //FIXME: this should probably be done in the fs classes... 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( - 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 ), partition .get_path() ) ) ) ; + //convert start sector to hex string std::stringstream ss ; ss << std::hex << partition .sector_start ; Glib::ustring hex = ss .str() ; - + //fill with zeros and reverse... hex .insert( 0, 8 - hex .length(), '0' ) ; Glib::ustring reversed_hex ; for ( int t = 6 ; t >= 0 ; t -=2 ) reversed_hex .append( hex .substr( t, 2 ) ) ; - Glib::ustring output, error, command ; - command = - "echo " + reversed_hex + " | xxd -r -p | dd conv=notrunc of=" + partition .get_path() + " bs=1 seek=28" ; + //convert reversed hex codes into ascii characters + char buf[4] ; + 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 ) ) ; - bool succes = ! Utils::execute_command( command, output, error ) ; + //write new Number of Hidden Sectors value into NTFS boot sector at offset 0x1C + 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() ) - operationdetail .get_last_child() .get_last_child() .add_child( OperationDetail( output, STATUS_NONE, FONT_ITALIC ) ) ; - - if ( ! error .empty() ) - operationdetail .get_last_child() .get_last_child() .add_child( OperationDetail( error, STATUS_NONE, FONT_ITALIC ) ) ; + //append error messages if any + bool succes = true ; + if ( ! error_message .empty() ) + { + 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 ) ; return succes ; diff --git a/src/Utils.cc b/src/Utils.cc index 750d3ec3..35d4a7f6 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -157,7 +157,7 @@ Glib::ustring Utils::get_filesystem_software( FILESYSTEM filesystem ) case FS_HFSPLUS : return "hfsprogs" ; case FS_JFS : return "jfsutils" ; 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_REISERFS : return "reiserfsprogs" ; case FS_UFS : return "" ; diff --git a/src/ntfs.cc b/src/ntfs.cc index 45037447..72fbace4 100644 --- a/src/ntfs.cc +++ b/src/ntfs.cc @@ -49,18 +49,11 @@ FS ntfs::get_filesystem_support() 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 - if ( ! Glib::find_program_in_path( "ntfsclone" ) .empty() && - ! Glib::find_program_in_path( "xxd" ) .empty() && - ! Glib::find_program_in_path( "dd" ) .empty() ) + if ( ! Glib::find_program_in_path( "ntfsclone" ) .empty() ) fs .copy = GParted::FS::EXTERNAL ; - if ( fs .check && - ! Glib::find_program_in_path( "xxd" ) .empty() && - ! Glib::find_program_in_path( "dd" ) .empty() ) + if ( fs .check ) fs .move = GParted::FS::GPARTED ; return fs ;