File indexing completed on 2024-05-05 05:48:45
0001 /* 0002 SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2012-2018 Andrius Štikonas <andrius@stikonas.eu> 0004 SPDX-FileCopyrightText: 2016 Teo Mrnjavac <teo@kde.org> 0005 SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com> 0006 SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net> 0007 SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com> 0008 SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com> 0009 0010 SPDX-License-Identifier: GPL-3.0-or-later 0011 */ 0012 0013 #include "fs/linuxswap.h" 0014 0015 #include "util/externalcommand.h" 0016 0017 #include <KLocalizedString> 0018 0019 #include <QFileInfo> 0020 #include <QRegularExpression> 0021 #include <QTextStream> 0022 0023 namespace FS 0024 { 0025 FileSystem::CommandSupportType linuxswap::m_Create = FileSystem::cmdSupportNone; 0026 FileSystem::CommandSupportType linuxswap::m_Grow = FileSystem::cmdSupportNone; 0027 FileSystem::CommandSupportType linuxswap::m_Shrink = FileSystem::cmdSupportNone; 0028 FileSystem::CommandSupportType linuxswap::m_Move = FileSystem::cmdSupportNone; 0029 FileSystem::CommandSupportType linuxswap::m_Copy = FileSystem::cmdSupportNone; 0030 FileSystem::CommandSupportType linuxswap::m_GetUsed = FileSystem::cmdSupportNone; 0031 FileSystem::CommandSupportType linuxswap::m_GetLabel = FileSystem::cmdSupportNone; 0032 FileSystem::CommandSupportType linuxswap::m_SetLabel = FileSystem::cmdSupportNone; 0033 FileSystem::CommandSupportType linuxswap::m_GetUUID = FileSystem::cmdSupportNone; 0034 FileSystem::CommandSupportType linuxswap::m_UpdateUUID = FileSystem::cmdSupportNone; 0035 0036 linuxswap::linuxswap(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) : 0037 FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::LinuxSwap) 0038 { 0039 } 0040 0041 void linuxswap::init() 0042 { 0043 m_SetLabel = m_Shrink = m_Grow = m_Create = m_UpdateUUID = (findExternal(QStringLiteral("mkswap"))) ? cmdSupportFileSystem : cmdSupportNone; 0044 m_GetLabel = cmdSupportCore; 0045 m_GetUsed = cmdSupportFileSystem; 0046 m_Copy = cmdSupportFileSystem; 0047 m_Move = cmdSupportCore; 0048 m_GetUUID = cmdSupportCore; 0049 } 0050 0051 bool linuxswap::supportToolFound() const 0052 { 0053 return 0054 m_GetUsed != cmdSupportNone && 0055 m_GetLabel != cmdSupportNone && 0056 m_SetLabel != cmdSupportNone && 0057 m_Create != cmdSupportNone && 0058 // m_Check != cmdSupportNone && 0059 m_UpdateUUID != cmdSupportNone && 0060 m_Grow != cmdSupportNone && 0061 m_Shrink != cmdSupportNone && 0062 m_Copy != cmdSupportNone && 0063 m_Move != cmdSupportNone && 0064 // m_Backup != cmdSupportNone && 0065 m_GetUUID != cmdSupportNone; 0066 } 0067 0068 FileSystem::SupportTool linuxswap::supportToolName() const 0069 { 0070 return SupportTool(QStringLiteral("util-linux"), QUrl(QStringLiteral("https://github.com/karelzak/util-linux"))); 0071 } 0072 0073 int linuxswap::maxLabelLength() const 0074 { 0075 return 15; 0076 } 0077 0078 bool linuxswap::create(Report& report, const QString& deviceNode) 0079 { 0080 ExternalCommand cmd(report, QStringLiteral("mkswap"), { deviceNode }); 0081 return cmd.run(-1) && cmd.exitCode() == 0; 0082 } 0083 0084 bool linuxswap::resize(Report& report, const QString& deviceNode, qint64 length) const 0085 { 0086 Q_UNUSED(length) 0087 const QString label = readLabel(deviceNode); 0088 const QString uuid = readUUID(deviceNode); 0089 0090 QStringList args; 0091 if (!label.isEmpty()) 0092 args << QStringLiteral("--label") << label; 0093 if (!uuid.isEmpty()) 0094 args << QStringLiteral("--uuid") << uuid; 0095 0096 args << deviceNode; 0097 0098 ExternalCommand cmd(report, QStringLiteral("mkswap"), args); 0099 return cmd.run(-1) && cmd.exitCode() == 0; 0100 } 0101 0102 bool linuxswap::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const 0103 { 0104 const QString label = readLabel(sourceDeviceNode); 0105 const QString uuid = readUUID(sourceDeviceNode); 0106 0107 QStringList args; 0108 if (!label.isEmpty()) 0109 args << QStringLiteral("--label") << label; 0110 if (!uuid.isEmpty()) 0111 args << QStringLiteral("--uuid") << uuid; 0112 0113 args << targetDeviceNode; 0114 0115 ExternalCommand cmd(report, QStringLiteral("mkswap"), args); 0116 return cmd.run(-1) && cmd.exitCode() == 0; 0117 } 0118 0119 bool linuxswap::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) 0120 { 0121 ExternalCommand cmd(report, QStringLiteral("swaplabel"), { QStringLiteral("--label"), newLabel, deviceNode }); 0122 return cmd.run(-1) && cmd.exitCode() == 0; 0123 } 0124 0125 QString linuxswap::mountTitle() const 0126 { 0127 return xi18nc("@title:menu", "Activate swap"); 0128 } 0129 0130 QString linuxswap::unmountTitle() const 0131 { 0132 return xi18nc("@title:menu", "Deactivate swap"); 0133 } 0134 0135 bool linuxswap::canMount(const QString& deviceNode, const QString& mountPoint) const { 0136 Q_UNUSED(deviceNode) 0137 // linux swap doesn't require mount point to activate 0138 return mountPoint != QStringLiteral("/"); 0139 } 0140 0141 bool linuxswap::mount(Report& report, const QString& deviceNode, const QString& mountPoint) 0142 { 0143 Q_UNUSED(mountPoint) 0144 ExternalCommand cmd(report, QStringLiteral("swapon"), { deviceNode }); 0145 return cmd.run(-1) && cmd.exitCode() == 0; 0146 } 0147 0148 bool linuxswap::unmount(Report& report, const QString& deviceNode) 0149 { 0150 ExternalCommand cmd(report, QStringLiteral("swapoff"), { deviceNode }); 0151 return cmd.run(-1) && cmd.exitCode() == 0; 0152 } 0153 0154 bool linuxswap::updateUUID(Report& report, const QString& deviceNode) const 0155 { 0156 const QString label = readLabel(deviceNode); 0157 0158 QStringList args; 0159 if (!label.isEmpty()) 0160 args << QStringLiteral("--label") << label; 0161 0162 args << deviceNode; 0163 0164 ExternalCommand cmd(report, QStringLiteral("mkswap"), args); 0165 return cmd.run(-1) && cmd.exitCode() == 0; 0166 } 0167 0168 qint64 linuxswap::readUsedCapacity(const QString& deviceNode) const 0169 { 0170 QFile swapsFile(QStringLiteral("/proc/swaps")); 0171 0172 if (swapsFile.open(QIODevice::ReadOnly)) { 0173 QByteArray data = swapsFile.readAll(); 0174 swapsFile.close(); 0175 QTextStream in(&data); 0176 while (!in.atEnd()) { 0177 QStringList line = in.readLine().split(QRegularExpression(QStringLiteral("\\s+"))); 0178 QFileInfo kernelPath(deviceNode); 0179 if (line[0] == kernelPath.canonicalFilePath()) 0180 return line[3].toLongLong() * 1024; 0181 } 0182 } 0183 return -1; 0184 } 0185 }