8#include "fstabhandling.h"
9#include "fstab_debug.h"
14#include <QRegularExpression>
15#include <QStandardPaths>
17#include <QThreadStorage>
19#include <solid/devices/soliddefs_p.h>
21#include <solid/config-solid.h>
39#define FSTAB "/etc/fstab"
47Solid::Backends::Fstab::FstabHandling::FstabHandling()
48 : m_fstabCacheValid(false)
49 , m_mtabCacheValid(false)
53bool _k_isFstabNetworkFileSystem(
const QString &fstype,
const QString &devName)
68bool _k_isFstabSupportedLocalFileSystem(
const QString &fstype)
82 return QStringLiteral(
"fuse.%1").arg(orig);
90 return fstype + mountpoint;
97 auto _mountpoint = mountpoint;
107void Solid::Backends::Fstab::FstabHandling::_k_updateFstabMountPointsCache()
109 if (globalFstabCache->localData().m_fstabCacheValid) {
113 globalFstabCache->localData().m_fstabCache.clear();
114 globalFstabCache->localData().m_fstabOptionsCache.clear();
118 struct libmnt_table *table = mnt_new_table();
123 if (mnt_table_parse_fstab(table, NULL) != 0) {
124 mnt_free_table(table);
128 struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD);
129 struct libmnt_fs *fs;
131 while (mnt_table_next_fs(table, itr, &fs) == 0) {
134 if (_k_isFstabNetworkFileSystem(fstype, fsname) || _k_isFstabSupportedLocalFileSystem(fstype)) {
136 const QString device = _k_deviceNameForMountpoint(fsname, fstype, mountpoint);
137 char *
name = mnt_fs_strdup_options(fs);
141 globalFstabCache->localData().m_fstabCache.insert(device, mountpoint);
142 globalFstabCache->localData().m_fstabFstypeCache.insert(device, fstype);
143 for (
const auto &optionLine : options) {
144 const auto split = optionLine.split(
QLatin1Char(
'='));
145 const auto optionName = split[0];
146 const auto optionValue = split.size() > 1 ? split[1] :
QString{};
148 globalFstabCache->localData().m_fstabOptionsCache[device].
insert(optionName, optionValue);
155 mnt_free_table(table);
159 QFile fstab(QStringLiteral(FSTAB));
167 while (!stream.atEnd()) {
175 if (items.
count() < 4) {
180 const QString fstype = _k_mntFstype(items.
at(2));
183 if (_k_isFstabNetworkFileSystem(fstype, device) || _k_isFstabSupportedLocalFileSystem(fstype)) {
193 globalFstabCache->localData().m_fstabCache.insert(device, mountpoint);
199 globalFstabCache->localData().m_fstabCacheValid =
true;
202QStringList Solid::Backends::Fstab::FstabHandling::deviceList()
204 _k_updateFstabMountPointsCache();
205 _k_updateMtabMountPointsCache();
207 QStringList devices = globalFstabCache->localData().m_mtabCache.keys();
212 for (
auto it = globalFstabCache->localData().m_fstabCache.constBegin(), end = globalFstabCache->localData().m_fstabCache.constEnd(); it != end; ++it) {
213 auto device = it.key();
226 if (!devices.
contains(deviceName)) {
235 _k_updateFstabMountPointsCache();
236 _k_updateMtabMountPointsCache();
238 QStringList mountpoints = globalFstabCache->localData().m_fstabCache.values(device);
239 mountpoints += globalFstabCache->localData().m_mtabCache.values(device);
246 _k_updateFstabMountPointsCache();
247 _k_updateMtabMountPointsCache();
249 auto options = globalFstabCache->localData().m_mtabOptionsCache.value(device);
251 const auto optionsFstab = globalFstabCache->localData().m_fstabOptionsCache.value(device);
252 for (
const auto &it : optionsFstab.asKeyValueRange()) {
253 if (!options.contains(it.first)) {
254 options.insert(it.first, it.second);
261QString Solid::Backends::Fstab::FstabHandling::fstype(
const QString &device)
263 _k_updateFstabMountPointsCache();
265 return globalFstabCache->localData().m_fstabFstypeCache.value(device);
268bool Solid::Backends::Fstab::FstabHandling::callSystemCommand(
const QString &commandName,
271 std::function<
void(
QProcess *)> callback)
273 static const QStringList searchPaths{QStringLiteral(
"/sbin"), QStringLiteral(
"/bin"), QStringLiteral(
"/usr/sbin"), QStringLiteral(
"/usr/bin")};
277 qCWarning(FSTAB_LOG) <<
"Couldn't find executable" << commandName <<
"in" << joinedPaths;
288 Q_UNUSED(exitStatus);
297 process->
start(exec, args);
307void Solid::Backends::Fstab::FstabHandling::_k_updateMtabMountPointsCache()
309 if (globalFstabCache->localData().m_mtabCacheValid) {
313 globalFstabCache->localData().m_mtabCache.clear();
314 globalFstabCache->localData().m_mtabOptionsCache.clear();
318#if GETMNTINFO_USES_STATVFS
319 struct statvfs *mounted;
321 struct statfs *mounted;
324 int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
326 for (
int i = 0; i < num_fs; i++) {
328 if (_k_isFstabNetworkFileSystem(type,
QString()) || _k_isFstabSupportedLocalFileSystem(type)) {
331 const QString device = _k_deviceNameForMountpoint(fsname, type, mountpoint);
332 globalFstabCache->localData().m_mtabCache.insert(device, mountpoint);
333 globalFstabCache->localData().m_fstabFstypeCache.insert(device, type);
339 struct libmnt_table *table = mnt_new_table();
344 if (mnt_table_parse_mtab(table, NULL) != 0) {
345 mnt_free_table(table);
349 struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD);
350 struct libmnt_fs *fs;
352 while (mnt_table_next_fs(table, itr, &fs) == 0) {
354 if (_k_isFstabNetworkFileSystem(fstype,
QString{}) || _k_isFstabSupportedLocalFileSystem(fstype)) {
357 const QString device = _k_deviceNameForMountpoint(fsname, fstype, mountpoint);
358 char *
name = mnt_fs_strdup_options(fs);
362 globalFstabCache->localData().m_mtabCache.insert(device, mountpoint);
363 globalFstabCache->localData().m_fstabFstypeCache.insert(device, fstype);
364 for (
const auto &optionLine : options) {
365 const auto split = optionLine.split(
QLatin1Char(
'='));
366 const auto optionName = split[0];
367 const auto optionValue = split.size() > 1 ? split[1] :
QString{};
369 globalFstabCache->localData().m_mtabOptionsCache[device].
insert(optionName, optionValue);
376 mnt_free_table(table);
380 globalFstabCache->localData().m_mtabCacheValid =
true;
383QStringList Solid::Backends::Fstab::FstabHandling::currentMountPoints(
const QString &device)
385 _k_updateMtabMountPointsCache();
386 return globalFstabCache->localData().m_mtabCache.values(device);
389void Solid::Backends::Fstab::FstabHandling::flushMtabCache()
391 globalFstabCache->localData().m_mtabCacheValid =
false;
394void Solid::Backends::Fstab::FstabHandling::flushFstabCache()
396 globalFstabCache->localData().m_fstabCacheValid =
false;
Type type(const QSqlDatabase &db)
QString name(StandardAction id)
QString decodeName(const QByteArray &localFileName)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setEnvironment(const QStringList &environment)
void finished(int exitCode, QProcess::ExitStatus exitStatus)
void start(OpenMode mode)
QStringList systemEnvironment()
bool waitForStarted(int msecs)
QString findExecutable(const QString &executableName, const QStringList &paths)
QString & append(QChar ch)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
QString & prepend(QChar ch)
QString simplified() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
qsizetype removeDuplicates()
QStringList & replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)