File indexing completed on 2024-04-21 05:48:34
0001 /* 0002 SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>, 2023 Jonathan Esk-Riddell <jr@jriddell.org> 0003 SPDX-License-Identifier: GPL-3.0-or-later 0004 */ 0005 0006 //////////////////////////////////////////////////////////////////////////////// 0007 // This file contains Linux implementation of platform-dependent functions 0008 0009 #include <KLocalizedString> 0010 #include <QDBusInterface> 0011 #include <QDBusReply> 0012 #include <QDBusConnection> 0013 #include <QDBusObjectPath> 0014 #include <QtDBus/QtDBus> 0015 #include <QMessageBox> 0016 #include <QDir> 0017 #include <QRegularExpression> 0018 0019 #include "mainapplication.h" 0020 #include "usbdevice.h" 0021 0022 typedef QHash<QString, QVariantMap> InterfacesAndProperties; 0023 typedef QHash<QDBusObjectPath, InterfacesAndProperties> DBusIntrospection; 0024 Q_DECLARE_METATYPE(InterfacesAndProperties) 0025 Q_DECLARE_METATYPE(DBusIntrospection) 0026 0027 UsbDevice* handleObject(const QDBusObjectPath &object_path, const InterfacesAndProperties &interfaces_and_properties) { 0028 QRegularExpression numberRE("[0-9]$"); 0029 QRegularExpressionMatch numberREMatch = numberRE.match(object_path.path()); 0030 QRegularExpression mmcRE("[0-9]p[0-9]$"); 0031 QRegularExpressionMatch mmcREMatch = mmcRE.match(object_path.path()); 0032 QDBusObjectPath driveId = qvariant_cast<QDBusObjectPath>(interfaces_and_properties["org.freedesktop.UDisks2.Block"]["Drive"]); 0033 0034 QDBusInterface driveInterface("org.freedesktop.UDisks2", driveId.path(), "org.freedesktop.UDisks2.Drive", QDBusConnection::systemBus()); 0035 UsbDevice* deviceData = new UsbDevice; 0036 0037 if ((numberREMatch.hasMatch() && !object_path.path().startsWith("/org/freedesktop/UDisks2/block_devices/mmcblk")) || 0038 mmcREMatch.hasMatch()) 0039 return nullptr; 0040 0041 if (!driveId.path().isEmpty() && driveId.path() != "/") { 0042 bool portable = driveInterface.property("Removable").toBool(); 0043 bool optical = driveInterface.property("Optical").toBool(); 0044 bool containsMedia = driveInterface.property("MediaAvailable").toBool(); 0045 QString connectionBus = driveInterface.property("ConnectionBus").toString().toLower(); 0046 bool isValid = containsMedia && !optical && (portable || connectionBus == "usb"); 0047 0048 QString vendor = driveInterface.property("Vendor").toString(); 0049 QString model = driveInterface.property("Model").toString(); 0050 uint64_t size = driveInterface.property("Size").toULongLong(); 0051 //bool isoLayout = interfaces_and_properties["org.freedesktop.UDisks2.Block"]["IdType"].toString() == "iso9660"; 0052 0053 QString name; 0054 if (vendor.isEmpty()) 0055 if (model.isEmpty()) 0056 name = interfaces_and_properties["org.freedesktop.UDisks2.Block"]["Device"].toByteArray(); 0057 else 0058 name = model; 0059 else 0060 if (model.isEmpty()) 0061 name = vendor; 0062 else 0063 name = QString("%1 %2").arg(vendor).arg(model); 0064 0065 //qDebug() << "New drive" << driveId.path() << "-" << name << "(" << size << "bytes;" << (isValid ? "removable;" : "nonremovable;") << connectionBus << ")"; 0066 0067 deviceData->m_PhysicalDevice = object_path.path(); 0068 deviceData->m_Volumes = QStringList{ deviceData->m_PhysicalDevice }; 0069 deviceData->m_SectorSize = 512; 0070 deviceData->m_Size = size; 0071 deviceData->m_VisibleName = name; 0072 0073 if (isValid) { 0074 return deviceData; 0075 } 0076 } 0077 return nullptr; 0078 } 0079 0080 bool platformEnumFlashDevices(AddFlashDeviceCallbackProc callback, void* cbParam) 0081 { 0082 0083 qDBusRegisterMetaType<InterfacesAndProperties>(); 0084 qDBusRegisterMetaType<DBusIntrospection>(); 0085 QDBusInterface* m_objManager = new QDBusInterface("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2", "org.freedesktop.DBus.ObjectManager", QDBusConnection::systemBus()); 0086 QDBusPendingReply<DBusIntrospection> reply = m_objManager->asyncCall("GetManagedObjects"); 0087 reply.waitForFinished(); 0088 if (reply.isError()) { 0089 qDebug() << "Could not read drives from UDisks:" << reply.error().name() << reply.error().message(); 0090 return false; 0091 } 0092 DBusIntrospection introspection = reply.argumentAt<0>(); 0093 for (auto i : introspection.keys()) { 0094 // ignore anything not block device 0095 if (!i.path().startsWith("/org/freedesktop/UDisks2/block_devices")) { 0096 continue; 0097 } 0098 UsbDevice* deviceData = nullptr; 0099 deviceData = handleObject(i, introspection[i]); 0100 if (deviceData) { 0101 callback(cbParam, deviceData); 0102 } 0103 } 0104 0105 return true; 0106 } 0107 0108 bool ensureElevated() 0109 { 0110 // on Linux we use udisks2 which uses polkit to run necessary bits as root 0111 return true; 0112 }