[gparted] Refactor GParted internal file system signature detection (#741430)



commit cb645b16cf6cb6f0d04b693440e88c8d994aac52
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Tue Dec 23 18:22:04 2014 +0000

    Refactor GParted internal file system signature detection (#741430)
    
    Refactor GParted internal file system signature detection to remove code
    duplication.  There were 5 separate copies of code to: allocate a
    buffer, open, read and close the device, free the buffer and compare the
    signature.
    
    Bug 741430 - GParted cannot recognise LVM signature on unpartitioned
                 drive

 include/GParted_Core.h |    1 +
 src/GParted_Core.cc    |  195 ++++++++++++++++++++---------------------------
 2 files changed, 84 insertions(+), 112 deletions(-)
---
diff --git a/include/GParted_Core.h b/include/GParted_Core.h
index 819cfdf..1f497c3 100644
--- a/include/GParted_Core.h
+++ b/include/GParted_Core.h
@@ -78,6 +78,7 @@ private:
        static void read_mountpoints_from_mount_command( std::map< Glib::ustring, std::vector<Glib::ustring> 
& map ) ;
        Glib::ustring get_partition_path( PedPartition * lp_partition ) ;
        void set_device_partitions( Device & device, PedDevice* lp_device, PedDisk* lp_disk ) ;
+       static FILESYSTEM recognise_filesystem_signature( PedDevice * lp_device, PedPartition * lp_partition 
);
        GParted::FILESYSTEM get_filesystem( PedDevice* lp_device, PedPartition* lp_partition,
                                            std::vector<Glib::ustring>& messages ) ;
        void read_label( Partition & partition ) ;
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 650960c..dee3d34 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -1245,11 +1245,86 @@ void GParted_Core::set_device_partitions( Device & device, PedDevice* lp_device,
        insert_unallocated( device .get_path(), device .partitions, 0, device .length -1, device 
.sector_size, false ) ; 
 }
 
+// GParted simple internal file system signature detection.  Use sparingly.  Only when
+// (old versions of) blkid and libparted don't recognise a signature.
+FILESYSTEM GParted_Core::recognise_filesystem_signature( PedDevice * lp_device, PedPartition * lp_partition )
+{
+       char magic1[16];  // Big enough for largest signatures[].sig1 or sig2
+       char magic2[16];
+       FILESYSTEM fstype = FS_UNKNOWN;
+
+       char * buf = static_cast<char *>( malloc( lp_device->sector_size ) );
+       if ( ! buf )
+               return FS_UNKNOWN;
+
+       if ( ! ped_device_open( lp_device ) )
+       {
+               free( buf );
+               return FS_UNKNOWN;
+       }
+
+       struct {
+               Byte_Value   offset1;
+               const char * sig1;
+               Byte_Value   offset2;
+               const char * sig2;
+               FILESYSTEM   fstype;
+       } signatures[] = {
+               //offset1, sig1          , offset2, sig2  , fstype
+               { 65536LL, "ReIsEr4"     ,     0LL, NULL  , FS_REISER4   },
+               {   512LL, "LABELONE"    ,   536LL, "LVM2", FS_LVM2_PV   },
+               {     0LL, "LUKS\xBA\xBE",     0LL, NULL  , FS_LUKS      },
+               { 65600LL, "_BHRfS_M"    ,     0LL, NULL  , FS_BTRFS     },
+               {     3LL, "-FVE-FS-"    ,     0LL, NULL  , FS_BITLOCKER }
+       };
+       // Reference:
+       //   Detecting BitLocker
+       //   http://blogs.msdn.com/b/si_team/archive/2006/10/26/detecting-bitlocker.aspx
+       // Consider validation of BIOS Parameter Block fields as unnecessary for
+       // simple recognition only of BitLocker.
+
+       for ( unsigned int i = 0 ; i < sizeof( signatures ) / sizeof( signatures[0] ) ; i ++ )
+       {
+               const size_t len1 = std::min( ( signatures[i].sig1 == NULL ) ? 0U : strlen( 
signatures[i].sig1 ),
+                                             sizeof( magic1 ) );
+               const size_t len2 = std::min( ( signatures[i].sig2 == NULL ) ? 0U : strlen( 
signatures[i].sig2 ),
+                                             sizeof( magic2 ) );
+               // NOTE: From this point onwards signatures[].sig1 and .sig2 are treated
+               // as character buffers of known lengths len1 and len2, not NUL terminated
+               // strings.
+               if ( len1 == 0UL || ( signatures[i].sig2 != NULL && len2 == 0UL ) )
+                       continue;  // Don't allow 0 length signatures to match
+
+               memset( buf, 0, lp_device->sector_size );
+               if ( ped_geometry_read( &lp_partition->geom, buf, signatures[i].offset1 / 
lp_device->sector_size, 1 ) != 0 )
+               {
+                       memcpy( magic1, buf + signatures[i].offset1 % lp_device->sector_size, len1 );
+
+                       // WARNING: This assumes offset2 is in the same sector as offset1
+                       if ( signatures[i].sig2 != NULL )
+                       {
+                               memcpy( magic2, buf + signatures[i].offset2 % lp_device->sector_size, len2 );
+                       }
+
+                       if ( memcmp( magic1, signatures[i].sig1, len1 ) == 0     &&
+                            ( signatures[i].sig2 != NULL ||
+                              memcmp( magic2, signatures[i].sig2, len2 ) == 0 )     )
+                       {
+                               fstype = signatures[i].fstype;
+                               break;
+                       }
+               }
+       }
+
+       ped_device_close( lp_device );
+       free( buf );
+
+       return fstype;
+}
+
 GParted::FILESYSTEM GParted_Core::get_filesystem( PedDevice* lp_device, PedPartition* lp_partition,
                                                   std::vector<Glib::ustring>& messages )
 {
-       char magic1[16] = "";
-       char magic2[16] = "";
        FS_Info fs_info ;
        Glib::ustring fs_type = "" ;
        static Glib::ustring luks_unsupported = _("Linux Unified Key Setup encryption is not yet supported.");
@@ -1336,118 +1411,14 @@ GParted::FILESYSTEM GParted_Core::get_filesystem( PedDevice* lp_device, PedParti
                        return FS_REFS;
        }
 
-
-
-       //other file systems libparted couldn't detect (i've send patches for these file systems to the 
parted guys)
-       // - no patches sent to parted for lvm2, or luks
-
-       //reiser4
-       char * buf = static_cast<char *>( malloc( lp_device->sector_size ) );
-       if ( buf )
-       {
-               ped_device_open( lp_device );
-               ped_geometry_read( & lp_partition ->geom
-                                , buf
-                                , (65536 / lp_device ->sector_size) 
-                                , 1
-                                ) ;
-               memcpy(magic1, buf+0, 7) ; //set binary magic data
-               ped_device_close( lp_device );
-               free( buf ) ;
-
-               if ( 0 == memcmp( magic1, "ReIsEr4", 7 ) )
-                       return GParted::FS_REISER4 ;
-       }
-
-       //lvm2
-       //NOTE: lvm2 is not a file system but we do wish to recognize the Physical Volume
-       buf = static_cast<char *>( malloc( lp_device ->sector_size ) ) ;
-       if ( buf )
-       {
-               ped_device_open( lp_device );
-               if ( lp_device ->sector_size == 512 )
-               {
-                       ped_geometry_read( & lp_partition ->geom, buf, 1, 1 ) ;
-                       memcpy(magic1, buf+ 0, 8) ; // set binary magic data
-                       memcpy(magic2, buf+24, 4) ; // set binary magic data
-               }
-               else
-               {
-                       ped_geometry_read( & lp_partition ->geom, buf, 0, 1 ) ;
-                       memcpy(magic1, buf+ 0+512, 8) ; // set binary magic data
-                       memcpy(magic2, buf+24+512, 4) ; // set binary magic data
-               }
-               ped_device_close( lp_device );
-               free( buf ) ;
-
-               if (    0 == memcmp( magic1, "LABELONE", 8 )
-                    && 0 == memcmp( magic2, "LVM2", 4 ) )
-               {
-                       return GParted::FS_LVM2_PV ;
-               }
-       }
-
-       //LUKS encryption
-       buf = static_cast<char *>( malloc( lp_device->sector_size ) );
-       if ( buf )
+       // Fallback to GParted simple internal file system detection
+       if ( lp_partition )
        {
-               ped_device_open( lp_device );
-               ped_geometry_read( & lp_partition->geom, buf, 0, 1 );
-               memcpy(magic1, buf+0, 6);  // set binary magic data
-               ped_device_close( lp_device );
-               free( buf );
-
-               if ( 0 == memcmp( magic1 , "LUKS\xBA\xBE", 6 ) )
-               {
+               FILESYSTEM fstype = recognise_filesystem_signature( lp_device, lp_partition );
+               if ( fstype == FS_LUKS )
                        messages.push_back( luks_unsupported );
-                       return FS_LUKS;
-               }
-       }
-
-       //btrfs
-       const Sector BTRFS_SUPER_INFO_SIZE   = 4096 ;
-       const Sector BTRFS_SUPER_INFO_OFFSET = (64 * 1024) ;
-       const char* const BTRFS_SIGNATURE  = "_BHRfS_M" ;
-
-       char    buf_btrfs[BTRFS_SUPER_INFO_SIZE] ;
-
-       ped_device_open( lp_device ) ;
-       ped_geometry_read( & lp_partition ->geom
-                        , buf_btrfs
-                        , (BTRFS_SUPER_INFO_OFFSET / lp_device ->sector_size)
-                        , (BTRFS_SUPER_INFO_SIZE / lp_device ->sector_size)
-                        ) ;
-       memcpy(magic1, buf_btrfs+64, strlen(BTRFS_SIGNATURE) ) ;  //set binary magic data
-       ped_device_close( lp_device ) ;
-
-       if ( 0 == memcmp( magic1, BTRFS_SIGNATURE, strlen(BTRFS_SIGNATURE) ) )
-       {
-               return GParted::FS_BTRFS ;
-       }
-
-       //bitlocker
-       //  Detecting BitLocker
-       //  http://blogs.msdn.com/b/si_team/archive/2006/10/26/detecting-bitlocker.aspx
-       //  Validation of BIOS Parameter Block fields is unnecessary for recognition only
-       const size_t BITLOCKER_SIG_OFFSET = 3UL ;
-       const char * const BITLOCKER_SIGNATURE = "-FVE-FS-" ;
-       const size_t BITLOCKER_SIG_LEN = strlen( BITLOCKER_SIGNATURE ) ;
-       buf = static_cast<char *>( malloc( lp_device ->sector_size ) ) ;
-       if ( buf )
-       {
-               memset( buf, 0, lp_device ->sector_size ) ;
-               if ( ped_device_open( lp_device ) )
-               {
-                       if ( ped_geometry_read( & lp_partition ->geom, buf, 0, 1 ) != 0 )
-                       {
-                               memcpy( magic1, buf + BITLOCKER_SIG_OFFSET, BITLOCKER_SIG_LEN ) ;
-                       }
-                       ped_device_close( lp_device );
-               }
-               free( buf ) ;
-
-               if ( 0 == memcmp( magic1, BITLOCKER_SIGNATURE, BITLOCKER_SIG_LEN ) )
-                       return FS_BITLOCKER ;
+               if ( fstype != FS_UNKNOWN )
+                       return fstype;
        }
 
        //no file system found....


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