Parse FS_Info cache into fields while loading (#767842)

FS_Info module caches the output from blkid as a single string and uses
regular expressions to find the line matching the requested block
special file name.  This is not compatible with using BlockSpecial
objects to represent block special files, and perform matching by major,
minor device number.  Therefore parse the blkid output into a vector of
structures containing the needed fields, ready for switching to
BlockSpecial objects in the following patch.

Interface to the module remains unchanged.

Bug 767842 - File system usage missing when tools report alternate block
             device names
This commit is contained in:
Mike Fleetwood 2016-07-07 13:11:44 +01:00 committed by Curtis Gedak
parent 8aa34f7baa
commit 23da3ab9a8
2 changed files with 137 additions and 88 deletions

View File

@ -17,11 +17,22 @@
#ifndef GPARTED_FS_INFO_H
#define GPARTED_FS_INFO_H
#include "../include/Utils.h"
#include <glibmm/ustring.h>
#include <vector>
namespace GParted
{
struct FS_Entry
{
Glib::ustring path;
Glib::ustring type;
Glib::ustring sec_type;
Glib::ustring uuid;
bool have_label;
Glib::ustring label;
};
class FS_Info
{
public:
@ -33,14 +44,16 @@ public:
Glib::ustring get_uuid( const Glib::ustring & path ) ;
Glib::ustring get_path_by_uuid( const Glib::ustring & uuid ) ;
Glib::ustring get_path_by_label( const Glib::ustring & label ) ;
private:
void load_fs_info_cache() ;
void set_commands_found() ;
Glib::ustring get_device_entry( const Glib::ustring & path ) ;
static void set_commands_found();
static void load_fs_info_cache();
static const FS_Entry & get_cache_entry_by_path( const Glib::ustring & path );
static bool fs_info_cache_initialized ;
static bool blkid_found ;
static bool need_blkid_vfat_cache_update_workaround;
static Glib::ustring fs_info_cache ;
static std::vector<FS_Entry> fs_info_cache;
};
}//GParted

View File

@ -15,6 +15,10 @@
*/
#include "../include/FS_Info.h"
#include "../include/Utils.h"
#include <glibmm/ustring.h>
#include <vector>
namespace GParted
{
@ -25,7 +29,20 @@ bool FS_Info::blkid_found = false ;
// Assume workaround is needed just in case determination fails and as
// it only costs a fraction of a second to run blkid command again.
bool FS_Info::need_blkid_vfat_cache_update_workaround = true;
Glib::ustring FS_Info::fs_info_cache = "";
// Vector of file system information.
// E.g.
// //path , type , sec_type, uuid , have_label, label
// [{"/dev/sda1" , "xfs" , "" , "f828ee8c-1e16-4ca9-b234-e4949dcd4bd1" , false , "" },
// {"/dev/sda2" , "LVM2_member", "" , "p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG", false , "" },
// {"/dev/block/8:2" , "LVM2_member", "" , "p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG", false , "" },
// {"/dev/mapper/centos-root", "xfs" , "" , "a195605d-22c1-422d-9213-1ed67f1eee46" , false , "" },
// {"/dev/mapper/centos-swap", "swap" , "" , "8d419cb6-c663-4db7-b91c-6bcef8418a4d" , false , "" },
// {"/dev/sdb1" , "ext3" , "ext2" , "f218c3b8-237e-4fbe-92c5-76623bba4062" , true , "test-ext3" },
// {"/dev/sdb2" , "vfat" , "msdos" , "9F87-1061" , true , "TEST-FAT16"},
// {"/dev/sdb3" , "" , "" , "" , false , "" }
// ]
std::vector<FS_Entry> FS_Info::fs_info_cache;
FS_Info::FS_Info()
{
@ -57,18 +74,73 @@ FS_Info::~FS_Info()
{
}
void FS_Info::load_fs_info_cache()
// Retrieve the file system type for the path
Glib::ustring FS_Info::get_fs_type( const Glib::ustring & path )
{
Glib::ustring output, error ;
if ( blkid_found )
const FS_Entry & fs_entry = get_cache_entry_by_path( path );
Glib::ustring fs_type = fs_entry.type;
Glib::ustring fs_sec_type = fs_entry.sec_type;
// If vfat, decide whether fat16 or fat32
if ( fs_type == "vfat" )
{
if ( ! Utils::execute_command( "blkid", output, error, true ) )
fs_info_cache = output ;
if ( need_blkid_vfat_cache_update_workaround )
{
// Blkid cache does not correctly add and remove SEC_TYPE when
// overwriting FAT16 and FAT32 file systems with each other, so
// prevents correct identification. Run blkid command again,
// bypassing the the cache to get the correct results.
Glib::ustring output;
Glib::ustring error;
if ( ! Utils::execute_command( "blkid -c /dev/null " + path, output, error, true ) )
fs_sec_type = Utils::regexp_label( output, " SEC_TYPE=\"([^\"]*)\"" );
}
if ( fs_sec_type == "msdos" )
fs_type = "fat16";
else
fs_info_cache = "" ;
fs_type = "fat32";
}
return fs_type;
}
// Retrieve the label and set found indicator for the path
Glib::ustring FS_Info::get_label( const Glib::ustring & path, bool & found )
{
const FS_Entry & fs_entry = get_cache_entry_by_path( path );
found = fs_entry.have_label;
return fs_entry.label;
}
// Retrieve the uuid given for the path
Glib::ustring FS_Info::get_uuid( const Glib::ustring & path )
{
const FS_Entry & fs_entry = get_cache_entry_by_path( path );
return fs_entry.uuid;
}
// Retrieve the path given the uuid
Glib::ustring FS_Info::get_path_by_uuid( const Glib::ustring & uuid )
{
for ( unsigned int i = 0 ; i < fs_info_cache.size() ; i ++ )
if ( uuid == fs_info_cache[i].uuid )
return fs_info_cache[i].path;
return "";
}
// Retrieve the path given the label
Glib::ustring FS_Info::get_path_by_label( const Glib::ustring & label )
{
for ( unsigned int i = 0 ; i < fs_info_cache.size() ; i ++ )
if ( label == fs_info_cache[i].label )
return fs_info_cache[i].path;
return "";
}
// Private methods
void FS_Info::set_commands_found()
{
//Set status of commands found
@ -92,92 +164,56 @@ void FS_Info::set_commands_found()
}
}
Glib::ustring FS_Info::get_device_entry( const Glib::ustring & path )
void FS_Info::load_fs_info_cache()
{
//Retrieve the line containing the device path
Glib::ustring regexp = "^" + path + ":([^\n]*)$" ;
Glib::ustring entry = Utils::regexp_label( fs_info_cache, regexp ) ;
return entry;
}
fs_info_cache.clear();
Glib::ustring FS_Info::get_fs_type( const Glib::ustring & path )
{
Glib::ustring fs_type = "" ;
Glib::ustring fs_sec_type = "" ;
//Retrieve the line containing the device path
Glib::ustring dev_path_line = get_device_entry( path ) ;
//Retrieve TYPE
fs_type = Utils::regexp_label( dev_path_line, " TYPE=\"([^\"]*)\"" );
fs_sec_type = Utils::regexp_label( dev_path_line, " SEC_TYPE=\"([^\"]*)\"" );
//If vfat, decide whether fat16 or fat32
Glib::ustring output, error;
if ( fs_type == "vfat" )
// Parse blkid output line by line extracting fields mandatory field path and
// optional fields: type, sec_type, uuid, label.
// Example output:
// /dev/sda1: UUID="f828ee8c-1e16-4ca9-b234-e4949dcd4bd1" TYPE="xfs"
// /dev/sda2: UUID="p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG" TYPE="LVM2_member"
// /dev/block/8:2: UUID="p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG" TYPE="LVM2_member"
// /dev/mapper/centos-root: UUID="a195605d-22c1-422d-9213-1ed67f1eee46" TYPE="xfs"
// /dev/mapper/centos-swap: UUID="8d419cb6-c663-4db7-b91c-6bcef8418a4d" TYPE="swap"
// /dev/sdb1: LABEL="test-ext3" UUID="f218c3b8-237e-4fbe-92c5-76623bba4062" SEC_TYPE="ext2" TYPE="ext3" PARTUUID="71b3e059-30c5-492e-a526-9251dff7bbeb"
// /dev/sdb2: SEC_TYPE="msdos" LABEL="TEST-FAT16" UUID="9F87-1061" TYPE="vfat" PARTUUID="9d07ad9a-d468-428f-9bfd-724f5efae4fb"
// /dev/sdb3: PARTUUID="bb8438e1-d9f1-45d3-9888-e990b598900d"
Glib::ustring output;
Glib::ustring error;
if ( blkid_found &&
! Utils::execute_command( "blkid", output, error, true ) )
{
if ( need_blkid_vfat_cache_update_workaround )
std::vector<Glib::ustring> lines;
Utils::split( output, lines, "\n" );
for ( unsigned int i = 0 ; i < lines.size() ; i ++ )
{
// Blkid cache does not correctly add and remove SEC_TYPE when
// overwriting FAT16 and FAT32 file systems with each other, so
// prevents correct identification. Run blkid command again,
// bypassing the the cache to get the correct results.
if ( ! Utils::execute_command( "blkid -c /dev/null " + path, output, error, true ) )
fs_sec_type = Utils::regexp_label( output, " SEC_TYPE=\"([^\"]*)\"" );
FS_Entry fs_entry = {"", "", "", "", false, ""};
fs_entry.path = Utils::regexp_label( lines[i], "^(.*): " );
if ( fs_entry.path.length() > 0 )
{
fs_entry.type = Utils::regexp_label( lines[i], " TYPE=\"([^\"]*)\"" );
fs_entry.sec_type = Utils::regexp_label( lines[i], " SEC_TYPE=\"([^\"]*)\"" );
fs_entry.uuid = Utils::regexp_label( lines[i], " UUID=\"([^\"]*)\"" );
if ( lines[i].find( " LABEL=\"" ) != Glib::ustring::npos )
{
fs_entry.have_label = true;
fs_entry.label = Utils::regexp_label( lines[i], " LABEL=\"([^\"]*)\"" );
}
fs_info_cache.push_back( fs_entry );
}
}
if ( fs_sec_type == "msdos" )
fs_type = "fat16" ;
else
fs_type = "fat32" ;
}
return fs_type ;
}
Glib::ustring FS_Info::get_label( const Glib::ustring & path, bool & found )
const FS_Entry & FS_Info::get_cache_entry_by_path( const Glib::ustring & path )
{
Glib::ustring label = "" ;
found = false ;
for ( unsigned int i = 0 ; i < fs_info_cache.size() ; i ++ )
if ( path == fs_info_cache[i].path )
return fs_info_cache[i];
//Retrieve the line containing the device path
Glib::ustring temp = get_device_entry( path ) ;
//Set indicator if LABEL found
if ( Utils::regexp_label( temp, "( LABEL=\")") != "" )
found = true ;
//Retrieve LABEL
label = Utils::regexp_label( temp, " LABEL=\"([^\"]*)\"" );
return label ;
}
Glib::ustring FS_Info::get_uuid( const Glib::ustring & path )
{
//Retrieve the line containing the device path
Glib::ustring temp = get_device_entry( path ) ;
//Retrieve the UUID
Glib::ustring uuid = Utils::regexp_label( temp, " UUID=\"([^\"]*)\"" );
return uuid ;
}
Glib::ustring FS_Info::get_path_by_uuid( const Glib::ustring & uuid )
{
//Retrieve the path given the uuid
Glib::ustring regexp = "^([^:]*):.* UUID=\"" + uuid + "\".*$";
Glib::ustring path = Utils::regexp_label( fs_info_cache, regexp ) ;
return path ;
}
Glib::ustring FS_Info::get_path_by_label( const Glib::ustring & label )
{
//Retrieve the path given the label
Glib::ustring regexp = "^([^:]*):.* LABEL=\"" + label + "\".*$";
Glib::ustring path = Utils::regexp_label( fs_info_cache, regexp ) ;
return path ;
static FS_Entry not_found = {"", "", "", "", false, ""};
return not_found;
}
}//GParted