File indexing completed on 2024-05-05 05:48:43
0001 /* 0002 SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2012-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/ext2.h" 0011 0012 #include "util/externalcommand.h" 0013 #include "util/capacity.h" 0014 0015 #include <QRegularExpression> 0016 #include <QString> 0017 0018 namespace FS 0019 { 0020 FileSystem::CommandSupportType ext2::m_GetUsed = FileSystem::cmdSupportNone; 0021 FileSystem::CommandSupportType ext2::m_GetLabel = FileSystem::cmdSupportNone; 0022 FileSystem::CommandSupportType ext2::m_Create = FileSystem::cmdSupportNone; 0023 FileSystem::CommandSupportType ext2::m_Grow = FileSystem::cmdSupportNone; 0024 FileSystem::CommandSupportType ext2::m_Shrink = FileSystem::cmdSupportNone; 0025 FileSystem::CommandSupportType ext2::m_Move = FileSystem::cmdSupportNone; 0026 FileSystem::CommandSupportType ext2::m_Check = FileSystem::cmdSupportNone; 0027 FileSystem::CommandSupportType ext2::m_Copy = FileSystem::cmdSupportNone; 0028 FileSystem::CommandSupportType ext2::m_Backup = FileSystem::cmdSupportNone; 0029 FileSystem::CommandSupportType ext2::m_SetLabel = FileSystem::cmdSupportNone; 0030 FileSystem::CommandSupportType ext2::m_UpdateUUID = FileSystem::cmdSupportNone; 0031 FileSystem::CommandSupportType ext2::m_GetUUID = FileSystem::cmdSupportNone; 0032 0033 ext2::ext2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features, FileSystem::Type t) : 0034 FileSystem(firstsector, lastsector, sectorsused, label, features, t) 0035 { 0036 } 0037 0038 void ext2::init() 0039 { 0040 m_GetUsed = findExternal(QStringLiteral("dumpe2fs")) ? cmdSupportFileSystem : cmdSupportNone; 0041 m_GetLabel = cmdSupportCore; 0042 m_SetLabel = findExternal(QStringLiteral("e2label")) ? cmdSupportFileSystem : cmdSupportNone; 0043 m_Create = findExternal(QStringLiteral("mkfs.ext2")) ? cmdSupportFileSystem : cmdSupportNone; 0044 m_Check = findExternal(QStringLiteral("e2fsck"), { QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; 0045 m_UpdateUUID = findExternal(QStringLiteral("tune2fs")) ? cmdSupportFileSystem : cmdSupportNone; 0046 m_Grow = (m_Check != cmdSupportNone && findExternal(QStringLiteral("resize2fs"))) ? cmdSupportFileSystem : cmdSupportNone; 0047 m_Shrink = (m_Grow != cmdSupportNone && m_GetUsed) != cmdSupportNone ? cmdSupportFileSystem : cmdSupportNone; 0048 m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; 0049 m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; 0050 m_Backup = cmdSupportCore; 0051 m_GetUUID = cmdSupportCore; 0052 0053 if (m_Create == cmdSupportFileSystem) { 0054 addAvailableFeature(QStringLiteral("64bit")); 0055 addAvailableFeature(QStringLiteral("bigalloc")); 0056 addAvailableFeature(QStringLiteral("casefold")); 0057 addAvailableFeature(QStringLiteral("dir_index")); 0058 addAvailableFeature(QStringLiteral("dir_nlink")); 0059 addAvailableFeature(QStringLiteral("ea_inode")); 0060 addAvailableFeature(QStringLiteral("encrypt")); 0061 addAvailableFeature(QStringLiteral("ext_attr")); 0062 addAvailableFeature(QStringLiteral("extent")); 0063 addAvailableFeature(QStringLiteral("extra_isize")); 0064 addAvailableFeature(QStringLiteral("filetype")); 0065 addAvailableFeature(QStringLiteral("flex_bg")); 0066 addAvailableFeature(QStringLiteral("has_journal")); 0067 addAvailableFeature(QStringLiteral("huge_file")); 0068 addAvailableFeature(QStringLiteral("inline_data")); 0069 addAvailableFeature(QStringLiteral("journal_dev")); 0070 addAvailableFeature(QStringLiteral("large_dir")); 0071 addAvailableFeature(QStringLiteral("large_file")); 0072 addAvailableFeature(QStringLiteral("metadata_csum")); 0073 addAvailableFeature(QStringLiteral("metadata_csum_seed")); 0074 addAvailableFeature(QStringLiteral("meta_bg")); 0075 addAvailableFeature(QStringLiteral("mmp")); 0076 addAvailableFeature(QStringLiteral("project")); 0077 addAvailableFeature(QStringLiteral("quota")); 0078 addAvailableFeature(QStringLiteral("resize_inode")); 0079 addAvailableFeature(QStringLiteral("sparse_super")); 0080 addAvailableFeature(QStringLiteral("sparse_super2")); 0081 addAvailableFeature(QStringLiteral("uninit_bg")); 0082 } 0083 } 0084 0085 bool ext2::supportToolFound() const 0086 { 0087 return 0088 m_GetUsed != cmdSupportNone && 0089 m_GetLabel != cmdSupportNone && 0090 m_SetLabel != cmdSupportNone && 0091 m_Create != cmdSupportNone && 0092 m_Check != cmdSupportNone && 0093 m_UpdateUUID != cmdSupportNone && 0094 m_Grow != cmdSupportNone && 0095 m_Shrink != cmdSupportNone && 0096 m_Copy != cmdSupportNone && 0097 m_Move != cmdSupportNone && 0098 m_Backup != cmdSupportNone && 0099 m_GetUUID != cmdSupportNone; 0100 } 0101 0102 FileSystem::SupportTool ext2::supportToolName() const 0103 { 0104 return SupportTool(QStringLiteral("e2fsprogs"), QUrl(QStringLiteral("http://e2fsprogs.sf.net"))); 0105 } 0106 0107 qint64 ext2::maxCapacity() const 0108 { 0109 return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); 0110 } 0111 0112 int ext2::maxLabelLength() const 0113 { 0114 return 16; 0115 } 0116 0117 qint64 ext2::readUsedCapacity(const QString& deviceNode) const 0118 { 0119 ExternalCommand cmd(QStringLiteral("dumpe2fs"), { QStringLiteral("-h"), deviceNode }); 0120 0121 if (cmd.run()) { 0122 qint64 blockCount = -1; 0123 QRegularExpression re(QStringLiteral("Block count:\\s+(\\d+)")); 0124 QRegularExpressionMatch reBlockCount = re.match(cmd.output()); 0125 0126 if (reBlockCount.hasMatch()) 0127 blockCount = reBlockCount.captured(1).toLongLong(); 0128 0129 qint64 freeBlocks = -1; 0130 re.setPattern(QStringLiteral("Free blocks:\\s+(\\d+)")); 0131 QRegularExpressionMatch reFreeBlocks = re.match(cmd.output()); 0132 0133 if (reFreeBlocks.hasMatch()) 0134 freeBlocks = reFreeBlocks.captured(1).toLongLong(); 0135 0136 qint64 blockSize = -1; 0137 re.setPattern(QStringLiteral("Block size:\\s+(\\d+)")); 0138 QRegularExpressionMatch reBlockSize = re.match(cmd.output()); 0139 0140 if (reBlockSize.hasMatch()) 0141 blockSize = reBlockSize.captured(1).toLongLong(); 0142 0143 if (blockCount > -1 && freeBlocks > -1 && blockSize > -1) 0144 return (blockCount - freeBlocks) * blockSize; 0145 } 0146 0147 return -1; 0148 } 0149 0150 bool ext2::check(Report& report, const QString& deviceNode) const 0151 { 0152 ExternalCommand cmd(report, QStringLiteral("e2fsck"), { QStringLiteral("-f"), QStringLiteral("-y"), QStringLiteral("-v"), deviceNode }); 0153 return cmd.run(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 1 || cmd.exitCode() == 2 || cmd.exitCode() == 256); 0154 } 0155 0156 bool ext2::create(Report& report, const QString& deviceNode) 0157 { 0158 QStringList args = QStringList(); 0159 0160 if (!this->features().isEmpty()) { 0161 QStringList feature_list = QStringList(); 0162 for (const auto& k : this->features().keys()) { 0163 const auto& v = this->features().value(k); 0164 if (v.type() == QVariant::Type::Bool) { 0165 if (v.toBool()) 0166 feature_list << k; 0167 else 0168 feature_list << (QStringLiteral("^") + k); 0169 } else { 0170 qWarning() << "Ignoring feature" << k << "of type" << v.type() << "; requires type QVariant::bool."; 0171 } 0172 } 0173 args << QStringLiteral("-O") << feature_list.join(QStringLiteral(",")); 0174 } 0175 args << QStringLiteral("-qF") << deviceNode; 0176 0177 ExternalCommand cmd(report, QStringLiteral("mkfs.ext2"), args); 0178 return cmd.run(-1) && cmd.exitCode() == 0; 0179 } 0180 0181 bool ext2::resize(Report& report, const QString& deviceNode, qint64 length) const 0182 { 0183 const QString len = QString::number(length / 512) + QStringLiteral("s"); 0184 0185 ExternalCommand cmd(report, QStringLiteral("resize2fs"), { deviceNode, len }); 0186 return cmd.run(-1) && cmd.exitCode() == 0; 0187 } 0188 0189 bool ext2::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) 0190 { 0191 ExternalCommand cmd(report, QStringLiteral("e2label"), { deviceNode, newLabel }); 0192 return cmd.run(-1) && cmd.exitCode() == 0; 0193 } 0194 0195 bool ext2::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) 0196 { 0197 Q_UNUSED(mountPoint) 0198 return writeLabel(report, deviceNode, newLabel); 0199 } 0200 0201 bool ext2::updateUUID(Report& report, const QString& deviceNode) const 0202 { 0203 ExternalCommand cmd(report, QStringLiteral("tune2fs"), { QStringLiteral("-U"), QStringLiteral("random"), deviceNode }); 0204 return cmd.run(-1) && cmd.exitCode() == 0; 0205 } 0206 }