File indexing completed on 2024-05-05 05:48:45
0001 /* 0002 SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2013-2018 Andrius Štikonas <andrius@stikonas.eu> 0004 SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com> 0005 SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com> 0006 0007 SPDX-License-Identifier: GPL-3.0-or-later 0008 */ 0009 0010 #include "fs/jfs.h" 0011 0012 #include "util/externalcommand.h" 0013 #include "util/report.h" 0014 #include "util/capacity.h" 0015 0016 #include <QRegularExpression> 0017 #include <QStringList> 0018 #include <QTemporaryDir> 0019 0020 #include <KLocalizedString> 0021 0022 namespace FS 0023 { 0024 FileSystem::CommandSupportType jfs::m_GetUsed = FileSystem::cmdSupportNone; 0025 FileSystem::CommandSupportType jfs::m_GetLabel = FileSystem::cmdSupportNone; 0026 FileSystem::CommandSupportType jfs::m_Create = FileSystem::cmdSupportNone; 0027 FileSystem::CommandSupportType jfs::m_Grow = FileSystem::cmdSupportNone; 0028 FileSystem::CommandSupportType jfs::m_Move = FileSystem::cmdSupportNone; 0029 FileSystem::CommandSupportType jfs::m_Check = FileSystem::cmdSupportNone; 0030 FileSystem::CommandSupportType jfs::m_Copy = FileSystem::cmdSupportNone; 0031 FileSystem::CommandSupportType jfs::m_Backup = FileSystem::cmdSupportNone; 0032 FileSystem::CommandSupportType jfs::m_SetLabel = FileSystem::cmdSupportNone; 0033 0034 jfs::jfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) : 0035 FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Jfs) 0036 { 0037 } 0038 0039 void jfs::init() 0040 { 0041 m_GetUsed = findExternal(QStringLiteral("jfs_debugfs")) ? cmdSupportFileSystem : cmdSupportNone; 0042 m_GetLabel = cmdSupportCore; 0043 m_SetLabel = findExternal(QStringLiteral("jfs_tune"), { QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; 0044 m_Create = findExternal(QStringLiteral("mkfs.jfs"),{ QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; 0045 m_Grow = m_Check = findExternal(QStringLiteral("fsck.jfs"), { QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; 0046 m_Copy = m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; 0047 m_Backup = cmdSupportCore; 0048 } 0049 0050 bool jfs::supportToolFound() const 0051 { 0052 return 0053 m_GetUsed != cmdSupportNone && 0054 m_GetLabel != cmdSupportNone && 0055 m_SetLabel != cmdSupportNone && 0056 m_Create != cmdSupportNone && 0057 m_Check != cmdSupportNone && 0058 // m_UpdateUUID != cmdSupportNone && 0059 m_Grow != cmdSupportNone && 0060 // m_Shrink != cmdSupportNone && 0061 m_Copy != cmdSupportNone && 0062 m_Move != cmdSupportNone && 0063 m_Backup != cmdSupportNone; 0064 // m_GetUUID != cmdSupportNone; 0065 } 0066 0067 FileSystem::SupportTool jfs::supportToolName() const 0068 { 0069 return SupportTool(QStringLiteral("jfsutils"), QUrl(QStringLiteral("http://jfs.sourceforge.net/"))); 0070 } 0071 0072 qint64 jfs::minCapacity() const 0073 { 0074 return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); 0075 } 0076 0077 qint64 jfs::maxCapacity() const 0078 { 0079 return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB); 0080 } 0081 0082 int jfs::maxLabelLength() const 0083 { 0084 return 11; 0085 } 0086 0087 qint64 jfs::readUsedCapacity(const QString& deviceNode) const 0088 { 0089 ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode); 0090 0091 if (cmd.write(QByteArrayLiteral("dm")) && cmd.start()) { 0092 qint64 blockSize = -1; 0093 QRegularExpression re(QStringLiteral("Block Size: (\\d+)")); 0094 QRegularExpressionMatch reBlockSize = re.match(cmd.output()); 0095 0096 if (reBlockSize.hasMatch()) 0097 blockSize = reBlockSize.captured(1).toLongLong(); 0098 0099 qint64 nBlocks = -1; 0100 re.setPattern(QStringLiteral("dn_mapsize:\\s+0x(\\x+)")); 0101 QRegularExpressionMatch renBlocks = re.match(cmd.output()); 0102 0103 bool ok = false; 0104 if (renBlocks.hasMatch()) { 0105 nBlocks = renBlocks.captured(1).toLongLong(&ok, 16); 0106 if (!ok) 0107 nBlocks = -1; 0108 } 0109 0110 qint64 nFree = -1; 0111 re.setPattern(QStringLiteral("dn_nfree:\\s+0x(\\x+)")); 0112 QRegularExpressionMatch renFree = re.match(cmd.output()); 0113 0114 if (renFree.hasMatch()) { 0115 nFree = renFree.captured(1).toLongLong(&ok, 16); 0116 if (!ok) 0117 nFree = -1; 0118 } 0119 0120 if (nBlocks > -1 && blockSize > -1 && nFree > -1) 0121 return (nBlocks - nFree) * blockSize; 0122 } 0123 0124 return -1; 0125 } 0126 0127 bool jfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) 0128 { 0129 ExternalCommand cmd(report, QStringLiteral("jfs_tune"), { QStringLiteral("-L"), newLabel, deviceNode }); 0130 return cmd.run(-1) && cmd.exitCode() == 0; 0131 } 0132 0133 bool jfs::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) 0134 { 0135 Q_UNUSED(mountPoint) 0136 return writeLabel(report, deviceNode, newLabel); 0137 } 0138 0139 bool jfs::check(Report& report, const QString& deviceNode) const 0140 { 0141 ExternalCommand cmd(report, QStringLiteral("fsck.jfs"), { QStringLiteral("-f"), deviceNode }); 0142 return cmd.run(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 1); 0143 } 0144 0145 bool jfs::create(Report& report, const QString& deviceNode) 0146 { 0147 ExternalCommand cmd(report, QStringLiteral("mkfs.jfs"), { QStringLiteral("-q"), deviceNode }); 0148 return cmd.run(-1) && cmd.exitCode() == 0; 0149 } 0150 0151 bool jfs::resize(Report& report, const QString& deviceNode, qint64) const 0152 { 0153 QTemporaryDir tempDir; 0154 if (!tempDir.isValid()) { 0155 report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition <filename>%1</filename> failed: Could not create temp dir.", deviceNode); 0156 return false; 0157 } 0158 0159 bool rval = false; 0160 0161 ExternalCommand mountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--type"), QStringLiteral("jfs"), deviceNode, tempDir.path() }); 0162 0163 if (mountCmd.run(-1)) { 0164 ExternalCommand resizeMountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--type"), QStringLiteral("jfs"), QStringLiteral("--options"), QStringLiteral("remount,resize"), deviceNode, tempDir.path() }); 0165 0166 if (resizeMountCmd.run(-1) && resizeMountCmd.exitCode() == 0) 0167 rval = true; 0168 else 0169 report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition <filename>%1</filename> failed: Remount failed.", deviceNode); 0170 0171 ExternalCommand unmountCmd(report, QStringLiteral("umount"), { tempDir.path() }); 0172 0173 if (!unmountCmd.run(-1)) 0174 report.line() << xi18nc("@info:progress", "<warning>Resizing JFS file system on partition <filename>%1</filename>: Unmount failed.</warning>", deviceNode); 0175 } else 0176 report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition <filename>%1</filename> failed: Initial mount failed.", deviceNode); 0177 0178 return rval; 0179 } 0180 bool jfs::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64) const 0181 { 0182 0183 ExternalCommand resizeMountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--type"), QStringLiteral("jfs"), QStringLiteral("--options"), QStringLiteral("remount,resize"), deviceNode, mountPoint }); 0184 0185 if (resizeMountCmd.run(-1) && resizeMountCmd.exitCode() == 0) 0186 return true; 0187 0188 report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition <filename>%1</filename> failed: Remount failed.", deviceNode); 0189 return false; 0190 } 0191 }