Fix reading FAT16/32 FS labels on Alpine Linux (!104)
Several of the FAT16/32 file system unit tests fail on Alpine Linux. In this commit we are just looking at the failure to read the label. The test fails like this: $ ./test_SupportedFileSystems --gtest_filter='*CreateAndReadLabel/fat16' ... [ RUN ] My/SupportedFileSystemsTest.CreateAndReadLabel/fat16 test_SupportedFileSystems.cc:551: Failure Expected equality of these values: fs_label Which is: "TEST_LABEL" m_partition.get_filesystem_label().c_str() Which is: "" test_SupportedFileSystems.cc:554: Failure Value of: m_partition.get_messages().empty() Actual: false Expected: true Partition messages: Mtools version 4.0.39, dated April 10th, 2022 Usage: mlabel [-vscVn] [-N serial] drive: [ FAILED ] My/SupportedFileSystemsTest.CreateAndReadLabel/fat16, where GetParam() = 13 (21 ms) The same error can be seen by using GParted to display a FAT16 or FAT32 file system on Alpine Linux. The Partition Information dialog displays this warning: Mtools version 4.0.39, dated April 10th, 2022 Usage: mlabel [-vscVn] [-N serial] drive: Reproduce this on the command line: # mkfs.fat -F 16 -v -I -n TEST_LABEL /dev/sdb1 # mlabel -s :: -i /dev/sdb1 Mtools version 4.0.39, dated April 10th, 2022 Usage: mlabel [-vscVn] [-N serial] drive: # echo $? 1 The mlabel.c source [1] uses getopt(3) to parse the command line arguments. musl libc's [2] getopt(3) must be strictly POSIX compliant [3][4] and stops reading options at the first non-option argument, '::' in this case. Move the non-option argument to the end of the command line and it works: # mlabel -s -i /dev/sdb1 :: Volume label is TEST_LABEL Where as GNU Libc's getopt(3) [5] says that by default it reorders argv eventually moving all non-option arguments to the end, hence why this has worked on every Linux distribution using GNU Libc. This can be broken on any Linux distribution using GNU Libc by enforcing strict POSIX behaviour from getopt(3). For example on Fedora 36: # mkfs.fat -F 16 -v -I -n TEST_LABEL /dev/sdb1 # export POSIXLY_CORRECT=1 # mlabel -s :: -i /dev/sdb1 Mtools version 4.0.39, dated April 10th, 2022 Usage: mlabel [-vscVn] [-N serial] drive: # echo $? 1 # mlabel -s -i /dev/sdb1 :: Hidden (2048) does not match sectors (63) Volume label is TEST_LABEL # echo $? 0 Fix by moving the non-option (image file drive specification) '::' to the end of the mlabel command line. [1] Mtools https://www.gnu.org/software/mtools/ [2] musl libc https://musl.libc.org/ "musl is an implementation of the C standard library built on top of the Linux system call API, including interfaces defined in the base language standard, POSIX, and widely agreed-upon extensions. " [3] POSIX.1-2017, Functions, getopt https://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html [4] getopt(3p) https://man7.org/linux/man-pages/man3/getopt.3p.html [5] getopt(3) https://www.man7.org/linux/man-pages/man3/getopt.3.html "By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end. Two other scanning modes are also implemented. If the first character of optstring is '+' or the environment variable POSIXLY_CORRECT is set, then option processing stops as soon as a nonoption argument is encountered. " Closes !104 - Add Alpine Linux CI jobs and resolve label and UUID issues with FAT16/32
This commit is contained in:
parent
407e0ac6e3
commit
a48b29ba19
|
@ -192,7 +192,7 @@ void fat16::set_used_sectors( Partition & partition )
|
|||
|
||||
void fat16::read_label(Partition& partition)
|
||||
{
|
||||
exit_status = Utils::execute_command("mlabel -s :: -i " + Glib::shell_quote(partition.get_path()),
|
||||
exit_status = Utils::execute_command("mlabel -s -i " + Glib::shell_quote(partition.get_path()) + " ::",
|
||||
output, error, true);
|
||||
if (exit_status != 0)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue