[gparted] Add support for long UDF labels and check for old versions of mkudffs (#784533)



commit 861bc8df5d65c1df500161fc9904b0285773357c
Author: Pali Rohár <pali rohar gmail com>
Date:   Sun Jul 23 14:24:30 2017 +0200

    Add support for long UDF labels and check for old versions of mkudffs (#784533)
    
    UDF label is stored in the Logical Volume Identifier which has space for
    either 126 Latin1 or 63 UCS-2 characters.  For compatibility reasons
    with older versions of blkid, the possibly truncated UDF label is also
    stored in the Volume Identifier which only has space for 30 Latin1 or 15
    UCS-2 characters.
    
    Because versions of mkudffs prior to 1.1 damage the label if it contains
    non-ASCII characters, make sure GParted does not call such versions of
    mkudffs with a non-ASCII character label.
    
    Bug 784533 - Add support for UDF file system

 include/udf.h |    5 ++++
 src/Utils.cc  |    2 +-
 src/udf.cc    |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 68 insertions(+), 6 deletions(-)
---
diff --git a/include/udf.h b/include/udf.h
index a02d736..929984f 100644
--- a/include/udf.h
+++ b/include/udf.h
@@ -27,8 +27,13 @@ namespace GParted
 class udf : public FileSystem
 {
 public:
+       udf() : old_mkudffs( false ) {};
+
        FS get_filesystem_support();
        bool create( const Partition & new_partition, OperationDetail & operationdetail );
+
+private:
+       bool old_mkudffs;  // Pre 1.1 version of mkudffs
 };
 
 } //GParted
diff --git a/src/Utils.cc b/src/Utils.cc
index b6ad9bf..cb7c929 100644
--- a/src/Utils.cc
+++ b/src/Utils.cc
@@ -233,7 +233,7 @@ int Utils::get_filesystem_label_maxlength( FILESYSTEM filesystem )
                case FS_NTFS            : return 128 ;
                case FS_REISER4         : return 16 ;
                case FS_REISERFS        : return 16 ;
-               case FS_UDF             : return 30;  // and only 15 if label contains character above U+FF
+               case FS_UDF             : return 126;  // and only 63 if label contains character above U+FF
                //case FS_UFS           : return  ;
                case FS_XFS             : return 12 ;
 
diff --git a/src/udf.cc b/src/udf.cc
index 61a8c44..184ed81 100644
--- a/src/udf.cc
+++ b/src/udf.cc
@@ -44,6 +44,10 @@ FS udf::get_filesystem_support()
                fs.create_with_label = FS::EXTERNAL;
        }
 
+       // Detect old mkudffs prior to version 1.1 by lack of --label option.
+       Utils::execute_command( "mkudffs --help", output, error, true );
+       old_mkudffs = Utils::regexp_label( output + error, "--label" ).empty();
+
        // NOTE: Other external programs do not exist yet
 
        return fs;
@@ -73,17 +77,70 @@ bool udf::create( const Partition & new_partition, OperationDetail & operationde
        // NOTE: UDF Logical Volume Identifier (--lvid) represents the label but blkid
        // (from util-linux) prior to version v2.26 used the Volume Identifier (--vid).
        // Therefore for compatibility reasons store label in both locations.
+
        Glib::ustring label_args;
        if ( ! new_partition.get_filesystem_label().empty() )
-               label_args = "--lvid=\"" + new_partition.get_filesystem_label() + "\" " +
-                            "--vid=\"" + new_partition.get_filesystem_label() + "\" ";
+       {
+               const Glib::ustring label = new_partition.get_filesystem_label();
+               int non_ascii_pos_label = -1;
+               int non_latin1_pos_label = -1;
+               int pos = 0;
+
+               for ( Glib::ustring::const_iterator it = label.begin(); it != label.end(); ++it )
+               {
+                       if ( *it > 0x7F && non_ascii_pos_label == -1 )
+                               non_ascii_pos_label = pos;
+                       if ( *it > 0xFF && non_latin1_pos_label == -1 )
+                               non_latin1_pos_label = pos;
+                       if ( non_ascii_pos_label != -1 && non_latin1_pos_label != -1 )
+                               break;
+                       ++pos;
+               }
+
+               // NOTE: mkudffs from udftools prior to version 1.1 damage label if contains
+               // non-ASCII characters. So do not allow non-ASCII characters in old mkudffs.
+               if ( old_mkudffs && non_ascii_pos_label != -1 )
+               {
+                       operationdetail.add_child( OperationDetail(
+                                                  _("mkudffs prior to version 1.1 does not support non-ASCII 
characters in the label."),
+                                                  STATUS_ERROR ) );
+                       return false;
+               }
+
+               // NOTE: UDF Volume Identifier (--vid) can contain maximally 30 Unicode code
+               // points. And if one is above U+FF then only 15. UDF Logical Volume Identifier
+               // (--lvid) can contain maximally 126 resp. 63 Unicode code points. To allow
+               // long 126 characters in label, UDF Volume Identifier would be truncated.
+               // When UDF Volume Identifier or UDF Logical Volume Identifier is too long
+               // mkuddfs fail with error.
+
+               // NOTE: According to the OSTA specification, UDF supports only strings
+               // encoded in 8-bit or 16-bit OSTA Compressed Unicode format.  They are
+               // equivalent to ISO-8859-1 (Latin 1) and UCS-2BE respectively.
+               // Conversion from UTF-8 passed on the command line to OSTA format is done
+               // by mkudffs.  Strictly speaking UDF does not support UTF-16 as the UDF
+               // specification was created before the introduction of UTF-16, but lots
+               // of UDF tools are able to decode UTF-16 including UTF-16 Surrogate pairs
+               // outside the BMP (Basic Multilingual Plane).
+
+               Glib::ustring vid_arg;
+               if ( non_latin1_pos_label > 30 )
+                       vid_arg = new_partition.get_filesystem_label().substr(0, 30);
+               else if ( non_latin1_pos_label > 15 )
+                       vid_arg = new_partition.get_filesystem_label().substr(0, non_latin1_pos_label-1);
+               else if ( non_latin1_pos_label == -1 && label.length() > 30 )
+                       vid_arg = new_partition.get_filesystem_label().substr(0, 30);
+               else if ( label.length() > 15 )
+                       vid_arg = new_partition.get_filesystem_label().substr(0, 15);
+               else
+                       vid_arg = new_partition.get_filesystem_label();
+
+               label_args = "--lvid=\"" + label + "\" " + "--vid=\"" + vid_arg + "\" ";
+       }
 
        // NOTE: UDF block size must match logical sector size of underlying media.
        Glib::ustring blocksize_args = "--blocksize=" + Utils::num_to_str( new_partition.sector_size ) + " ";
 
-       // FIXME: mkudffs from udftools prior to version 1.1 damage label if contains
-       // non-ascii characters.
-
        // TODO: Add GUI option for choosing different optical disks and UDF revision.
        // For now format as UDF revision 2.01 for hard disk media type.
        return ! execute_command( "mkudffs --utf8 --media-type=hd --udfrev=0x201 " +


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