Add exFAT file system usage reporting (!67)
exfatprogs 1.1.0 released 2021-02-09 [1] has gained support for
reporting file system usage [2][3] so add that capability to GParted.
It works like this:
# dump.exfat /dev/sdb1 | egrep 'Volume Length\(sectors\):|Sector Size Bits:|Sector per Cluster bits:|Free Clusters:'
Volume Length(sectors): 524288
Sector Size Bits: 9
Sector per Cluster bits: 3
Free Clusters: 23585
Unfortunately dump.exfat returns a non-zero status on success so that
can't be used to check for failure:
# dump.exfat /dev/sdb1
exfatprogs version : 1.1.0
-------------- Dump Boot sector region --------------
Volume Length(sectors): 524288
...
# echo $?
192
dump.exfat only writes errors to stderr, so use this to identify failure:
# dump.exfat /dev/sdb1 1> /dev/null
# echo $?
192
# dump.exfat /dev/zero 1> /dev/null
invalid block device size(/dev/zero)
bogus sector size bits : 0
# echo $?
234
[1] exfatprogs-1.1.0 version released
http://github.com/exfaoprogs/exfatprogs/releases/tag/1.1.0
[2] [feature request] File system usage reporting
https://github.com/exfatprogs/exfatprogs/issues/139
[3] exfatprogs: add dump.exfat
7ce9b2336b
Closes !67 - Add support for reading exFAT usage and updating the UUID
This commit is contained in:
parent
7c9a7cb297
commit
57507e21e2
|
@ -31,6 +31,7 @@ class exfat : public FileSystem
|
|||
{
|
||||
public:
|
||||
FS get_filesystem_support();
|
||||
void set_used_sectors(Partition& partition);
|
||||
bool create(const Partition& new_partition, OperationDetail& operationdetail);
|
||||
void read_label(Partition& partition);
|
||||
bool write_label(const Partition& partition, OperationDetail& operationdetail);
|
||||
|
|
67
src/exfat.cc
67
src/exfat.cc
|
@ -37,6 +37,9 @@ FS exfat::get_filesystem_support()
|
|||
fs .move = FS::GPARTED ;
|
||||
fs .online_read = FS::GPARTED ;
|
||||
|
||||
if (! Glib::find_program_in_path("dump.exfat").empty())
|
||||
fs.read = FS::EXTERNAL;
|
||||
|
||||
if (! Glib::find_program_in_path("mkfs.exfat").empty())
|
||||
{
|
||||
Utils::execute_command("mkfs.exfat -V", output, error, true);
|
||||
|
@ -61,6 +64,70 @@ FS exfat::get_filesystem_support()
|
|||
}
|
||||
|
||||
|
||||
void exfat::set_used_sectors(Partition& partition)
|
||||
{
|
||||
Utils::execute_command("dump.exfat " + Glib::shell_quote(partition.get_path()), output, error, true);
|
||||
// dump.exfat returns non-zero status for both success and failure. Instead use
|
||||
// non-empty stderr to identify failure.
|
||||
if (! error.empty())
|
||||
{
|
||||
if (! output.empty())
|
||||
partition.push_back_message(output);
|
||||
if (! error.empty())
|
||||
partition.push_back_message(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Example output (lines of interest only):
|
||||
// $ dump.exfat /dev/sdb1
|
||||
// Volume Length(sectors): 524288
|
||||
// Sector Size Bits: 9
|
||||
// Sector per Cluster bits: 3
|
||||
// Free Clusters: 23585
|
||||
//
|
||||
// "exFAT file system specification"
|
||||
// https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification
|
||||
// Section 3.1.5 VolumeLength field
|
||||
// Section 3.1.14 BytesPerSectorShift field
|
||||
// Section 3.1.15 SectorsPerClusterShift field
|
||||
|
||||
// FS size in [FS] sectors
|
||||
long long volume_length = -1;
|
||||
Glib::ustring::size_type index = output.find("Volume Length(sectors):");
|
||||
if (index < output.length())
|
||||
sscanf(output.substr(index).c_str(), "Volume Length(sectors): %lld", &volume_length);
|
||||
|
||||
// FS sector size = 2^(bytes_per_sector_shift)
|
||||
long long bytes_per_sector_shift = -1;
|
||||
index = output.find("Sector Size Bits:");
|
||||
if (index < output.length())
|
||||
sscanf(output.substr(index).c_str(), "Sector Size Bits: %lld", &bytes_per_sector_shift);
|
||||
|
||||
// Cluster size = sector_size * 2^(sectors_per_cluster_shift)
|
||||
long long sectors_per_cluster_shift = -1;
|
||||
index = output.find("Sector per Cluster bits:");
|
||||
if (index < output.length())
|
||||
sscanf(output.substr(index).c_str(), "Sector per Cluster bits: %lld", §ors_per_cluster_shift);
|
||||
|
||||
// Free clusters
|
||||
long long free_clusters = -1;
|
||||
index = output.find("Free Clusters:");
|
||||
if (index < output.length())
|
||||
sscanf(output.substr(index).c_str(), "Free Clusters: %lld", &free_clusters);
|
||||
|
||||
if ( volume_length > -1 && bytes_per_sector_shift > -1 &&
|
||||
sectors_per_cluster_shift > -1 && free_clusters > -1 )
|
||||
{
|
||||
Byte_Value sector_size = 1 << bytes_per_sector_shift;
|
||||
Byte_Value cluster_size = sector_size * (1 << sectors_per_cluster_shift);
|
||||
Sector fs_free = free_clusters * cluster_size / partition.sector_size;
|
||||
Sector fs_size = volume_length * sector_size / partition.sector_size;
|
||||
partition.set_sector_usage(fs_size, fs_free);
|
||||
partition.fs_block_size = cluster_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool exfat::create(const Partition& new_partition, OperationDetail& operationdetail)
|
||||
{
|
||||
return ! execute_command("mkfs.exfat -L " + Glib::shell_quote(new_partition.get_filesystem_label()) +
|
||||
|
|
Loading…
Reference in New Issue