1 /*
2     SPDX-FileCopyrightText: 2012 Lukáš Tinkl <ltinkl@redhat.com>
3 
4     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "udisksblock.h"
8 
9 #if defined(Q_OS_LINUX)
10 #include <linux/kdev_t.h>
11 #else
12 // taken from linux/kdev_t.h
13 #define MINORBITS 20
14 #define MINORMASK ((1U << MINORBITS) - 1)
15 #define MAJOR(dev) ((unsigned int)((dev) >> MINORBITS))
16 #define MINOR(dev) ((unsigned int)((dev)&MINORMASK))
17 #endif
18 
19 #include <QDBusConnection>
20 #include <QDBusPendingReply>
21 #include <QDomDocument>
22 #include <QFile>
23 
24 #include "udisks_debug.h"
25 
26 using namespace Solid::Backends::UDisks2;
27 
Block(Device * dev)28 Block::Block(Device *dev)
29     : DeviceInterface(dev)
30 {
31     m_devNum = m_device->prop("DeviceNumber").toULongLong();
32     m_devFile = QFile::decodeName(m_device->prop("Device").toByteArray());
33 
34     // we have a drive (non-block device for udisks), so let's find the corresponding (real) block device
35     if (m_devNum == 0 || m_devFile.isEmpty()) {
36         const QString path = "/org/freedesktop/UDisks2/block_devices";
37         QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, DBUS_INTERFACE_INTROSPECT, "Introspect");
38         QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
39         reply.waitForFinished();
40 
41         if (reply.isValid()) {
42             QDomDocument dom;
43             dom.setContent(reply.value());
44             QDomNodeList nodeList = dom.documentElement().elementsByTagName("node");
45             for (int i = 0; i < nodeList.count(); i++) {
46                 QDomElement nodeElem = nodeList.item(i).toElement();
47                 if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) {
48                     const QString udi = path + "/" + nodeElem.attribute("name");
49 
50                     Device device(udi);
51                     if (device.drivePath() == dev->udi()) {
52                         m_devNum = device.prop("DeviceNumber").toULongLong();
53                         m_devFile = QFile::decodeName(device.prop("Device").toByteArray());
54                         break;
55                     }
56                 }
57             }
58         } else {
59             qCWarning(UDISKS2) << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
60         }
61     }
62 
63     // qDebug() << "devnum:" << m_devNum << "dev file:" << m_devFile;
64 }
65 
~Block()66 Block::~Block()
67 {
68 }
69 
device() const70 QString Block::device() const
71 {
72     return m_devFile;
73 }
74 
deviceMinor() const75 int Block::deviceMinor() const
76 {
77     return MINOR(m_devNum);
78 }
79 
deviceMajor() const80 int Block::deviceMajor() const
81 {
82     return MAJOR(m_devNum);
83 }
84