diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca6625abf..d7e9083ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -973,6 +973,8 @@ if(HAVE_DBUS) PROPERTIES NO_NAMESPACE dbus/udisks2block INCLUDE dbus/metatypes.h) set_source_files_properties(dbus/org.freedesktop.UDisks2.Drive.xml PROPERTIES NO_NAMESPACE dbus/udisks2drive INCLUDE dbus/metatypes.h) + set_source_files_properties(dbus/org.freedesktop.UDisks2.Job.xml + PROPERTIES NO_NAMESPACE dbus/udisks2job INCLUDE dbus/metatypes.h) qt4_add_dbus_interface(SOURCES dbus/org.freedesktop.DBus.ObjectManager.xml dbus/objectmanager) @@ -985,6 +987,9 @@ if(HAVE_DBUS) qt4_add_dbus_interface(SOURCES dbus/org.freedesktop.UDisks2.Drive.xml dbus/udisks2drive) + qt4_add_dbus_interface(SOURCES + dbus/org.freedesktop.UDisks2.Job.xml + dbus/udisks2job) endif(HAVE_UDISKS2) # Wiimotedev interface classes diff --git a/src/dbus/org.freedesktop.UDisks2.Job.xml b/src/dbus/org.freedesktop.UDisks2.Job.xml new file mode 100644 index 000000000..2cd42533d --- /dev/null +++ b/src/dbus/org.freedesktop.UDisks2.Job.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp index df6fb6203..023de0602 100644 --- a/src/devices/udisks2lister.cpp +++ b/src/devices/udisks2lister.cpp @@ -8,6 +8,7 @@ #include "dbus/udisks2filesystem.h" #include "dbus/udisks2block.h" #include "dbus/udisks2drive.h" +#include "dbus/udisks2job.h" const QString Udisks2Lister::udisks2service_ = "org.freedesktop.UDisks2"; @@ -165,6 +166,16 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path, if (interface.key() != "org.freedesktop.UDisks2.Job") continue; + std::shared_ptr job = std::make_shared( + udisks2service_, + path.path(), + QDBusConnection::systemBus()); + + if (!job->isValid()) + continue; + + // For some reason access through Job interface returns all properties + // as invalid for unmount job so we're doing this the hard way bool isMountJob = false; if (interface.value()["Operation"] == "filesystem-mount") isMountJob = true; @@ -173,30 +184,24 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path, else continue; - const QDBusArgument &objects = interface.value()["Objects"].value(); - - QList mountedParititons; - objects.beginArray(); - while (!objects.atEnd()) { - QDBusObjectPath extractedPath; - objects >> extractedPath; - mountedParititons.push_back(extractedPath); - } - objects.endArray(); + QList mountedParititons + = GetMountedPartitionsFromDBusArgument(interface.value()["Objects"].value()); if (mountedParititons.isEmpty()) { qLog(Warning) << "Empty Udisks2 mount/umount job " << path.path(); - return; + continue; } - qLog(Debug) << "Adding Udisks job " << path.path() - << " | Operation = " << interface.value()["Operation"].toString() - << " with first path: " << mountedParititons.at(0).path(); - { QMutexLocker locker(&jobs_lock_); - mounting_jobs_[path.path()].isMount = isMountJob; - mounting_jobs_[path.path()].mount_paths = mountedParititons; + qLog(Debug) << "Adding pending job | DBus Path = " << job->path() + << " | IsMountJob = " << isMountJob + << " | First partition = " << mountedParititons.at(0).path(); + mounting_jobs_[path].dbus_interface = job; + mounting_jobs_[path].isMount = isMountJob; + mounting_jobs_[path].mounted_partitions = mountedParititons; + connect(job.get(), SIGNAL(Completed(bool, const QString&)), + SLOT(JobCompleted(bool, const QString&))); } } } @@ -207,47 +212,12 @@ void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath &path, const QStr } bool Udisks2Lister::isPendingJob(const QDBusObjectPath &jobPath) { - // should be actually done with a succcess signal from job, I guess, but it makes it kinda complicated QMutexLocker locker(&jobs_lock_); - if (!mounting_jobs_.contains(jobPath.path())) + if (!mounting_jobs_.contains(jobPath)) return false; - const auto &mountPaths = mounting_jobs_[jobPath.path()].mount_paths; - const auto &isMount = mounting_jobs_[jobPath.path()].isMount; - for (const auto &partition : mountPaths) { - auto data = ReadPartitionData(partition, true); - if (!data.dbus_path.isEmpty()) { - if (isMount) { - qLog(Debug) << "UDisks2 mount job finished: Drive = " << data.dbus_drive_path - << " | Partition = " << data.dbus_path; - QWriteLocker locker(&device_data_lock_); - device_data_[data.unique_id()] = data; - DeviceAdded(data.unique_id()); - } else { - QWriteLocker locker(&device_data_lock_); - QString id; - for (auto &data : device_data_) { - if (data.mount_paths.contains(partition.path())) { - qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path - << " | Partition = " << data.dbus_path; - data.mount_paths.removeOne(partition.path()); - if (data.mount_paths.empty()) - id = data.unique_id(); - break; - } - } - - if (!id.isEmpty()) - { - qLog(Debug) << "Partition " << data.dbus_path << " has no more mount points, removing it from device list"; - device_data_.remove(id); - DeviceRemoved(id); - } - } - } - } - mounting_jobs_.remove(jobPath.path()); + mounting_jobs_.remove(jobPath); return true; } @@ -269,6 +239,67 @@ void Udisks2Lister::RemoveDevice(const QDBusObjectPath &devicePath) { DeviceRemoved(id); } +QList Udisks2Lister::GetMountedPartitionsFromDBusArgument(const QDBusArgument &input) { + QList result; + + input.beginArray(); + while (!input.atEnd()) { + QDBusObjectPath extractedPath; + input >> extractedPath; + result.push_back(extractedPath); + } + input.endArray(); + + return result; +} + +void Udisks2Lister::JobCompleted(bool success, const QString &message) { + auto job = qobject_cast(sender()); + QDBusObjectPath jobPath(job->path()); + + if (!job->isValid() + || !success + || !mounting_jobs_.contains(jobPath)) + return; + + qLog(Debug) << "Pending Job Completed | Path = " << job->path() + << " | Mount? = " << mounting_jobs_[jobPath].isMount + << " | Success = " << success; + + for (const auto &mountedObject : mounting_jobs_[jobPath].mounted_partitions) { + auto data = ReadPartitionData(mountedObject, false); + if (data.dbus_path.isEmpty()) + continue; + + if (mounting_jobs_[jobPath].isMount) { + qLog(Debug) << "UDisks2 mount job finished: Drive = " << data.dbus_drive_path + << " | Partition = " << data.dbus_path; + QWriteLocker locker(&device_data_lock_); + device_data_[data.unique_id()] = data; + DeviceAdded(data.unique_id()); + } else { + QWriteLocker locker(&device_data_lock_); + QString id; + for (auto &data : device_data_) { + if (data.mount_paths.contains(mountedObject.path())) { + qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path + << " | Partition = " << data.dbus_path; + data.mount_paths.removeOne(mountedObject.path()); + if (data.mount_paths.empty()) + id = data.unique_id(); + break; + } + } + + if (!id.isEmpty()) { + qLog(Debug) << "Partition " << data.dbus_path << " has no more mount points, removing it from device list"; + device_data_.remove(id); + DeviceRemoved(id); + } + } + } +} + Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path, bool beingMounted) { PartitionData result; diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h index 37320edd1..62d283520 100644 --- a/src/devices/udisks2lister.h +++ b/src/devices/udisks2lister.h @@ -6,6 +6,8 @@ #include "dbus/objectmanager.h" +class OrgFreedesktopUDisks2JobInterface; + class Udisks2Lister : public DeviceLister { Q_OBJECT @@ -35,20 +37,23 @@ protected: private slots: void DBusInterfaceAdded(const QDBusObjectPath &path, const InterfacesAndProperties &ifaces); void DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces); + void JobCompleted(bool success, const QString &message); private: bool isPendingJob(const QDBusObjectPath &jobPath); void RemoveDevice(const QDBusObjectPath &devicePath); + QList GetMountedPartitionsFromDBusArgument(const QDBusArgument &input); - class MountJob + class Udisks2Job { public: bool isMount = true; - QList mount_paths; + QList mounted_partitions; + std::shared_ptr dbus_interface; }; QMutex jobs_lock_; - QMap mounting_jobs_; + QMap mounting_jobs_; private: class PartitionData {