File indexing completed on 2024-06-09 04:00:37

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 "fstabstorageaccess.h"
0008 #include "fstabwatcher.h"
0009 #include <QStringList>
0010 #include <solid/devices/backends/fstab/fstabdevice.h>
0011 #include <solid/devices/backends/fstab/fstabhandling.h>
0012 #include <solid/devices/backends/fstab/fstabservice.h>
0013 
0014 #include <QDir>
0015 #include <QProcess>
0016 #include <QTimer>
0017 
0018 #include <errno.h>
0019 
0020 #define MTAB "/etc/mtab"
0021 
0022 using namespace Solid::Backends::Fstab;
0023 
0024 FstabStorageAccess::FstabStorageAccess(Solid::Backends::Fstab::FstabDevice *device)
0025     : QObject(device)
0026     , m_fstabDevice(device)
0027 {
0028     QStringList currentMountPoints = FstabHandling::currentMountPoints(device->device());
0029     if (currentMountPoints.isEmpty()) {
0030         QStringList mountPoints = FstabHandling::mountPoints(device->device());
0031         m_filePath = mountPoints.isEmpty() ? QString() : mountPoints.first();
0032         m_isAccessible = false;
0033     } else {
0034         m_filePath = currentMountPoints.first();
0035         m_isAccessible = true;
0036     }
0037 
0038     const bool inUserPath =
0039         m_filePath.startsWith(QLatin1String("/media/")) || m_filePath.startsWith(QLatin1String("/run/media/")) || m_filePath.startsWith(QDir::homePath());
0040 
0041     const bool gvfsHidden = FstabHandling::options(device->device()).contains(QLatin1String("x-gvfs-hide"));
0042     const bool fsIsOverlay = FstabHandling::fstype(device->device()) == QLatin1String("overlay");
0043 
0044     m_isIgnored = gvfsHidden ||
0045         // ignore overlay fs not pointing to / or seemingly mounted by user
0046         (fsIsOverlay && m_filePath != QLatin1String("/") && !inUserPath);
0047 
0048     connect(device, SIGNAL(mtabChanged(QString)), this, SLOT(onMtabChanged(QString)));
0049     QTimer::singleShot(0, this, SLOT(connectDBusSignals()));
0050 }
0051 
0052 FstabStorageAccess::~FstabStorageAccess()
0053 {
0054 }
0055 
0056 void FstabStorageAccess::connectDBusSignals()
0057 {
0058     m_fstabDevice->registerAction("setup", this, SLOT(slotSetupRequested()), SLOT(slotSetupDone(int, QString)));
0059 
0060     m_fstabDevice->registerAction("teardown", this, SLOT(slotTeardownRequested()), SLOT(slotTeardownDone(int, QString)));
0061 }
0062 
0063 const Solid::Backends::Fstab::FstabDevice *FstabStorageAccess::fstabDevice() const
0064 {
0065     return m_fstabDevice;
0066 }
0067 
0068 bool FstabStorageAccess::isAccessible() const
0069 {
0070     return m_isAccessible;
0071 }
0072 
0073 QString FstabStorageAccess::filePath() const
0074 {
0075     return m_filePath;
0076 }
0077 
0078 bool FstabStorageAccess::isIgnored() const
0079 {
0080     return m_isIgnored;
0081 }
0082 
0083 bool FstabStorageAccess::isEncrypted() const
0084 {
0085     return m_fstabDevice->isEncrypted();
0086 }
0087 
0088 bool FstabStorageAccess::setup()
0089 {
0090     if (filePath().isEmpty()) {
0091         return false;
0092     }
0093     m_fstabDevice->broadcastActionRequested("setup");
0094     return FstabHandling::callSystemCommand("mount", {filePath()}, this, [this](QProcess *process) {
0095         if (process->exitCode() == 0) {
0096             m_fstabDevice->broadcastActionDone("setup", Solid::NoError, QString());
0097         } else {
0098             m_fstabDevice->broadcastActionDone("setup", Solid::UnauthorizedOperation, process->readAllStandardError().trimmed());
0099         }
0100     });
0101 }
0102 
0103 void FstabStorageAccess::slotSetupRequested()
0104 {
0105     Q_EMIT setupRequested(m_fstabDevice->udi());
0106 }
0107 
0108 bool FstabStorageAccess::teardown()
0109 {
0110     if (filePath().isEmpty()) {
0111         return false;
0112     }
0113     m_fstabDevice->broadcastActionRequested("teardown");
0114     return FstabHandling::callSystemCommand("umount", {filePath()}, this, [this](QProcess *process) {
0115         if (process->exitCode() == 0) {
0116             m_fstabDevice->broadcastActionDone("teardown", Solid::NoError);
0117         } else if (process->exitCode() == EBUSY) {
0118             m_fstabDevice->broadcastActionDone("teardown", Solid::DeviceBusy);
0119         } else if (process->exitCode() == EPERM) {
0120             m_fstabDevice->broadcastActionDone("teardown", Solid::UnauthorizedOperation, process->readAllStandardError().trimmed());
0121         } else {
0122             m_fstabDevice->broadcastActionDone("teardown", Solid::OperationFailed, process->readAllStandardError().trimmed());
0123         }
0124     });
0125 }
0126 
0127 void FstabStorageAccess::slotTeardownRequested()
0128 {
0129     Q_EMIT teardownRequested(m_fstabDevice->udi());
0130 }
0131 
0132 void FstabStorageAccess::slotSetupDone(int error, const QString &errorString)
0133 {
0134     Q_EMIT setupDone(static_cast<Solid::ErrorType>(error), errorString, m_fstabDevice->udi());
0135 }
0136 
0137 void FstabStorageAccess::slotTeardownDone(int error, const QString &errorString)
0138 {
0139     Q_EMIT teardownDone(static_cast<Solid::ErrorType>(error), errorString, m_fstabDevice->udi());
0140 }
0141 
0142 void FstabStorageAccess::onMtabChanged(const QString &device)
0143 {
0144     QStringList currentMountPoints = FstabHandling::currentMountPoints(device);
0145     if (currentMountPoints.isEmpty()) {
0146         // device umounted
0147         m_filePath = FstabHandling::mountPoints(device).first();
0148         m_isAccessible = false;
0149         Q_EMIT accessibilityChanged(false, QString(FSTAB_UDI_PREFIX) + "/" + device);
0150     } else {
0151         // device added
0152         m_filePath = currentMountPoints.first();
0153         m_isAccessible = true;
0154         Q_EMIT accessibilityChanged(true, QString(FSTAB_UDI_PREFIX) + "/" + device);
0155     }
0156 }
0157 
0158 #include "moc_fstabstorageaccess.cpp"