[gparted] Display device serial numbers (#751251)



commit 4b72ecd44eba71b055f939fa5eff4572bb480ad9
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Mon Jun 22 14:08:02 2015 +0100

    Display device serial numbers (#751251)
    
    Run "hdparm -I /dev/DISK" to get the hard drive serial number of
    every device which has one and display it in the Device Information.
    The displayed value can either be the actual serial number, "none" or
    blank.  "none" means the device doesn't have a hard drive serial number,
    such as for Linux software RAID arrays, BIOS fake RAID arrays or USB
    flash drives.  Blank means something went wrong getting the serial
    number.  Either it couldn't be found in the hdparm output or the hdparm
    command wasn't installed.
    
    Example real hard drive:
        # hdparm -I /dev/sda
        ...
        ATA device, with non-removable media
                Model Number:       SAMSUNG HM500JI
                Serial Number:      S1WFJDSZ123732
        ...
    
    Example Linux software RAID array:
        # hdparm -I /dev/md127
    
        /dev/md127:
         HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device
    
    On my desktop with 4 internal hard drives 2 Linux software RAID arrays
    on those hard drives, 2 USB flash drives and 1 USB hard drive attached,
    running hdparm 9 times added 0.07 seconds to the device refresh time.
    
    Bug 751251 - Show serial number in device information

 README                 |    1 +
 include/Device.h       |    1 +
 include/GParted_Core.h |    1 +
 src/Device.cc          |    4 +++-
 src/GParted_Core.cc    |   35 +++++++++++++++++++++++++++++++++++
 src/Win_GParted.cc     |    9 ++++++++-
 6 files changed, 49 insertions(+), 2 deletions(-)
---
diff --git a/README b/README
index d6be5a2..fe20249 100644
--- a/README
+++ b/README
@@ -243,6 +243,7 @@ Several more commands are optionally used by GParted if found on the system.
 These commands include:
 
    blkid         - used to read volume labels and detect ext4 file systems
+   hdparm        - used to query disk device serial numbers
    vol_id        - used to read volume labels
    udisks        - used to prevent automounting of file systems
    devkit-disks  - used to prevent automounting of file systems
diff --git a/include/Device.h b/include/Device.h
index 3184058..7935a96 100644
--- a/include/Device.h
+++ b/include/Device.h
@@ -50,6 +50,7 @@ public:
        Sector cylinders ;
        Sector cylsize ;
        Glib::ustring model;
+       Glib::ustring serial_number;
        Glib::ustring disktype;
        int sector_size ;
        int max_prims ;
diff --git a/include/GParted_Core.h b/include/GParted_Core.h
index 8a59685..d8ec507 100644
--- a/include/GParted_Core.h
+++ b/include/GParted_Core.h
@@ -78,6 +78,7 @@ private:
        static bool have_rootfs_dev( std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) ;
        static void read_mountpoints_from_mount_command( std::map< Glib::ustring, std::vector<Glib::ustring> 
& map ) ;
        static Glib::ustring get_partition_path( PedPartition * lp_partition );
+       void set_device_serial_number( Device & device );
        void set_device_partitions( Device & device, PedDevice* lp_device, PedDisk* lp_disk ) ;
        void set_device_one_partition( Device & device, PedDevice * lp_device, FILESYSTEM fstype,
                                       std::vector<Glib::ustring> & messages );
diff --git a/src/Device.cc b/src/Device.cc
index 933aa16..96a79dd 100644
--- a/src/Device.cc
+++ b/src/Device.cc
@@ -31,7 +31,9 @@ void Device::Reset()
        partitions .clear() ;
        length = cylsize = 0 ;
        heads = sectors = cylinders = 0 ;
-       model = disktype = "" ;
+       model = "";
+       serial_number = "";
+       disktype = "";
        sector_size = max_prims = highest_busy = 0 ;
        readonly = false ;      
        max_partition_name_length = 0;
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index c84c691..2f8398f 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -275,6 +275,7 @@ void GParted_Core::set_devices_thread( std::vector<Device> * pdevices )
                        temp_device .sectors    =       lp_device ->bios_geom .sectors ;
                        temp_device .cylinders  =       lp_device ->bios_geom .cylinders ;
                        temp_device .cylsize    =       temp_device .heads * temp_device .sectors ; 
+                       set_device_serial_number( temp_device );
                
                        //make sure cylsize is at least 1 MiB
                        if ( temp_device .cylsize < (MEBIBYTE / temp_device .sector_size) )
@@ -1179,6 +1180,40 @@ Glib::ustring GParted_Core::get_partition_path( PedPartition * lp_partition )
        return partition_path ;
 }
 
+void GParted_Core::set_device_serial_number( Device & device )
+{
+       if ( Glib::find_program_in_path( "hdparm" ).empty() )
+               // Serial number left blank when the hdparm command is not installed.
+               return;
+
+       Glib::ustring output;
+       Glib::ustring error;
+       Utils::execute_command( "hdparm -I " + device.get_path(), output, error, true );
+       if ( ! error.empty() )
+       {
+               // hdparm reported an error message to stderr.  Assume it's a device
+               // without a hard drive serial number.
+               //
+               // Using hdparm -I to query Linux software RAID arrays and BIOS fake RAID
+               // arrays, both devices without their own hard drive serial numbers,
+               // produce this error:
+               //     HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device
+               //
+               // And querying USB flash drives, also a device type without their own
+               // hard drive serial numbers, generates this error:
+               //     SG_IO: bad/missing sense data, sb[]:  70 00 05 00 00 00 00 0a ...
+               device.serial_number = "none";
+       }
+       else
+       {
+               Glib::ustring serial_number = Utils::trim( Utils::regexp_label( output,
+                               "^[[:blank:]]*Serial Number:[[:blank:]]*(.*)[[:blank:]]*$" ) );
+               if ( ! serial_number.empty() )
+                       device.serial_number = serial_number;
+       }
+       // Otherwise serial number left blank when not found in the hdparm output.
+}
+
 /**
  * Fills the device.partitions member of device by scanning
  * all partitions
diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc
index 5d3b9e4..b2a7538 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -474,7 +474,13 @@ void Win_GParted::init_device_info()
                        Gtk::FILL ) ;
        device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
        table ->attach( * device_info .back(), 1, 2, top++, bottom++, Gtk::FILL ) ;
-       
+
+       // Serial number
+       table->attach( *Utils::mk_label( " <b>" + static_cast<Glib::ustring>( _("Serial:") ) + "</b>" ),
+                      0, 1, top, bottom, Gtk::FILL );
+       device_info.push_back( Utils::mk_label( "", true, false, true ) );
+       table->attach( *device_info.back(), 1, 2, top++, bottom++, Gtk::FILL );
+
        //size
        table ->attach( * Utils::mk_label( " <b>" + static_cast<Glib::ustring>( _("Size:") ) + "</b>" ),
                        0, 1,
@@ -675,6 +681,7 @@ void Win_GParted::Fill_Label_Device_Info( bool clear )
                
                //global info...
                device_info[ t++ ] ->set_text( devices[ current_device ] .model ) ;
+               device_info[ t++ ] ->set_text( devices[current_device].serial_number );
                device_info[ t++ ] ->set_text( Utils::format_size( devices[ current_device ] .length, 
devices[ current_device ] .sector_size ) ) ;
                device_info[ t++ ] ->set_text( Glib::build_path( "\n", devices[ current_device ] .get_paths() 
) ) ;
                


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