[gparted] Add support for UDF file system (#784533)



commit 5f327feb25bcb8b55ffa2eab1bb86d5f75d75fba
Author: Pali Rohár <pali rohar gmail com>
Date:   Wed Jul 5 02:15:35 2017 +0200

    Add support for UDF file system (#784533)
    
    Add support for detecting UDF file systems and formatting hard disks
    with revision 2.01 UDF file systems using udftools.  Formatting optical
    disks or any other media types is not supported yet.  Changing label or
    UUID after formatting is not supported as the tools do not yet exist.
    
    Bug 784533 - Add support for UDF file system

 README                    |    1 +
 gparted.appdata.xml.in    |    2 +-
 include/Makefile.am       |    1 +
 include/Utils.h           |   23 ++++++-----
 include/udf.h             |   36 +++++++++++++++++
 po/POTFILES.in            |    1 +
 src/Dialog_Rescue_Data.cc |    2 +-
 src/GParted_Core.cc       |   11 +++++
 src/Makefile.am           |    1 +
 src/Utils.cc              |    5 ++
 src/udf.cc                |   95 +++++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 165 insertions(+), 13 deletions(-)
---
diff --git a/README b/README
index 4837f2d..ca4375d 100644
--- a/README
+++ b/README
@@ -222,6 +222,7 @@ provide this support:
    ntfs-3g / ntfsprogs
    reiser4progs
    reiserfsprogs / reiserfs-utils / reiserfs
+   udftools
    xfsprogs, xfsdump
 
 
diff --git a/gparted.appdata.xml.in b/gparted.appdata.xml.in
index 610ff50..5dcbef0 100644
--- a/gparted.appdata.xml.in
+++ b/gparted.appdata.xml.in
@@ -17,7 +17,7 @@
     <_p>
     GParted works with many file systems including: btrfs, ext2, ext3,
     ext4, fat16, fat32, hfs, hfs+, linux-swap, lvm2 pv, nilfs2, ntfs,
-    reiserfs, reiser4, ufs, and xfs.
+    reiserfs, reiser4, udf, ufs, and xfs.
     </_p>
   </description>
   <url type="homepage">http://gparted.org</url>
diff --git a/include/Makefile.am b/include/Makefile.am
index 6f0a851..d0a9d3e 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -64,5 +64,6 @@ EXTRA_DIST = \
        ntfs.h                          \
        reiser4.h                       \
        reiserfs.h                      \
+       udf.h                           \
        ufs.h                           \
        xfs.h
diff --git a/include/Utils.h b/include/Utils.h
index bda3f19..173a34e 100644
--- a/include/Utils.h
+++ b/include/Utils.h
@@ -85,21 +85,22 @@ enum FILESYSTEM
        FS_NTFS            = 20,
        FS_REISER4         = 21,
        FS_REISERFS        = 22,
-       FS_UFS             = 23,
-       FS_XFS             = 24,
+       FS_UDF             = 23,
+       FS_UFS             = 24,
+       FS_XFS             = 25,
 
        // Recognised signatures but otherwise unsupported file system types
-       FS_BITLOCKER       = 25,
-       FS_GRUB2_CORE_IMG  = 26,
-       FS_ISO9660         = 27,
-       FS_LINUX_SWRAID    = 28,
-       FS_LINUX_SWSUSPEND = 29,
-       FS_REFS            = 30,
-       FS_ZFS             = 31,
+       FS_BITLOCKER       = 26,
+       FS_GRUB2_CORE_IMG  = 27,
+       FS_ISO9660         = 28,
+       FS_LINUX_SWRAID    = 29,
+       FS_LINUX_SWSUSPEND = 30,
+       FS_REFS            = 31,
+       FS_ZFS             = 32,
 
        // Partition space usage colours
-       FS_USED            = 32,
-       FS_UNUSED          = 33
+       FS_USED            = 33,
+       FS_UNUSED          = 34
 } ;
 
 enum SIZE_UNIT
diff --git a/include/udf.h b/include/udf.h
new file mode 100644
index 0000000..a02d736
--- /dev/null
+++ b/include/udf.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2017 Pali Rohár <pali rohar gmail com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GPARTED_UDF_H
+#define GPARTED_UDF_H
+
+#include "FileSystem.h"
+#include "Partition.h"
+
+namespace GParted
+{
+
+class udf : public FileSystem
+{
+public:
+       FS get_filesystem_support();
+       bool create( const Partition & new_partition, OperationDetail & operationdetail );
+};
+
+} //GParted
+
+#endif /* GPARTED_UDF_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 51841dd..9e3cba2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -57,5 +57,6 @@ src/ntfs.cc
 src/nilfs2.cc
 src/reiser4.cc
 src/reiserfs.cc
+src/udf.cc
 src/ufs.cc
 src/xfs.cc
diff --git a/src/Dialog_Rescue_Data.cc b/src/Dialog_Rescue_Data.cc
index de075f5..692f63b 100644
--- a/src/Dialog_Rescue_Data.cc
+++ b/src/Dialog_Rescue_Data.cc
@@ -386,7 +386,7 @@ void Dialog_Rescue_Data::read_partitions_from_buffer()
                                                        fs=GParted::FS_FAT32;
                                                        break;
                                                }
-                                               case 0x07: //NTFS and HPFS
+                                               case 0x07: //NTFS, HPFS, exFAT and UDF
                                                {
                                                        fs=GParted::FS_NTFS;
                                                        break;
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 733c28a..d386168 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -48,6 +48,7 @@
 #include "hfs.h"
 #include "hfsplus.h"
 #include "reiser4.h"
+#include "udf.h"
 #include "ufs.h"
 
 #include <cerrno>
@@ -1473,6 +1474,8 @@ FILESYSTEM GParted_Core::detect_filesystem( PedDevice * lp_device, PedPartition
                          fsname == "hfsx"    ||
                          fsname == "hfsplus"    )
                        return GParted::FS_HFSPLUS ;
+               else if ( fsname == "udf" )
+                       return GParted::FS_UDF;
                else if ( fsname == "ufs" )
                        return GParted::FS_UFS ;
                else if ( fsname == "iso9660" )
@@ -3494,6 +3497,13 @@ bool GParted_Core::set_partition_type( const Partition & partition, OperationDet
                        if ( ! lp_fs_type && fs_type == "linux-swap" )
                                lp_fs_type = ped_file_system_type_get( "linux-swap(new)" );
 
+                       // If not found, and FS is udf, then try ntfs.
+                       // Actually MBR 07 IFS (Microsoft Installable File System) or
+                       // GPT BDP (Windows Basic Data Partition).
+                       // Ref: https://serverfault.com/a/829172
+                       if ( ! lp_fs_type && fs_type == "udf" )
+                               lp_fs_type = ped_file_system_type_get( "ntfs" );
+
                        // default is Linux (83)
                        if ( ! lp_fs_type )
                                lp_fs_type = ped_file_system_type_get( "ext2" );
@@ -4122,6 +4132,7 @@ void GParted_Core::init_filesystems()
        FILESYSTEM_MAP[FS_NTFS]            = new ntfs();
        FILESYSTEM_MAP[FS_REISER4]         = new reiser4();
        FILESYSTEM_MAP[FS_REISERFS]        = new reiserfs();
+       FILESYSTEM_MAP[FS_UDF]             = new udf();
        FILESYSTEM_MAP[FS_UFS]             = new ufs();
        FILESYSTEM_MAP[FS_XFS]             = new xfs();
        FILESYSTEM_MAP[FS_BITLOCKER]       = NULL;
diff --git a/src/Makefile.am b/src/Makefile.am
index 81b99e5..2e8a03f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -75,6 +75,7 @@ gpartedbin_SOURCES = \
        ntfs.cc                         \
        reiser4.cc                      \
        reiserfs.cc                     \
+       udf.cc                          \
        ufs.cc                          \
        xfs.cc
 
diff --git a/src/Utils.cc b/src/Utils.cc
index 811a374..cffcbf2 100644
--- a/src/Utils.cc
+++ b/src/Utils.cc
@@ -111,6 +111,7 @@ Glib::ustring Utils::get_color( FILESYSTEM filesystem )
                case FS_JFS                     : return "#E0C39E" ;    //face skin medium
                case FS_HFS                     : return "#E0B6AF" ;    //red hilight
                case FS_HFSPLUS         : return "#C0A39E" ;    // ~ serene red
+               case FS_UDF             : return "#105210";     // Accent Green Shadow
                case FS_UFS                     : return "#D1940C" ;    //accent yellow dark
                case FS_USED            : return "#F8F8BA" ;    // ~ light tan yellow
                case FS_UNUSED          : return "#FFFFFF" ;    //white
@@ -232,6 +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_UFS           : return  ;
                case FS_XFS             : return 12 ;
 
@@ -289,6 +291,7 @@ Glib::ustring Utils::get_filesystem_string( FILESYSTEM filesystem )
                case FS_JFS             : return "jfs" ;
                case FS_HFS             : return "hfs" ;
                case FS_HFSPLUS         : return "hfs+" ;
+               case FS_UDF             : return "udf";
                case FS_UFS             : return "ufs" ;
                case FS_USED            : return _("used") ;
                case FS_UNUSED          : return _("unused") ;
@@ -337,6 +340,7 @@ const Glib::ustring Utils::get_filesystem_kernel_name( FILESYSTEM fstype )
                case FS_NTFS     : return "ntfs";
                case FS_REISER4  : return "reiser4";
                case FS_REISERFS : return "reiserfs";
+               case FS_UDF      : return "udf";
                case FS_UFS      : return "ufs";
                case FS_XFS      : return "xfs";
                default          : return "";
@@ -364,6 +368,7 @@ Glib::ustring Utils::get_filesystem_software( FILESYSTEM filesystem )
                case FS_NTFS        : return "ntfs-3g / ntfsprogs" ;
                case FS_REISER4     : return "reiser4progs" ;
                case FS_REISERFS    : return "reiserfsprogs / reiserfs-utils" ;
+               case FS_UDF         : return "udftools";
                case FS_UFS         : return "" ;
                case FS_XFS         : return "xfsprogs, xfsdump" ;
 
diff --git a/src/udf.cc b/src/udf.cc
new file mode 100644
index 0000000..61a8c44
--- /dev/null
+++ b/src/udf.cc
@@ -0,0 +1,95 @@
+/* Copyright (C) 2017 Pali Rohár <pali rohar gmail com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "udf.h"
+#include "Partition.h"
+#include "Utils.h"
+
+namespace GParted
+{
+
+const Byte_Value MIN_UDF_BLOCKS = 282;
+const Byte_Value MAX_UDF_BLOCKS = (1LL << 32) - 1;
+
+const Byte_Value MIN_UDF_BLOCKSIZE = 512;
+const Byte_Value MAX_UDF_BLOCKSIZE = 4096;
+
+FS udf::get_filesystem_support()
+{
+       FS fs( FS_UDF );
+
+       fs.busy = FS::GPARTED;
+       fs.move = FS::GPARTED;
+       fs.copy = FS::GPARTED;
+       fs.online_read = FS::GPARTED;
+       fs.MIN = MIN_UDF_BLOCKS * MIN_UDF_BLOCKSIZE;
+       fs.MAX = MAX_UDF_BLOCKS * MAX_UDF_BLOCKSIZE;
+
+       if ( ! Glib::find_program_in_path( "mkudffs" ).empty() )
+       {
+               fs.create = FS::EXTERNAL;
+               fs.create_with_label = FS::EXTERNAL;
+       }
+
+       // NOTE: Other external programs do not exist yet
+
+       return fs;
+}
+
+bool udf::create( const Partition & new_partition, OperationDetail & operationdetail )
+{
+       // NOTE: mkudffs from udftools prior to version 1.1 does not check for partition
+       // limits and crashes.
+       if ( new_partition.get_sector_length() > MAX_UDF_BLOCKS )
+       {
+               operationdetail.add_child( OperationDetail( String::ucompose(
+                                          _("Partition is too large, maximum size is %1"),
+                                          Utils::format_size( MAX_UDF_BLOCKS, new_partition.sector_size ) ),
+                                          STATUS_ERROR ) );
+               return false;
+       }
+       else if ( new_partition.get_sector_length() < MIN_UDF_BLOCKS )
+       {
+               operationdetail.add_child( OperationDetail( String::ucompose(
+                                          _("Partition is too small, minimum size is %1"),
+                                          Utils::format_size( MIN_UDF_BLOCKS, new_partition.sector_size ) ),
+                                          STATUS_ERROR ) );
+               return false;
+       }
+
+       // 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() + "\" ";
+
+       // 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 " +
+                                 blocksize_args + label_args + new_partition.get_path(),
+                                 operationdetail,
+                                 EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
+}
+
+} //GParted


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