[gparted] Add support for updating the exFAT UUID (!67)



commit b7c9b3e5a61debeb3f3ad53b54598a73d372793e
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Wed Feb 10 14:53:08 2021 +0000

    Add support for updating the exFAT UUID (!67)
    
    Also with exfatprogs 1.1.0 [1], tune.exfat and exfatlabel gained the
    capability to report and set the exFAT Volume Serial Number [2][3][4].
    This is what blkid and therefore GParted reports as the UUID.
    
    Report serial number:
    
        # tune.exfat -i /dev/sdb1
        exfatprogs version : 1.1.0
        volume serial : 0x772ffe5d
        # echo $?
        0
    
        # blkid /dev/sdb1
        /dev/sdb1: LABEL="test exfat" UUID="772F-FE5D" TYPE="exfat" PTTYPE="dos"
    
    Set serial number:
    
        # tune.exfat -I 0xf96ef190 /dev/sdb1
        exfatprogs version : 1.1.0
        New volume serial : 0xf96ef190
        # echo $?
        0
    
    tune.exfat exists in earlier releases of exfatprogs so check it has the
    capability by searching for "Set volume serial" in the help output
    before enabling this capability.
    
        # tune.exfat
        exfatprogs version : 1.1.0
        Usage: tune.exfat
                -l | --print-label                    Print volume label
                -L | --set-label=label                Set volume label
                -i | --print-serial                   Print volume serial
                -L | --set-serial=value               Set volume serial
                -V | --version                        Show version
                -v | --verbose                        Print debug
                -h | --help                           Show help
    
    (Note the cut and paste error reporting the set volume serial flag as
    '-L' rather than actually '-S').
    
    [1] exfatprogs-1.1.0 version released
        http://github.com/exfaoprogs/exfatprogs/releases/tag/1.1.0
    
    [2] [tools][feature request] Allow To Change Volume Serial Number ("ID")
        #138
        https://github.com/exfatprogs/exfatprogs/issues/138
    
    [3] exfatlabel:add get/set volume serial option
        https://github.com/exfatprogs/exfatprogs/commit/b4d9c9eeb5c28b503e103e2c4ec22bc146446d9f
    
    [4] exFAT file system specification, 3.1.11 VolumeSerialNumber Field
        
https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification#3111-volumeserialnumber-field
    
    Closes !67 - Add support for reading exFAT usage and updating the UUID

 include/exfat.h |  6 ++++++
 src/exfat.cc    | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)
---
diff --git a/include/exfat.h b/include/exfat.h
index ea8b7794..20541d8d 100644
--- a/include/exfat.h
+++ b/include/exfat.h
@@ -35,7 +35,13 @@ public:
        bool create(const Partition& new_partition, OperationDetail& operationdetail);
        void read_label(Partition& partition);
        bool write_label(const Partition& partition, OperationDetail& operationdetail);
+       void read_uuid(Partition& partition);
+       bool write_uuid(const Partition& partition, OperationDetail& operationdetail);
        bool check_repair(const Partition& partition, OperationDetail& operationdetail);
+
+private:
+       Glib::ustring serial_to_blkid_uuid(const Glib::ustring& serial);
+       Glib::ustring random_serial();
 };
 
 
diff --git a/src/exfat.cc b/src/exfat.cc
index 4d82ff38..ada3bbbe 100644
--- a/src/exfat.cc
+++ b/src/exfat.cc
@@ -51,6 +51,15 @@ FS exfat::get_filesystem_support()
        {
                fs.read_label = FS::EXTERNAL;
                fs.write_label = FS::EXTERNAL;
+
+               // Get/set exFAT Volume Serial Number support was added to exfatprogs
+               // 1.1.0.  Check the help text for the feature before enabling.
+               Utils::execute_command("tune.exfat", output, error, true);
+               if (error.find("Set volume serial") < error.length())
+               {
+                       fs.read_uuid  = FS::EXTERNAL;
+                       fs.write_uuid  = FS::EXTERNAL;
+               }
        }
 
        if (! Glib::find_program_in_path("fsck.exfat").empty())
@@ -161,6 +170,31 @@ bool exfat::write_label(const Partition& partition, OperationDetail& operationde
 }
 
 
+void exfat::read_uuid(Partition& partition)
+{
+       exit_status = Utils::execute_command("tune.exfat -i " + Glib::shell_quote(partition.get_path()),
+                                            output, error, true);
+       if (exit_status != 0)
+       {
+               if (! output.empty())
+                       partition.push_back_message(output);
+               if (! output.empty())
+                       partition.push_back_message(error);
+               return;
+       }
+
+       partition.uuid = serial_to_blkid_uuid(
+                       Utils::regexp_label(output, "volume serial : (0x[[:xdigit:]][[:xdigit:]]*)"));
+}
+
+
+bool exfat::write_uuid(const Partition& partition, OperationDetail& operationdetail)
+{
+       return ! execute_command("tune.exfat -I " + random_serial() + " " + 
Glib::shell_quote(partition.get_path()),
+                                operationdetail, EXEC_CHECK_STATUS);
+}
+
+
 bool exfat::check_repair(const Partition& partition, OperationDetail& operationdetail)
 {
        return ! execute_command("fsck.exfat -v " + Glib::shell_quote(partition.get_path()),
@@ -168,4 +202,29 @@ bool exfat::check_repair(const Partition& partition, OperationDetail& operationd
 }
 
 
+// Private methods
+
+// Reformat exfat printed serial into the same format which blkid reports and GParted
+// displays to users.  Returns "" if source is not correctly formatted.
+// E.g. "0x772ffe5d" -> "772F-FE5D"
+Glib::ustring exfat::serial_to_blkid_uuid(const Glib::ustring& serial)
+{
+       Glib::ustring verified_serial = Utils::regexp_label(serial, "^(0x[[:xdigit:]][[:xdigit:]]*)$");
+       if (verified_serial.empty())
+               return verified_serial;
+
+       Glib::ustring canonical_uuid = verified_serial.substr(2, 4).uppercase() + "-" +
+                                      verified_serial.substr(6, 4).uppercase();
+       return canonical_uuid;
+}
+
+
+// Generate a random exfat serial.
+// E.g. -> "0x772ffe5d"
+Glib::ustring exfat::random_serial()
+{
+       return "0x" + Utils::generate_uuid().substr(0, 8);
+}
+
+
 } //GParted


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