File indexing completed on 2024-05-26 04:05:32

0001 /*
0002     SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "fstabwatcher.h"
0008 #include "fstab_debug.h"
0009 #include "soliddefs_p.h"
0010 
0011 #include <QCoreApplication>
0012 #include <QFile>
0013 #include <QFileSystemWatcher>
0014 #include <QSocketNotifier>
0015 
0016 namespace Solid
0017 {
0018 namespace Backends
0019 {
0020 namespace Fstab
0021 {
0022 Q_GLOBAL_STATIC(FstabWatcher, globalFstabWatcher)
0023 
0024 static const QString s_mtabFile = QStringLiteral("/etc/mtab");
0025 #ifdef Q_OS_SOLARIS
0026 static const QString s_fstabFile = QStringLiteral("/etc/vfstab");
0027 #else
0028 static const QString s_fstabFile = QStringLiteral("/etc/fstab");
0029 #endif
0030 static const QString s_fstabPath = QStringLiteral("/etc");
0031 
0032 FstabWatcher::FstabWatcher()
0033     : m_isRoutineInstalled(false)
0034     , m_fileSystemWatcher(new QFileSystemWatcher(this))
0035 {
0036     if (qApp) {
0037         connect(qApp, &QCoreApplication::aboutToQuit, this, &FstabWatcher::orphanFileSystemWatcher);
0038     }
0039 
0040     m_mtabFile = new QFile(s_mtabFile, this);
0041     if (m_mtabFile && m_mtabFile->symLinkTarget().startsWith("/proc/") && m_mtabFile->open(QIODevice::ReadOnly)) {
0042         m_mtabSocketNotifier = new QSocketNotifier(m_mtabFile->handle(), QSocketNotifier::Exception, this);
0043         connect(m_mtabSocketNotifier, &QSocketNotifier::activated, this, &FstabWatcher::mtabChanged);
0044     } else {
0045         m_fileSystemWatcher->addPath(s_mtabFile);
0046     }
0047 
0048     m_fileSystemWatcher->addPath(s_fstabPath);
0049     connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &) {
0050         if (!m_isFstabWatched) {
0051             m_isFstabWatched = m_fileSystemWatcher->addPath(s_fstabFile);
0052             if (m_isFstabWatched) {
0053                 qCDebug(FSTAB_LOG) << "Re-added" << s_fstabFile;
0054                 Q_EMIT onFileChanged(s_fstabFile);
0055             }
0056         }
0057     });
0058 
0059     m_isFstabWatched = m_fileSystemWatcher->addPath(s_fstabFile);
0060     connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &FstabWatcher::onFileChanged);
0061 }
0062 
0063 FstabWatcher::~FstabWatcher()
0064 {
0065     // The QFileSystemWatcher doesn't work correctly in a singleton
0066     // The solution so far was to destroy the QFileSystemWatcher when the application quits
0067     // But we have some crash with this solution.
0068     // For the moment to workaround the problem, we detach the QFileSystemWatcher from the parent
0069     // effectively leaking it on purpose.
0070 
0071 #if 0
0072     //qRemovePostRoutine(globalFstabWatcher.destroy);
0073 #else
0074     m_fileSystemWatcher->setParent(nullptr);
0075 #endif
0076 }
0077 
0078 void FstabWatcher::orphanFileSystemWatcher()
0079 {
0080     m_fileSystemWatcher->setParent(nullptr);
0081 }
0082 
0083 FstabWatcher *FstabWatcher::instance()
0084 {
0085 #if 0
0086     FstabWatcher *fstabWatcher = globalFstabWatcher;
0087 
0088     if (fstabWatcher && !fstabWatcher->m_isRoutineInstalled) {
0089         qAddPostRoutine(globalFstabWatcher.destroy);
0090         fstabWatcher->m_isRoutineInstalled = true;
0091     }
0092     return fstabWatcher;
0093 #else
0094     return globalFstabWatcher;
0095 #endif
0096 }
0097 
0098 void FstabWatcher::onFileChanged(const QString &path)
0099 {
0100     if (path == s_mtabFile) {
0101         Q_EMIT mtabChanged();
0102         if (!m_fileSystemWatcher->files().contains(s_mtabFile)) {
0103             m_fileSystemWatcher->addPath(s_mtabFile);
0104         }
0105     }
0106     if (path == s_fstabFile) {
0107         Q_EMIT fstabChanged();
0108         if (!m_fileSystemWatcher->files().contains(s_fstabFile)) {
0109             m_isFstabWatched = m_fileSystemWatcher->addPath(s_fstabFile);
0110             qCDebug(FSTAB_LOG) << "Fstab removed, re-added:" << m_isFstabWatched;
0111         }
0112     }
0113 }
0114 
0115 }
0116 }
0117 } // namespace Solid:Backends::Fstab
0118 
0119 #include "moc_fstabwatcher.cpp"