From 34712dd2ed499dd2c78ea07de9b3b499f32c86f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 13 Sep 2017 18:46:33 +0100 Subject: [PATCH] Add fstab file parser. Remove dependency on KMountPoint and hence KIO. --- CMakeLists.txt | 1 - src/CMakeLists.txt | 1 - src/core/fstab.cpp | 132 ++++++++++++++++++++++++++++++++++++++++ src/core/fstab.h | 85 ++++++++++++++++++++++++++ src/fs/filesystem.cpp | 31 ++++++---- src/util/htmlreport.cpp | 4 +- 6 files changed, 237 insertions(+), 17 deletions(-) create mode 100644 src/core/fstab.cpp create mode 100644 src/core/fstab.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c949dcc..0af09d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,6 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS # Load the frameworks we need find_package(KF5 REQUIRED I18n - KIO Service WidgetsAddons ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dc93d24..74a82fd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,7 +45,6 @@ target_link_libraries( kpmcore ${LIBATASMART_LIBRARIES} Qt5::DBus KF5::I18n - KF5::KIOCore KF5::Service KF5::WidgetsAddons ) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp new file mode 100644 index 0000000..465c7e7 --- /dev/null +++ b/src/core/fstab.cpp @@ -0,0 +1,132 @@ +/************************************************************************* + * Copyright (C) 2009, 2010 by Volker Lanz * + * Copyright (C) 2016 by Teo Mrnjavac * + * Copyright (C) 2017 by Andrius Štikonas * + * * + * 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 .* + *************************************************************************/ + +#include "core/fstab.h" + +#include + +#include +#include +#include + +static QString findBlkIdDevice(const QString& token, const QString& value) +{ + blkid_cache cache; + QString rval; + + if (blkid_get_cache(&cache, nullptr) == 0) { + if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), &cache)) { + rval = QString::fromLocal8Bit(c); + free(c); + } + + blkid_put_cache(cache); + } + + return rval; +} + +FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) + : m_fsSpec(fsSpec) + , m_mountPoint(mountPoint) + , m_type(type) + , m_options(options) + , m_dumpFreq(dumpFreq) + , m_passNumber(passNumber) + , m_comment(comment) +{ + m_entryType = FstabEntryType::comment; + if (fsSpec.startsWith(QStringLiteral("UUID="))) { + m_entryType = FstabEntryType::uuid; + m_deviceNode = findBlkIdDevice(QStringLiteral("UUID"), QString(fsSpec).remove(QStringLiteral("UUID="))); + } else if (fsSpec.startsWith(QStringLiteral("LABEL="))) { + m_entryType = FstabEntryType::label; + m_deviceNode = findBlkIdDevice(QStringLiteral("LABEL"), QString(fsSpec).remove(QStringLiteral("LABEL="))); + } else if (fsSpec.startsWith(QStringLiteral("PARTUUID="))) { + m_entryType = FstabEntryType::uuid; + m_deviceNode = findBlkIdDevice(QStringLiteral("PARTUUID"), QString(fsSpec).remove(QStringLiteral("PARTUUID="))); + } else if (fsSpec.startsWith(QStringLiteral("PARTLABEL="))) { + m_entryType = FstabEntryType::label; + m_deviceNode = findBlkIdDevice(QStringLiteral("PARTLABEL"), QString(fsSpec).remove(QStringLiteral("PARTLABEL="))); + } else if (fsSpec.startsWith(QStringLiteral("/"))) { + m_entryType = FstabEntryType::deviceNode; + m_deviceNode = fsSpec; + } +} + +FstabEntryList readFstabEntries( const QString& fstabPath ) +{ + FstabEntryList fstabEntries; + QFile fstabFile( fstabPath ); + if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + const QStringList fstabLines = QString::fromLocal8Bit(fstabFile.readAll()).split( QLatin1Char('\n') ); + for ( const QString& rawLine : fstabLines ) + { + QString line = rawLine.simplified(); + if ( line.startsWith( QLatin1Char('#') ) || line.isEmpty()) { + fstabEntries.append( { {}, {}, {}, {}, {}, {}, line } ); + continue; + } + + QString comment = line.section( QLatin1Char('#'), 1 ); + QStringList splitLine = line.section( QLatin1Char('#'), 0, 0 ).split( QLatin1Char(' ') ); + + // We now split the standard components of /etc/fstab entry: + // (0) path, or UUID, or LABEL, etc, + // (1) mount point, + // (2) file system type, + // (3) options, + // (4) dump frequency (optional, defaults to 0), no comment is allowed if omitted, + // (5) pass number (optional, defaults to 0), no comment is allowed if omitted, + // (#) comment (optional). + switch (splitLine.length()) { + case 4: + fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3) } ); + break; + case 5: + fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt() } ); + break; + case 6: + fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt(), splitLine.at(5).toInt(), comment } ); + break; + default: + fstabEntries.append( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } ); + } + } + + fstabFile.close(); + } + + return fstabEntries; +} + +QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath) +{ + QStringList mountPoints; + QFileInfo kernelPath(deviceNode); + QString canonicalPath = kernelPath.canonicalFilePath(); + const FstabEntryList fstabEntryList = readFstabEntries( fstabPath ); + for (const FstabEntry &entry : fstabEntryList) { + QFileInfo kernelPath2(entry.deviceNode()); + if (kernelPath2.canonicalFilePath() == canonicalPath) + mountPoints.append(entry.mountPoint()); + } + return mountPoints; +} diff --git a/src/core/fstab.h b/src/core/fstab.h new file mode 100644 index 0000000..dcf19e0 --- /dev/null +++ b/src/core/fstab.h @@ -0,0 +1,85 @@ +/************************************************************************* + * Copyright (C) 2017 by Andrius Štikonas * + * * + * 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 .* + *************************************************************************/ + +#ifndef KPMCORE_FSTAB_H +#define KPMCORE_FSTAB_H + +#include "util/libpartitionmanagerexport.h" + +#include +#include + +enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment }; + +/** Base class for fstab handling. + + FstabEntry stores a single line of /etc/fstab file which can be a comment + + @author Andrius Štikonas +*/ + +class LIBKPMCORE_EXPORT FstabEntry +{ +public: + FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq = 0, int passNumber = 0, const QString& comment = QString()); + + const QString& fsSpec() const { + return m_fsSpec; /**< @return the fs_spec field of fstab entry */ + } + const QString& deviceNode() const { + return m_deviceNode; /**< @return the device node corresponding to fs_spec entry */ + } + const QString& mountPoint() const { + return m_mountPoint; /**< @return the mount point (target) for the file system */ + } + const QString& type() const { + return m_type; /**< @return the type of the file system */ + } + const QString& options() const { + return m_options; /**< @return the mount options associated with the file system */ + } + int dumpFreq() const { + return m_dumpFreq; /**< @return the fs_freq field of fstab entry */ + } + int passNumber() const { + return m_passNumber; /**< @return the fs_passno field of fstab entry */ + } + const QString& comment() const { + return m_comment; /**< @return commented part of the line in fstab file */ + } + FstabEntryType entryType() const { + return m_entryType; /**< @return the type of fstab entry, e.g. device node or UUID or comment only */ + } + +private: + QString m_fsSpec; + QString m_deviceNode; + QString m_mountPoint; + QString m_type; + QString m_options; + int m_dumpFreq; + int m_passNumber; + QString m_comment; + FstabEntryType m_entryType; +}; + +typedef QList FstabEntryList; + +FstabEntryList readFstabEntries(const QString& fstabPath = QStringLiteral("/etc/fstab")); +QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath = QStringLiteral("/etc/fstab")); + +#endif diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index 0563ee2..23f5dde 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -17,6 +17,8 @@ * along with this program. If not, see .* *************************************************************************/ +#include "core/fstab.h" + #include "fs/filesystem.h" #include "fs/lvm2_pv.h" @@ -29,10 +31,10 @@ #include -#include #include -#include +#include +#include const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode = { @@ -125,19 +127,22 @@ FileSystem::Type FileSystem::detectFileSystem(const QString& partitionPath) QString FileSystem::detectMountPoint(FileSystem* fs, const QString& partitionPath) { - QString mountPoint = QString(); + if (fs->type() == FileSystem::Lvm2_PV) + return FS::lvm2_pv::getVGName(partitionPath); - KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName); - mountPoints.append(KMountPoint::possibleMountPoints(KMountPoint::NeedRealDeviceName)); - - if (fs->type() == FileSystem::Lvm2_PV) { - mountPoint = FS::lvm2_pv::getVGName(partitionPath); - } else { - mountPoint = mountPoints.findByDevice(partitionPath) ? - mountPoints.findByDevice(partitionPath)->mountPoint() : - QString(); + QStringList mountPoints; + QFileInfo kernelPath(partitionPath); + const QList mountedVolumes = QStorageInfo::mountedVolumes(); + for (const QStorageInfo &storage : QStorageInfo::mountedVolumes()) { + QFileInfo kernelPath2(QString::fromUtf8(storage.device())); + if (kernelPath2.canonicalFilePath() == kernelPath.canonicalFilePath() ) { + mountPoints.append(storage.rootPath()); + } } - return mountPoint; + + mountPoints.append(possibleMountPoints(partitionPath)); + + return mountPoints.first(); } bool FileSystem::detectMountStatus(FileSystem* fs, const QString& partitionPath) diff --git a/src/util/htmlreport.cpp b/src/util/htmlreport.cpp index 20c8f7f..e0b00d6 100644 --- a/src/util/htmlreport.cpp +++ b/src/util/htmlreport.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include @@ -77,7 +77,7 @@ QString HtmlReport::header() << tableLine(i18n("Date:"), QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat)) << tableLine(i18n("Program version:"), QCoreApplication::applicationVersion()) << tableLine(i18n("Backend:"), QStringLiteral("%1 (%2)").arg(CoreBackendManager::self()->backend()->id()).arg(CoreBackendManager::self()->backend()->version())) - << tableLine(i18n("KDE Frameworks version:"), QStringLiteral(KIO_VERSION_STRING)) + << tableLine(i18n("KDE Frameworks version:"), QStringLiteral(KI18N_VERSION_STRING)) << tableLine(i18n("Machine:"), unameString) << "\n
\n";