[gparted] Use btrfs filesystem label to read the FS label (!105)



commit ee823b0be40e7074bf1607a9593d4af8c68d1268
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Fri Jul 22 13:13:28 2022 +0100

    Use btrfs filesystem label to read the FS label (!105)
    
    Until now GParted has run 'btrfs filesystem show' to read the file
    system label.  This has a number of issues and limitations:
    1.  Doesn't work on a file system image so can't be unit tested in the
        GitLab CI test job where a loop device can't be created [1] or as a
        non-root user.
    2.  Reported failed exit status 1 when successfully showing a mounted
        btrfs, but only when using btrfs-progs v3.14 and 3.14.1 [2][3].
    3.  Failed to distinguish between label set to "none" and no label
        reported as none, but only when mounted and with btrfs-progs v3.12
        [3].
    
    As non-root user run btrfs read label unit test:
        $ tests/test_SupportedFileSystems --gtest_filter='*CreateAndReadLabel/btrfs'
        ...
        [ RUN      ] My/SupportedFileSystemsTest.CreateAndReadLabel/btrfs
        test_SupportedFileSystem.cc:539: Skip test.  Not root to be able to create required loop device
        [       OK ] My/SupportedFileSystemsTest.CreateAndReadLabel/btrfs (0 ms)
    
    Even as root, 'btrfs filesystem show' fails to work on an image file:
        # truncate -s 256M /tmp/test.img
        # mkfs.btrfs /tmp/test.img
        # btrfs filesystem show /tmp/test.img
        ERROR: not a valid btrfs filesystem: /tmp/test.img
        # echo $?
        1
        # rm /tmp/test.img
    
    Instead use 'btrfs filesystem label' to read the label.  It also works
    on an image file, the exit status is informative and output is just the
    label followed by a new line character [4] so very simple to parse.
    
    Error case:
        $ truncate -s 256M /tmp/test.img
        $ btrfs filesystem label /tmp/test.img
        No valid Btrfs found on /tmp/test.img
        $ echo $?
        255
    
    No label case:
        $ mkfs.btrfs /tmp/test.img
        $ btrfs filesystem label /tmp/test.img
    
        $ echo $?
        0
        $ btrfs filesystem label /tmp/test.img | hexdump -C
        00000000  0a                                                |.|
        00000001
    
    Label case:
        $ mkfs.btrfs -L 'label with
        > new line and trailing space ' /tmp/test.img
        $ btrfs filesystem label /tmp/test.img
        label with
        new line and trailing space
        $ echo $?
        0
        $ btrfs filesystem label /tmp/test.img | hexdump -C
        00000000  6c 61 62 65 6c 20 77 69  74 68 0a 6e 65 77 20 6c  |label with.new l|
        00000010  69 6e 65 20 61 6e 64 20  74 72 61 69 6c 69 6e 67  |ine and trailing|
        00000020  20 73 70 61 63 65 20 0a                           | space .|
        00000028
    
    Run 'btrfs filesystem label' always passing the block device as this
    works for both mounted and unmounted file systems.  This is in
    contrast to writing the label for a mounted btrfs where the mount
    mount must be used [5].
        # mkfs.btrfs -L 'test label' /dev/sdb1
        # btrfs filesystem label /dev/sdb1
        test label
        # mount /dev/sdb1 /mnt/1
        # btrfs filesystem label /dev/sdb1
        test label
    
    [1] 07ad43a1072a104543bfc45bc5d357f3d8f8d6f6
        Create loop devices for BTRFS read file system interface tests (!49)
    [2] 82c6265fa5599bd5acfe33abecaa99de150d71e9
        Update parsing of btrfs filesystem show for the UUID (#733601)
    [3] eca732fb0cefe35db76a7ac96145e2004e8eed08
        Update parsing of btrfs filesystem show for the label (#733601)
    [4] btrfs-progs v3.14, cmd_label() function
        
https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git/tree/cmds-filesystem.c?h=v3.14#n984
    [5] eb034b17597713bbc08dd3ab90444eaa2c0e7ff5
        Add labelling of mounted btrfs (#163)
    
    Closes !105 - Update used btrfs file system commands, new minimum is
                  btrfs-progs 4.5

 src/btrfs.cc | 47 +++++++++++++++++++----------------------------
 1 file changed, 19 insertions(+), 28 deletions(-)
---
diff --git a/src/btrfs.cc b/src/btrfs.cc
index 99461347..e8ad9862 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -20,8 +20,10 @@
 #include "FileSystem.h"
 #include "Mount_Info.h"
 #include "Partition.h"
+#include "Utils.h"
 
 #include <ctype.h>
+#include <glibmm/ustring.h>
 #include <glibmm/miscutils.h>
 #include <glibmm/shell.h>
 
@@ -341,40 +343,29 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
        return success ;
 }
 
-void btrfs::read_label( Partition & partition )
-{
-       Utils::execute_command("btrfs filesystem show " + Glib::shell_quote(partition.get_path()),
-                              output, error, true);
-       //In many cases the exit status doesn't reflect valid output or an error condition
-       //  so rely on parsing the output to determine success.
 
-       if ( output .compare( 0, 18, "Label: none  uuid:" ) == 0 )
+void btrfs::read_label(Partition& partition)
+{
+       exit_status = Utils::execute_command("btrfs filesystem label " + 
Glib::shell_quote(partition.get_path()),
+                                            output, error, true);
+       if (exit_status != 0)
        {
-               //Indistinguishable cases of either no label or the label is actually set
-               //  to "none".  Assume no label case.
-               partition.set_filesystem_label( "" );
+               if (! output.empty())
+                       partition.push_back_message(output);
+               if (! error.empty())
+                       partition.push_back_message(error);
+               return;
        }
-       else
-       {
-               // Try matching a label enclosed in single quotes, then without quotes, to
-               // handle reporting of mounted file systems by old btrfs-progs 3.12.
-               Glib::ustring label = Utils::regexp_label( output, "^Label: '(.*)'  uuid:" ) ;
-               if ( label .empty() )
-                       label = Utils::regexp_label( output, "^Label: (.*)  uuid:" ) ;
-
-               if ( ! label .empty() )
-                       partition.set_filesystem_label( label );
-               else
-               {
-                       if ( ! output .empty() )
-                               partition.push_back_message( output );
 
-                       if ( ! error .empty() )
-                               partition.push_back_message( error );
-               }
-       }
+       // Strip terminating new line from output.
+       size_t len = output.length();
+       if (len > 0 && output[len-1] == '\n')
+               output.resize(len-1);
+
+       partition.set_filesystem_label(output);
 }
 
+
 void btrfs::read_uuid( Partition & partition )
 {
        Utils::execute_command("btrfs filesystem show " + Glib::shell_quote(partition.get_path()),


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