2015-06-04 01:29:22 +01:00
/*************************************************************************
* Copyright ( C ) 2008 by Volker Lanz < vl @ fidra . de > *
2016-03-02 19:00:31 +00:00
* Copyright ( C ) 2016 by Andrius Š tikonas < andrius @ stikonas . eu > *
2015-06-04 01:29:22 +01:00
* *
* 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 3 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 "fs/xfs.h"
# include "util/externalcommand.h"
# include "util/capacity.h"
# include "util/report.h"
2016-05-12 16:37:37 +01:00
# include <QRegularExpression>
2015-06-04 01:29:22 +01:00
# include <QString>
# include <QStringList>
# include <QTemporaryDir>
# include <KLocalizedString>
namespace FS
{
2015-07-13 15:16:36 +01:00
FileSystem : : CommandSupportType xfs : : m_GetUsed = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_GetLabel = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_Create = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_Grow = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_Move = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_Check = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_Copy = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_Backup = FileSystem : : cmdSupportNone ;
FileSystem : : CommandSupportType xfs : : m_SetLabel = FileSystem : : cmdSupportNone ;
xfs : : xfs ( qint64 firstsector , qint64 lastsector , qint64 sectorsused , const QString & label ) :
FileSystem ( firstsector , lastsector , sectorsused , label , FileSystem : : Xfs )
{
}
void xfs : : init ( )
{
m_GetLabel = cmdSupportCore ;
m_SetLabel = m_GetUsed = findExternal ( QStringLiteral ( " xfs_db " ) ) ? cmdSupportFileSystem : cmdSupportNone ;
m_Create = findExternal ( QStringLiteral ( " mkfs.xfs " ) ) ? cmdSupportFileSystem : cmdSupportNone ;
m_Check = findExternal ( QStringLiteral ( " xfs_repair " ) ) ? cmdSupportFileSystem : cmdSupportNone ;
2016-04-21 22:48:05 +01:00
m_Grow = ( findExternal ( QStringLiteral ( " xfs_growfs " ) , { QStringLiteral ( " -V " ) } ) & & m_Check ! = cmdSupportNone ) ? cmdSupportFileSystem : cmdSupportNone ;
2015-07-13 15:16:36 +01:00
m_Copy = findExternal ( QStringLiteral ( " xfs_copy " ) ) ? cmdSupportFileSystem : cmdSupportNone ;
m_Move = ( m_Check ! = cmdSupportNone ) ? cmdSupportCore : cmdSupportNone ;
m_Backup = cmdSupportCore ;
}
bool xfs : : supportToolFound ( ) const
{
return
m_GetUsed ! = cmdSupportNone & &
m_GetLabel ! = cmdSupportNone & &
m_SetLabel ! = cmdSupportNone & &
m_Create ! = cmdSupportNone & &
m_Check ! = cmdSupportNone & &
// m_UpdateUUID != cmdSupportNone &&
m_Grow ! = cmdSupportNone & &
// m_Shrink != cmdSupportNone &&
m_Copy ! = cmdSupportNone & &
m_Move ! = cmdSupportNone & &
m_Backup ! = cmdSupportNone ;
// m_GetUUID != cmdSupportNone;
}
FileSystem : : SupportTool xfs : : supportToolName ( ) const
{
return SupportTool ( QStringLiteral ( " xfsprogs " ) , QUrl ( QStringLiteral ( " http://oss.sgi.com/projects/xfs/ " ) ) ) ;
}
qint64 xfs : : minCapacity ( ) const
{
return 32 * Capacity : : unitFactor ( Capacity : : Byte , Capacity : : MiB ) ;
}
qint64 xfs : : maxCapacity ( ) const
{
return Capacity : : unitFactor ( Capacity : : Byte , Capacity : : EiB ) ;
}
2017-09-11 16:52:20 +01:00
int xfs : : maxLabelLength ( ) const
2015-07-13 15:16:36 +01:00
{
return 12 ;
}
qint64 xfs : : readUsedCapacity ( const QString & deviceNode ) const
{
2016-04-21 22:48:05 +01:00
ExternalCommand cmd ( QStringLiteral ( " xfs_db " ) , { QStringLiteral ( " -c " ) , QStringLiteral ( " sb 0 " ) , QStringLiteral ( " -c " ) , QStringLiteral ( " print " ) , deviceNode } ) ;
2015-07-13 15:16:36 +01:00
2016-05-12 16:37:37 +01:00
if ( cmd . run ( - 1 ) & & cmd . exitCode ( ) = = 0 ) {
2015-07-13 15:16:36 +01:00
qint64 dBlocks = - 1 ;
2016-05-12 16:37:37 +01:00
QRegularExpression re ( QStringLiteral ( " dblocks = ( \\ d+) " )) ;
QRegularExpressionMatch reDBlocks = re . match ( cmd . output ( ) ) ;
2015-07-13 15:16:36 +01:00
2016-05-12 16:37:37 +01:00
if ( reDBlocks . hasMatch ( ) )
dBlocks = reDBlocks . captured ( 1 ) . toLongLong ( ) ;
2015-07-13 15:16:36 +01:00
qint64 blockSize = - 1 ;
2016-05-12 16:37:37 +01:00
re . setPattern ( QStringLiteral ( " blocksize = ( \\ d+) " ) ) ;
QRegularExpressionMatch reBlockSize = re . match ( cmd . output ( ) ) ;
2015-07-13 15:16:36 +01:00
2016-05-12 16:37:37 +01:00
if ( reBlockSize . hasMatch ( ) )
blockSize = reBlockSize . captured ( 1 ) . toLongLong ( ) ;
2015-07-13 15:16:36 +01:00
qint64 fdBlocks = - 1 ;
2016-05-12 16:37:37 +01:00
re . setPattern ( QStringLiteral ( " fdblocks = ( \\ d+) " ) ) ;
QRegularExpressionMatch reFdBlocks = re . match ( cmd . output ( ) ) ;
2015-07-13 15:16:36 +01:00
2016-05-12 16:37:37 +01:00
if ( reFdBlocks . hasMatch ( ) )
fdBlocks = reFdBlocks . captured ( 1 ) . toLongLong ( ) ;
2015-07-13 15:16:36 +01:00
if ( dBlocks > - 1 & & blockSize > - 1 & & fdBlocks > - 1 )
return ( dBlocks - fdBlocks ) * blockSize ;
}
return - 1 ;
}
bool xfs : : writeLabel ( Report & report , const QString & deviceNode , const QString & newLabel )
{
2016-04-21 22:48:05 +01:00
ExternalCommand cmd ( report , QStringLiteral ( " xfs_db " ) , { QStringLiteral ( " -x " ) , QStringLiteral ( " -c " ) , QStringLiteral ( " sb 0 " ) , QStringLiteral ( " -c " ) , QStringLiteral ( " label " ) + newLabel , deviceNode } ) ;
2015-07-13 15:16:36 +01:00
return cmd . run ( - 1 ) & & cmd . exitCode ( ) = = 0 ;
}
bool xfs : : check ( Report & report , const QString & deviceNode ) const
{
2016-04-21 22:48:05 +01:00
ExternalCommand cmd ( report , QStringLiteral ( " xfs_repair " ) , { QStringLiteral ( " -v " ) , deviceNode } ) ;
2015-07-13 15:16:36 +01:00
return cmd . run ( - 1 ) & & cmd . exitCode ( ) = = 0 ;
}
2016-09-05 12:10:56 +01:00
bool xfs : : create ( Report & report , const QString & deviceNode )
2015-07-13 15:16:36 +01:00
{
2016-04-21 22:48:05 +01:00
ExternalCommand cmd ( report , QStringLiteral ( " mkfs.xfs " ) , { QStringLiteral ( " -f " ) , deviceNode } ) ;
2015-07-13 15:16:36 +01:00
return cmd . run ( - 1 ) & & cmd . exitCode ( ) = = 0 ;
}
bool xfs : : copy ( Report & report , const QString & targetDeviceNode , const QString & sourceDeviceNode ) const
{
2016-04-21 22:48:05 +01:00
ExternalCommand cmd ( report , QStringLiteral ( " xfs_copy " ) , { sourceDeviceNode , targetDeviceNode } ) ;
2015-07-13 15:16:36 +01:00
// xfs_copy behaves a little strangely. It apparently kills itself at the end of main, causing QProcess
// to report that it crashed.
// See http://oss.sgi.com/archives/xfs/2004-11/msg00169.html
// So we cannot rely on QProcess::exitStatus() and thus not on ExternalCommand::run() returning true.
cmd . run ( - 1 ) ;
return cmd . exitCode ( ) = = 0 ;
}
bool xfs : : resize ( Report & report , const QString & deviceNode , qint64 ) const
{
QTemporaryDir tempDir ;
if ( ! tempDir . isValid ( ) ) {
2016-07-17 23:41:00 +01:00
report . line ( ) < < xi18nc ( " @info:progress " , " Resizing XFS file system on partition <filename>%1</filename> failed: Could not create temp dir. " , deviceNode ) ;
2015-07-13 15:16:36 +01:00
return false ;
}
bool rval = false ;
2016-04-21 22:48:05 +01:00
ExternalCommand mountCmd ( report , QStringLiteral ( " mount " ) , { QStringLiteral ( " --verbose " ) , QStringLiteral ( " --types " ) , QStringLiteral ( " xfs " ) , deviceNode , tempDir . path ( ) } ) ;
2015-07-13 15:16:36 +01:00
if ( mountCmd . run ( - 1 ) ) {
2016-04-21 22:48:05 +01:00
ExternalCommand resizeCmd ( report , QStringLiteral ( " xfs_growfs " ) , { tempDir . path ( ) } ) ;
2015-07-13 15:16:36 +01:00
2016-08-08 02:01:35 +01:00
if ( resizeCmd . run ( - 1 ) & & resizeCmd . exitCode ( ) = = 0 )
2015-07-13 15:16:36 +01:00
rval = true ;
else
2016-07-17 23:41:00 +01:00
report . line ( ) < < xi18nc ( " @info:progress " , " Resizing XFS file system on partition <filename>%1</filename> failed: xfs_growfs failed. " , deviceNode ) ;
2015-07-13 15:16:36 +01:00
2016-04-21 22:48:05 +01:00
ExternalCommand unmountCmd ( report , QStringLiteral ( " umount " ) , { tempDir . path ( ) } ) ;
2015-07-13 15:16:36 +01:00
if ( ! unmountCmd . run ( - 1 ) )
2016-07-18 12:50:52 +01:00
report . line ( ) < < xi18nc ( " @info:progress " , " <warning>Resizing XFS file system on partition <filename>%1</filename> failed: Unmount failed.</warning> " , deviceNode ) ;
2015-07-13 15:16:36 +01:00
} else
2016-07-17 23:41:00 +01:00
report . line ( ) < < xi18nc ( " @info:progress " , " Resizing XFS file system on partition <filename>%1</filename> failed: Initial mount failed. " , deviceNode ) ;
2015-07-13 15:16:36 +01:00
return rval ;
}
2016-08-08 02:01:35 +01:00
bool xfs : : resizeOnline ( Report & report , const QString & deviceNode , const QString & mountPoint , qint64 ) const
{
ExternalCommand resizeCmd ( report , QStringLiteral ( " xfs_growfs " ) , { mountPoint } ) ;
if ( resizeCmd . run ( - 1 ) & & resizeCmd . exitCode ( ) = = 0 )
return true ;
report . line ( ) < < xi18nc ( " @info:progress " , " Resizing XFS file system on partition <filename>%1</filename> failed: xfs_growfs failed. " , deviceNode ) ;
return false ;
}
2015-06-04 01:29:22 +01:00
}