"Fossies" - the Fresh Open Source Software Archive

Member "gparted-1.3.1/src/xfs.cc" (19 Jun 2021, 10627 Bytes) of package /linux/misc/gparted-1.3.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xfs.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.3.0_vs_1.3.1.

    1 /* Copyright (C) 2004 Bart
    2  * Copyright (C) 2008, 2009, 2010 Curtis Gedak
    3  *
    4  *  This program is free software; you can redistribute it and/or modify
    5  *  it under the terms of the GNU General Public License as published by
    6  *  the Free Software Foundation; either version 2 of the License, or
    7  *  (at your option) any later version.
    8  *
    9  *  This program is distributed in the hope that it will be useful,
   10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  *  GNU General Public License for more details.
   13  *
   14  *  You should have received a copy of the GNU General Public License
   15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
   16  */
   17 
   18 #include "xfs.h"
   19 #include "FileSystem.h"
   20 #include "OperationDetail.h"
   21 #include "Partition.h"
   22 #include "Utils.h"
   23 
   24 #include <glibmm/ustring.h>
   25 #include <glibmm/miscutils.h>
   26 #include <glibmm/shell.h>
   27 
   28 
   29 namespace GParted
   30 {
   31 
   32 FS xfs::get_filesystem_support()
   33 {
   34     FS fs( FS_XFS );
   35 
   36     fs .busy = FS::GPARTED ;
   37 
   38     if ( ! Glib::find_program_in_path( "xfs_db" ) .empty() )    
   39     {
   40         fs.read = FS::EXTERNAL;
   41         fs .read_label = FS::EXTERNAL ;
   42     }
   43 
   44     if ( ! Glib::find_program_in_path( "xfs_admin" ) .empty() )     
   45     {
   46         fs .write_label = FS::EXTERNAL ;
   47         fs .read_uuid = FS::EXTERNAL ;
   48         fs .write_uuid = FS::EXTERNAL ;
   49     }
   50 
   51     if ( ! Glib::find_program_in_path( "mkfs.xfs" ) .empty() )
   52     {
   53         fs.create = FS::EXTERNAL;
   54         fs.create_with_label = FS::EXTERNAL;
   55     }
   56 
   57     if ( ! Glib::find_program_in_path( "xfs_repair" ) .empty() )    
   58         fs.check = FS::EXTERNAL;
   59 
   60     //Mounted operations require mount, umount and xfs support in the kernel
   61     if ( ! Glib::find_program_in_path( "mount" ) .empty()  &&
   62          ! Glib::find_program_in_path( "umount" ) .empty() &&
   63          fs .check                                         &&
   64          Utils::kernel_supports_fs( "xfs" )                   )
   65     {
   66         //Grow
   67         if ( ! Glib::find_program_in_path( "xfs_growfs" ) .empty() )
   68             fs .grow = FS::EXTERNAL ;
   69 
   70         //Copy using xfsdump, xfsrestore
   71         if ( ! Glib::find_program_in_path( "xfsdump" ) .empty()    &&
   72              ! Glib::find_program_in_path( "xfsrestore" ) .empty() &&
   73              fs .create                                               )
   74             fs .copy = FS::EXTERNAL ;
   75     }
   76 
   77     if ( fs .check )
   78         fs.move = FS::GPARTED;
   79 
   80     fs .online_read = FS::GPARTED ;
   81 #ifdef ENABLE_ONLINE_RESIZE
   82     if ( Utils::kernel_version_at_least( 3, 6, 0 ) )
   83         fs .online_grow = fs .grow ;
   84 #endif
   85 
   86     // Official minsize = 16MB, but the smallest xfs_repair can handle is 32MB.
   87     fs_limits.min_size = 32 * MEBIBYTE;
   88 
   89     return fs ;
   90 }
   91 
   92 void xfs::set_used_sectors( Partition & partition ) 
   93 {
   94     if ( ! Utils::execute_command( "xfs_db -r -c 'sb 0' -c 'print blocksize' -c 'print dblocks'"
   95                                    " -c 'print fdblocks' " + Glib::shell_quote( partition.get_path() ),
   96                                    output, error, true )                                                   )
   97     {
   98         //blocksize
   99         if ( sscanf( output.c_str(), "blocksize = %lld", &S ) != 1 )
  100             S = -1 ;
  101 
  102         //filesystem blocks
  103         Glib::ustring::size_type index = output.find( "\ndblocks" );
  104         if ( index > output .length() ||
  105              sscanf( output.substr( index ).c_str(), "\ndblocks = %lld", &T ) != 1 )
  106             T = -1 ;
  107 
  108         //free blocks
  109         index = output .find( "\nfdblocks" ) ;
  110         if ( index > output .length() ||
  111              sscanf( output.substr( index ).c_str(), "\nfdblocks = %lld", &N ) != 1 )
  112             N = -1 ;
  113 
  114         if ( T > -1 && N > -1 && S > -1 )
  115         {
  116             T = Utils::round( T * ( S / double(partition .sector_size) ) ) ;
  117             N = Utils::round( N * ( S / double(partition .sector_size) ) ) ;
  118             partition .set_sector_usage( T, N ) ;
  119             partition.fs_block_size = S;
  120         }
  121 
  122     }
  123     else
  124     {
  125         if ( ! output .empty() )
  126             partition.push_back_message( output );
  127         
  128         if ( ! error .empty() )
  129             partition.push_back_message( error );
  130     }
  131 }
  132 
  133 void xfs::read_label( Partition & partition )
  134 {
  135     if ( ! Utils::execute_command( "xfs_db -r -c 'label' " + Glib::shell_quote( partition.get_path() ),
  136                                    output, error, true )                                                )
  137     {
  138         partition.set_filesystem_label( Utils::regexp_label( output, "^label = \"(.*)\"" ) );
  139     }
  140     else
  141     {
  142         if ( ! output .empty() )
  143             partition.push_back_message( output );
  144         
  145         if ( ! error .empty() )
  146             partition.push_back_message( error );
  147     }
  148 }
  149 
  150 bool xfs::write_label( const Partition & partition, OperationDetail & operationdetail )
  151 {
  152     Glib::ustring cmd = "" ;
  153     if( partition.get_filesystem_label().empty() )
  154         cmd = "xfs_admin -L -- " + Glib::shell_quote( partition.get_path() );
  155     else
  156         cmd = "xfs_admin -L " + Glib::shell_quote( partition.get_filesystem_label() ) +
  157               " " + partition.get_path();
  158     return ! execute_command( cmd, operationdetail, EXEC_CHECK_STATUS );
  159 }
  160 
  161 void xfs::read_uuid( Partition & partition )
  162 {
  163     if ( ! Utils::execute_command( "xfs_admin -u " + Glib::shell_quote( partition.get_path() ),
  164                                    output, error, true )                                        )
  165     {
  166         partition .uuid = Utils::regexp_label( output, "^UUID[[:blank:]]*=[[:blank:]]*(" RFC4122_NONE_NIL_UUID_REGEXP ")" ) ;
  167     }
  168     else
  169     {
  170         if ( ! output .empty() )
  171             partition.push_back_message( output );
  172 
  173         if ( ! error .empty() )
  174             partition.push_back_message( error );
  175     }
  176 }
  177 
  178 bool xfs::write_uuid( const Partition & partition, OperationDetail & operationdetail )
  179 {
  180     return ! execute_command( "xfs_admin -U generate " + Glib::shell_quote( partition.get_path() ),
  181                               operationdetail, EXEC_CHECK_STATUS );
  182 }
  183 
  184 bool xfs::create( const Partition & new_partition, OperationDetail & operationdetail )
  185 {
  186     return ! execute_command( "mkfs.xfs -f -L " + Glib::shell_quote( new_partition.get_filesystem_label() ) +
  187                               " " + Glib::shell_quote( new_partition.get_path() ),
  188                               operationdetail,
  189                               EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
  190 }
  191 
  192 bool xfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
  193 {
  194     bool success = true ;
  195 
  196     Glib::ustring mount_point ;
  197     if ( ! partition_new .busy )
  198     {
  199         mount_point = mk_temp_dir( "", operationdetail ) ;
  200         if ( mount_point.empty() )
  201             return false ;
  202         success &= ! execute_command( "mount -v -t xfs " + Glib::shell_quote( partition_new.get_path() ) +
  203                                       " " + Glib::shell_quote( mount_point ),
  204                                       operationdetail, EXEC_CHECK_STATUS );
  205     }
  206     else
  207         mount_point = partition_new .get_mountpoint() ;
  208 
  209     if ( success )
  210     {
  211         success &= ! execute_command( "xfs_growfs " + Glib::shell_quote( mount_point ),
  212                                       operationdetail, EXEC_CHECK_STATUS );
  213 
  214         if ( ! partition_new .busy )
  215             success &= ! execute_command( "umount -v " + Glib::shell_quote( mount_point ),
  216                                           operationdetail, EXEC_CHECK_STATUS );
  217     }
  218 
  219     if ( ! partition_new .busy )
  220         rm_temp_dir( mount_point, operationdetail ) ;
  221 
  222     return success ;
  223 }
  224 
  225 bool xfs::copy( const Partition & src_part,
  226         Partition & dest_part,
  227         OperationDetail & operationdetail )
  228 {
  229     bool success = true ;
  230 
  231     success &= ! execute_command("mkfs.xfs -f -L " + Glib::shell_quote(dest_part.get_filesystem_label()) +
  232                                  " -m uuid=" + Glib::shell_quote(dest_part.uuid) +
  233                                  " " + Glib::shell_quote(dest_part.get_path()),
  234                                  operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE);
  235     if ( ! success )
  236         return false ;
  237 
  238     Glib::ustring src_mount_point = mk_temp_dir( "src", operationdetail ) ;
  239     if ( src_mount_point .empty() )
  240         return false ;
  241 
  242     dest_mount_point = mk_temp_dir( "dest", operationdetail );
  243     if ( dest_mount_point .empty() )
  244     {
  245         rm_temp_dir( src_mount_point, operationdetail ) ;
  246         return false ;
  247     }
  248 
  249     success &= ! execute_command( "mount -v -t xfs -o noatime,ro " + Glib::shell_quote( src_part.get_path() ) +
  250                                   " " + Glib::shell_quote( src_mount_point ),
  251                                   operationdetail, EXEC_CHECK_STATUS );
  252 
  253     // Get source FS used bytes, needed in progress update calculation
  254     Byte_Value fs_size;
  255     Byte_Value fs_free;
  256     if ( Utils::get_mounted_filesystem_usage( src_mount_point, fs_size, fs_free, error ) == 0 )
  257         src_used = fs_size - fs_free;
  258     else
  259         src_used = -1LL;
  260 
  261     if ( success )
  262     {
  263         success &= ! execute_command("mount -v -t xfs -o nouuid " + Glib::shell_quote(dest_part.get_path()) +
  264                                      " " + Glib::shell_quote(dest_mount_point),
  265                                      operationdetail, EXEC_CHECK_STATUS);
  266 
  267         if ( success )
  268         {
  269             const Glib::ustring copy_cmd = "xfsdump -J - " + Glib::shell_quote( src_mount_point ) +
  270                                            " | xfsrestore -J - " + Glib::shell_quote( dest_mount_point );
  271             success &= ! execute_command( "sh -c " + Glib::shell_quote( copy_cmd ),
  272                                           operationdetail,
  273                                           EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_TIMED,
  274                                           static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) );
  275 
  276             success &= ! execute_command( "umount -v " + Glib::shell_quote( dest_mount_point ),
  277                                           operationdetail, EXEC_CHECK_STATUS );
  278         }
  279 
  280         success &= ! execute_command( "umount -v " + Glib::shell_quote( src_mount_point ),
  281                                       operationdetail, EXEC_CHECK_STATUS );
  282     }
  283 
  284     rm_temp_dir( dest_mount_point, operationdetail ) ;
  285 
  286     rm_temp_dir( src_mount_point, operationdetail ) ;
  287 
  288     return success ;
  289 }
  290 
  291 bool xfs::check_repair( const Partition & partition, OperationDetail & operationdetail )
  292 {
  293     return ! execute_command( "xfs_repair -v " + Glib::shell_quote( partition.get_path() ),
  294                               operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
  295 }
  296 
  297 //Private methods
  298 
  299 // Report progress of XFS copy.  Monitor destination FS used bytes and track against
  300 // recorded source FS used bytes.
  301 bool xfs::copy_progress( OperationDetail * operationdetail )
  302 {
  303     if ( src_used <= 0LL )
  304     {
  305         operationdetail->stop_progressbar();
  306         // Failed to get source FS used bytes.  Remove this timed callback early.
  307         return false;
  308     }
  309     Byte_Value fs_size;
  310     Byte_Value fs_free;
  311     Byte_Value dst_used;
  312     if ( Utils::get_mounted_filesystem_usage( dest_mount_point, fs_size, fs_free, error ) != 0 )
  313     {
  314         operationdetail->stop_progressbar();
  315         // Failed to get destination FS used bytes.  Remove this timed callback early.
  316         return false;
  317     }
  318     dst_used = fs_size - fs_free;
  319     operationdetail->run_progressbar( (double)dst_used, (double)src_used, PROGRESSBAR_TEXT_COPY_BYTES );
  320     return true;
  321 }
  322 
  323 } //GParted