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
    b4d9c9eeb5

[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
This commit is contained in:
Mike Fleetwood 2021-02-10 14:53:08 +00:00 committed by Curtis Gedak
parent 57507e21e2
commit b7c9b3e5a6
2 changed files with 65 additions and 0 deletions

View File

@ -35,7 +35,13 @@ public:
bool create(const Partition& new_partition, OperationDetail& operationdetail); bool create(const Partition& new_partition, OperationDetail& operationdetail);
void read_label(Partition& partition); void read_label(Partition& partition);
bool write_label(const Partition& partition, OperationDetail& operationdetail); 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); bool check_repair(const Partition& partition, OperationDetail& operationdetail);
private:
Glib::ustring serial_to_blkid_uuid(const Glib::ustring& serial);
Glib::ustring random_serial();
}; };

View File

@ -51,6 +51,15 @@ FS exfat::get_filesystem_support()
{ {
fs.read_label = FS::EXTERNAL; fs.read_label = FS::EXTERNAL;
fs.write_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()) 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) bool exfat::check_repair(const Partition& partition, OperationDetail& operationdetail)
{ {
return ! execute_command("fsck.exfat -v " + Glib::shell_quote(partition.get_path()), 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 } //GParted