Magellan Linux

Annotation of /trunk/kdelibs/patches/kdelibs-4.9.4-udisks2-backend.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1990 - (hide annotations) (download)
Mon Dec 10 15:50:04 2012 UTC (11 years, 5 months ago) by niro
File size: 139746 byte(s)
-added udisks2 patches
1 niro 1990 diff --git a/solid/solid/CMakeLists.txt b/solid/solid/CMakeLists.txt
2     index 0aa7a43..b00e50a 100644
3     --- a/solid/solid/CMakeLists.txt
4     +++ b/solid/solid/CMakeLists.txt
5     @@ -1,6 +1,7 @@
6     set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
7     add_subdirectory( ifaces )
8     include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
9     +include_directories( ${QT_QTDBUS_INCLUDE_DIR} )
10    
11     if(WIN32)
12     include_directories( ${KDEWIN_INCLUDES} )
13     @@ -39,7 +40,6 @@ configure_file(config-processor.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-proce
14    
15     file(MAKE_DIRECTORY
16     ${CMAKE_CURRENT_BINARY_DIR}/backends/fakehw
17     - ${CMAKE_CURRENT_BINARY_DIR}/backends/hal
18     ${CMAKE_CURRENT_BINARY_DIR}/backends/udev
19     ${CMAKE_CURRENT_BINARY_DIR}/backends/wmi
20     )
21     @@ -225,33 +225,6 @@ if(NOT WIN32 AND NOT APPLE)
22     endif( UDEV_FOUND )
23    
24    
25     - message(STATUS "Building Solid HAL backend." )
26     - set(solid_LIB_SRCS ${solid_LIB_SRCS}
27     - backends/hal/halacadapter.cpp
28     - backends/hal/halaudiointerface.cpp
29     - backends/hal/halbattery.cpp
30     - backends/hal/halblock.cpp
31     - backends/hal/halbutton.cpp
32     - backends/hal/halcamera.cpp
33     - backends/hal/halcdrom.cpp
34     - backends/hal/haldeviceinterface.cpp
35     - backends/hal/haldvbinterface.cpp
36     - backends/hal/halfstabhandling.cpp
37     - backends/hal/halgenericinterface.cpp
38     - backends/hal/haldevice.cpp
39     - backends/hal/halmanager.cpp
40     - backends/hal/halnetworkinterface.cpp
41     - backends/hal/halserialinterface.cpp
42     - backends/hal/halopticaldisc.cpp
43     - backends/hal/halportablemediaplayer.cpp
44     - backends/hal/halprocessor.cpp
45     - backends/hal/halstorageaccess.cpp
46     - backends/hal/halstorage.cpp
47     - backends/hal/halvideo.cpp
48     - backends/hal/halvolume.cpp
49     - backends/hal/halsmartcardreader.cpp
50     - )
51     -
52     message(STATUS "Building Solid UPower backend." )
53     set(solid_LIB_SRCS ${solid_LIB_SRCS}
54     backends/upower/upowermanager.cpp
55     @@ -264,19 +237,39 @@ if(NOT WIN32 AND NOT APPLE)
56    
57     # FIXME: this should work on more Unix systems
58     if (CMAKE_SYSTEM_NAME MATCHES Linux)
59     - message(STATUS "Building Solid UDisks backend." )
60     - set(solid_LIB_SRCS ${solid_LIB_SRCS}
61     - backends/udisks/udisksmanager.cpp
62     - backends/udisks/udisksdevice.cpp
63     - backends/udisks/udisksblock.cpp
64     - backends/udisks/udisksstoragevolume.cpp
65     - backends/udisks/udisksdeviceinterface.cpp
66     - backends/udisks/udisksopticaldisc.cpp
67     - backends/udisks/udisksopticaldrive.cpp
68     - backends/udisks/udisksstoragedrive.cpp
69     - backends/udisks/udisksstorageaccess.cpp
70     - backends/udisks/udisksgenericinterface.cpp
71     - )
72     +
73     + if ( WITH_SOLID_UDISKS2 )
74     + message(STATUS "Building Solid UDisks2 backend." )
75     + add_definitions(-DWITH_SOLID_UDISKS2)
76     + set(solid_LIB_SRCS ${solid_LIB_SRCS}
77     + backends/udisks2/udisksmanager.cpp
78     + backends/udisks2/udisksdevice.cpp
79     + backends/udisks2/udisksdevicebackend.cpp
80     + backends/udisks2/udisksblock.cpp
81     + backends/udisks2/udisksstoragevolume.cpp
82     + backends/udisks2/udisksdeviceinterface.cpp
83     + backends/udisks2/udisksopticaldisc.cpp
84     + backends/udisks2/udisksopticaldrive.cpp
85     + backends/udisks2/udisksstoragedrive.cpp
86     + backends/udisks2/udisksstorageaccess.cpp
87     + backends/udisks2/udisksgenericinterface.cpp
88     + backends/udisks2/dbus/manager.cpp
89     + )
90     + else ( WITH_SOLID_UDISKS2 )
91     + message(STATUS "Building Solid UDisks backend." )
92     + set(solid_LIB_SRCS ${solid_LIB_SRCS}
93     + backends/udisks/udisksmanager.cpp
94     + backends/udisks/udisksdevice.cpp
95     + backends/udisks/udisksblock.cpp
96     + backends/udisks/udisksstoragevolume.cpp
97     + backends/udisks/udisksdeviceinterface.cpp
98     + backends/udisks/udisksopticaldisc.cpp
99     + backends/udisks/udisksopticaldrive.cpp
100     + backends/udisks/udisksstoragedrive.cpp
101     + backends/udisks/udisksstorageaccess.cpp
102     + backends/udisks/udisksgenericinterface.cpp
103     + )
104     + endif ( WITH_SOLID_UDISKS2 )
105     endif (CMAKE_SYSTEM_NAME MATCHES Linux)
106    
107     message(STATUS "Building Solid fstab backend." )
108     diff --git a/solid/solid/backends/udisks2/dbus/manager.cpp b/solid/solid/backends/udisks2/dbus/manager.cpp
109     new file mode 100644
110     index 0000000..7ea4aa8
111     --- /dev/null
112     +++ b/solid/solid/backends/udisks2/dbus/manager.cpp
113     @@ -0,0 +1,26 @@
114     +/*
115     + * This file was generated by qdbusxml2cpp version 0.7
116     + * Command line was: qdbusxml2cpp -p manager manager.xml
117     + *
118     + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
119     + *
120     + * This is an auto-generated file.
121     + * This file may have been hand-edited. Look for HAND-EDIT comments
122     + * before re-generating it.
123     + */
124     +
125     +#include "manager.h"
126     +
127     +/*
128     + * Implementation of interface class OrgFreedesktopDBusObjectManagerInterface
129     + */
130     +
131     +OrgFreedesktopDBusObjectManagerInterface::OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
132     + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
133     +{
134     +}
135     +
136     +OrgFreedesktopDBusObjectManagerInterface::~OrgFreedesktopDBusObjectManagerInterface()
137     +{
138     +}
139     +
140     diff --git a/solid/solid/backends/udisks2/dbus/manager.h b/solid/solid/backends/udisks2/dbus/manager.h
141     new file mode 100644
142     index 0000000..11f0be8
143     --- /dev/null
144     +++ b/solid/solid/backends/udisks2/dbus/manager.h
145     @@ -0,0 +1,59 @@
146     +/*
147     + * This file was generated by qdbusxml2cpp version 0.7
148     + * Command line was: qdbusxml2cpp -p manager manager.xml
149     + *
150     + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
151     + *
152     + * This is an auto-generated file.
153     + * Do not edit! All changes made to it will be lost.
154     + */
155     +
156     +#ifndef MANAGER_H_1329493525
157     +#define MANAGER_H_1329493525
158     +
159     +#include <QtCore/QObject>
160     +#include <QtCore/QByteArray>
161     +#include <QtCore/QList>
162     +#include <QtCore/QMap>
163     +#include <QtCore/QString>
164     +#include <QtCore/QStringList>
165     +#include <QtCore/QVariant>
166     +#include <QtDBus/QtDBus>
167     +
168     +#include "../udisks2.h"
169     +
170     +/*
171     + * Proxy class for interface org.freedesktop.DBus.ObjectManager
172     + */
173     +class OrgFreedesktopDBusObjectManagerInterface: public QDBusAbstractInterface
174     +{
175     + Q_OBJECT
176     +public:
177     + static inline const char *staticInterfaceName()
178     + { return "org.freedesktop.DBus.ObjectManager"; }
179     +
180     +public:
181     + OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
182     +
183     + ~OrgFreedesktopDBusObjectManagerInterface();
184     +
185     +public Q_SLOTS: // METHODS
186     + inline QDBusPendingReply<DBUSManagerStruct> GetManagedObjects()
187     + {
188     + QList<QVariant> argumentList;
189     + return asyncCallWithArgumentList(QLatin1String("GetManagedObjects"), argumentList);
190     + }
191     +
192     +Q_SIGNALS: // SIGNALS
193     + void InterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
194     + void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
195     +};
196     +
197     +namespace org {
198     + namespace freedesktop {
199     + namespace DBus {
200     + typedef ::OrgFreedesktopDBusObjectManagerInterface ObjectManager;
201     + }
202     + }
203     +}
204     +#endif
205     diff --git a/solid/solid/backends/udisks2/dbus/manager.xml b/solid/solid/backends/udisks2/dbus/manager.xml
206     new file mode 100644
207     index 0000000..8f25cb6
208     --- /dev/null
209     +++ b/solid/solid/backends/udisks2/dbus/manager.xml
210     @@ -0,0 +1,21 @@
211     +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
212     + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
213     +<node>
214     + <interface name="org.freedesktop.DBus.ObjectManager">
215     + <method name="GetManagedObjects">
216     + <arg type="a{oa{sa{sv}}}" name="object_paths_interfaces_and_properties" direction="out">
217     + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="DBUSManagerStruct"/>
218     + </arg>
219     + </method>
220     + <signal name="InterfacesAdded">
221     + <arg type="o" name="object_path"/>
222     + <arg type="a{sa{sv}}" name="interfaces_and_properties">
223     + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMapMap"/>
224     + </arg>
225     + </signal>
226     + <signal name="InterfacesRemoved">
227     + <arg type="o" name="object_path"/>
228     + <arg type="as" name="interfaces"/>
229     + </signal>
230     + </interface>
231     +</node>
232     diff --git a/solid/solid/backends/udisks2/udisks2.h b/solid/solid/backends/udisks2/udisks2.h
233     new file mode 100644
234     index 0000000..8dda86a
235     --- /dev/null
236     +++ b/solid/solid/backends/udisks2/udisks2.h
237     @@ -0,0 +1,78 @@
238     +/*
239     + Copyright 2012 Lukáš Tinkl <ltinkl@redhat.com>
240     +
241     + This library is free software; you can redistribute it and/or
242     + modify it under the terms of the GNU Lesser General Public
243     + License as published by the Free Software Foundation; either
244     + version 2.1 of the License, or (at your option) version 3, or any
245     + later version accepted by the membership of KDE e.V. (or its
246     + successor approved by the membership of KDE e.V.), which shall
247     + act as a proxy defined in Section 6 of version 3 of the license.
248     +
249     + This library is distributed in the hope that it will be useful,
250     + but WITHOUT ANY WARRANTY; without even the implied warranty of
251     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
252     + Lesser General Public License for more details.
253     +
254     + You should have received a copy of the GNU Lesser General Public
255     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
256     +*/
257     +
258     +#ifndef SOLID_BACKENDS_UDISKS2_H
259     +#define SOLID_BACKENDS_UDISKS2_H
260     +
261     +#include <QMetaType>
262     +#include <QtDBus>
263     +#include <QVariant>
264     +#include <QMap>
265     +#include <QList>
266     +
267     +typedef QList<QByteArray> QByteArrayList;
268     +Q_DECLARE_METATYPE(QByteArrayList)
269     +
270     +typedef QMap<QString,QVariantMap> QVariantMapMap;
271     +Q_DECLARE_METATYPE(QVariantMapMap)
272     +
273     +typedef QMap<QDBusObjectPath, QVariantMapMap> DBUSManagerStruct;
274     +Q_DECLARE_METATYPE(DBUSManagerStruct)
275     +
276     +/* UDisks2 */
277     +#define UD2_DBUS_SERVICE "org.freedesktop.UDisks2"
278     +#define UD2_DBUS_PATH "/org/freedesktop/UDisks2"
279     +#define UD2_UDI_DISKS_PREFIX "/org/freedesktop/UDisks2"
280     +#define UD2_DBUS_PATH_MANAGER "/org/freedesktop/UDisks2/Manager"
281     +#define UD2_DBUS_PATH_DRIVES "/org/freedesktop/UDisks2/drives/"
282     +#define UD2_DBUS_PATH_JOBS "/org/freedesktop/UDisks2/jobs/"
283     +#define DBUS_INTERFACE_PROPS "org.freedesktop.DBus.Properties"
284     +#define DBUS_INTERFACE_INTROSPECT "org.freedesktop.DBus.Introspectable"
285     +#define DBUS_INTERFACE_MANAGER "org.freedesktop.DBus.ObjectManager"
286     +#define UD2_DBUS_INTERFACE_BLOCK "org.freedesktop.UDisks2.Block"
287     +#define UD2_DBUS_INTERFACE_DRIVE "org.freedesktop.UDisks2.Drive"
288     +#define UD2_DBUS_INTERFACE_PARTITION "org.freedesktop.UDisks2.Partition"
289     +#define UD2_DBUS_INTERFACE_PARTITIONTABLE "org.freedesktop.UDisks2.PartitionTable"
290     +#define UD2_DBUS_INTERFACE_FILESYSTEM "org.freedesktop.UDisks2.Filesystem"
291     +#define UD2_DBUS_INTERFACE_ENCRYPTED "org.freedesktop.UDisks2.Encrypted"
292     +#define UD2_DBUS_INTERFACE_SWAP "org.freedesktop.UDisks2.Swapspace"
293     +#define UD2_DBUS_INTERFACE_LOOP "org.freedesktop.UDisks2.Loop"
294     +
295     +/* errors */
296     +#define UD2_ERROR_UNAUTHORIZED "org.freedesktop.PolicyKit.Error.NotAuthorized"
297     +#define UD2_ERROR_BUSY "org.freedesktop.UDisks2.Error.DeviceBusy"
298     +#define UD2_ERROR_FAILED "org.freedesktop.UDisks2.Error.Failed"
299     +#define UD2_ERROR_CANCELED "org.freedesktop.UDisks2.Error.Cancelled"
300     +#define UD2_ERROR_INVALID_OPTION "org.freedesktop.UDisks2.Error.OptionNotPermitted"
301     +#define UD2_ERROR_MISSING_DRIVER "org.freedesktop.UDisks2.Error.NotSupported"
302     +
303     +#define UD2_ERROR_ALREADY_MOUNTED "org.freedesktop.UDisks2.Error.AlreadyMounted"
304     +#define UD2_ERROR_NOT_MOUNTED "org.freedesktop.UDisks2.Error.NotMounted"
305     +#define UD2_ERROR_MOUNTED_BY_OTHER_USER "org.freedesktop.UDisks2.Error.MountedByOtherUser"
306     +#define UD2_ERROR_ALREADY_UNMOUNTING "org.freedesktop.UDisks2.Error.AlreadyUnmounting"
307     +#define UD2_ERROR_TIMED_OUT "org.freedesktop.UDisks2.Error.Timedout"
308     +#define UD2_ERROR_WOULD_WAKEUP "org.freedesktop.UDisks2.Error.WouldWakeup"
309     +#define UD2_ERROR_ALREADY_CANCELLED "org.freedesktop.UDisks2.Error.AlreadyCancelled"
310     +
311     +#define UD2_ERROR_NOT_AUTHORIZED "org.freedesktop.UDisks2.Error.NotAuthorized"
312     +#define UD2_ERROR_NOT_AUTHORIZED_CAN_OBTAIN "org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain"
313     +#define UD2_ERROR_NOT_AUTHORIZED_DISMISSED "org.freedesktop.UDisks2.Error.NotAuthorizedDismissed"
314     +
315     +#endif // SOLID_BACKENDS_UDISKS2_H
316     diff --git a/solid/solid/backends/udisks2/udisksblock.cpp b/solid/solid/backends/udisks2/udisksblock.cpp
317     new file mode 100644
318     index 0000000..f3cd1e8
319     --- /dev/null
320     +++ b/solid/solid/backends/udisks2/udisksblock.cpp
321     @@ -0,0 +1,88 @@
322     +/*
323     + Copyright 2012 Lukáš Tinkl <ltinkl@redhat.com>
324     +
325     + This library is free software; you can redistribute it and/or
326     + modify it under the terms of the GNU Lesser General Public
327     + License as published by the Free Software Foundation; either
328     + version 2.1 of the License, or (at your option) version 3, or any
329     + later version accepted by the membership of KDE e.V. (or its
330     + successor approved by the membership of KDE e.V.), which shall
331     + act as a proxy defined in Section 6 of version 3 of the license.
332     +
333     + This library is distributed in the hope that it will be useful,
334     + but WITHOUT ANY WARRANTY; without even the implied warranty of
335     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
336     + Lesser General Public License for more details.
337     +
338     + You should have received a copy of the GNU Lesser General Public
339     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
340     +*/
341     +
342     +#include <linux/kdev_t.h>
343     +
344     +#include <QFile>
345     +#include <QtDBus/QDBusConnection>
346     +#include <QtDBus/QDBusPendingReply>
347     +#include <QtXml/QDomDocument>
348     +
349     +#include "udisksblock.h"
350     +
351     +using namespace Solid::Backends::UDisks2;
352     +
353     +Block::Block(Device *dev)
354     + : DeviceInterface(dev)
355     +{
356     + m_devNum = m_device->prop("DeviceNumber").toULongLong();
357     + m_devFile = QFile::decodeName(m_device->prop("Device").toByteArray());
358     +
359     + // we have a drive (non-block device for udisks), so let's find the corresponding (real) block device
360     + if (m_devNum == 0 || m_devFile.isEmpty()) {
361     + const QString path = "/org/freedesktop/UDisks2/block_devices";
362     + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path,
363     + DBUS_INTERFACE_INTROSPECT, "Introspect");
364     + QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
365     + reply.waitForFinished();
366     +
367     + if (reply.isValid()) {
368     + QDomDocument dom;
369     + dom.setContent(reply.value());
370     + QDomNodeList nodeList = dom.documentElement().elementsByTagName("node");
371     + for (int i = 0; i < nodeList.count(); i++) {
372     + QDomElement nodeElem = nodeList.item(i).toElement();
373     + if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) {
374     + const QString udi = path + "/" + nodeElem.attribute("name");
375     +
376     + Device device(udi);
377     + if (device.drivePath() == dev->udi()) {
378     + m_devNum = device.prop("DeviceNumber").toULongLong();
379     + m_devFile = QFile::decodeName(device.prop("Device").toByteArray());
380     + break;
381     + }
382     + }
383     + }
384     + }
385     + else
386     + qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
387     + }
388     +
389     + //qDebug() << "devnum:" << m_devNum << "dev file:" << m_devFile;
390     +}
391     +
392     +Block::~Block()
393     +{
394     +}
395     +
396     +QString Block::device() const
397     +{
398     + return m_devFile;
399     +}
400     +
401     +int Block::deviceMinor() const
402     +{
403     + return MINOR(m_devNum);
404     +}
405     +
406     +int Block::deviceMajor() const
407     +{
408     + return MAJOR(m_devNum);
409     +}
410     diff --git a/solid/solid/backends/udisks2/udisksblock.h b/solid/solid/backends/udisks2/udisksblock.h
411     new file mode 100644
412     index 0000000..19cb70a
413     --- /dev/null
414     +++ b/solid/solid/backends/udisks2/udisksblock.h
415     @@ -0,0 +1,56 @@
416     +/*
417     + Copyright 2012 Lukáš Tinkl <ltinkl@redhat.com>
418     +
419     + This library is free software; you can redistribute it and/or
420     + modify it under the terms of the GNU Lesser General Public
421     + License as published by the Free Software Foundation; either
422     + version 2.1 of the License, or (at your option) version 3, or any
423     + later version accepted by the membership of KDE e.V. (or its
424     + successor approved by the membership of KDE e.V.), which shall
425     + act as a proxy defined in Section 6 of version 3 of the license.
426     +
427     + This library is distributed in the hope that it will be useful,
428     + but WITHOUT ANY WARRANTY; without even the implied warranty of
429     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
430     + Lesser General Public License for more details.
431     +
432     + You should have received a copy of the GNU Lesser General Public
433     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
434     +*/
435     +
436     +#ifndef UDISKS2BLOCK_H
437     +#define UDISKS2BLOCK_H
438     +
439     +#include <solid/ifaces/block.h>
440     +#include "udisksdeviceinterface.h"
441     +
442     +namespace Solid
443     +{
444     +namespace Backends
445     +{
446     +namespace UDisks2
447     +{
448     +
449     +class Block: public DeviceInterface, virtual public Solid::Ifaces::Block
450     +{
451     +
452     + Q_OBJECT
453     + Q_INTERFACES(Solid::Ifaces::Block)
454     +
455     +public:
456     + Block(Device *dev);
457     + virtual ~Block();
458     +
459     + virtual QString device() const;
460     + virtual int deviceMinor() const;
461     + virtual int deviceMajor() const;
462     +private:
463     + dev_t m_devNum;
464     + QString m_devFile;
465     +};
466     +
467     +}
468     +}
469     +}
470     +
471     +#endif // UDISKS2BLOCK_H
472     diff --git a/solid/solid/backends/udisks2/udisksdevice.cpp b/solid/solid/backends/udisks2/udisksdevice.cpp
473     new file mode 100644
474     index 0000000..b888360
475     --- /dev/null
476     +++ b/solid/solid/backends/udisks2/udisksdevice.cpp
477     @@ -0,0 +1,834 @@
478     +/*
479     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
480     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
481     +
482     + This library is free software; you can redistribute it and/or
483     + modify it under the terms of the GNU Lesser General Public
484     + License as published by the Free Software Foundation; either
485     + version 2.1 of the License, or (at your option) version 3, or any
486     + later version accepted by the membership of KDE e.V. (or its
487     + successor approved by the membership of KDE e.V.), which shall
488     + act as a proxy defined in Section 6 of version 3 of the license.
489     +
490     + This library is distributed in the hope that it will be useful,
491     + but WITHOUT ANY WARRANTY; without even the implied warranty of
492     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
493     + Lesser General Public License for more details.
494     +
495     + You should have received a copy of the GNU Lesser General Public
496     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
497     +*/
498     +
499     +#include "udisksdevice.h"
500     +#include "udisksdevicebackend.h"
501     +#include "udisksblock.h"
502     +#include "udisksdeviceinterface.h"
503     +#include "udisksstoragevolume.h"
504     +#include "udisksopticaldisc.h"
505     +#include "udisksopticaldrive.h"
506     +#include "udisksstorageaccess.h"
507     +#include "udisksgenericinterface.h"
508     +
509     +#include <solid/genericinterface.h>
510     +#include <solid/deviceinterface.h>
511     +#include <solid/device.h>
512     +
513     +#include <QtCore/QDebug>
514     +
515     +#include <QtDBus/QDBusMessage>
516     +#include <QtDBus/QDBusMetaType>
517     +#include <QtDBus/QDBusPendingReply>
518     +#include <QtDBus/QDBusArgument>
519     +
520     +#include <QtXml/QDomDocument>
521     +
522     +using namespace Solid::Backends::UDisks2;
523     +
524     +// Adapted from KLocale as Solid needs to be Qt-only
525     +static QString formatByteSize(double size)
526     +{
527     + // Per IEC 60027-2
528     +
529     + // Binary prefixes
530     + //Tebi-byte TiB 2^40 1,099,511,627,776 bytes
531     + //Gibi-byte GiB 2^30 1,073,741,824 bytes
532     + //Mebi-byte MiB 2^20 1,048,576 bytes
533     + //Kibi-byte KiB 2^10 1,024 bytes
534     +
535     + QString s;
536     + // Gibi-byte
537     + if ( size >= 1073741824.0 )
538     + {
539     + size /= 1073741824.0;
540     + if ( size > 1024 ) // Tebi-byte
541     + s = QCoreApplication::translate("", "%1 TiB").arg(QLocale().toString(size / 1024.0, 'f', 1));
542     + else
543     + s = QCoreApplication::translate("", "%1 GiB").arg(QLocale().toString(size, 'f', 1));
544     + }
545     + // Mebi-byte
546     + else if ( size >= 1048576.0 )
547     + {
548     + size /= 1048576.0;
549     + s = QCoreApplication::translate("", "%1 MiB").arg(QLocale().toString(size, 'f', 1));
550     + }
551     + // Kibi-byte
552     + else if ( size >= 1024.0 )
553     + {
554     + size /= 1024.0;
555     + s = QCoreApplication::translate("", "%1 KiB").arg(QLocale().toString(size, 'f', 1));
556     + }
557     + // Just byte
558     + else if ( size > 0 )
559     + {
560     + s = QCoreApplication::translate("", "%1 B").arg(QLocale().toString(size, 'f', 1));
561     + }
562     + // Nothing
563     + else
564     + {
565     + s = QCoreApplication::translate("", "0 B");
566     + }
567     + return s;
568     +}
569     +
570     +Device::Device(const QString &udi)
571     + : Solid::Ifaces::Device()
572     + , m_backend(DeviceBackend::backendForUDI(udi))
573     +{
574     + if (m_backend) {
575     + connect(m_backend, SIGNAL(changed()), this, SIGNAL(changed()));
576     + connect(m_backend, SIGNAL(propertyChanged(QMap<QString,int>)), this, SIGNAL(propertyChanged(QMap<QString,int>)));
577     + } else {
578     + qDebug() << "Created invalid Device for udi" << udi;
579     + }
580     +}
581     +
582     +Device::~Device()
583     +{
584     +
585     +}
586     +
587     +QObject* Device::createDeviceInterface(const Solid::DeviceInterface::Type& type)
588     +{
589     + if (!queryDeviceInterface(type)) {
590     + return 0;
591     + }
592     +
593     + DeviceInterface *iface = 0;
594     + switch (type)
595     + {
596     + case Solid::DeviceInterface::GenericInterface:
597     + iface = new GenericInterface(this);
598     + break;
599     + case Solid::DeviceInterface::Block:
600     + iface = new Block(this);
601     + break;
602     + case Solid::DeviceInterface::StorageAccess:
603     + iface = new StorageAccess(this);
604     + break;
605     + case Solid::DeviceInterface::StorageDrive:
606     + iface = new StorageDrive(this);
607     + break;
608     + case Solid::DeviceInterface::OpticalDrive:
609     + iface = new OpticalDrive(this);
610     + break;
611     + case Solid::DeviceInterface::StorageVolume:
612     + iface = new StorageVolume(this);
613     + break;
614     + case Solid::DeviceInterface::OpticalDisc:
615     + iface = new OpticalDisc(this);
616     + break;
617     + default:
618     + break;
619     + }
620     + return iface;
621     +}
622     +
623     +bool Device::queryDeviceInterface(const Solid::DeviceInterface::Type& type) const
624     +{
625     + switch (type) {
626     + case Solid::DeviceInterface::GenericInterface:
627     + return true;
628     + case Solid::DeviceInterface::Block:
629     + return isBlock() || isDrive();
630     + case Solid::DeviceInterface::StorageVolume:
631     + return isStorageVolume();
632     + case Solid::DeviceInterface::StorageAccess:
633     + return isStorageAccess();
634     + case Solid::DeviceInterface::StorageDrive:
635     + return isDrive();
636     + case Solid::DeviceInterface::OpticalDrive:
637     + return isOpticalDrive();
638     + case Solid::DeviceInterface::OpticalDisc:
639     + return isOpticalDisc();
640     + default:
641     + return false;
642     + }
643     +}
644     +
645     +QStringList Device::emblems() const
646     +{
647     + QStringList res;
648     +
649     + if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess))
650     + {
651     + const UDisks2::StorageAccess accessIface(const_cast<Device *>(this));
652     + if (accessIface.isAccessible())
653     + {
654     + if (isEncryptedContainer())
655     + res << "emblem-encrypted-unlocked";
656     + else
657     + res << "emblem-mounted";
658     + }
659     + else
660     + {
661     + if (isEncryptedContainer())
662     + res << "emblem-encrypted-locked";
663     + else
664     + res << "emblem-unmounted";
665     + }
666     + }
667     +
668     + return res;
669     +}
670     +
671     +QString Device::description() const
672     +{
673     + const QString hintName = property("HintName").toString(); // non-cached
674     + if (!hintName.isEmpty())
675     + return hintName;
676     +
677     + if (isLoop())
678     + return QObject::tr("Loop Device");
679     + else if (isSwap())
680     + return QObject::tr("Swap Space");
681     + else if (queryDeviceInterface(Solid::DeviceInterface::StorageDrive))
682     + return storageDescription();
683     + else if (queryDeviceInterface(Solid::DeviceInterface::StorageVolume))
684     + return volumeDescription();
685     + else
686     + return product();
687     +}
688     +
689     +QString Device::storageDescription() const
690     +{
691     + QString description;
692     + const UDisks2::StorageDrive storageDrive(const_cast<Device*>(this));
693     + Solid::StorageDrive::DriveType drive_type = storageDrive.driveType();
694     + const bool drive_is_hotpluggable = storageDrive.isHotpluggable();
695     +
696     + if (drive_type == Solid::StorageDrive::CdromDrive)
697     + {
698     + const UDisks2::OpticalDrive opticalDrive(const_cast<Device*>(this));
699     + Solid::OpticalDrive::MediumTypes mediumTypes = opticalDrive.supportedMedia();
700     + QString first;
701     + QString second;
702     +
703     + first = QCoreApplication::translate("", "CD-ROM", "First item of %1%2 Drive sentence");
704     + if (mediumTypes & Solid::OpticalDrive::Cdr)
705     + first = QCoreApplication::translate("", "CD-R", "First item of %1%2 Drive sentence");
706     + if (mediumTypes & Solid::OpticalDrive::Cdrw)
707     + first = QCoreApplication::translate("", "CD-RW", "First item of %1%2 Drive sentence");
708     +
709     + if (mediumTypes & Solid::OpticalDrive::Dvd)
710     + second = QCoreApplication::translate("", "/DVD-ROM", "Second item of %1%2 Drive sentence");
711     + if (mediumTypes & Solid::OpticalDrive::Dvdplusr)
712     + second = QCoreApplication::translate("", "/DVD+R", "Second item of %1%2 Drive sentence");
713     + if (mediumTypes & Solid::OpticalDrive::Dvdplusrw)
714     + second = QCoreApplication::translate("", "/DVD+RW", "Second item of %1%2 Drive sentence");
715     + if (mediumTypes & Solid::OpticalDrive::Dvdr)
716     + second = QCoreApplication::translate("", "/DVD-R", "Second item of %1%2 Drive sentence");
717     + if (mediumTypes & Solid::OpticalDrive::Dvdrw)
718     + second = QCoreApplication::translate("", "/DVD-RW", "Second item of %1%2 Drive sentence");
719     + if (mediumTypes & Solid::OpticalDrive::Dvdram)
720     + second = QCoreApplication::translate("", "/DVD-RAM", "Second item of %1%2 Drive sentence");
721     + if ((mediumTypes & Solid::OpticalDrive::Dvdr) && (mediumTypes & Solid::OpticalDrive::Dvdplusr))
722     + {
723     + if(mediumTypes & Solid::OpticalDrive::Dvdplusdl)
724     + second = QObject::trUtf8("/DVD±R DL", "Second item of %1%2 Drive sentence");
725     + else
726     + second = QObject::trUtf8("/DVD±R", "Second item of %1%2 Drive sentence");
727     + }
728     + if ((mediumTypes & Solid::OpticalDrive::Dvdrw) && (mediumTypes & Solid::OpticalDrive::Dvdplusrw))
729     + {
730     + if((mediumTypes & Solid::OpticalDrive::Dvdplusdl) || (mediumTypes & Solid::OpticalDrive::Dvdplusdlrw))
731     + second = QObject::trUtf8("/DVD±RW DL", "Second item of %1%2 Drive sentence");
732     + else
733     + second = QObject::trUtf8("/DVD±RW", "Second item of %1%2 Drive sentence");
734     + }
735     + if (mediumTypes & Solid::OpticalDrive::Bd)
736     + second = QCoreApplication::translate("", "/BD-ROM", "Second item of %1%2 Drive sentence");
737     + if (mediumTypes & Solid::OpticalDrive::Bdr)
738     + second = QCoreApplication::translate("", "/BD-R", "Second item of %1%2 Drive sentence");
739     + if (mediumTypes & Solid::OpticalDrive::Bdre)
740     + second = QCoreApplication::translate("", "/BD-RE", "Second item of %1%2 Drive sentence");
741     + if (mediumTypes & Solid::OpticalDrive::HdDvd)
742     + second = QCoreApplication::translate("", "/HD DVD-ROM", "Second item of %1%2 Drive sentence");
743     + if (mediumTypes & Solid::OpticalDrive::HdDvdr)
744     + second = QCoreApplication::translate("", "/HD DVD-R", "Second item of %1%2 Drive sentence");
745     + if (mediumTypes & Solid::OpticalDrive::HdDvdrw)
746     + second = QCoreApplication::translate("", "/HD DVD-RW", "Second item of %1%2 Drive sentence");
747     +
748     + if (drive_is_hotpluggable)
749     + description = QCoreApplication::translate("", "External %1%2 Drive", "%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").arg(first).arg(second);
750     + else
751     + description = QCoreApplication::translate("", "%1%2 Drive", "%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").arg(first).arg(second);
752     +
753     + return description;
754     + }
755     +
756     + if (drive_type == Solid::StorageDrive::Floppy)
757     + {
758     + if (drive_is_hotpluggable)
759     + description = QCoreApplication::translate("", "External Floppy Drive");
760     + else
761     + description = QCoreApplication::translate("", "Floppy Drive");
762     +
763     + return description;
764     + }
765     +
766     + const bool drive_is_removable = storageDrive.isRemovable();
767     +
768     + if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
769     + {
770     + QString size_str = formatByteSize(storageDrive.size());
771     + if (!size_str.isEmpty())
772     + {
773     + if (drive_is_hotpluggable)
774     + description = QCoreApplication::translate("", "%1 External Hard Drive", "%1 is the size").arg(size_str);
775     + else
776     + description = QCoreApplication::translate("", "%1 Hard Drive", "%1 is the size").arg(size_str);
777     + } else {
778     + if (drive_is_hotpluggable)
779     + description = QCoreApplication::translate("", "External Hard Drive");
780     + else
781     + description = QCoreApplication::translate("", "Hard Drive");
782     + }
783     +
784     + return description;
785     + }
786     +
787     + QString vendormodel_str;
788     + QString model = product();
789     + QString vendor_str = vendor();
790     +
791     + if (vendor_str.isEmpty())
792     + {
793     + if (!model.isEmpty())
794     + vendormodel_str = model;
795     + }
796     + else
797     + {
798     + if (model.isEmpty())
799     + vendormodel_str = vendor_str;
800     + else
801     + {
802     + if (model.startsWith(vendor_str))
803     + {
804     + // e.g. vendor is "Nokia" and model is "Nokia N950" we do not want "Nokia Nokia N950" as description
805     + vendormodel_str = model;
806     + }
807     + else
808     + {
809     + vendormodel_str = QCoreApplication::translate("", "%1 %2", "%1 is the vendor, %2 is the model of the device").arg(vendor_str).arg(model);
810     + }
811     + }
812     + }
813     +
814     + if (vendormodel_str.isEmpty())
815     + description = QCoreApplication::translate("", "Drive");
816     + else
817     + description = vendormodel_str;
818     +
819     + return description;
820     +}
821     +
822     +QString Device::volumeDescription() const
823     +{
824     + QString description;
825     + const UDisks2::StorageVolume storageVolume(const_cast<Device*>(this));
826     + QString volume_label = prop("IdLabel").toString();
827     + if (volume_label.isEmpty())
828     + volume_label = prop("Name").toString();
829     + if (!volume_label.isEmpty())
830     + return volume_label;
831     +
832     + UDisks2::Device storageDevice(drivePath());
833     + const UDisks2::StorageDrive storageDrive(&storageDevice);
834     + Solid::StorageDrive::DriveType drive_type = storageDrive.driveType();
835     +
836     + // Handle media in optical drives
837     + if (drive_type == Solid::StorageDrive::CdromDrive)
838     + {
839     + const UDisks2::OpticalDisc disc(const_cast<Device*>(this));
840     + switch (disc.discType())
841     + {
842     + case Solid::OpticalDisc::UnknownDiscType:
843     + case Solid::OpticalDisc::CdRom:
844     + description = QCoreApplication::translate("", "CD-ROM");
845     + break;
846     +
847     + case Solid::OpticalDisc::CdRecordable:
848     + if (disc.isBlank())
849     + description = QCoreApplication::translate("", "Blank CD-R");
850     + else
851     + description = QCoreApplication::translate("", "CD-R");
852     + break;
853     +
854     + case Solid::OpticalDisc::CdRewritable:
855     + if (disc.isBlank())
856     + description = QCoreApplication::translate("", "Blank CD-RW");
857     + else
858     + description = QCoreApplication::translate("", "CD-RW");
859     + break;
860     +
861     + case Solid::OpticalDisc::DvdRom:
862     + description = QCoreApplication::translate("", "DVD-ROM");
863     + break;
864     +
865     + case Solid::OpticalDisc::DvdRam:
866     + if (disc.isBlank())
867     + description = QCoreApplication::translate("", "Blank DVD-RAM");
868     + else
869     + description = QCoreApplication::translate("", "DVD-RAM");
870     + break;
871     +
872     + case Solid::OpticalDisc::DvdRecordable:
873     + if (disc.isBlank())
874     + description = QCoreApplication::translate("", "Blank DVD-R");
875     + else
876     + description = QCoreApplication::translate("", "DVD-R");
877     + break;
878     +
879     + case Solid::OpticalDisc::DvdPlusRecordableDuallayer:
880     + if (disc.isBlank())
881     + description = QCoreApplication::translate("", "Blank DVD+R Dual-Layer");
882     + else
883     + description = QCoreApplication::translate("", "DVD+R Dual-Layer");
884     + break;
885     +
886     + case Solid::OpticalDisc::DvdRewritable:
887     + if (disc.isBlank())
888     + description = QCoreApplication::translate("", "Blank DVD-RW");
889     + else
890     + description = QCoreApplication::translate("", "DVD-RW");
891     + break;
892     +
893     + case Solid::OpticalDisc::DvdPlusRecordable:
894     + if (disc.isBlank())
895     + description = QCoreApplication::translate("", "Blank DVD+R");
896     + else
897     + description = QCoreApplication::translate("", "DVD+R");
898     + break;
899     +
900     + case Solid::OpticalDisc::DvdPlusRewritable:
901     + if (disc.isBlank())
902     + description = QCoreApplication::translate("", "Blank DVD+RW");
903     + else
904     + description = QCoreApplication::translate("", "DVD+RW");
905     + break;
906     +
907     + case Solid::OpticalDisc::DvdPlusRewritableDuallayer:
908     + if (disc.isBlank())
909     + description = QCoreApplication::translate("", "Blank DVD+RW Dual-Layer");
910     + else
911     + description = QCoreApplication::translate("", "DVD+RW Dual-Layer");
912     + break;
913     +
914     + case Solid::OpticalDisc::BluRayRom:
915     + description = QCoreApplication::translate("", "BD-ROM");
916     + break;
917     +
918     + case Solid::OpticalDisc::BluRayRecordable:
919     + if (disc.isBlank())
920     + description = QCoreApplication::translate("", "Blank BD-R");
921     + else
922     + description = QCoreApplication::translate("", "BD-R");
923     + break;
924     +
925     + case Solid::OpticalDisc::BluRayRewritable:
926     + if (disc.isBlank())
927     + description = QCoreApplication::translate("", "Blank BD-RE");
928     + else
929     + description = QCoreApplication::translate("", "BD-RE");
930     + break;
931     +
932     + case Solid::OpticalDisc::HdDvdRom:
933     + description = QCoreApplication::translate("", "HD DVD-ROM");
934     + break;
935     +
936     + case Solid::OpticalDisc::HdDvdRecordable:
937     + if (disc.isBlank())
938     + description = QCoreApplication::translate("", "Blank HD DVD-R");
939     + else
940     + description = QCoreApplication::translate("", "HD DVD-R");
941     + break;
942     +
943     + case Solid::OpticalDisc::HdDvdRewritable:
944     + if (disc.isBlank())
945     + description = QCoreApplication::translate("", "Blank HD DVD-RW");
946     + else
947     + description = QCoreApplication::translate("", "HD DVD-RW");
948     + break;
949     + }
950     +
951     + // Special case for pure audio disc
952     + if (disc.availableContent() == Solid::OpticalDisc::Audio)
953     + description = QCoreApplication::translate("", "Audio CD");
954     +
955     + return description;
956     + }
957     +
958     + const bool drive_is_removable = storageDrive.isRemovable();
959     + const bool drive_is_hotpluggable = storageDrive.isHotpluggable();
960     +
961     + QString size_str = formatByteSize(storageVolume.size());
962     + if (isEncryptedContainer())
963     + {
964     + if (!size_str.isEmpty())
965     + description = QCoreApplication::translate("", "%1 Encrypted Drive", "%1 is the size").arg(size_str);
966     + else
967     + description = QCoreApplication::translate("", "Encrypted Drive");
968     + }
969     + else if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
970     + {
971     + if (!size_str.isEmpty())
972     + {
973     + if (drive_is_hotpluggable)
974     + description = QCoreApplication::translate("", "%1 External Hard Drive", "%1 is the size").arg(size_str);
975     + else
976     + description = QCoreApplication::translate("", "%1 Hard Drive", "%1 is the size").arg(size_str);
977     + }
978     + else
979     + {
980     + if (drive_is_hotpluggable)
981     + description = QCoreApplication::translate("", "External Hard Drive");
982     + else
983     + description = QCoreApplication::translate("", "Hard Drive");
984     + }
985     + }
986     + else
987     + {
988     + if (drive_is_removable)
989     + description = QCoreApplication::translate("", "%1 Removable Media", "%1 is the size").arg(size_str);
990     + else
991     + description = QCoreApplication::translate("", "%1 Media", "%1 is the size").arg(size_str);
992     + }
993     +
994     + return description;
995     +}
996     +
997     +QString Device::icon() const
998     +{
999     + QString iconName = property( "HintIconName" ).toString(); // non-cached
1000     +
1001     + if ( !iconName.isEmpty() )
1002     + {
1003     + return iconName;
1004     + }
1005     + else if (isLoop() || isSwap())
1006     + {
1007     + return "drive-harddisk";
1008     + }
1009     + else if (isDrive()) {
1010     + const bool isRemovable = prop("Removable").toBool();
1011     + const QString conn = prop("ConnectionBus").toString();
1012     +
1013     + if (isOpticalDrive())
1014     + return "drive-optical";
1015     + else if (isRemovable && !prop("Optical").toBool()) {
1016     + if (conn == "usb")
1017     + return "drive-removable-media-usb";
1018     + else
1019     + return "drive-removable-media";
1020     + }
1021     + }
1022     + else if (isBlock()) {
1023     + const QString drv = drivePath();
1024     + if (drv.isEmpty() || drv == "/")
1025     + return "drive-harddisk"; // stuff like loop devices or swap which don't have the Drive prop set
1026     +
1027     + Device drive(drv);
1028     +
1029     + // handle media
1030     + const QString media = drive.prop("Media").toString();
1031     +
1032     + if ( !media.isEmpty() )
1033     + {
1034     + if ( drive.prop("Optical").toBool() ) // optical stuff
1035     + {
1036     + bool isWritable = drive.prop("OpticalBlank").toBool();
1037     +
1038     + const UDisks2::OpticalDisc disc(const_cast<Device*>(this));
1039     + Solid::OpticalDisc::ContentTypes availContent = disc.availableContent();
1040     +
1041     + if (availContent & Solid::OpticalDisc::VideoDvd) // Video DVD
1042     + return "media-optical-dvd-video";
1043     + else if ((availContent & Solid::OpticalDisc::VideoCd) || (availContent & Solid::OpticalDisc::SuperVideoCd)) // Video CD
1044     + return "media-optical-video";
1045     + else if ((availContent & Solid::OpticalDisc::Data) && (availContent & Solid::OpticalDisc::Audio)) // Mixed CD
1046     + return "media-optical-mixed-cd";
1047     + else if (availContent & Solid::OpticalDisc::Audio) // Audio CD
1048     + return "media-optical-audio";
1049     + else if (availContent & Solid::OpticalDisc::Data) // Data CD
1050     + return "media-optical-data";
1051     + else if ( isWritable )
1052     + return "media-optical-recordable";
1053     + else
1054     + {
1055     + if ( media.startsWith( "optical_dvd" ) || media.startsWith( "optical_hddvd" ) ) // DVD
1056     + return "media-optical-dvd";
1057     + else if ( media.startsWith( "optical_bd" ) ) // BluRay
1058     + return "media-optical-blu-ray";
1059     + }
1060     +
1061     + // fallback for every other optical disc
1062     + return "media-optical";
1063     + }
1064     +
1065     + if ( media == "flash_ms" ) // Flash & Co.
1066     + return "media-flash-memory-stick";
1067     + else if ( media == "flash_sd" || media == "flash_sdhc" || media == "flash_sdxc" || media == "flash_mmc" )
1068     + return "media-flash-sd-mmc";
1069     + else if ( media == "flash_sm" )
1070     + return "media-flash-smart-media";
1071     + else if ( media == "thumb" )
1072     + return "drive-removable-media-usb-pendrive";
1073     + else if ( media.startsWith( "flash" ) )
1074     + return "media-flash";
1075     + else if ( media == "floppy" ) // the good ol' floppy
1076     + return "media-floppy";
1077     + }
1078     +
1079     + if (drive.prop("ConnectionBus").toString() == "sdio") // hack for SD cards connected thru sdio bus
1080     + return "media-flash-sd-mmc";
1081     +
1082     + return drive.icon();
1083     + }
1084     +
1085     + return "drive-harddisk"; // general fallback
1086     +}
1087     +
1088     +QString Device::product() const
1089     +{
1090     + if (!isDrive()) {
1091     + Device drive(drivePath());
1092     + return drive.prop("Model").toString();
1093     + }
1094     +
1095     + return prop("Model").toString();
1096     +}
1097     +
1098     +QString Device::vendor() const
1099     +{
1100     + if (!isDrive()) {
1101     + Device drive(drivePath());
1102     + return drive.prop("Vendor").toString();
1103     + }
1104     +
1105     + return prop("Vendor").toString();
1106     +}
1107     +
1108     +QString Device::udi() const
1109     +{
1110     + if (m_backend) {
1111     + return m_backend->udi;
1112     + }
1113     +
1114     + return QString();
1115     +}
1116     +
1117     +QString Device::parentUdi() const
1118     +{
1119     + QString parent;
1120     +
1121     + if (propertyExists("Drive")) // block
1122     + parent = prop("Drive").value<QDBusObjectPath>().path();
1123     + else if (propertyExists("Table")) // partition
1124     + parent = prop("Table").value<QDBusObjectPath>().path();
1125     + else if (parent.isEmpty() || parent=="/") {
1126     + parent = UD2_UDI_DISKS_PREFIX;
1127     + }
1128     + return parent;
1129     +}
1130     +
1131     +QVariant Device::prop(const QString &key) const
1132     +{
1133     + if (m_backend) {
1134     + return m_backend->prop(key);
1135     + }
1136     +
1137     + return QVariant();
1138     +}
1139     +
1140     +bool Device::propertyExists(const QString &key) const
1141     +{
1142     + if (m_backend) {
1143     + return m_backend->propertyExists(key);
1144     + }
1145     +
1146     + return false;
1147     +}
1148     +
1149     +QVariantMap Device::allProperties() const
1150     +{
1151     + if (m_backend) {
1152     + return m_backend->allProperties();
1153     + }
1154     +
1155     + return QVariantMap();
1156     +}
1157     +
1158     +bool Device::hasInterface(const QString &name) const
1159     +{
1160     + if (m_backend) {
1161     + return m_backend->interfaces().contains(name);
1162     + }
1163     +
1164     + return false;
1165     +}
1166     +
1167     +QStringList Device::interfaces() const
1168     +{
1169     + if (m_backend) {
1170     + return m_backend->interfaces();
1171     + }
1172     +
1173     + return QStringList();
1174     +}
1175     +
1176     +QString Device::errorToString(const QString & error) const
1177     +{
1178     + if (error == UD2_ERROR_UNAUTHORIZED || error == UD2_ERROR_NOT_AUTHORIZED)
1179     + return QCoreApplication::translate("", "You are not authorized to perform this operation");
1180     + else if (error == UD2_ERROR_BUSY)
1181     + return QCoreApplication::translate("", "The device is currently busy");
1182     + else if (error == UD2_ERROR_FAILED)
1183     + return QCoreApplication::translate("", "The requested operation has failed");
1184     + else if (error == UD2_ERROR_CANCELED)
1185     + return QCoreApplication::translate("", "The requested operation has been canceled");
1186     + else if (error == UD2_ERROR_INVALID_OPTION)
1187     + return QCoreApplication::translate("", "An invalid or malformed option has been given");
1188     + else if (error == UD2_ERROR_MISSING_DRIVER)
1189     + return QCoreApplication::translate("", "The kernel driver for this filesystem type is not available");
1190     + else if (error == UD2_ERROR_ALREADY_MOUNTED)
1191     + return QCoreApplication::translate("", "The device is already mounted");
1192     + else if (error == UD2_ERROR_NOT_MOUNTED)
1193     + return QCoreApplication::translate("", "The device is not mounted");
1194     + else if (error == UD2_ERROR_MOUNTED_BY_OTHER_USER)
1195     + return QCoreApplication::translate("", "The device is mounted by another user");
1196     + else if (error == UD2_ERROR_ALREADY_UNMOUNTING)
1197     + return QCoreApplication::translate("", "The device is already unmounting");
1198     + else if (error == UD2_ERROR_TIMED_OUT)
1199     + return QCoreApplication::translate("", "The operation timed out");
1200     + else if (error == UD2_ERROR_WOULD_WAKEUP)
1201     + return QCoreApplication::translate("", "The operation would wake up a disk that is in a deep-sleep state");
1202     + else if (error == UD2_ERROR_ALREADY_CANCELLED)
1203     + return QCoreApplication::translate("", "The operation has already been canceled");
1204     + else
1205     + return QCoreApplication::translate("", "An unspecified error has occurred");
1206     +}
1207     +
1208     +Solid::ErrorType Device::errorToSolidError(const QString & error) const
1209     +{
1210     + if (error == UD2_ERROR_BUSY)
1211     + return Solid::DeviceBusy;
1212     + else if (error == UD2_ERROR_FAILED)
1213     + return Solid::OperationFailed;
1214     + else if (error == UD2_ERROR_CANCELED)
1215     + return Solid::UserCanceled;
1216     + else if (error == UD2_ERROR_INVALID_OPTION)
1217     + return Solid::InvalidOption;
1218     + else if (error == UD2_ERROR_MISSING_DRIVER)
1219     + return Solid::MissingDriver;
1220     + else
1221     + return Solid::UnauthorizedOperation;
1222     +}
1223     +
1224     +bool Device::isBlock() const
1225     +{
1226     + return hasInterface(UD2_DBUS_INTERFACE_BLOCK);
1227     +}
1228     +
1229     +bool Device::isPartition() const
1230     +{
1231     + return hasInterface(UD2_DBUS_INTERFACE_PARTITION);
1232     +}
1233     +
1234     +bool Device::isPartitionTable() const
1235     +{
1236     + return hasInterface(UD2_DBUS_INTERFACE_PARTITIONTABLE);
1237     +}
1238     +
1239     +bool Device::isStorageVolume() const
1240     +{
1241     + return isPartition() || isPartitionTable() || isStorageAccess() || isOpticalDisc();
1242     +}
1243     +
1244     +bool Device::isStorageAccess() const
1245     +{
1246     + return hasInterface(UD2_DBUS_INTERFACE_FILESYSTEM) || isEncryptedContainer();
1247     +}
1248     +
1249     +bool Device::isDrive() const
1250     +{
1251     + return hasInterface(UD2_DBUS_INTERFACE_DRIVE);
1252     +}
1253     +
1254     +bool Device::isOpticalDrive() const
1255     +{
1256     + return isDrive() && !prop("MediaCompatibility").toStringList().filter("optical_").isEmpty();
1257     +}
1258     +
1259     +bool Device::isOpticalDisc() const
1260     +{
1261     + const QString drv = drivePath();
1262     + if (drv.isEmpty() || drv == "/")
1263     + return false;
1264     +
1265     + Device drive(drv);
1266     + return drive.prop("Optical").toBool();
1267     +}
1268     +
1269     +bool Device::mightBeOpticalDisc() const
1270     +{
1271     + const QString drv = drivePath();
1272     + if (drv.isEmpty() || drv == "/")
1273     + return false;
1274     +
1275     + Device drive(drv);
1276     + return drive.isOpticalDrive();
1277     +}
1278     +
1279     +bool Device::isMounted() const
1280     +{
1281     + return propertyExists("MountPoints") && !qdbus_cast<QByteArrayList>(prop("MountPoints")).isEmpty();
1282     +}
1283     +
1284     +bool Device::isEncryptedContainer() const
1285     +{
1286     + return hasInterface(UD2_DBUS_INTERFACE_ENCRYPTED);
1287     +}
1288     +
1289     +bool Device::isEncryptedCleartext() const
1290     +{
1291     + const QString holderDevice = prop("CryptoBackingDevice").toString();
1292     + if (holderDevice.isEmpty() || holderDevice == "/")
1293     + return false;
1294     + else
1295     + return true;
1296     +}
1297     +
1298     +bool Device::isSwap() const
1299     +{
1300     + return hasInterface(UD2_DBUS_INTERFACE_SWAP);
1301     +}
1302     +
1303     +bool Device::isLoop() const
1304     +{
1305     + return hasInterface(UD2_DBUS_INTERFACE_LOOP);
1306     +}
1307     +
1308     +QString Device::drivePath() const
1309     +{
1310     + return prop("Drive").value<QDBusObjectPath>().path();
1311     +}
1312     diff --git a/solid/solid/backends/udisks2/udisksdevice.h b/solid/solid/backends/udisks2/udisksdevice.h
1313     new file mode 100644
1314     index 0000000..90bb042
1315     --- /dev/null
1316     +++ b/solid/solid/backends/udisks2/udisksdevice.h
1317     @@ -0,0 +1,103 @@
1318     +/*
1319     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
1320     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
1321     +
1322     + This library is free software; you can redistribute it and/or
1323     + modify it under the terms of the GNU Lesser General Public
1324     + License as published by the Free Software Foundation; either
1325     + version 2.1 of the License, or (at your option) version 3, or any
1326     + later version accepted by the membership of KDE e.V. (or its
1327     + successor approved by the membership of KDE e.V.), which shall
1328     + act as a proxy defined in Section 6 of version 3 of the license.
1329     +
1330     + This library is distributed in the hope that it will be useful,
1331     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1332     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1333     + Lesser General Public License for more details.
1334     +
1335     + You should have received a copy of the GNU Lesser General Public
1336     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1337     +*/
1338     +
1339     +#ifndef UDISKS2DEVICE_H
1340     +#define UDISKS2DEVICE_H
1341     +
1342     +#include "udisks2.h"
1343     +
1344     +#include <ifaces/device.h>
1345     +#include <solid/deviceinterface.h>
1346     +#include <solid/solidnamespace.h>
1347     +
1348     +#include <QtDBus/QDBusInterface>
1349     +#include <QtDBus/QDBusObjectPath>
1350     +#include <QtCore/QStringList>
1351     +
1352     +namespace Solid
1353     +{
1354     +namespace Backends
1355     +{
1356     +namespace UDisks2
1357     +{
1358     +
1359     +class DeviceBackend;
1360     +
1361     +class Device: public Solid::Ifaces::Device
1362     +{
1363     + Q_OBJECT
1364     +public:
1365     + Device(const QString &udi);
1366     + virtual ~Device();
1367     +
1368     + virtual QObject* createDeviceInterface(const Solid::DeviceInterface::Type& type);
1369     + virtual bool queryDeviceInterface(const Solid::DeviceInterface::Type& type) const;
1370     + virtual QString description() const;
1371     + virtual QStringList emblems() const;
1372     + virtual QString icon() const;
1373     + virtual QString product() const;
1374     + virtual QString vendor() const;
1375     + virtual QString udi() const;
1376     + virtual QString parentUdi() const;
1377     +
1378     + QVariant prop(const QString &key) const;
1379     + bool propertyExists(const QString &key) const;
1380     + QVariantMap allProperties() const;
1381     +
1382     + bool hasInterface(const QString & name) const;
1383     + QStringList interfaces() const;
1384     +
1385     + QString errorToString(const QString & error) const;
1386     + Solid::ErrorType errorToSolidError(const QString & error) const;
1387     +
1388     + bool isBlock() const;
1389     + bool isPartition() const;
1390     + bool isPartitionTable() const;
1391     + bool isStorageVolume() const;
1392     + bool isStorageAccess() const;
1393     + bool isDrive() const;
1394     + bool isOpticalDrive() const;
1395     + bool isOpticalDisc() const;
1396     + bool mightBeOpticalDisc() const;
1397     + bool isMounted() const;
1398     + bool isEncryptedContainer() const;
1399     + bool isEncryptedCleartext() const;
1400     + bool isSwap() const;
1401     + bool isLoop() const;
1402     +
1403     + QString drivePath() const;
1404     +
1405     +Q_SIGNALS:
1406     + void changed();
1407     + void propertyChanged(const QMap<QString,int> &changes);
1408     +
1409     +private:
1410     + QString storageDescription() const;
1411     + QString volumeDescription() const;
1412     +
1413     + DeviceBackend *m_backend;
1414     +};
1415     +
1416     +}
1417     +}
1418     +}
1419     +
1420     +#endif // UDISKS2DEVICE_H
1421     diff --git a/solid/solid/backends/udisks2/udisksdevicebackend.cpp b/solid/solid/backends/udisks2/udisksdevicebackend.cpp
1422     new file mode 100644
1423     index 0000000..ffa98db
1424     --- /dev/null
1425     +++ b/solid/solid/backends/udisks2/udisksdevicebackend.cpp
1426     @@ -0,0 +1,205 @@
1427     +/*
1428     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
1429     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
1430     + Copyright 2012 Dan Vrátil <dvratil@redhat.com>
1431     +
1432     + This library is free software; you can redistribute it and/or
1433     + modify it under the terms of the GNU Lesser General Public
1434     + License as published by the Free Software Foundation; either
1435     + version 2.1 of the License, or (at your option) version 3, or any
1436     + later version accepted by the membership of KDE e.V. (or its
1437     + successor approved by the membership of KDE e.V.), which shall
1438     + act as a proxy defined in Section 6 of version 3 of the license.
1439     +
1440     + This library is distributed in the hope that it will be useful,
1441     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1442     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1443     + Lesser General Public License for more details.
1444     +
1445     + You should have received a copy of the GNU Lesser General Public
1446     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1447     +*/
1448     +
1449     +#include "udisksdevicebackend.h"
1450     +
1451     +#include <QtDBus/QDBusConnection>
1452     +#include <QtDBus/QDBusInterface>
1453     +#include <QtXml/QDomDocument>
1454     +
1455     +#include "solid/deviceinterface.h"
1456     +#include "solid/genericinterface.h"
1457     +
1458     +using namespace Solid::Backends::UDisks2;
1459     +
1460     +/* Static cache for DeviceBackends for all UDIs */
1461     +QMap<QString /* UDI */, DeviceBackend*> DeviceBackend::s_backends;
1462     +
1463     +DeviceBackend* DeviceBackend::backendForUDI(const QString& udi)
1464     +{
1465     + DeviceBackend *backend = 0;
1466     + if (udi.isEmpty()) {
1467     + return backend;
1468     + }
1469     +
1470     + if (s_backends.contains(udi)) {
1471     + backend = s_backends.value(udi);
1472     + } else {
1473     + backend = new DeviceBackend(udi);
1474     + s_backends.insert(udi, backend);
1475     + }
1476     +
1477     + return backend;
1478     +}
1479     +
1480     +DeviceBackend::DeviceBackend(const QString& udi)
1481     + : udi(udi)
1482     +{
1483     + qDebug() << "Creating backend for device" << udi;
1484     + m_device = new QDBusInterface(UD2_DBUS_SERVICE, udi,
1485     + QString(), // no interface, we aggregate them
1486     + QDBusConnection::systemBus(), this);
1487     +
1488     + if (m_device->isValid()) {
1489     + QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
1490     + SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList)));
1491     + QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesAdded",
1492     + this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap)));
1493     + QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesRemoved",
1494     + this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList)));
1495     +
1496     + initInterfaces();
1497     + }
1498     +}
1499     +
1500     +DeviceBackend::~DeviceBackend()
1501     +{
1502     +}
1503     +
1504     +void DeviceBackend::initInterfaces()
1505     +{
1506     + m_interfaces.clear();
1507     + const QString xmlData = introspect();
1508     + QDomDocument dom;
1509     + dom.setContent(xmlData);
1510     + QDomNodeList ifaceNodeList = dom.elementsByTagName("interface");
1511     + for (int i = 0; i < ifaceNodeList.count(); i++) {
1512     + QDomElement ifaceElem = ifaceNodeList.item(i).toElement();
1513     + if (!ifaceElem.isNull())
1514     + m_interfaces.append(ifaceElem.attribute("name"));
1515     + }
1516     +}
1517     +
1518     +QStringList DeviceBackend::interfaces() const
1519     +{
1520     + return m_interfaces;
1521     +}
1522     +
1523     +
1524     +QString DeviceBackend::introspect() const
1525     +{
1526     + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, udi,
1527     + DBUS_INTERFACE_INTROSPECT, "Introspect");
1528     + QDBusPendingReply<QString> reply = QDBusConnection::systemBus().call(call);
1529     +
1530     + if (reply.isValid())
1531     + return reply.value();
1532     + else {
1533     + return QString();
1534     + }
1535     +}
1536     +
1537     +QVariant DeviceBackend::prop(const QString& key)
1538     +{
1539     + checkCache(key);
1540     + return m_propertyCache.value(key);
1541     +}
1542     +
1543     +bool DeviceBackend::propertyExists(const QString& key)
1544     +{
1545     + checkCache(key);
1546     + return m_propertyCache.contains(key);
1547     +}
1548     +
1549     +
1550     +QVariantMap DeviceBackend::allProperties() const
1551     +{
1552     + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "GetAll");
1553     +
1554     + Q_FOREACH (const QString & iface, m_interfaces) {
1555     + if (iface.startsWith("org.freedesktop.DBus")) {
1556     + continue;
1557     + }
1558     +
1559     + call.setArguments(QVariantList() << iface);
1560     + QDBusPendingReply<QVariantMap> reply = QDBusConnection::systemBus().call(call);
1561     +
1562     + if (reply.isValid()) {
1563     + m_propertyCache.unite(reply.value());
1564     + } else {
1565     + qWarning() << "Error getting props:" << reply.error().name() << reply.error().message();
1566     + }
1567     + //qDebug() << "After iface" << iface << ", cache now contains" << m_cache.size() << "items";
1568     + }
1569     +
1570     + return m_propertyCache;
1571     +}
1572     +
1573     +void DeviceBackend::checkCache(const QString& key) const
1574     +{
1575     + if (m_propertyCache.isEmpty()) { // recreate the cache
1576     + allProperties();
1577     + }
1578     +
1579     + if (m_propertyCache.contains(key)) {
1580     + return;
1581     + }
1582     +
1583     + QVariant reply = m_device->property(key.toUtf8());
1584     +
1585     + if (reply.isValid()) {
1586     + m_propertyCache.insert(key, reply);
1587     + } else {
1588     + qWarning() << "got invalid reply for cache:" << key;
1589     + }
1590     +}
1591     +
1592     +void DeviceBackend::slotPropertiesChanged(const QString& ifaceName, const QVariantMap& changedProps, const QStringList& invalidatedProps)
1593     +{
1594     + qDebug() << udi << "'s interface" << ifaceName << "changed props:";
1595     +
1596     + QMap<QString, int> changeMap;
1597     +
1598     + Q_FOREACH(const QString & key, invalidatedProps) {
1599     + m_propertyCache.remove(key);
1600     + changeMap.insert(key, Solid::GenericInterface::PropertyRemoved);
1601     + qDebug() << "\t invalidated:" << key;
1602     + }
1603     +
1604     + QMapIterator<QString, QVariant> i(changedProps);
1605     + while (i.hasNext()) {
1606     + i.next();
1607     + const QString key = i.key();
1608     + m_propertyCache.insert(key, i.value()); // replace the value
1609     + changeMap.insert(key, Solid::GenericInterface::PropertyModified);
1610     + qDebug() << "\t modified:" << key << ":" << m_propertyCache.value(key);
1611     + }
1612     +
1613     + Q_EMIT propertyChanged(changeMap);
1614     + Q_EMIT changed();
1615     +}
1616     +
1617     +void DeviceBackend::slotInterfacesAdded(const QDBusObjectPath& object_path, const QVariantMapMap& interfaces_and_properties)
1618     +{
1619     + if (object_path.path() == udi) {
1620     + m_interfaces.append(interfaces_and_properties.keys());
1621     + }
1622     +}
1623     +
1624     +void DeviceBackend::slotInterfacesRemoved(const QDBusObjectPath& object_path, const QStringList& interfaces)
1625     +{
1626     + if (object_path.path() == udi) {
1627     + Q_FOREACH(const QString & iface, interfaces) {
1628     + m_interfaces.removeAll(iface);
1629     + }
1630     + }
1631     +}
1632     diff --git a/solid/solid/backends/udisks2/udisksdevicebackend.h b/solid/solid/backends/udisks2/udisksdevicebackend.h
1633     new file mode 100644
1634     index 0000000..4953ad5
1635     --- /dev/null
1636     +++ b/solid/solid/backends/udisks2/udisksdevicebackend.h
1637     @@ -0,0 +1,83 @@
1638     +/*
1639     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
1640     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
1641     + Copyright 2012 Dan Vrátil <dvratil@redhat.com>
1642     +
1643     + This library is free software; you can redistribute it and/or
1644     + modify it under the terms of the GNU Lesser General Public
1645     + License as published by the Free Software Foundation; either
1646     + version 2.1 of the License, or (at your option) version 3, or any
1647     + later version accepted by the membership of KDE e.V. (or its
1648     + successor approved by the membership of KDE e.V.), which shall
1649     + act as a proxy defined in Section 6 of version 3 of the license.
1650     +
1651     + This library is distributed in the hope that it will be useful,
1652     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1653     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1654     + Lesser General Public License for more details.
1655     +
1656     + You should have received a copy of the GNU Lesser General Public
1657     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1658     +*/
1659     +
1660     +#ifndef UDISKSDEVICEBACKEND_H
1661     +#define UDISKSDEVICEBACKEND_H
1662     +
1663     +#include <QObject>
1664     +#include <QtDBus/QDBusConnection>
1665     +#include <QtDBus/QDBusObjectPath>
1666     +#include <QtDBus/QDBusInterface>
1667     +#include <QStringList>
1668     +
1669     +#include "udisks2.h"
1670     +
1671     +namespace Solid {
1672     +namespace Backends {
1673     +namespace UDisks2 {
1674     +
1675     +class DeviceBackend: public QObject {
1676     +
1677     + Q_OBJECT
1678     +
1679     + public:
1680     + static DeviceBackend* backendForUDI(const QString &udi);
1681     +
1682     + DeviceBackend(const QString &udi);
1683     + ~DeviceBackend();
1684     +
1685     + void initInterfaces();
1686     + QString introspect() const;
1687     +
1688     + QVariant prop(const QString &key);
1689     + bool propertyExists(const QString &key);
1690     + QVariantMap allProperties() const;
1691     + void checkCache(const QString &key) const;
1692     +
1693     + QStringList interfaces() const;
1694     +
1695     + QString udi;
1696     +
1697     + Q_SIGNALS:
1698     + void propertyChanged(const QMap<QString, int> &changeMap);
1699     + void changed();
1700     +
1701     + private Q_SLOTS:
1702     + void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
1703     + void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
1704     + void slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps);
1705     +
1706     + private:
1707     + QDBusInterface *m_device;
1708     +
1709     + mutable QVariantMap m_propertyCache;
1710     + QStringList m_interfaces;
1711     +
1712     + static QMap<QString, DeviceBackend*> s_backends;
1713     +
1714     +};
1715     +
1716     +} /* namespace UDisks2 */
1717     +} /* namespace Backends */
1718     +} /* namespace Solid */
1719     +
1720     +#endif /* UDISKSDEVICEBACKEND_H */
1721     \ No newline at end of file
1722     diff --git a/solid/solid/backends/udisks2/udisksdeviceinterface.cpp b/solid/solid/backends/udisks2/udisksdeviceinterface.cpp
1723     new file mode 100644
1724     index 0000000..9fa60e5
1725     --- /dev/null
1726     +++ b/solid/solid/backends/udisks2/udisksdeviceinterface.cpp
1727     @@ -0,0 +1,33 @@
1728     +/*
1729     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
1730     +
1731     + This library is free software; you can redistribute it and/or
1732     + modify it under the terms of the GNU Lesser General Public
1733     + License as published by the Free Software Foundation; either
1734     + version 2.1 of the License, or (at your option) version 3, or any
1735     + later version accepted by the membership of KDE e.V. (or its
1736     + successor approved by the membership of KDE e.V.), which shall
1737     + act as a proxy defined in Section 6 of version 3 of the license.
1738     +
1739     + This library is distributed in the hope that it will be useful,
1740     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1741     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1742     + Lesser General Public License for more details.
1743     +
1744     + You should have received a copy of the GNU Lesser General Public
1745     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1746     +*/
1747     +
1748     +#include "udisksdeviceinterface.h"
1749     +
1750     +using namespace Solid::Backends::UDisks2;
1751     +
1752     +DeviceInterface::DeviceInterface(Device *device)
1753     + : QObject(device), m_device(device)
1754     +{
1755     +
1756     +}
1757     +
1758     +DeviceInterface::~DeviceInterface()
1759     +{
1760     +}
1761     diff --git a/solid/solid/backends/udisks2/udisksdeviceinterface.h b/solid/solid/backends/udisks2/udisksdeviceinterface.h
1762     new file mode 100644
1763     index 0000000..43a1b6f
1764     --- /dev/null
1765     +++ b/solid/solid/backends/udisks2/udisksdeviceinterface.h
1766     @@ -0,0 +1,148 @@
1767     +/*
1768     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
1769     +
1770     + This library is free software; you can redistribute it and/or
1771     + modify it under the terms of the GNU Lesser General Public
1772     + License as published by the Free Software Foundation; either
1773     + version 2.1 of the License, or (at your option) version 3, or any
1774     + later version accepted by the membership of KDE e.V. (or its
1775     + successor approved by the membership of KDE e.V.), which shall
1776     + act as a proxy defined in Section 6 of version 3 of the license.
1777     +
1778     + This library is distributed in the hope that it will be useful,
1779     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1780     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1781     + Lesser General Public License for more details.
1782     +
1783     + You should have received a copy of the GNU Lesser General Public
1784     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1785     +*/
1786     +
1787     +#ifndef UDISKS2DEVICEINTERFACE_H
1788     +#define UDISKS2DEVICEINTERFACE_H
1789     +
1790     +#include <ifaces/deviceinterface.h>
1791     +#include "udisksdevice.h"
1792     +
1793     +#include <QtCore/QObject>
1794     +#include <QtCore/QStringList>
1795     +
1796     +namespace Solid
1797     +{
1798     +namespace Backends
1799     +{
1800     +namespace UDisks2
1801     +{
1802     +
1803     +class DeviceInterface : public QObject, virtual public Solid::Ifaces::DeviceInterface
1804     +{
1805     + Q_OBJECT
1806     + Q_INTERFACES(Solid::Ifaces::DeviceInterface)
1807     +public:
1808     + DeviceInterface(Device *device);
1809     + virtual ~DeviceInterface();
1810     +
1811     +protected:
1812     + Device *m_device;
1813     +
1814     +public:
1815     + inline static QStringList toStringList(Solid::DeviceInterface::Type type)
1816     + {
1817     + QStringList list;
1818     +
1819     + switch(type)
1820     + {
1821     + case Solid::DeviceInterface::GenericInterface:
1822     + list << "generic";
1823     + break;
1824     + case Solid::DeviceInterface::Processor:
1825     + // Doesn't exist with UDisks
1826     + break;
1827     + case Solid::DeviceInterface::Block:
1828     + list << "block";
1829     + break;
1830     + case Solid::DeviceInterface::StorageAccess:
1831     + list << "volume";
1832     + break;
1833     + case Solid::DeviceInterface::StorageDrive:
1834     + list << "storage";
1835     + break;
1836     + case Solid::DeviceInterface::OpticalDrive:
1837     + list << "storage.cdrom";
1838     + break;
1839     + case Solid::DeviceInterface::StorageVolume:
1840     + list << "volume";
1841     + break;
1842     + case Solid::DeviceInterface::OpticalDisc:
1843     + list << "volume.disc";
1844     + break;
1845     + case Solid::DeviceInterface::Camera:
1846     + // Doesn't exist with UDisks
1847     + break;
1848     + case Solid::DeviceInterface::PortableMediaPlayer:
1849     + // Doesn't exist with UDisks
1850     + break;
1851     + case Solid::DeviceInterface::NetworkInterface:
1852     + // Doesn't exist with UDisks
1853     + break;
1854     + case Solid::DeviceInterface::AcAdapter:
1855     + // Doesn't exist with UDisks
1856     + break;
1857     + case Solid::DeviceInterface::Battery:
1858     + // Doesn't exist with UDisks
1859     + break;
1860     + case Solid::DeviceInterface::Button:
1861     + // Doesn't exist with UDisks
1862     + break;
1863     + case Solid::DeviceInterface::AudioInterface:
1864     + // Doesn't exist with UDisks
1865     + break;
1866     + case Solid::DeviceInterface::DvbInterface:
1867     + // Doesn't exist with UDisks
1868     + break;
1869     + case Solid::DeviceInterface::Video:
1870     + // Doesn't exist with UDisks
1871     + break;
1872     + case Solid::DeviceInterface::SerialInterface:
1873     + // Doesn't exist with UDisks
1874     + break;
1875     + case Solid::DeviceInterface::InternetGateway:
1876     + break;
1877     + case Solid::DeviceInterface::SmartCardReader:
1878     + // Doesn't exist with UDisks
1879     + case Solid::DeviceInterface::NetworkShare:
1880     + // Doesn't exist with UDisks
1881     + break;
1882     + case Solid::DeviceInterface::Unknown:
1883     + break;
1884     + case Solid::DeviceInterface::Last:
1885     + break;
1886     + }
1887     +
1888     + return list;
1889     + }
1890     +
1891     + inline static Solid::DeviceInterface::Type fromString(const QString &capability)
1892     + {
1893     + if (capability == "generic")
1894     + return Solid::DeviceInterface::GenericInterface;
1895     + else if (capability == "block")
1896     + return Solid::DeviceInterface::Block;
1897     + else if (capability == "storage")
1898     + return Solid::DeviceInterface::StorageDrive;
1899     + else if (capability == "storage.cdrom")
1900     + return Solid::DeviceInterface::OpticalDrive;
1901     + else if (capability == "volume")
1902     + return Solid::DeviceInterface::StorageVolume;
1903     + else if (capability == "volume.disc")
1904     + return Solid::DeviceInterface::OpticalDisc;
1905     + else
1906     + return Solid::DeviceInterface::Unknown;
1907     + }
1908     +};
1909     +
1910     +}
1911     +}
1912     +}
1913     +
1914     +#endif // UDISKS2DEVICEINTERFACE_H
1915     diff --git a/solid/solid/backends/udisks2/udisksgenericinterface.cpp b/solid/solid/backends/udisks2/udisksgenericinterface.cpp
1916     new file mode 100644
1917     index 0000000..2d8cea2
1918     --- /dev/null
1919     +++ b/solid/solid/backends/udisks2/udisksgenericinterface.cpp
1920     @@ -0,0 +1,53 @@
1921     +/*
1922     + Copyright 2009 Pino Toscano <pino@kde.org>
1923     + Copyright 2012 Lukáš Tinkl <ltinkl@redhat.com>
1924     +
1925     + This library is free software; you can redistribute it and/or
1926     + modify it under the terms of the GNU Lesser General Public
1927     + License as published by the Free Software Foundation; either
1928     + version 2.1 of the License, or (at your option) version 3, or any
1929     + later version accepted by the membership of KDE e.V. (or its
1930     + successor approved by the membership of KDE e.V.), which shall
1931     + act as a proxy defined in Section 6 of version 3 of the license.
1932     +
1933     + This library is distributed in the hope that it will be useful,
1934     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1935     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1936     + Lesser General Public License for more details.
1937     +
1938     + You should have received a copy of the GNU Lesser General Public
1939     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1940     +*/
1941     +
1942     +#include "udisksgenericinterface.h"
1943     +
1944     +#include "udisksdevice.h"
1945     +
1946     +using namespace Solid::Backends::UDisks2;
1947     +
1948     +GenericInterface::GenericInterface(Device *device)
1949     + : DeviceInterface(device)
1950     +{
1951     + connect(device, SIGNAL(propertyChanged(QMap<QString,int>)),
1952     + this, SIGNAL(propertyChanged(QMap<QString,int>)));
1953     +}
1954     +
1955     +GenericInterface::~GenericInterface()
1956     +{
1957     +}
1958     +
1959     +QVariant GenericInterface::property(const QString &key) const
1960     +{
1961     + return m_device->prop(key);
1962     +}
1963     +
1964     +QVariantMap GenericInterface::allProperties() const
1965     +{
1966     + return m_device->allProperties();
1967     +}
1968     +
1969     +bool GenericInterface::propertyExists(const QString &key) const
1970     +{
1971     + return m_device->propertyExists(key);
1972     +}
1973     +
1974     diff --git a/solid/solid/backends/udisks2/udisksgenericinterface.h b/solid/solid/backends/udisks2/udisksgenericinterface.h
1975     new file mode 100644
1976     index 0000000..d225f32
1977     --- /dev/null
1978     +++ b/solid/solid/backends/udisks2/udisksgenericinterface.h
1979     @@ -0,0 +1,57 @@
1980     +/*
1981     + Copyright 2009 Pino Toscano <pino@kde.org>
1982     +
1983     + This library is free software; you can redistribute it and/or
1984     + modify it under the terms of the GNU Lesser General Public
1985     + License as published by the Free Software Foundation; either
1986     + version 2.1 of the License, or (at your option) version 3, or any
1987     + later version accepted by the membership of KDE e.V. (or its
1988     + successor approved by the membership of KDE e.V.), which shall
1989     + act as a proxy defined in Section 6 of version 3 of the license.
1990     +
1991     + This library is distributed in the hope that it will be useful,
1992     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1993     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1994     + Lesser General Public License for more details.
1995     +
1996     + You should have received a copy of the GNU Lesser General Public
1997     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
1998     +*/
1999     +
2000     +#ifndef SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H
2001     +#define SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H
2002     +
2003     +#include <solid/ifaces/genericinterface.h>
2004     +#include <solid/genericinterface.h>
2005     +#include "udisksdeviceinterface.h"
2006     +
2007     +namespace Solid
2008     +{
2009     +namespace Backends
2010     +{
2011     +namespace UDisks2
2012     +{
2013     +class Device;
2014     +
2015     +class GenericInterface : public DeviceInterface, virtual public Solid::Ifaces::GenericInterface
2016     +{
2017     + Q_OBJECT
2018     + Q_INTERFACES(Solid::Ifaces::GenericInterface)
2019     +
2020     +public:
2021     + GenericInterface(Device *device);
2022     + virtual ~GenericInterface();
2023     +
2024     + virtual QVariant property(const QString &key) const;
2025     + virtual QVariantMap allProperties() const;
2026     + virtual bool propertyExists(const QString &key) const;
2027     +
2028     +Q_SIGNALS:
2029     + void propertyChanged(const QMap<QString, int> &changes);
2030     + void conditionRaised(const QString &condition, const QString &reason);
2031     +};
2032     +}
2033     +}
2034     +}
2035     +
2036     +#endif // SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H
2037     diff --git a/solid/solid/backends/udisks2/udisksmanager.cpp b/solid/solid/backends/udisks2/udisksmanager.cpp
2038     new file mode 100644
2039     index 0000000..69e053f
2040     --- /dev/null
2041     +++ b/solid/solid/backends/udisks2/udisksmanager.cpp
2042     @@ -0,0 +1,238 @@
2043     +/*
2044     + Copyright 2012 Lukáš Tinkl <ltinkl@redhat.com>
2045     +
2046     + This library is free software; you can redistribute it and/or
2047     + modify it under the terms of the GNU Lesser General Public
2048     + License as published by the Free Software Foundation; either
2049     + version 2.1 of the License, or (at your option) version 3, or any
2050     + later version accepted by the membership of KDE e.V. (or its
2051     + successor approved by the membership of KDE e.V.), which shall
2052     + act as a proxy defined in Section 6 of version 3 of the license.
2053     +
2054     + This library is distributed in the hope that it will be useful,
2055     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2056     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2057     + Lesser General Public License for more details.
2058     +
2059     + You should have received a copy of the GNU Lesser General Public
2060     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
2061     +*/
2062     +
2063     +#include "udisksmanager.h"
2064     +
2065     +#include <QtCore/QCoreApplication>
2066     +#include <QtCore/QDebug>
2067     +#include <QtDBus>
2068     +#include <QtXml/QDomDocument>
2069     +
2070     +#include "../shared/rootdevice.h"
2071     +
2072     +using namespace Solid::Backends::UDisks2;
2073     +using namespace Solid::Backends::Shared;
2074     +
2075     +Manager::Manager(QObject *parent)
2076     + : Solid::Ifaces::DeviceManager(parent),
2077     + m_manager(UD2_DBUS_SERVICE,
2078     + UD2_DBUS_PATH,
2079     + QDBusConnection::systemBus())
2080     +{
2081     + m_supportedInterfaces
2082     + << Solid::DeviceInterface::GenericInterface
2083     + << Solid::DeviceInterface::Block
2084     + << Solid::DeviceInterface::StorageAccess
2085     + << Solid::DeviceInterface::StorageDrive
2086     + << Solid::DeviceInterface::OpticalDrive
2087     + << Solid::DeviceInterface::OpticalDisc
2088     + << Solid::DeviceInterface::StorageVolume;
2089     +
2090     + qDBusRegisterMetaType<QList<QDBusObjectPath> >();
2091     + qDBusRegisterMetaType<QVariantMap>();
2092     + qDBusRegisterMetaType<QVariantMapMap>();
2093     + qDBusRegisterMetaType<QByteArrayList>();
2094     + qDBusRegisterMetaType<DBUSManagerStruct>();
2095     +
2096     + bool serviceFound = m_manager.isValid();
2097     + if (!serviceFound) {
2098     + // find out whether it will be activated automatically
2099     + QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus",
2100     + "/org/freedesktop/DBus",
2101     + "org.freedesktop.DBus",
2102     + "ListActivatableNames");
2103     +
2104     + QDBusReply<QStringList> reply = QDBusConnection::systemBus().call(message);
2105     + if (reply.isValid() && reply.value().contains(UD2_DBUS_SERVICE)) {
2106     + QDBusConnection::systemBus().interface()->startService(UD2_DBUS_SERVICE);
2107     + serviceFound = true;
2108     + }
2109     + }
2110     +
2111     + if (serviceFound) {
2112     + connect(&m_manager, SIGNAL(InterfacesAdded(QDBusObjectPath, QVariantMapMap)),
2113     + this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap)));
2114     + connect(&m_manager, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)),
2115     + this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList)));
2116     + }
2117     +}
2118     +
2119     +Manager::~Manager()
2120     +{
2121     + QDBusConnection::systemBus().disconnectFromBus("Solid::UDisks2");
2122     +}
2123     +
2124     +QObject* Manager::createDevice(const QString& udi)
2125     +{
2126     + if (udi==udiPrefix()) {
2127     + RootDevice *root = new RootDevice(udi);
2128     +
2129     + root->setProduct(QCoreApplication::translate("", "Storage"));
2130     + root->setDescription(QCoreApplication::translate("", "Storage devices"));
2131     + root->setIcon("server-database"); // Obviously wasn't meant for that, but maps nicely in oxygen icon set :-p
2132     +
2133     + return root;
2134     + } else if (deviceCache().contains(udi)) {
2135     + return new Device(udi);
2136     + } else {
2137     + return 0;
2138     + }
2139     +}
2140     +
2141     +QStringList Manager::devicesFromQuery(const QString& parentUdi, Solid::DeviceInterface::Type type)
2142     +{
2143     + QStringList result;
2144     +
2145     + if (!parentUdi.isEmpty())
2146     + {
2147     + Q_FOREACH (const QString &udi, deviceCache())
2148     + {
2149     + Device device(udi);
2150     + if (device.queryDeviceInterface(type) && device.parentUdi() == parentUdi)
2151     + result << udi;
2152     + }
2153     +
2154     + return result;
2155     + }
2156     + else if (type != Solid::DeviceInterface::Unknown)
2157     + {
2158     + Q_FOREACH (const QString &udi, deviceCache())
2159     + {
2160     + Device device(udi);
2161     + if (device.queryDeviceInterface(type))
2162     + result << udi;
2163     + }
2164     +
2165     + return result;
2166     + }
2167     +
2168     + return deviceCache();
2169     +}
2170     +
2171     +QStringList Manager::allDevices()
2172     +{
2173     + m_deviceCache.clear();
2174     +
2175     + introspect("/org/freedesktop/UDisks2/block_devices", true /*checkOptical*/);
2176     + introspect("/org/freedesktop/UDisks2/drives");
2177     +
2178     + return m_deviceCache;
2179     +}
2180     +
2181     +void Manager::introspect(const QString & path, bool checkOptical)
2182     +{
2183     + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path,
2184     + DBUS_INTERFACE_INTROSPECT, "Introspect");
2185     + QDBusPendingReply<QString> reply = QDBusConnection::systemBus().call(call);
2186     +
2187     + if (reply.isValid()) {
2188     + QDomDocument dom;
2189     + dom.setContent(reply.value());
2190     + QDomNodeList nodeList = dom.documentElement().elementsByTagName("node");
2191     + for (int i = 0; i < nodeList.count(); i++) {
2192     + QDomElement nodeElem = nodeList.item(i).toElement();
2193     + if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) {
2194     + const QString udi = path + "/" + nodeElem.attribute("name");
2195     +
2196     + if (checkOptical) {
2197     + Device device(udi);
2198     + if (device.mightBeOpticalDisc()) {
2199     + QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
2200     + SLOT(slotMediaChanged(QDBusMessage)));
2201     + if (!device.isOpticalDisc()) // skip empty CD disc
2202     + continue;
2203     + }
2204     + }
2205     +
2206     + m_deviceCache.append(udi);
2207     + }
2208     + }
2209     + }
2210     + else
2211     + qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
2212     +}
2213     +
2214     +QSet< Solid::DeviceInterface::Type > Manager::supportedInterfaces() const
2215     +{
2216     + return m_supportedInterfaces;
2217     +}
2218     +
2219     +QString Manager::udiPrefix() const
2220     +{
2221     + return UD2_UDI_DISKS_PREFIX;
2222     +}
2223     +
2224     +void Manager::slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties)
2225     +{
2226     + const QString udi = object_path.path();
2227     +
2228     + qDebug() << udi << "has new interfaces:" << interfaces_and_properties.keys();
2229     +
2230     + // new device, we don't know it yet
2231     + if (!m_deviceCache.contains(udi)) {
2232     + m_deviceCache.append(udi);
2233     + Q_EMIT deviceAdded(udi);
2234     + }
2235     +}
2236     +
2237     +void Manager::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces)
2238     +{
2239     + const QString udi = object_path.path();
2240     +
2241     + qDebug() << udi << "lost interfaces:" << interfaces;
2242     +
2243     + Device device(udi);
2244     +
2245     + if (!udi.isEmpty() && (interfaces.isEmpty() || device.interfaces().isEmpty() || device.interfaces().contains(UD2_DBUS_INTERFACE_FILESYSTEM))) {
2246     + Q_EMIT deviceRemoved(udi);
2247     + m_deviceCache.removeAll(udi);
2248     + }
2249     +}
2250     +
2251     +void Manager::slotMediaChanged(const QDBusMessage & msg)
2252     +{
2253     + const QVariantMap properties = qdbus_cast<QVariantMap>(msg.arguments().at(1));
2254     +
2255     + if (!properties.contains("Size")) // react only on Size changes
2256     + return;
2257     +
2258     + const QString udi = msg.path();
2259     + qulonglong size = properties.value("Size").toULongLong();
2260     + qDebug() << "MEDIA CHANGED in" << udi << "; size is:" << size;
2261     +
2262     + if (!m_deviceCache.contains(udi) && size > 0) { // we don't know the optdisc, got inserted
2263     + m_deviceCache.append(udi);
2264     + Q_EMIT deviceAdded(udi);
2265     + }
2266     +
2267     + if (m_deviceCache.contains(udi) && size == 0) { // we know the optdisc, got removed
2268     + Q_EMIT deviceRemoved(udi);
2269     + m_deviceCache.removeAll(udi);
2270     + }
2271     +}
2272     +
2273     +const QStringList & Manager::deviceCache()
2274     +{
2275     + if (m_deviceCache.isEmpty())
2276     + allDevices();
2277     +
2278     + return m_deviceCache;
2279     +}
2280     +
2281     diff --git a/solid/solid/backends/udisks2/udisksmanager.h b/solid/solid/backends/udisks2/udisksmanager.h
2282     new file mode 100644
2283     index 0000000..fb929ce
2284     --- /dev/null
2285     +++ b/solid/solid/backends/udisks2/udisksmanager.h
2286     @@ -0,0 +1,70 @@
2287     +/*
2288     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
2289     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
2290     +
2291     + This library is free software; you can redistribute it and/or
2292     + modify it under the terms of the GNU Lesser General Public
2293     + License as published by the Free Software Foundation; either
2294     + version 2.1 of the License, or (at your option) version 3, or any
2295     + later version accepted by the membership of KDE e.V. (or its
2296     + successor approved by the membership of KDE e.V.), which shall
2297     + act as a proxy defined in Section 6 of version 3 of the license.
2298     +
2299     + This library is distributed in the hope that it will be useful,
2300     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2301     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2302     + Lesser General Public License for more details.
2303     +
2304     + You should have received a copy of the GNU Lesser General Public
2305     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
2306     +*/
2307     +
2308     +#ifndef UDISKS2MANAGER_H
2309     +#define UDISKS2MANAGER_H
2310     +
2311     +#include "udisks2.h"
2312     +#include "udisksdevice.h"
2313     +#include "dbus/manager.h"
2314     +
2315     +#include "solid/ifaces/devicemanager.h"
2316     +
2317     +#include <QtDBus/QDBusInterface>
2318     +#include <QtCore/QSet>
2319     +
2320     +namespace Solid
2321     +{
2322     +namespace Backends
2323     +{
2324     +namespace UDisks2
2325     +{
2326     +
2327     +class Manager: public Solid::Ifaces::DeviceManager
2328     +{
2329     + Q_OBJECT
2330     +
2331     +public:
2332     + Manager(QObject *parent);
2333     + virtual QObject* createDevice(const QString& udi);
2334     + virtual QStringList devicesFromQuery(const QString& parentUdi, Solid::DeviceInterface::Type type);
2335     + virtual QStringList allDevices();
2336     + virtual QSet< Solid::DeviceInterface::Type > supportedInterfaces() const;
2337     + virtual QString udiPrefix() const;
2338     + virtual ~Manager();
2339     +
2340     +private Q_SLOTS:
2341     + void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
2342     + void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
2343     + void slotMediaChanged(const QDBusMessage &msg);
2344     +
2345     +private:
2346     + const QStringList &deviceCache();
2347     + void introspect(const QString & path, bool checkOptical = false);
2348     + QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
2349     + org::freedesktop::DBus::ObjectManager m_manager;
2350     + QStringList m_deviceCache;
2351     +};
2352     +
2353     +}
2354     +}
2355     +}
2356     +#endif // UDISKS2MANAGER_H
2357     diff --git a/solid/solid/backends/udisks2/udisksopticaldisc.cpp b/solid/solid/backends/udisks2/udisksopticaldisc.cpp
2358     new file mode 100644
2359     index 0000000..dc5256d
2360     --- /dev/null
2361     +++ b/solid/solid/backends/udisks2/udisksopticaldisc.cpp
2362     @@ -0,0 +1,297 @@
2363     +/*
2364     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
2365     + Copyright 2010 - 2012 Lukáš Tinkl <ltinkl@redhat.com>
2366     +
2367     + This library is free software; you can redistribute it and/or
2368     + modify it under the terms of the GNU Lesser General Public
2369     + License as published by the Free Software Foundation; either
2370     + version 2.1 of the License, or (at your option) version 3, or any
2371     + later version accepted by the membership of KDE e.V. (or its
2372     + successor approved by the membership of KDE e.V.), which shall
2373     + act as a proxy defined in Section 6 of version 3 of the license.
2374     +
2375     + This library is distributed in the hope that it will be useful,
2376     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2377     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2378     + Lesser General Public License for more details.
2379     +
2380     + You should have received a copy of the GNU Lesser General Public
2381     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
2382     +*/
2383     +
2384     +#include <sys/types.h>
2385     +#include <unistd.h>
2386     +#include <sys/stat.h>
2387     +#include <fcntl.h>
2388     +
2389     +#include <QtCore/QFile>
2390     +#include <QtCore/QMap>
2391     +#include <QtCore/QMutexLocker>
2392     +#include <QtDBus/QDBusConnection>
2393     +
2394     +#include "../shared/udevqt.h"
2395     +
2396     +#include "udisks2.h"
2397     +#include "udisksopticaldisc.h"
2398     +#include "soliddefs_p.h"
2399     +
2400     +typedef QMap<QByteArray, Solid::OpticalDisc::ContentTypes> ContentTypesCache;
2401     +SOLID_GLOBAL_STATIC(ContentTypesCache, cache)
2402     +SOLID_GLOBAL_STATIC(QMutex, cacheLock)
2403     +
2404     +// inspired by http://cgit.freedesktop.org/hal/tree/hald/linux/probing/probe-volume.c
2405     +static Solid::OpticalDisc::ContentType advancedDiscDetect(const QByteArray & device_file)
2406     +{
2407     + /* the discs block size */
2408     + unsigned short bs;
2409     + /* the path table size */
2410     + unsigned short ts;
2411     + /* the path table location (in blocks) */
2412     + unsigned int tl;
2413     + /* length of the directory name in current path table entry */
2414     + unsigned char len_di = 0;
2415     + /* the number of the parent directory's path table entry */
2416     + unsigned int parent = 0;
2417     + /* filename for the current path table entry */
2418     + char dirname[256];
2419     + /* our position into the path table */
2420     + int pos = 0;
2421     + /* the path table record we're on */
2422     + int curr_record = 1;
2423     +
2424     + Solid::OpticalDisc::ContentType result = Solid::OpticalDisc::NoContent;
2425     +
2426     + int fd = open(device_file.constData(), O_RDONLY);
2427     +
2428     + /* read the block size */
2429     + lseek (fd, 0x8080, SEEK_CUR);
2430     + if (read (fd, &bs, 2) != 2)
2431     + {
2432     + qDebug("Advanced probing on %s failed while reading block size", qPrintable(device_file));
2433     + goto out;
2434     + }
2435     +
2436     + /* read in size of path table */
2437     + lseek (fd, 2, SEEK_CUR);
2438     + if (read (fd, &ts, 2) != 2)
2439     + {
2440     + qDebug("Advanced probing on %s failed while reading path table size", qPrintable(device_file));
2441     + goto out;
2442     + }
2443     +
2444     + /* read in which block path table is in */
2445     + lseek (fd, 6, SEEK_CUR);
2446     + if (read (fd, &tl, 4) != 4)
2447     + {
2448     + qDebug("Advanced probing on %s failed while reading path table block", qPrintable(device_file));
2449     + goto out;
2450     + }
2451     +
2452     + /* seek to the path table */
2453     + lseek (fd, bs * tl, SEEK_SET);
2454     +
2455     + /* loop through the path table entries */
2456     + while (pos < ts)
2457     + {
2458     + /* get the length of the filename of the current entry */
2459     + if (read (fd, &len_di, 1) != 1)
2460     + {
2461     + qDebug("Advanced probing on %s failed, cannot read more entries", qPrintable(device_file));
2462     + break;
2463     + }
2464     +
2465     + /* get the record number of this entry's parent
2466     + i'm pretty sure that the 1st entry is always the top directory */
2467     + lseek (fd, 5, SEEK_CUR);
2468     + if (read (fd, &parent, 2) != 2)
2469     + {
2470     + qDebug("Advanced probing on %s failed, couldn't read parent entry", qPrintable(device_file));
2471     + break;
2472     + }
2473     +
2474     + /* read the name */
2475     + if (read (fd, dirname, len_di) != len_di)
2476     + {
2477     + qDebug("Advanced probing on %s failed, couldn't read the entry name", qPrintable(device_file));
2478     + break;
2479     + }
2480     + dirname[len_di] = 0;
2481     +
2482     + /* if we found a folder that has the root as a parent, and the directory name matches
2483     + one of the special directories then set the properties accordingly */
2484     + if (parent == 1)
2485     + {
2486     + if (!strcasecmp (dirname, "VIDEO_TS"))
2487     + {
2488     + qDebug("Disc in %s is a Video DVD", qPrintable(device_file));
2489     + result = Solid::OpticalDisc::VideoDvd;
2490     + break;
2491     + }
2492     + else if (!strcasecmp (dirname, "BDMV"))
2493     + {
2494     + qDebug("Disc in %s is a Blu-ray video disc", qPrintable(device_file));
2495     + result = Solid::OpticalDisc::VideoBluRay;
2496     + break;
2497     + }
2498     + else if (!strcasecmp (dirname, "VCD"))
2499     + {
2500     + qDebug("Disc in %s is a Video CD", qPrintable(device_file));
2501     + result = Solid::OpticalDisc::VideoCd;
2502     + break;
2503     + }
2504     + else if (!strcasecmp (dirname, "SVCD"))
2505     + {
2506     + qDebug("Disc in %s is a Super Video CD", qPrintable(device_file));
2507     + result = Solid::OpticalDisc::SuperVideoCd;
2508     + break;
2509     + }
2510     + }
2511     +
2512     + /* all path table entries are padded to be even,
2513     + so if this is an odd-length table, seek a byte to fix it */
2514     + if (len_di%2 == 1)
2515     + {
2516     + lseek (fd, 1, SEEK_CUR);
2517     + pos++;
2518     + }
2519     +
2520     + /* update our position */
2521     + pos += 8 + len_di;
2522     + curr_record++;
2523     + }
2524     +
2525     + close(fd);
2526     + return result;
2527     +
2528     +out:
2529     + /* go back to the start of the file */
2530     + lseek (fd, 0, SEEK_SET);
2531     + close(fd);
2532     + return result;
2533     +}
2534     +
2535     +using namespace Solid::Backends::UDisks2;
2536     +
2537     +OpticalDisc::OpticalDisc(Device *dev)
2538     + : StorageVolume(dev), m_needsReprobe(true), m_cachedContent(Solid::OpticalDisc::NoContent)
2539     +{
2540     + UdevQt::Client client(this);
2541     + m_udevDevice = client.deviceByDeviceFile(device());
2542     + //qDebug() << "udev device:" << m_udevDevice.name() << "valid:" << m_udevDevice.isValid();
2543     + /*qDebug() << "\tProperties:" << */ m_udevDevice.deviceProperties(); // initialize the properties DB so that it doesn't crash further down, #298416
2544     +
2545     + m_drive = new Device(m_device->prop("Drive").value<QDBusObjectPath>().path());
2546     + QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_drive->udi(), DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
2547     + SLOT(slotDrivePropertiesChanged(QString,QVariantMap,QStringList)));
2548     +}
2549     +
2550     +OpticalDisc::~OpticalDisc()
2551     +{
2552     + delete m_drive;
2553     +}
2554     +
2555     +qulonglong OpticalDisc::capacity() const
2556     +{
2557     + return m_device->prop("Size").toULongLong();
2558     +}
2559     +
2560     +bool OpticalDisc::isRewritable() const
2561     +{
2562     + // the hard way, udisks has no notion of a disc "rewritability"
2563     + const QString mediaType = media();
2564     + return mediaType == "optical_cd_rw" || mediaType == "optical_dvd_rw" || mediaType == "optical_dvd_ram" ||
2565     + mediaType == "optical_dvd_plus_rw" || mediaType == "optical_dvd_plus_rw_dl" ||
2566     + mediaType == "optical_bd_re" || mediaType == "optical_hddvd_rw";
2567     +}
2568     +
2569     +bool OpticalDisc::isBlank() const
2570     +{
2571     + return m_drive->prop("OpticalBlank").toBool();
2572     +}
2573     +
2574     +bool OpticalDisc::isAppendable() const
2575     +{
2576     + //qDebug() << "appendable prop" << m_udevDevice.deviceProperty("ID_CDROM_MEDIA_STATE");
2577     + return m_udevDevice.deviceProperty("ID_CDROM_MEDIA_STATE").toString() == QLatin1String("appendable");
2578     +}
2579     +
2580     +Solid::OpticalDisc::DiscType OpticalDisc::discType() const
2581     +{
2582     + QMap<Solid::OpticalDisc::DiscType, QString> map;
2583     + map[Solid::OpticalDisc::CdRom] = "optical_cd";
2584     + map[Solid::OpticalDisc::CdRecordable] = "optical_cd_r";
2585     + map[Solid::OpticalDisc::CdRewritable] = "optical_cd_rw";
2586     + map[Solid::OpticalDisc::DvdRom] = "optical_dvd";
2587     + map[Solid::OpticalDisc::DvdRecordable] = "optical_dvd_r";
2588     + map[Solid::OpticalDisc::DvdRewritable] ="optical_dvd_rw";
2589     + map[Solid::OpticalDisc::DvdRam] ="optical_dvd_ram";
2590     + map[Solid::OpticalDisc::DvdPlusRecordable] ="optical_dvd_plus_r";
2591     + map[Solid::OpticalDisc::DvdPlusRewritable] ="optical_dvd_plus_rw";
2592     + map[Solid::OpticalDisc::DvdPlusRecordableDuallayer] ="optical_dvd_plus_r_dl";
2593     + map[Solid::OpticalDisc::DvdPlusRewritableDuallayer] ="optical_dvd_plus_rw_dl";
2594     + map[Solid::OpticalDisc::BluRayRom] ="optical_bd";
2595     + map[Solid::OpticalDisc::BluRayRecordable] ="optical_bd_r";
2596     + map[Solid::OpticalDisc::BluRayRewritable] ="optical_bd_re";
2597     + map[Solid::OpticalDisc::HdDvdRom] ="optical_hddvd";
2598     + map[Solid::OpticalDisc::HdDvdRecordable] ="optical_hddvd_r";
2599     + map[Solid::OpticalDisc::HdDvdRewritable] ="optical_hddvd_rw";
2600     + // TODO add these to Solid
2601     + //map[Solid::OpticalDisc::MagnetoOptical] ="optical_mo";
2602     + //map[Solid::OpticalDisc::MountRainer] ="optical_mrw";
2603     + //map[Solid::OpticalDisc::MountRainerWritable] ="optical_mrw_w";
2604     +
2605     + return map.key(media(), Solid::OpticalDisc::UnknownDiscType); // FIXME optimize, lookup by value, not key
2606     +}
2607     +
2608     +Solid::OpticalDisc::ContentTypes OpticalDisc::availableContent() const
2609     +{
2610     + if (isBlank()) {
2611     + m_needsReprobe = false;
2612     + return Solid::OpticalDisc::NoContent;
2613     + }
2614     +
2615     + if (m_needsReprobe) {
2616     + QMutexLocker lock(cacheLock);
2617     +
2618     + const QByteArray deviceFile = m_device->prop("Device").toByteArray();
2619     +
2620     + if (cache->contains(deviceFile)) {
2621     + m_cachedContent = cache->value(deviceFile);
2622     + m_needsReprobe = false;
2623     + return m_cachedContent;
2624     + }
2625     +
2626     + m_cachedContent = Solid::OpticalDisc::NoContent;
2627     + const bool hasData = m_drive->prop("OpticalNumDataTracks").toUInt() > 0;
2628     + const bool hasAudio = m_drive->prop("OpticalNumAudioTracks").toUInt() > 0;
2629     +
2630     + if ( hasData ) {
2631     + m_cachedContent |= Solid::OpticalDisc::Data;
2632     + m_cachedContent |= advancedDiscDetect(deviceFile);
2633     + }
2634     + if ( hasAudio )
2635     + m_cachedContent |= Solid::OpticalDisc::Audio;
2636     +
2637     + m_needsReprobe = false;
2638     + cache->insert(deviceFile, m_cachedContent);
2639     + }
2640     +
2641     + return m_cachedContent;
2642     +}
2643     +
2644     +void OpticalDisc::slotDrivePropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
2645     +{
2646     + Q_UNUSED(ifaceName);
2647     +
2648     + if (changedProps.keys().contains("Media") || invalidatedProps.contains("Media")) {
2649     + QMutexLocker lock(cacheLock);
2650     + m_needsReprobe = true;
2651     + m_cachedContent = Solid::OpticalDisc::NoContent;
2652     + cache->remove(m_device->prop("Device").toByteArray());
2653     + }
2654     +}
2655     +
2656     +QString OpticalDisc::media() const
2657     +{
2658     + return m_drive->prop("Media").toString();
2659     +}
2660     diff --git a/solid/solid/backends/udisks2/udisksopticaldisc.h b/solid/solid/backends/udisks2/udisksopticaldisc.h
2661     new file mode 100644
2662     index 0000000..0cdcc66
2663     --- /dev/null
2664     +++ b/solid/solid/backends/udisks2/udisksopticaldisc.h
2665     @@ -0,0 +1,69 @@
2666     +/*
2667     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
2668     + Copyright 2010 - 2012 Lukáš Tinkl <ltinkl@redhat.com>
2669     +
2670     + This library is free software; you can redistribute it and/or
2671     + modify it under the terms of the GNU Lesser General Public
2672     + License as published by the Free Software Foundation; either
2673     + version 2.1 of the License, or (at your option) version 3, or any
2674     + later version accepted by the membership of KDE e.V. (or its
2675     + successor approved by the membership of KDE e.V.), which shall
2676     + act as a proxy defined in Section 6 of version 3 of the license.
2677     +
2678     + This library is distributed in the hope that it will be useful,
2679     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2680     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2681     + Lesser General Public License for more details.
2682     +
2683     + You should have received a copy of the GNU Lesser General Public
2684     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
2685     +*/
2686     +
2687     +#ifndef UDISKS2OPTICALDISC_H
2688     +#define UDISKS2OPTICALDISC_H
2689     +
2690     +#include <solid/ifaces/opticaldisc.h>
2691     +
2692     +#include "../shared/udevqt.h"
2693     +
2694     +#include "udisksstoragevolume.h"
2695     +#include "udisksdevice.h"
2696     +
2697     +namespace Solid
2698     +{
2699     +namespace Backends
2700     +{
2701     +namespace UDisks2
2702     +{
2703     +
2704     +class OpticalDisc: public StorageVolume, virtual public Solid::Ifaces::OpticalDisc
2705     +{
2706     + Q_OBJECT
2707     + Q_INTERFACES(Solid::Ifaces::OpticalDisc)
2708     +
2709     +public:
2710     + OpticalDisc(Device *dev);
2711     + virtual ~OpticalDisc();
2712     +
2713     + virtual qulonglong capacity() const;
2714     + virtual bool isRewritable() const;
2715     + virtual bool isBlank() const;
2716     + virtual bool isAppendable() const;
2717     + virtual Solid::OpticalDisc::DiscType discType() const;
2718     + virtual Solid::OpticalDisc::ContentTypes availableContent() const;
2719     +
2720     +private Q_SLOTS:
2721     + void slotDrivePropertiesChanged(const QString & ifaceName, const QVariantMap & changedProps, const QStringList & invalidatedProps);
2722     +
2723     +private:
2724     + QString media() const;
2725     + mutable bool m_needsReprobe;
2726     + mutable Solid::OpticalDisc::ContentTypes m_cachedContent;
2727     + Device * m_drive;
2728     + UdevQt::Device m_udevDevice;
2729     +};
2730     +
2731     +}
2732     +}
2733     +}
2734     +#endif // UDISKS2OPTICALDISC_H
2735     diff --git a/solid/solid/backends/udisks2/udisksopticaldrive.cpp b/solid/solid/backends/udisks2/udisksopticaldrive.cpp
2736     new file mode 100644
2737     index 0000000..74a901e
2738     --- /dev/null
2739     +++ b/solid/solid/backends/udisks2/udisksopticaldrive.cpp
2740     @@ -0,0 +1,226 @@
2741     +/*
2742     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
2743     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
2744     +
2745     + This library is free software; you can redistribute it and/or
2746     + modify it under the terms of the GNU Lesser General Public
2747     + License as published by the Free Software Foundation; either
2748     + version 2.1 of the License, or (at your option) version 3, or any
2749     + later version accepted by the membership of KDE e.V. (or its
2750     + successor approved by the membership of KDE e.V.), which shall
2751     + act as a proxy defined in Section 6 of version 3 of the license.
2752     +
2753     + This library is distributed in the hope that it will be useful,
2754     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2755     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2756     + Lesser General Public License for more details.
2757     +
2758     + You should have received a copy of the GNU Lesser General Public
2759     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
2760     +*/
2761     +
2762     +#include <sys/types.h>
2763     +#include <sys/stat.h>
2764     +#include <fcntl.h>
2765     +#include <string.h>
2766     +#include <errno.h>
2767     +#include <unistd.h>
2768     +#include <stdlib.h>
2769     +
2770     +#include <QtCore/QFile>
2771     +#include <QtCore/QDebug>
2772     +
2773     +#include "udisksopticaldrive.h"
2774     +#include "udisks2.h"
2775     +#include "udisksdevice.h"
2776     +#include "dbus/manager.h"
2777     +
2778     +using namespace Solid::Backends::UDisks2;
2779     +
2780     +OpticalDrive::OpticalDrive(Device *device)
2781     + : StorageDrive(device)
2782     + , m_ejectInProgress(false)
2783     + , m_readSpeed(0)
2784     + , m_writeSpeed(0)
2785     + , m_speedsInit(false)
2786     +{
2787     + m_device->registerAction("eject", this,
2788     + SLOT(slotEjectRequested()),
2789     + SLOT(slotEjectDone(int, const QString&)));
2790     +
2791     + connect(m_device, SIGNAL(changed()), this, SLOT(slotChanged()));
2792     +}
2793     +
2794     +OpticalDrive::~OpticalDrive()
2795     +{
2796     +}
2797     +
2798     +bool OpticalDrive::eject()
2799     +{
2800     + if (m_ejectInProgress)
2801     + return false;
2802     + m_ejectInProgress = true;
2803     + m_device->broadcastActionRequested("eject");
2804     +
2805     + const QString path = m_device->udi();
2806     + QDBusConnection c = QDBusConnection::systemBus();
2807     +
2808     + // if the device is mounted, unmount first
2809     + QString blockPath;
2810     + org::freedesktop::DBus::ObjectManager manager(UD2_DBUS_SERVICE, UD2_DBUS_PATH, c);
2811     + QDBusPendingReply<DBUSManagerStruct> reply = manager.GetManagedObjects();
2812     + reply.waitForFinished();
2813     + if (!reply.isError()) { // enum devices
2814     + Q_FOREACH(const QDBusObjectPath &objPath, reply.value().keys()) {
2815     + const QString udi = objPath.path();
2816     +
2817     + //qDebug() << "Inspecting" << udi;
2818     +
2819     + if (udi == UD2_DBUS_PATH_MANAGER || udi == UD2_UDI_DISKS_PREFIX || udi.startsWith(UD2_DBUS_PATH_JOBS))
2820     + continue;
2821     +
2822     + Device device(udi);
2823     + if (device.drivePath() == path && device.isMounted()) {
2824     + //qDebug() << "Got mounted block device:" << udi;
2825     + blockPath = udi;
2826     + break;
2827     + }
2828     + }
2829     + }
2830     + else // show error
2831     + {
2832     + qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
2833     + }
2834     +
2835     + if (!blockPath.isEmpty()) {
2836     + //qDebug() << "Calling unmount on" << blockPath;
2837     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, blockPath, UD2_DBUS_INTERFACE_FILESYSTEM, "Unmount");
2838     + msg << QVariantMap(); // options, unused now
2839     + c.call(msg, QDBus::BlockWithGui);
2840     + }
2841     +
2842     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_DRIVE, "Eject");
2843     + msg << QVariantMap();
2844     + return c.callWithCallback(msg, this, SLOT(slotDBusReply(const QDBusMessage &)), SLOT(slotDBusError(const QDBusError &)));
2845     +}
2846     +
2847     +void OpticalDrive::slotDBusReply(const QDBusMessage &/*reply*/)
2848     +{
2849     + m_ejectInProgress = false;
2850     + m_device->broadcastActionDone("eject");
2851     +}
2852     +
2853     +void OpticalDrive::slotDBusError(const QDBusError &error)
2854     +{
2855     + m_ejectInProgress = false;
2856     + m_device->broadcastActionDone("eject", m_device->errorToSolidError(error.name()),
2857     + m_device->errorToString(error.name()) + ": " +error.message());
2858     +}
2859     +
2860     +void OpticalDrive::slotEjectRequested()
2861     +{
2862     + m_ejectInProgress = true;
2863     + Q_EMIT ejectRequested(m_device->udi());
2864     +}
2865     +
2866     +void OpticalDrive::slotEjectDone(int error, const QString &errorString)
2867     +{
2868     + m_ejectInProgress = false;
2869     + Q_EMIT ejectDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
2870     +}
2871     +
2872     +void OpticalDrive::initReadWriteSpeeds() const
2873     +{
2874     +#if 0
2875     + int read_speed, write_speed;
2876     + char *write_speeds = 0;
2877     + QByteArray device_file = QFile::encodeName(m_device->property("Device").toString());
2878     +
2879     + //qDebug("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file.constData());
2880     + int fd = open(device_file, O_RDONLY | O_NONBLOCK);
2881     + if (fd < 0) {
2882     + qWarning("Cannot open %s: %s", device_file.constData(), strerror (errno));
2883     + return;
2884     + }
2885     +
2886     + if (get_read_write_speed(fd, &read_speed, &write_speed, &write_speeds) >= 0) {
2887     + m_readSpeed = read_speed;
2888     + m_writeSpeed = write_speed;
2889     +
2890     + QStringList list = QString::fromLatin1(write_speeds).split(',', QString::SkipEmptyParts);
2891     + Q_FOREACH (const QString & speed, list)
2892     + m_writeSpeeds.append(speed.toInt());
2893     +
2894     + free(write_speeds);
2895     +
2896     + m_speedsInit = true;
2897     + }
2898     +
2899     + close(fd);
2900     +#endif
2901     +}
2902     +
2903     +QList<int> OpticalDrive::writeSpeeds() const
2904     +{
2905     + if (!m_speedsInit)
2906     + initReadWriteSpeeds();
2907     + //qDebug() << "solid write speeds:" << m_writeSpeeds;
2908     + return m_writeSpeeds;
2909     +}
2910     +
2911     +int OpticalDrive::writeSpeed() const
2912     +{
2913     + if (!m_speedsInit)
2914     + initReadWriteSpeeds();
2915     + return m_writeSpeed;
2916     +}
2917     +
2918     +int OpticalDrive::readSpeed() const
2919     +{
2920     + if (!m_speedsInit)
2921     + initReadWriteSpeeds();
2922     + return m_readSpeed;
2923     +}
2924     +
2925     +Solid::OpticalDrive::MediumTypes OpticalDrive::supportedMedia() const
2926     +{
2927     + const QStringList mediaTypes = m_device->prop("MediaCompatibility").toStringList();
2928     + Solid::OpticalDrive::MediumTypes supported;
2929     +
2930     + QMap<Solid::OpticalDrive::MediumType, QString> map;
2931     + map[Solid::OpticalDrive::Cdr] = "optical_cd_r";
2932     + map[Solid::OpticalDrive::Cdrw] = "optical_cd_rw";
2933     + map[Solid::OpticalDrive::Dvd] = "optical_dvd";
2934     + map[Solid::OpticalDrive::Dvdr] = "optical_dvd_r";
2935     + map[Solid::OpticalDrive::Dvdrw] ="optical_dvd_rw";
2936     + map[Solid::OpticalDrive::Dvdram] ="optical_dvd_ram";
2937     + map[Solid::OpticalDrive::Dvdplusr] ="optical_dvd_plus_r";
2938     + map[Solid::OpticalDrive::Dvdplusrw] ="optical_dvd_plus_rw";
2939     + map[Solid::OpticalDrive::Dvdplusdl] ="optical_dvd_plus_r_dl";
2940     + map[Solid::OpticalDrive::Dvdplusdlrw] ="optical_dvd_plus_rw_dl";
2941     + map[Solid::OpticalDrive::Bd] ="optical_bd";
2942     + map[Solid::OpticalDrive::Bdr] ="optical_bd_r";
2943     + map[Solid::OpticalDrive::Bdre] ="optical_bd_re";
2944     + map[Solid::OpticalDrive::HdDvd] ="optical_hddvd";
2945     + map[Solid::OpticalDrive::HdDvdr] ="optical_hddvd_r";
2946     + map[Solid::OpticalDrive::HdDvdrw] ="optical_hddvd_rw";
2947     + // TODO add these to Solid
2948     + //map[Solid::OpticalDrive::Mo] ="optical_mo";
2949     + //map[Solid::OpticalDrive::Mr] ="optical_mrw";
2950     + //map[Solid::OpticalDrive::Mrw] ="optical_mrw_w";
2951     +
2952     + Q_FOREACH ( const Solid::OpticalDrive::MediumType & type, map.keys() )
2953     + {
2954     + if ( mediaTypes.contains( map[type] ) )
2955     + {
2956     + supported |= type;
2957     + }
2958     + }
2959     +
2960     + return supported;
2961     +}
2962     +
2963     +void OpticalDrive::slotChanged()
2964     +{
2965     + m_speedsInit = false; // reset the read/write speeds, changes eg. with an inserted media
2966     +}
2967     diff --git a/solid/solid/backends/udisks2/udisksopticaldrive.h b/solid/solid/backends/udisks2/udisksopticaldrive.h
2968     new file mode 100644
2969     index 0000000..4c98ef5
2970     --- /dev/null
2971     +++ b/solid/solid/backends/udisks2/udisksopticaldrive.h
2972     @@ -0,0 +1,81 @@
2973     +/*
2974     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
2975     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
2976     +
2977     + This library is free software; you can redistribute it and/or
2978     + modify it under the terms of the GNU Lesser General Public
2979     + License as published by the Free Software Foundation; either
2980     + version 2.1 of the License, or (at your option) version 3, or any
2981     + later version accepted by the membership of KDE e.V. (or its
2982     + successor approved by the membership of KDE e.V.), which shall
2983     + act as a proxy defined in Section 6 of version 3 of the license.
2984     +
2985     + This library is distributed in the hope that it will be useful,
2986     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2987     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2988     + Lesser General Public License for more details.
2989     +
2990     + You should have received a copy of the GNU Lesser General Public
2991     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
2992     +*/
2993     +
2994     +#ifndef UDISKS2OPTICALDRIVE_H
2995     +#define UDISKS2OPTICALDRIVE_H
2996     +
2997     +#include <solid/ifaces/opticaldrive.h>
2998     +#include "udisksstoragedrive.h"
2999     +
3000     +namespace Solid
3001     +{
3002     +namespace Backends
3003     +{
3004     +namespace UDisks2
3005     +{
3006     +
3007     +class OpticalDrive: public StorageDrive, virtual public Solid::Ifaces::OpticalDrive
3008     +{
3009     + Q_OBJECT
3010     + Q_INTERFACES(Solid::Ifaces::OpticalDrive)
3011     +
3012     +public:
3013     + OpticalDrive(Device *device);
3014     + virtual ~OpticalDrive();
3015     +
3016     +Q_SIGNALS:
3017     + void ejectPressed(const QString &udi);
3018     + void ejectDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
3019     + void ejectRequested(const QString &udi);
3020     +
3021     +public:
3022     + virtual bool eject();
3023     + virtual QList<int> writeSpeeds() const;
3024     + virtual int writeSpeed() const;
3025     + virtual int readSpeed() const;
3026     + virtual Solid::OpticalDrive::MediumTypes supportedMedia() const;
3027     +
3028     +private Q_SLOTS:
3029     + void slotDBusReply(const QDBusMessage &reply);
3030     + void slotDBusError(const QDBusError &error);
3031     +
3032     + void slotEjectRequested();
3033     + void slotEjectDone(int error, const QString &errorString);
3034     +
3035     + void slotChanged();
3036     +
3037     +private:
3038     + void initReadWriteSpeeds() const;
3039     +
3040     + bool m_ejectInProgress;
3041     +
3042     + // read/write speeds
3043     + mutable int m_readSpeed;
3044     + mutable int m_writeSpeed;
3045     + mutable QList<int> m_writeSpeeds;
3046     + mutable bool m_speedsInit;
3047     +};
3048     +
3049     +}
3050     +}
3051     +}
3052     +
3053     +#endif // UDISKS2OPTICALDRIVE_H
3054     diff --git a/solid/solid/backends/udisks2/udisksstorageaccess.cpp b/solid/solid/backends/udisks2/udisksstorageaccess.cpp
3055     new file mode 100644
3056     index 0000000..6958459
3057     --- /dev/null
3058     +++ b/solid/solid/backends/udisks2/udisksstorageaccess.cpp
3059     @@ -0,0 +1,390 @@
3060     +/*
3061     + Copyright 2009 Pino Toscano <pino@kde.org>
3062     + Copyright 2009-2012 Lukáš Tinkl <ltinkl@redhat.com>
3063     +
3064     + This library is free software; you can redistribute it and/or
3065     + modify it under the terms of the GNU Lesser General Public
3066     + License as published by the Free Software Foundation; either
3067     + version 2.1 of the License, or (at your option) version 3, or any
3068     + later version accepted by the membership of KDE e.V. (or its
3069     + successor approved by the membership of KDE e.V.), which shall
3070     + act as a proxy defined in Section 6 of version 3 of the license.
3071     +
3072     + This library is distributed in the hope that it will be useful,
3073     + but WITHOUT ANY WARRANTY; without even the implied warranty of
3074     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3075     + Lesser General Public License for more details.
3076     +
3077     + You should have received a copy of the GNU Lesser General Public
3078     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
3079     +*/
3080     +
3081     +#include "udisksstorageaccess.h"
3082     +#include "udisks2.h"
3083     +
3084     +#include <QtDBus/QtDBus>
3085     +#include <QtGui/QApplication>
3086     +#include <QtGui/QWidget>
3087     +#include <QtXml/QDomDocument>
3088     +
3089     +using namespace Solid::Backends::UDisks2;
3090     +
3091     +StorageAccess::StorageAccess(Device *device)
3092     + : DeviceInterface(device), m_setupInProgress(false), m_teardownInProgress(false), m_passphraseRequested(false)
3093     +{
3094     + connect(device, SIGNAL(changed()), this, SLOT(checkAccessibility()));
3095     + updateCache();
3096     +
3097     + // Delay connecting to DBus signals to avoid the related time penalty
3098     + // in hot paths such as predicate matching
3099     + QTimer::singleShot(0, this, SLOT(connectDBusSignals()));
3100     +}
3101     +
3102     +StorageAccess::~StorageAccess()
3103     +{
3104     +}
3105     +
3106     +void StorageAccess::connectDBusSignals()
3107     +{
3108     + m_device->registerAction("setup", this,
3109     + SLOT(slotSetupRequested()),
3110     + SLOT(slotSetupDone(int, const QString&)));
3111     +
3112     + m_device->registerAction("teardown", this,
3113     + SLOT(slotTeardownRequested()),
3114     + SLOT(slotTeardownDone(int, const QString&)));
3115     +}
3116     +
3117     +bool StorageAccess::isLuksDevice() const
3118     +{
3119     + return m_device->isEncryptedContainer(); // encrypted device
3120     +}
3121     +
3122     +bool StorageAccess::isAccessible() const
3123     +{
3124     + if (isLuksDevice()) { // check if the cleartext slave is mounted
3125     + const QString path = clearTextPath();
3126     + //qDebug() << Q_FUNC_INFO << "CLEARTEXT device path: " << path;
3127     + if (path.isEmpty() || path == "/")
3128     + return false;
3129     + Device holderDevice(path);
3130     + return holderDevice.isMounted();
3131     + }
3132     +
3133     + return m_device->isMounted();
3134     +}
3135     +
3136     +QString StorageAccess::filePath() const
3137     +{
3138     + QByteArrayList mntPoints;
3139     +
3140     + if (isLuksDevice()) { // encrypted (and unlocked) device
3141     + const QString path = clearTextPath();
3142     + if (path.isEmpty() || path == "/")
3143     + return QString();
3144     + Device holderDevice(path);
3145     + mntPoints = qdbus_cast<QByteArrayList>(holderDevice.prop("MountPoints"));
3146     + if (!mntPoints.isEmpty())
3147     + return QFile::decodeName(mntPoints.first()); // FIXME Solid doesn't support multiple mount points
3148     + else
3149     + return QString();
3150     + }
3151     +
3152     + mntPoints = qdbus_cast<QByteArrayList>(m_device->prop("MountPoints"));
3153     +
3154     + if (!mntPoints.isEmpty())
3155     + return QFile::decodeName(mntPoints.first()); // FIXME Solid doesn't support multiple mount points
3156     + else
3157     + return QString();
3158     +}
3159     +
3160     +bool StorageAccess::isIgnored() const
3161     +{
3162     + return m_device->prop("HintIgnore").toBool();
3163     +}
3164     +
3165     +bool StorageAccess::setup()
3166     +{
3167     + if ( m_teardownInProgress || m_setupInProgress )
3168     + return false;
3169     + m_setupInProgress = true;
3170     + m_device->broadcastActionRequested("setup");
3171     +
3172     + if (m_device->isEncryptedContainer() && clearTextPath().isEmpty())
3173     + return requestPassphrase();
3174     + else
3175     + return mount();
3176     +}
3177     +
3178     +bool StorageAccess::teardown()
3179     +{
3180     + if ( m_teardownInProgress || m_setupInProgress )
3181     + return false;
3182     + m_teardownInProgress = true;
3183     + m_device->broadcastActionRequested("teardown");
3184     +
3185     + return unmount();
3186     +}
3187     +
3188     +void StorageAccess::updateCache()
3189     +{
3190     + m_isAccessible = isAccessible();
3191     +}
3192     +
3193     +void StorageAccess::checkAccessibility()
3194     +{
3195     + const bool old_isAccessible = m_isAccessible;
3196     + updateCache();
3197     +
3198     + if (old_isAccessible != m_isAccessible) {
3199     + Q_EMIT accessibilityChanged(m_isAccessible, m_device->udi());
3200     + }
3201     +}
3202     +
3203     +void StorageAccess::slotDBusReply( const QDBusMessage & /*reply*/ )
3204     +{
3205     + const QString ctPath = clearTextPath();
3206     + if (m_setupInProgress)
3207     + {
3208     + if (isLuksDevice() && !isAccessible()) { // unlocked device, now mount it
3209     + mount();
3210     + }
3211     + else // Don't broadcast setupDone unless the setup is really done. (Fix kde#271156)
3212     + {
3213     + m_setupInProgress = false;
3214     + m_device->broadcastActionDone("setup");
3215     +
3216     + checkAccessibility();
3217     + }
3218     + }
3219     + else if (m_teardownInProgress) // FIXME
3220     + {
3221     + if (isLuksDevice() && !ctPath.isEmpty() && ctPath != "/") // unlocked device, lock it
3222     + {
3223     + callCryptoTeardown();
3224     + }
3225     + else if (!ctPath.isEmpty() && ctPath != "/") {
3226     + callCryptoTeardown(true); // Lock crypted parent
3227     + }
3228     + else
3229     + {
3230     + // try to "eject" (aka safely remove) from the (parent) drive, e.g. SD card from a reader
3231     + QString drivePath = m_device->drivePath();
3232     + if (!drivePath.isEmpty() || drivePath != "/")
3233     + {
3234     + Device drive(drivePath);
3235     + if (drive.prop("Ejectable").toBool() &&
3236     + drive.prop("MediaAvailable").toBool() &&
3237     + !m_device->isOpticalDisc()) // optical drives have their Eject method
3238     + {
3239     + QDBusConnection c = QDBusConnection::systemBus();
3240     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, drivePath, UD2_DBUS_INTERFACE_DRIVE, "Eject");
3241     + msg << QVariantMap(); // options, unused now
3242     + c.call(msg, QDBus::NoBlock);
3243     + }
3244     + }
3245     +
3246     + m_teardownInProgress = false;
3247     + m_device->broadcastActionDone("teardown");
3248     +
3249     + checkAccessibility();
3250     + }
3251     + }
3252     +}
3253     +
3254     +void StorageAccess::slotDBusError( const QDBusError & error )
3255     +{
3256     + //qDebug() << Q_FUNC_INFO << "DBUS ERROR:" << error.name() << error.message();
3257     +
3258     + if (m_setupInProgress)
3259     + {
3260     + m_setupInProgress = false;
3261     + m_device->broadcastActionDone("setup", m_device->errorToSolidError(error.name()),
3262     + m_device->errorToString(error.name()) + ": " +error.message());
3263     +
3264     + checkAccessibility();
3265     + }
3266     + else if (m_teardownInProgress)
3267     + {
3268     + m_teardownInProgress = false;
3269     + m_device->broadcastActionDone("teardown", m_device->errorToSolidError(error.name()),
3270     + m_device->errorToString(error.name()) + ": " + error.message());
3271     + checkAccessibility();
3272     + }
3273     +}
3274     +
3275     +void StorageAccess::slotSetupRequested()
3276     +{
3277     + m_setupInProgress = true;
3278     + //qDebug() << "SETUP REQUESTED:" << m_device->udi();
3279     + Q_EMIT setupRequested(m_device->udi());
3280     +}
3281     +
3282     +void StorageAccess::slotSetupDone(int error, const QString &errorString)
3283     +{
3284     + m_setupInProgress = false;
3285     + //qDebug() << "SETUP DONE:" << m_device->udi();
3286     + Q_EMIT setupDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
3287     +
3288     + checkAccessibility();
3289     +}
3290     +
3291     +void StorageAccess::slotTeardownRequested()
3292     +{
3293     + m_teardownInProgress = true;
3294     + Q_EMIT teardownRequested(m_device->udi());
3295     +}
3296     +
3297     +void StorageAccess::slotTeardownDone(int error, const QString &errorString)
3298     +{
3299     + m_teardownInProgress = false;
3300     + Q_EMIT teardownDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
3301     +
3302     + checkAccessibility();
3303     +}
3304     +
3305     +bool StorageAccess::mount()
3306     +{
3307     + QString path = m_device->udi();
3308     + const QString ctPath = clearTextPath();
3309     +
3310     + if (isLuksDevice() && !ctPath.isEmpty()) { // mount options for the cleartext volume
3311     + path = ctPath;
3312     + }
3313     +
3314     + QDBusConnection c = QDBusConnection::systemBus();
3315     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_FILESYSTEM, "Mount");
3316     + QVariantMap options;
3317     +
3318     + if (m_device->prop("IdType").toString() == "vfat")
3319     + options.insert("options", "flush");
3320     +
3321     + msg << options;
3322     +
3323     + return c.callWithCallback(msg, this,
3324     + SLOT(slotDBusReply(const QDBusMessage &)),
3325     + SLOT(slotDBusError(const QDBusError &)));
3326     +}
3327     +
3328     +bool StorageAccess::unmount()
3329     +{
3330     + QString path = m_device->udi();
3331     + const QString ctPath = clearTextPath();
3332     +
3333     + if (isLuksDevice() && !ctPath.isEmpty()) { // unmount options for the cleartext volume
3334     + path = ctPath;
3335     + }
3336     +
3337     + QDBusConnection c = QDBusConnection::systemBus();
3338     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_FILESYSTEM, "Unmount");
3339     +
3340     + msg << QVariantMap(); // options, unused now
3341     +
3342     + return c.callWithCallback(msg, this,
3343     + SLOT(slotDBusReply(const QDBusMessage &)),
3344     + SLOT(slotDBusError(const QDBusError &)),
3345     + s_unmountTimeout);
3346     +}
3347     +
3348     +QString StorageAccess::generateReturnObjectPath()
3349     +{
3350     + static int number = 1;
3351     +
3352     + return "/org/kde/solid/UDisks2StorageAccess_"+QString::number(number++);
3353     +}
3354     +
3355     +QString StorageAccess::clearTextPath() const
3356     +{
3357     + const QString prefix = "/org/freedesktop/UDisks2/block_devices";
3358     + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, prefix,
3359     + DBUS_INTERFACE_INTROSPECT, "Introspect");
3360     + QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
3361     + reply.waitForFinished();
3362     +
3363     + if (reply.isValid()) {
3364     + QDomDocument dom;
3365     + dom.setContent(reply.value());
3366     + QDomNodeList nodeList = dom.documentElement().elementsByTagName("node");
3367     + for (int i = 0; i < nodeList.count(); i++) {
3368     + QDomElement nodeElem = nodeList.item(i).toElement();
3369     + if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) {
3370     + const QString udi = prefix + "/" + nodeElem.attribute("name");
3371     + Device holderDevice(udi);
3372     +
3373     + if (m_device->udi() == holderDevice.prop("CryptoBackingDevice").value<QDBusObjectPath>().path()) {
3374     + //qDebug() << Q_FUNC_INFO << "CLEARTEXT device path: " << udi;
3375     + return udi;
3376     + }
3377     + }
3378     + }
3379     + }
3380     +
3381     + return QString();
3382     +}
3383     +
3384     +bool StorageAccess::requestPassphrase()
3385     +{
3386     + QString udi = m_device->udi();
3387     + QString returnService = QDBusConnection::sessionBus().baseService();
3388     + m_lastReturnObject = generateReturnObjectPath();
3389     +
3390     + QDBusConnection::sessionBus().registerObject(m_lastReturnObject, this, QDBusConnection::ExportScriptableSlots);
3391     +
3392     + QWidget *activeWindow = QApplication::activeWindow();
3393     + uint wId = 0;
3394     + if (activeWindow!=0)
3395     + wId = (uint)activeWindow->winId();
3396     +
3397     + QString appId = QCoreApplication::applicationName();
3398     +
3399     + QDBusInterface soliduiserver("org.kde.kded", "/modules/soliduiserver", "org.kde.SolidUiServer");
3400     + QDBusReply<void> reply = soliduiserver.call("showPassphraseDialog", udi, returnService,
3401     + m_lastReturnObject, wId, appId);
3402     + m_passphraseRequested = reply.isValid();
3403     + if (!m_passphraseRequested)
3404     + qWarning() << "Failed to call the SolidUiServer, D-Bus said:" << reply.error();
3405     +
3406     + return m_passphraseRequested;
3407     +}
3408     +
3409     +void StorageAccess::passphraseReply(const QString & passphrase)
3410     +{
3411     + if (m_passphraseRequested)
3412     + {
3413     + QDBusConnection::sessionBus().unregisterObject(m_lastReturnObject);
3414     + m_passphraseRequested = false;
3415     + if (!passphrase.isEmpty())
3416     + callCryptoSetup(passphrase);
3417     + else
3418     + {
3419     + m_setupInProgress = false;
3420     + m_device->broadcastActionDone("setup");
3421     + }
3422     + }
3423     +}
3424     +
3425     +void StorageAccess::callCryptoSetup(const QString & passphrase)
3426     +{
3427     + QDBusConnection c = QDBusConnection::systemBus();
3428     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_device->udi(), UD2_DBUS_INTERFACE_ENCRYPTED, "Unlock");
3429     +
3430     + msg << passphrase;
3431     + msg << QVariantMap(); // options, unused now
3432     +
3433     + c.callWithCallback(msg, this,
3434     + SLOT(slotDBusReply(const QDBusMessage &)),
3435     + SLOT(slotDBusError(const QDBusError &)));
3436     +}
3437     +
3438     +bool StorageAccess::callCryptoTeardown(bool actOnParent)
3439     +{
3440     + QDBusConnection c = QDBusConnection::systemBus();
3441     + QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE,
3442     + actOnParent ? (m_device->prop("CryptoBackingDevice").value<QDBusObjectPath>().path()) : m_device->udi(),
3443     + UD2_DBUS_INTERFACE_ENCRYPTED, "Lock");
3444     + msg << QVariantMap(); // options, unused now
3445     +
3446     + return c.callWithCallback(msg, this,
3447     + SLOT(slotDBusReply(const QDBusMessage &)),
3448     + SLOT(slotDBusError(const QDBusError &)));
3449     +}
3450     diff --git a/solid/solid/backends/udisks2/udisksstorageaccess.h b/solid/solid/backends/udisks2/udisksstorageaccess.h
3451     new file mode 100644
3452     index 0000000..ec91f89
3453     --- /dev/null
3454     +++ b/solid/solid/backends/udisks2/udisksstorageaccess.h
3455     @@ -0,0 +1,104 @@
3456     +/*
3457     + Copyright 2009 Pino Toscano <pino@kde.org>
3458     + Copyright 2009-2012 Lukáš Tinkl <ltinkl@redhat.com>
3459     +
3460     + This library is free software; you can redistribute it and/or
3461     + modify it under the terms of the GNU Lesser General Public
3462     + License as published by the Free Software Foundation; either
3463     + version 2.1 of the License, or (at your option) version 3, or any
3464     + later version accepted by the membership of KDE e.V. (or its
3465     + successor approved by the membership of KDE e.V.), which shall
3466     + act as a proxy defined in Section 6 of version 3 of the license.
3467     +
3468     + This library is distributed in the hope that it will be useful,
3469     + but WITHOUT ANY WARRANTY; without even the implied warranty of
3470     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3471     + Lesser General Public License for more details.
3472     +
3473     + You should have received a copy of the GNU Lesser General Public
3474     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
3475     +*/
3476     +
3477     +#ifndef UDISKS2STORAGEACCESS_H
3478     +#define UDISKS2STORAGEACCESS_H
3479     +
3480     +#include <solid/ifaces/storageaccess.h>
3481     +#include "udisksdeviceinterface.h"
3482     +
3483     +#include <QtDBus/QDBusMessage>
3484     +#include <QtDBus/QDBusError>
3485     +
3486     +namespace Solid
3487     +{
3488     +namespace Backends
3489     +{
3490     +namespace UDisks2
3491     +{
3492     +class StorageAccess : public DeviceInterface, virtual public Solid::Ifaces::StorageAccess
3493     +{
3494     + Q_OBJECT
3495     + Q_INTERFACES(Solid::Ifaces::StorageAccess)
3496     +
3497     +public:
3498     + StorageAccess(Device *device);
3499     + virtual ~StorageAccess();
3500     +
3501     + virtual bool isAccessible() const;
3502     + virtual QString filePath() const;
3503     + virtual bool isIgnored() const;
3504     + virtual bool setup();
3505     + virtual bool teardown();
3506     +
3507     +Q_SIGNALS:
3508     + void accessibilityChanged(bool accessible, const QString &udi);
3509     + void setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
3510     + void teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
3511     + void setupRequested(const QString &udi);
3512     + void teardownRequested(const QString &udi);
3513     +
3514     +public Q_SLOTS:
3515     + Q_SCRIPTABLE Q_NOREPLY void passphraseReply(const QString & passphrase);
3516     +
3517     +private Q_SLOTS:
3518     + void slotDBusReply(const QDBusMessage & reply);
3519     + void slotDBusError(const QDBusError & error);
3520     +
3521     + void connectDBusSignals();
3522     +
3523     + void slotSetupRequested();
3524     + void slotSetupDone(int error, const QString &errorString);
3525     + void slotTeardownRequested();
3526     + void slotTeardownDone(int error, const QString &errorString);
3527     +
3528     + void checkAccessibility();
3529     +
3530     +private:
3531     + /// @return true if this device is luks and unlocked
3532     + bool isLuksDevice() const;
3533     +
3534     + void updateCache();
3535     +
3536     + bool mount();
3537     + bool unmount();
3538     +
3539     + bool requestPassphrase();
3540     + void callCryptoSetup( const QString & passphrase );
3541     + bool callCryptoTeardown( bool actOnParent=false );
3542     +
3543     + QString generateReturnObjectPath();
3544     + QString clearTextPath() const;
3545     +
3546     +private:
3547     + bool m_isAccessible;
3548     + bool m_setupInProgress;
3549     + bool m_teardownInProgress;
3550     + bool m_passphraseRequested;
3551     + QString m_lastReturnObject;
3552     +
3553     + static const int s_unmountTimeout = 0x7fffffff;
3554     +};
3555     +}
3556     +}
3557     +}
3558     +
3559     +#endif // UDISKS2STORAGEACCESS_H
3560     diff --git a/solid/solid/backends/udisks2/udisksstoragedrive.cpp b/solid/solid/backends/udisks2/udisksstoragedrive.cpp
3561     new file mode 100644
3562     index 0000000..e382154
3563     --- /dev/null
3564     +++ b/solid/solid/backends/udisks2/udisksstoragedrive.cpp
3565     @@ -0,0 +1,147 @@
3566     +/*
3567     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
3568     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
3569     +
3570     + This library is free software; you can redistribute it and/or
3571     + modify it under the terms of the GNU Lesser General Public
3572     + License as published by the Free Software Foundation; either
3573     + version 2.1 of the License, or (at your option) version 3, or any
3574     + later version accepted by the membership of KDE e.V. (or its
3575     + successor approved by the membership of KDE e.V.), which shall
3576     + act as a proxy defined in Section 6 of version 3 of the license.
3577     +
3578     + This library is distributed in the hope that it will be useful,
3579     + but WITHOUT ANY WARRANTY; without even the implied warranty of
3580     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3581     + Lesser General Public License for more details.
3582     +
3583     + You should have received a copy of the GNU Lesser General Public
3584     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
3585     +*/
3586     +
3587     +#include "udisksstoragedrive.h"
3588     +
3589     +#include "../shared/udevqt.h"
3590     +
3591     +#include <QtCore/QDebug>
3592     +#include <QtCore/QFile>
3593     +
3594     +using namespace Solid::Backends::UDisks2;
3595     +
3596     +StorageDrive::StorageDrive(Device *dev)
3597     + : Block(dev)
3598     +{
3599     + UdevQt::Client client(this);
3600     + m_udevDevice = client.deviceByDeviceFile(device());
3601     + m_udevDevice.deviceProperties();
3602     +}
3603     +
3604     +StorageDrive::~StorageDrive()
3605     +{
3606     +}
3607     +
3608     +qulonglong StorageDrive::size() const
3609     +{
3610     + return m_device->prop("Size").toULongLong();
3611     +}
3612     +
3613     +bool StorageDrive::isHotpluggable() const
3614     +{
3615     + const Solid::StorageDrive::Bus _bus = bus();
3616     + return _bus == Solid::StorageDrive::Usb || _bus == Solid::StorageDrive::Ieee1394;
3617     +}
3618     +
3619     +bool StorageDrive::isRemovable() const
3620     +{
3621     + return m_device->prop("MediaRemovable").toBool() || m_device->prop("Removable").toBool();
3622     +}
3623     +
3624     +Solid::StorageDrive::DriveType StorageDrive::driveType() const
3625     +{
3626     + const QStringList mediaTypes = m_device->prop("MediaCompatibility").toStringList();
3627     +
3628     + if ( m_device->isOpticalDrive() ) // optical disks
3629     + {
3630     + return Solid::StorageDrive::CdromDrive;
3631     + }
3632     + else if ( mediaTypes.contains( "floppy" ) )
3633     + {
3634     + return Solid::StorageDrive::Floppy;
3635     + }
3636     +#if 0 // TODO add to Solid
3637     + else if ( mediaTypes.contains( "floppy_jaz" ) )
3638     + {
3639     + return Solid::StorageDrive::Jaz;
3640     + }
3641     + else if ( mediaTypes.contains( "floppy_zip" ) )
3642     + {
3643     + return Solid::StorageDrive::Zip;
3644     + }
3645     + else if ( mediaTypes.contains( "flash" ) )
3646     + {
3647     + return Solid::StorageDrive::Flash;
3648     + }
3649     +#endif
3650     + else if ( mediaTypes.contains( "flash_cf" ) )
3651     + {
3652     + return Solid::StorageDrive::CompactFlash;
3653     + }
3654     + else if ( mediaTypes.contains( "flash_ms" ) )
3655     + {
3656     + return Solid::StorageDrive::MemoryStick;
3657     + }
3658     + else if ( mediaTypes.contains( "flash_sm" ) )
3659     + {
3660     + return Solid::StorageDrive::SmartMedia;
3661     + }
3662     + else if ( mediaTypes.contains( "flash_sd" ) || mediaTypes.contains( "flash_sdhc" )
3663     + || mediaTypes.contains( "flash_mmc" ) || mediaTypes.contains("flash_sdxc") )
3664     + {
3665     + return Solid::StorageDrive::SdMmc;
3666     + }
3667     + // FIXME: udisks2 doesn't know about xD cards
3668     + else
3669     + {
3670     + return Solid::StorageDrive::HardDisk;
3671     + }
3672     +}
3673     +
3674     +Solid::StorageDrive::Bus StorageDrive::bus() const
3675     +{
3676     + const QString bus = m_device->prop("ConnectionBus").toString();
3677     + const QString udevBus = m_udevDevice.deviceProperty("ID_BUS").toString();
3678     +
3679     + //qDebug() << "bus:" << bus << "udev bus:" << udevBus;
3680     +
3681     + if (udevBus == "ata")
3682     + {
3683     + if (m_udevDevice.deviceProperty("ID_ATA_SATA").toInt() == 1) // serial ATA
3684     + return Solid::StorageDrive::Sata;
3685     + else // parallel (classical) ATA
3686     + return Solid::StorageDrive::Ide;
3687     + }
3688     + else if (bus == "usb")
3689     + {
3690     + return Solid::StorageDrive::Usb;
3691     + }
3692     + else if (bus == "ieee1394")
3693     + {
3694     + return Solid::StorageDrive::Ieee1394;
3695     + }
3696     + else if (udevBus == "scsi")
3697     + {
3698     + return Solid::StorageDrive::Scsi;
3699     + }
3700     +#if 0 // TODO add these to Solid
3701     + else if ( bus == "sdio" )
3702     + {
3703     + return Solid::StorageDrive::SDIO;
3704     + }
3705     + else if ( bus == "virtual" )
3706     + {
3707     + return Solid::StorageDrive::Virtual;
3708     + }
3709     +#endif
3710     + else
3711     + return Solid::StorageDrive::Platform;
3712     +}
3713     diff --git a/solid/solid/backends/udisks2/udisksstoragedrive.h b/solid/solid/backends/udisks2/udisksstoragedrive.h
3714     new file mode 100644
3715     index 0000000..d8c1046
3716     --- /dev/null
3717     +++ b/solid/solid/backends/udisks2/udisksstoragedrive.h
3718     @@ -0,0 +1,61 @@
3719     +/*
3720     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
3721     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
3722     +
3723     + This library is free software; you can redistribute it and/or
3724     + modify it under the terms of the GNU Lesser General Public
3725     + License as published by the Free Software Foundation; either
3726     + version 2.1 of the License, or (at your option) version 3, or any
3727     + later version accepted by the membership of KDE e.V. (or its
3728     + successor approved by the membership of KDE e.V.), which shall
3729     + act as a proxy defined in Section 6 of version 3 of the license.
3730     +
3731     + This library is distributed in the hope that it will be useful,
3732     + but WITHOUT ANY WARRANTY; without even the implied warranty of
3733     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3734     + Lesser General Public License for more details.
3735     +
3736     + You should have received a copy of the GNU Lesser General Public
3737     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
3738     +*/
3739     +
3740     +#ifndef UDISKS2STORAGEDRIVE_H
3741     +#define UDISKS2STORAGEDRIVE_H
3742     +
3743     +#include <ifaces/storagedrive.h>
3744     +
3745     +#include "../shared/udevqt.h"
3746     +
3747     +#include "udisksblock.h"
3748     +
3749     +namespace Solid
3750     +{
3751     +namespace Backends
3752     +{
3753     +namespace UDisks2
3754     +{
3755     +
3756     +class StorageDrive: public Block, virtual public Solid::Ifaces::StorageDrive
3757     +{
3758     + Q_OBJECT
3759     + Q_INTERFACES(Solid::Ifaces::StorageDrive)
3760     +
3761     +public:
3762     + StorageDrive(Device *dev);
3763     + virtual ~StorageDrive();
3764     +
3765     + virtual qulonglong size() const;
3766     + virtual bool isHotpluggable() const;
3767     + virtual bool isRemovable() const;
3768     + virtual Solid::StorageDrive::DriveType driveType() const;
3769     + virtual Solid::StorageDrive::Bus bus() const;
3770     +
3771     +private:
3772     + UdevQt::Device m_udevDevice;
3773     +};
3774     +
3775     +}
3776     +}
3777     +}
3778     +
3779     +#endif // UDISK2SSTORAGEDRIVE_H
3780     diff --git a/solid/solid/backends/udisks2/udisksstoragevolume.cpp b/solid/solid/backends/udisks2/udisksstoragevolume.cpp
3781     new file mode 100644
3782     index 0000000..a7d8fad
3783     --- /dev/null
3784     +++ b/solid/solid/backends/udisks2/udisksstoragevolume.cpp
3785     @@ -0,0 +1,105 @@
3786     +/*
3787     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
3788     + Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
3789     +
3790     + This library is free software; you can redistribute it and/or
3791     + modify it under the terms of the GNU Lesser General Public
3792     + License as published by the Free Software Foundation; either
3793     + version 2.1 of the License, or (at your option) version 3, or any
3794     + later version accepted by the membership of KDE e.V. (or its
3795     + successor approved by the membership of KDE e.V.), which shall
3796     + act as a proxy defined in Section 6 of version 3 of the license.
3797     +
3798     + This library is distributed in the hope that it will be useful,
3799     + but WITHOUT ANY WARRANTY; without even the implied warranty of
3800     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3801     + Lesser General Public License for more details.
3802     +
3803     + You should have received a copy of the GNU Lesser General Public
3804     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
3805     +*/
3806     +
3807     +#include "udisksstoragevolume.h"
3808     +#include "udisks2.h"
3809     +
3810     +using namespace Solid::Backends::UDisks2;
3811     +
3812     +StorageVolume::StorageVolume(Device *device)
3813     + : Block(device)
3814     +{
3815     +}
3816     +
3817     +StorageVolume::~StorageVolume()
3818     +{
3819     +}
3820     +
3821     +QString StorageVolume::encryptedContainerUdi() const
3822     +{
3823     + const QString path = m_device->prop("CryptoBackingDevice").value<QDBusObjectPath>().path();
3824     + if ( path.isEmpty() || path == "/")
3825     + return QString();
3826     + else
3827     + return path;
3828     +}
3829     +
3830     +qulonglong StorageVolume::size() const
3831     +{
3832     + return m_device->prop("Size").toULongLong();
3833     +}
3834     +
3835     +QString StorageVolume::uuid() const
3836     +{
3837     + return m_device->prop("IdUUID").toString();
3838     +}
3839     +
3840     +QString StorageVolume::label() const
3841     +{
3842     + QString label = m_device->prop("HintName").toString();
3843     + if (label.isEmpty())
3844     + label = m_device->prop("IdLabel").toString();
3845     + if (label.isEmpty())
3846     + label = m_device->prop("Name").toString();
3847     + return label;
3848     +}
3849     +
3850     +QString StorageVolume::fsType() const
3851     +{
3852     + return m_device->prop("IdType").toString();
3853     +}
3854     +
3855     +Solid::StorageVolume::UsageType StorageVolume::usage() const
3856     +{
3857     + const QString usage = m_device->prop("IdUsage").toString();
3858     +
3859     + if (m_device->hasInterface(UD2_DBUS_INTERFACE_FILESYSTEM))
3860     + {
3861     + return Solid::StorageVolume::FileSystem;
3862     + }
3863     + else if (m_device->isPartitionTable())
3864     + {
3865     + return Solid::StorageVolume::PartitionTable;
3866     + }
3867     + else if (usage == "raid")
3868     + {
3869     + return Solid::StorageVolume::Raid;
3870     + }
3871     + else if (m_device->isEncryptedContainer())
3872     + {
3873     + return Solid::StorageVolume::Encrypted;
3874     + }
3875     + else if (usage == "unused" || usage.isEmpty())
3876     + {
3877     + return Solid::StorageVolume::Unused;
3878     + }
3879     + else
3880     + {
3881     + return Solid::StorageVolume::Other;
3882     + }
3883     +}
3884     +
3885     +bool StorageVolume::isIgnored() const
3886     +{
3887     + const Solid::StorageVolume::UsageType usg = usage();
3888     + return m_device->prop("HintIgnore").toBool() || m_device->isSwap() ||
3889     + ((usg == Solid::StorageVolume::Unused || usg == Solid::StorageVolume::Other || usg == Solid::StorageVolume::PartitionTable) && !m_device->isOpticalDisc());
3890     +}
3891     diff --git a/solid/solid/backends/udisks2/udisksstoragevolume.h b/solid/solid/backends/udisks2/udisksstoragevolume.h
3892     new file mode 100644
3893     index 0000000..2ca04d2
3894     --- /dev/null
3895     +++ b/solid/solid/backends/udisks2/udisksstoragevolume.h
3896     @@ -0,0 +1,57 @@
3897     +/*
3898     + Copyright 2010 Michael Zanetti <mzanetti@kde.org>
3899     +
3900     + This library is free software; you can redistribute it and/or
3901     + modify it under the terms of the GNU Lesser General Public
3902     + License as published by the Free Software Foundation; either
3903     + version 2.1 of the License, or (at your option) version 3, or any
3904     + later version accepted by the membership of KDE e.V. (or its
3905     + successor approved by the membership of KDE e.V.), which shall
3906     + act as a proxy defined in Section 6 of version 3 of the license.
3907     +
3908     + This library is distributed in the hope that it will be useful,
3909     + but WITHOUT ANY WARRANTY; without even the implied warranty of
3910     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3911     + Lesser General Public License for more details.
3912     +
3913     + You should have received a copy of the GNU Lesser General Public
3914     + License along with this library. If not, see <http://www.gnu.org/licenses/>.
3915     +*/
3916     +
3917     +#ifndef UDISKS2STORAGEVOLUME_H
3918     +#define UDISKS2STORAGEVOLUME_H
3919     +
3920     +#include <ifaces/storagevolume.h>
3921     +#include "udisksblock.h"
3922     +
3923     +
3924     +namespace Solid
3925     +{
3926     +namespace Backends
3927     +{
3928     +namespace UDisks2
3929     +{
3930     +
3931     +class StorageVolume: public Block, virtual public Solid::Ifaces::StorageVolume
3932     +{
3933     + Q_OBJECT
3934     + Q_INTERFACES(Solid::Ifaces::StorageVolume)
3935     +
3936     +public:
3937     + StorageVolume(Device *device);
3938     + virtual ~StorageVolume();
3939     +
3940     + virtual QString encryptedContainerUdi() const;
3941     + virtual qulonglong size() const;
3942     + virtual QString uuid() const;
3943     + virtual QString label() const;
3944     + virtual QString fsType() const;
3945     + virtual Solid::StorageVolume::UsageType usage() const;
3946     + virtual bool isIgnored() const;
3947     +};
3948     +
3949     +}
3950     +}
3951     +}
3952     +
3953     +#endif // UDISKS2STORAGEVOLUME_H
3954     diff --git a/solid/solid/managerbase.cpp b/solid/solid/managerbase.cpp
3955     index fb5a67c..c7005ff 100644
3956     --- a/solid/solid/managerbase.cpp
3957     +++ b/solid/solid/managerbase.cpp
3958     @@ -30,8 +30,11 @@
3959     #if defined (Q_OS_MAC)
3960     #include "backends/iokit/iokitmanager.h"
3961     #elif defined (Q_OS_UNIX)
3962     -#include "backends/hal/halmanager.h"
3963     +#if defined (WITH_SOLID_UDISKS2)
3964     +#include "backends/udisks2/udisksmanager.h"
3965     +#else
3966     #include "backends/udisks/udisksmanager.h"
3967     +#endif
3968     #include "backends/upower/upowermanager.h"
3969    
3970     #if defined (HUPNP_FOUND)
3971     @@ -71,22 +74,17 @@ void Solid::ManagerBasePrivate::loadBackends()
3972     # elif defined(Q_WS_WIN) && defined(HAVE_WBEM) && !defined(_WIN32_WCE)
3973     m_backends << new Solid::Backends::Wmi::WmiManager(0);
3974    
3975     -# elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
3976     - m_backends << new Solid::Backends::Hal::HalManager(0);
3977     -
3978     # elif defined(Q_OS_LINUX)
3979     - bool solidHalLegacyEnabled
3980     - = QString::fromLocal8Bit(qgetenv("SOLID_HAL_LEGACY")).toInt()==1;
3981     - if (solidHalLegacyEnabled) {
3982     - m_backends << new Solid::Backends::Hal::HalManager(0);
3983     - } else {
3984     # if defined(UDEV_FOUND)
3985     m_backends << new Solid::Backends::UDev::UDevManager(0);
3986     # endif
3987     +# if defined(WITH_SOLID_UDISKS2)
3988     + m_backends << new Solid::Backends::UDisks2::Manager(0)
3989     +# else
3990     m_backends << new Solid::Backends::UDisks::UDisksManager(0)
3991     +# endif
3992     << new Solid::Backends::UPower::UPowerManager(0)
3993     << new Solid::Backends::Fstab::FstabManager(0);
3994     - }
3995     # endif
3996    
3997     # if defined (HUPNP_FOUND)
3998     @@ -99,5 +97,3 @@ QList<QObject*> Solid::ManagerBasePrivate::managerBackends() const
3999     {
4000     return m_backends;
4001     }
4002     -
4003     -
4004     diff --git a/solid/tests/CMakeLists.txt b/solid/tests/CMakeLists.txt
4005     index ef507d1..9212741 100644
4006     --- a/solid/tests/CMakeLists.txt
4007     +++ b/solid/tests/CMakeLists.txt
4008     @@ -16,20 +16,6 @@ target_link_libraries(fakehardwaretest solid_static ${QT_QTCORE_LIBRARY} ${QT_QT
4009     add_definitions(-DTEST_DATA="\\"${CMAKE_CURRENT_SOURCE_DIR}/../solid/backends/fakehw/fakecomputer.xml\\"")
4010    
4011    
4012     -########### halbasictest ###############
4013     -
4014     -if(NOT WIN32 AND NOT APPLE)
4015     -set(halbasictest_SRCS halbasictest.cpp )
4016     -
4017     -kde4_add_executable(halbasictest ${halbasictest_SRCS})
4018     -
4019     -if(WIN32)
4020     - set_target_properties(halbasictest PROPERTIES COMPILE_FLAGS -DSOLID_EXPORT=)
4021     -endif(WIN32)
4022     -
4023     -target_link_libraries(halbasictest solid_static ${KDEWIN_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTTEST_LIBRARY} )
4024     -endif(NOT WIN32 AND NOT APPLE)
4025     -
4026     ########### solidhwtest ###############
4027    
4028     set(solidhwtest_SRCS