File indexing completed on 2024-03-24 16:27:21
0001 /*************************************************************************** 0002 Provides an interface to the computer's hardware 0003 ------------------- 0004 begin : Die Jul 14 2015 0005 copyright : (C) 2015-2020 by Alexander Reinholdt 0006 email : alexander.reinholdt@kdemail.net 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, but * 0016 * WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0018 * General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the * 0022 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston,* 0023 * MA 02110-1335, USA * 0024 ***************************************************************************/ 0025 0026 // application specific includes 0027 #include "smb4khardwareinterface.h" 0028 #include "smb4khardwareinterface_p.h" 0029 0030 #include <unistd.h> 0031 0032 // Qt includes 0033 #include <QDebug> 0034 #include <QTest> 0035 #include <QString> 0036 #include <QDBusReply> 0037 0038 // KDE includes 0039 #include <Solid/DeviceNotifier> 0040 #include <Solid/Device> 0041 #include <Solid/NetworkShare> 0042 #if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) 0043 #include <KIOCore/KMountPoint> 0044 #endif 0045 0046 Q_GLOBAL_STATIC(Smb4KHardwareInterfaceStatic, p); 0047 0048 0049 Smb4KHardwareInterface::Smb4KHardwareInterface(QObject *parent) 0050 : QObject(parent), d(new Smb4KHardwareInterfacePrivate) 0051 { 0052 // 0053 // Initialize some members 0054 // 0055 d->networkSession = nullptr; 0056 d->systemOnline = false; 0057 d->fileDescriptor.setFileDescriptor(-1); 0058 0059 // 0060 // Set up the DBUS interface 0061 // 0062 d->dbusInterface.reset(new QDBusInterface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus(), this)); 0063 0064 if (!d->dbusInterface->isValid()) 0065 { 0066 d->dbusInterface.reset(new QDBusInterface("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", QDBusConnection::systemBus(), this)); 0067 } 0068 0069 // 0070 // Do the initial setup of the network configuration 0071 // 0072 d->networkConfigManager.updateConfigurations(); 0073 0074 // 0075 // Connections 0076 // 0077 connect(&d->networkConfigManager, SIGNAL(updateCompleted()), this, SLOT(slotNetworkConfigUpdated())); 0078 connect(&d->networkConfigManager, SIGNAL(onlineStateChanged(bool)), this, SLOT(slotOnlineStateChanged(bool))); 0079 0080 connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(QString)), this, SLOT(slotDeviceAdded(QString))); 0081 connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(QString)), this, SLOT(slotDeviceRemoved(QString))); 0082 0083 #if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) 0084 startTimer(2000); 0085 #endif 0086 } 0087 0088 0089 Smb4KHardwareInterface::~Smb4KHardwareInterface() 0090 { 0091 } 0092 0093 0094 Smb4KHardwareInterface* Smb4KHardwareInterface::self() 0095 { 0096 return &p->instance; 0097 } 0098 0099 0100 bool Smb4KHardwareInterface::isOnline() const 0101 { 0102 if (d->networkSession) 0103 { 0104 return (d->networkSession->state() == QNetworkSession::Connected); 0105 } 0106 0107 return false; 0108 } 0109 0110 0111 void Smb4KHardwareInterface::inhibit() 0112 { 0113 if (d->fileDescriptor.isValid()) 0114 { 0115 return; 0116 } 0117 0118 if (d->dbusInterface->isValid()) 0119 { 0120 QVariantList args; 0121 args << QStringLiteral("shutdown:sleep"); 0122 args << QStringLiteral("Smb4K"); 0123 args << QStringLiteral("Mounting or unmounting in progress"); 0124 args << QStringLiteral("delay"); 0125 0126 QDBusReply<QDBusUnixFileDescriptor> descriptor = d->dbusInterface->callWithArgumentList(QDBus::Block, QStringLiteral("Inhibit"), args); 0127 0128 if (descriptor.isValid()) 0129 { 0130 d->fileDescriptor = descriptor.value(); 0131 } 0132 } 0133 } 0134 0135 0136 void Smb4KHardwareInterface::uninhibit() 0137 { 0138 if (!d->fileDescriptor.isValid()) 0139 { 0140 return; 0141 } 0142 0143 if (d->dbusInterface->isValid()) 0144 { 0145 close(d->fileDescriptor.fileDescriptor()); 0146 d->fileDescriptor.setFileDescriptor(-1); 0147 } 0148 } 0149 0150 0151 #if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) 0152 // Using FreeBSD 11 with KF 5.27, Solid is not able to detect mounted shares. 0153 // Thus, we check here whether shares have been mounted or unmounted. 0154 // This is a hack and should be removed as soon as possible. 0155 void Smb4KHardwareInterface::timerEvent(QTimerEvent */*e*/) 0156 { 0157 KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::BasicInfoNeeded|KMountPoint::NeedMountOptions); 0158 QStringList mountPointList, alreadyMounted; 0159 0160 for (const QExplicitlySharedDataPointer<KMountPoint> &mountPoint : mountPoints) 0161 { 0162 if (QString::compare(mountPoint->mountType(), "smbfs") == 0 || QString::compare(mountPoint->mountType(), "cifs") == 0) 0163 { 0164 mountPointList.append(mountPoint->mountPoint()); 0165 } 0166 } 0167 0168 QMutableStringListIterator it(mountPointList); 0169 0170 while (it.hasNext()) 0171 { 0172 QString mp = it.next(); 0173 int index = -1; 0174 0175 if ((index = d->mountPoints.indexOf(mp)) != -1) 0176 { 0177 d->mountPoints.removeAt(index); 0178 alreadyMounted.append(mp); 0179 it.remove(); 0180 } 0181 } 0182 0183 if (!d->mountPoints.isEmpty()) 0184 { 0185 emit networkShareRemoved(); 0186 } 0187 0188 if (!mountPointList.isEmpty()) 0189 { 0190 emit networkShareAdded(); 0191 } 0192 0193 d->mountPoints.clear(); 0194 d->mountPoints.append(alreadyMounted); 0195 d->mountPoints.append(mountPointList); 0196 } 0197 #endif 0198 0199 0200 void Smb4KHardwareInterface::slotNetworkConfigUpdated() 0201 { 0202 if (d->networkConfigManager.isOnline()) 0203 { 0204 // 0205 // Create a network session object and connect it to the stateChanged() 0206 // signal to monitor changes of the network connection. 0207 // 0208 if (!d->networkSession) 0209 { 0210 d->networkSession = new QNetworkSession(d->networkConfigManager.defaultConfiguration(), this); 0211 connect(d->networkSession, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(slotConnectionStateChanged(QNetworkSession::State))); 0212 } 0213 0214 // 0215 // Tell the program that the network session was initialized 0216 // 0217 emit networkSessionInitialized(); 0218 0219 // 0220 // Check the state of the network session and emit the onlineStateChanged() 0221 // signal accordingly. 0222 // 0223 if (d->networkSession->state() == QNetworkSession::Connected) 0224 { 0225 if (!d->systemOnline) 0226 { 0227 d->systemOnline = true; 0228 emit onlineStateChanged(true); 0229 } 0230 } 0231 else 0232 { 0233 if (d->systemOnline) 0234 { 0235 d->systemOnline = false; 0236 emit onlineStateChanged(false); 0237 } 0238 } 0239 0240 // 0241 // Disconnect from the network configuration manager, because we now have our 0242 // network session object 0243 // 0244 disconnect(&d->networkConfigManager, SIGNAL(updateCompleted()), this, SLOT(slotNetworkConfigUpdated())); 0245 disconnect(&d->networkConfigManager, SIGNAL(onlineStateChanged(bool)), this, SLOT(slotOnlineStateChanged(bool))); 0246 } 0247 else 0248 { 0249 d->systemOnline = false; 0250 emit onlineStateChanged(false); 0251 } 0252 } 0253 0254 0255 void Smb4KHardwareInterface::slotOnlineStateChanged(bool on) 0256 { 0257 if (on && !d->networkSession) 0258 { 0259 d->networkConfigManager.updateConfigurations(); 0260 } 0261 } 0262 0263 0264 void Smb4KHardwareInterface::slotConnectionStateChanged(QNetworkSession::State state) 0265 { 0266 if (state == QNetworkSession::Connected) 0267 { 0268 if (!d->systemOnline) 0269 { 0270 d->systemOnline = true; 0271 emit onlineStateChanged(true); 0272 } 0273 } 0274 else 0275 { 0276 if (d->systemOnline) 0277 { 0278 d->systemOnline = false; 0279 emit onlineStateChanged(false); 0280 } 0281 } 0282 } 0283 0284 0285 void Smb4KHardwareInterface::slotDeviceAdded(const QString& udi) 0286 { 0287 Solid::Device device(udi); 0288 0289 if (device.isDeviceInterface(Solid::DeviceInterface::NetworkShare)) 0290 { 0291 d->udis.append(udi); 0292 emit networkShareAdded(); 0293 } 0294 } 0295 0296 0297 void Smb4KHardwareInterface::slotDeviceRemoved(const QString& udi) 0298 { 0299 Solid::Device device(udi); 0300 0301 // For some reason, the device has no valid type at the moment (Frameworks 5.9, 0302 // July 2015). Thus, we need the code in the else block for now. 0303 if (device.isDeviceInterface(Solid::DeviceInterface::NetworkShare)) 0304 { 0305 emit networkShareRemoved(); 0306 } 0307 else 0308 { 0309 if (d->udis.contains(udi)) 0310 { 0311 emit networkShareRemoved(); 0312 d->udis.removeOne(udi); 0313 } 0314 } 0315 } 0316 0317