File indexing completed on 2024-05-05 05:48:46
0001 /* 0002 SPDX-FileCopyrightText: 2012-2018 Andrius Štikonas <andrius@stikonas.eu> 0003 SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net> 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/nilfs2.h" 0011 0012 #include "util/externalcommand.h" 0013 #include "util/capacity.h" 0014 #include "util/report.h" 0015 0016 #include <cmath> 0017 0018 #include <QRegularExpression> 0019 #include <QString> 0020 #include <QTemporaryDir> 0021 #include <QUuid> 0022 0023 #include <KLocalizedString> 0024 0025 namespace FS 0026 { 0027 FileSystem::CommandSupportType nilfs2::m_GetUsed = FileSystem::cmdSupportNone; 0028 FileSystem::CommandSupportType nilfs2::m_GetLabel = FileSystem::cmdSupportNone; 0029 FileSystem::CommandSupportType nilfs2::m_Create = FileSystem::cmdSupportNone; 0030 FileSystem::CommandSupportType nilfs2::m_Grow = FileSystem::cmdSupportNone; 0031 FileSystem::CommandSupportType nilfs2::m_Shrink = FileSystem::cmdSupportNone; 0032 FileSystem::CommandSupportType nilfs2::m_Move = FileSystem::cmdSupportNone; 0033 FileSystem::CommandSupportType nilfs2::m_Check = FileSystem::cmdSupportNone; 0034 FileSystem::CommandSupportType nilfs2::m_Copy = FileSystem::cmdSupportNone; 0035 FileSystem::CommandSupportType nilfs2::m_Backup = FileSystem::cmdSupportNone; 0036 FileSystem::CommandSupportType nilfs2::m_SetLabel = FileSystem::cmdSupportNone; 0037 FileSystem::CommandSupportType nilfs2::m_UpdateUUID = FileSystem::cmdSupportNone; 0038 FileSystem::CommandSupportType nilfs2::m_GetUUID = FileSystem::cmdSupportNone; 0039 0040 nilfs2::nilfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) : 0041 FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Nilfs2) 0042 { 0043 } 0044 0045 void nilfs2::init() 0046 { 0047 m_Create = findExternal(QStringLiteral("mkfs.nilfs2")) ? cmdSupportFileSystem : cmdSupportNone; 0048 m_Check = /*findExternal(QStringLiteral("fsck.nilfs2")) ? cmdSupportFileSystem : */cmdSupportNone; 0049 0050 m_GetLabel = cmdSupportCore; 0051 m_SetLabel = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; 0052 m_UpdateUUID = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; 0053 0054 m_Grow = findExternal(QStringLiteral("nilfs-resize")) ? cmdSupportFileSystem : cmdSupportNone; 0055 m_GetUsed = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; 0056 m_Shrink = (m_Grow != cmdSupportNone && m_GetUsed != cmdSupportNone) ? cmdSupportFileSystem : cmdSupportNone; 0057 0058 m_Copy =/* (m_Check != cmdSupportNone) ?*/ cmdSupportCore /*: cmdSupportNone*/; 0059 m_Move =/* (m_Check != cmdSupportNone) ?*/ cmdSupportCore /*: cmdSupportNone*/; 0060 0061 m_GetLabel = cmdSupportCore; 0062 m_Backup = cmdSupportCore; 0063 m_GetUUID = cmdSupportCore; 0064 } 0065 0066 bool nilfs2::supportToolFound() const 0067 { 0068 return 0069 m_GetUsed != cmdSupportNone && 0070 m_GetLabel != cmdSupportNone && 0071 m_SetLabel != cmdSupportNone && 0072 m_Create != cmdSupportNone && 0073 // m_Check != cmdSupportNone && 0074 m_UpdateUUID != cmdSupportNone && 0075 m_Grow != cmdSupportNone && 0076 m_Shrink != cmdSupportNone && 0077 m_Copy != cmdSupportNone && 0078 m_Move != cmdSupportNone && 0079 m_Backup != cmdSupportNone && 0080 m_GetUUID != cmdSupportNone; 0081 } 0082 0083 FileSystem::SupportTool nilfs2::supportToolName() const 0084 { 0085 return SupportTool(QStringLiteral("nilfs2-utils"), QUrl(QStringLiteral("https://github.com/nilfs-dev/nilfs-utils"))); 0086 } 0087 0088 qint64 nilfs2::minCapacity() const 0089 { 0090 return 128 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); 0091 } 0092 0093 qint64 nilfs2::maxCapacity() const 0094 { 0095 return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); 0096 } 0097 0098 int nilfs2::maxLabelLength() const 0099 { 0100 return 80; 0101 } 0102 0103 bool nilfs2::check(Report& report, const QString& deviceNode) const 0104 { 0105 ExternalCommand cmd(report, QStringLiteral("fsck.nilfs2"), { deviceNode }); 0106 return cmd.run(-1) && cmd.exitCode() == 0; 0107 } 0108 0109 bool nilfs2::create(Report& report, const QString& deviceNode) 0110 { 0111 ExternalCommand cmd(report, QStringLiteral("mkfs.nilfs2"), { QStringLiteral("-f"), deviceNode }); 0112 return cmd.run(-1) && cmd.exitCode() == 0; 0113 } 0114 0115 qint64 nilfs2::readUsedCapacity(const QString& deviceNode) const 0116 { 0117 ExternalCommand cmd(QStringLiteral("nilfs-tune"), { QStringLiteral("-l"), deviceNode }); 0118 0119 if (cmd.run(-1) && cmd.exitCode() == 0) { 0120 QRegularExpression re(QStringLiteral("Block size:\\s+(\\d+)")); 0121 QRegularExpressionMatch reBlockSize = re.match(cmd.output()); 0122 re.setPattern(QStringLiteral("Device size:\\s+(\\d+)")); 0123 QRegularExpressionMatch reDeviceSize = re.match(cmd.output()); 0124 re.setPattern(QStringLiteral("Free blocks count:\\s+(\\d+)")); 0125 QRegularExpressionMatch reFreeBlocks = re.match(cmd.output()); 0126 if (reBlockSize.hasMatch() && reDeviceSize.hasMatch() && reFreeBlocks.hasMatch()) 0127 return reDeviceSize.captured(1).toLongLong() - reBlockSize.captured(1).toLongLong() * reFreeBlocks.captured(1).toLongLong(); 0128 } 0129 0130 return -1; 0131 } 0132 0133 bool nilfs2::resize(Report& report, const QString& deviceNode, qint64 length) const 0134 { 0135 QTemporaryDir tempDir; 0136 if (!tempDir.isValid()) { 0137 report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition <filename>%1</filename> failed: Could not create temp dir.", deviceNode); 0138 return false; 0139 } 0140 0141 bool rval = false; 0142 0143 ExternalCommand mountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--types"), QStringLiteral("nilfs2"), deviceNode, tempDir.path() }); 0144 0145 if (mountCmd.run(-1) && mountCmd.exitCode() == 0) { 0146 ExternalCommand resizeCmd(report, QStringLiteral("nilfs-resize"), { QStringLiteral("--verbose"), QStringLiteral("--assume-yes"), deviceNode, QString::number(length) }); 0147 0148 if (resizeCmd.run(-1) && resizeCmd.exitCode() == 0) 0149 rval = true; 0150 else 0151 report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition <filename>%1</filename> failed: NILFS2 file system resize failed.", deviceNode); 0152 0153 ExternalCommand unmountCmd(report, QStringLiteral("umount"), { tempDir.path() }); 0154 0155 if (!unmountCmd.run(-1) && unmountCmd.exitCode() == 0) 0156 report.line() << xi18nc("@info:progress", "<warning>Resizing NILFS2 file system on partition <filename>%1</filename>: Unmount failed.</warning>", deviceNode); 0157 } else 0158 report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition <filename>%1</filename> failed: Initial mount failed.", deviceNode); 0159 0160 return rval; 0161 } 0162 0163 bool nilfs2::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const 0164 { 0165 ExternalCommand resizeCmd(report, QStringLiteral("nilfs-resize"), { QStringLiteral("--verbose"), QStringLiteral("--assume-yes"), deviceNode, QString::number(length) }); 0166 0167 if (resizeCmd.run(-1) && resizeCmd.exitCode() == 0) 0168 return true; 0169 0170 report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition <filename>%1</filename> failed: NILFS2 file system resize failed.", deviceNode); 0171 return false; 0172 } 0173 0174 bool nilfs2::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) 0175 { 0176 ExternalCommand cmd(report, QStringLiteral("nilfs-tune"), { QStringLiteral("-l"), newLabel, deviceNode }); 0177 return cmd.run(-1) && cmd.exitCode() == 0; 0178 } 0179 0180 bool nilfs2::updateUUID(Report& report, const QString& deviceNode) const 0181 { 0182 QUuid uuid = QUuid::createUuid(); 0183 ExternalCommand cmd(report, QStringLiteral("nilfs-tune"), { QStringLiteral("-U"), uuid.toString(), deviceNode }); 0184 return cmd.run(-1) && cmd.exitCode() == 0; 0185 } 0186 }