diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..8994b9b --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,60 @@ +set(udisksqt_SRC + dblockdevice.cpp + dblockpartition.cpp + ddiskdevice.cpp + ddiskmanager.cpp + dudisksjob.cpp + udisks2_dbus_common.cpp +) + +set(udisksqt_HEADERS + dblockdevice.h + dblockpartition.h + ddiskdevice.h + ddiskmanager.h + dudisksjob.h + udisks2_dbus_common.h +) + +set(udisksqt_HEADERS_PRIVATE + private/dblockdevice_p.h +) + +set_property(SOURCE org.freedesktop.UDisks2.xml PROPERTY INCLUDE udisks2_dbus_common.h) +set_property(SOURCE org.freedesktop.UDisks2.xml PROPERTY NO_NAMESPACE true) +qt5_add_dbus_interface(udisksqt_SRC org.freedesktop.UDisks2.xml udisks2_interface) + +set_property(SOURCE org.freedesktop.DBus.ObjectManager.xml PROPERTY INCLUDE udisks2_dbus_common.h) +set_property(SOURCE org.freedesktop.DBus.ObjectManager.xml PROPERTY NO_NAMESPACE true) +qt5_add_dbus_interface(udisksqt_SRC org.freedesktop.UDisks2.ObjectManager.xml objectmanager_interface) + +add_library(udisks2-qt5 SHARED ${udisksqt_SRC} ${udisksqt_HEADERS} ${udisksqt_HEADERS_PRIVATE}) +set_target_properties(udisks2-qt5 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${UDISKS_API_LEVEL}) + +list(APPEND udisksqt_HEADERS + ${CMAKE_CURRENT_BINARY_DIR}/udisks2_interface.h + ${CMAKE_CURRENT_BINARY_DIR}/objectmanager_interface.h +) +target_link_libraries(udisks2-qt5 + Qt5::Core + Qt5::DBus +) + +set_property(TARGET udisks2-qt5 PROPERTY COMPILE_DEFINITIONS UDISKS_STATIC) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/udisks2-qt5.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/udisks2-qt5.pc + @ONLY +) + +install(TARGETS udisks2-qt5 DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/udisks-qt5.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) +install(FILES ${udisksqt_HEADERS} + DESTINATION include/udisks2-qt5 +) +install(FILES ${udisksqt_HEADERS_PRIVATE} + DESTINATION include/udisks2-qt5/private +) +add_subdirectory(modules) diff --git a/src/dblockdevice.cpp b/src/dblockdevice.cpp new file mode 100644 index 0000000..720a030 --- /dev/null +++ b/src/dblockdevice.cpp @@ -0,0 +1,731 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dblockdevice.h" +#include "private/dblockdevice_p.h" +#include "udisks2_interface.h" +#include "objectmanager_interface.h" + +DBlockDevicePrivate::DBlockDevicePrivate(DBlockDevice *qq) + : q_ptr(qq) +{ + +} + +void DBlockDevice::onInterfacesAdded(const QDBusObjectPath &object_path, const QMap &interfaces_and_properties) +{ + Q_D(DBlockDevice); + + const QString &path = object_path.path(); + + if (path != d->dbus->path()) + return; + + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Filesystem"))) { + Q_EMIT hasFileSystemChanged(true); + } + + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Partition"))) { + Q_EMIT hasPartitionChanged(true); + } + + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Encrypted"))) { + Q_EMIT isEncryptedChanged(true); + } +} + +void DBlockDevice::onInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces) +{ + Q_D(DBlockDevice); + + const QString &path = object_path.path(); + + if (path != d->dbus->path()) + return; + + for (const QString &i : interfaces) { + if (i == QStringLiteral(UDISKS2_SERVICE ".Filesystem")) { + Q_EMIT hasFileSystemChanged(false); + } else if (i == QStringLiteral(UDISKS2_SERVICE ".Partition")) { + Q_EMIT hasPartitionChanged(false); + } else if (i == QStringLiteral(UDISKS2_SERVICE ".Encrypted")) { + Q_EMIT isEncryptedChanged(false); + } + } +} + +void DBlockDevice::onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties) +{ + if (interface.endsWith(".PartitionTable")) { + auto begin = changed_properties.begin(); + + while (begin != changed_properties.constEnd()) { + if (begin.key() == "Type") { + Q_EMIT ptTypeChanged(); + break; + } + + ++begin; + } + } else { + auto begin = changed_properties.begin(); + + for (; begin != changed_properties.constEnd(); ++begin) { + QString property_name = begin.key(); + + int pindex = this->metaObject()->indexOfProperty(property_name.toLatin1().constData()); + + if (pindex < 0) { + property_name[0] = property_name.at(0).toLower(); + + pindex = this->metaObject()->indexOfProperty(property_name.toLatin1().constData()); + } + + if (pindex < 0) + continue; + + const QMetaProperty &mp = this->metaObject()->property(pindex); + + if (!mp.hasNotifySignal()) + continue; + + mp.notifySignal().invoke(this, QGenericArgument(begin.value().typeName(), begin.value().constData())); + } + } +} + +DBlockDevice::~DBlockDevice() +{ + +} + +bool DBlockDevice::isValid() const +{ + Q_D(const DBlockDevice); + + return d->dbus->isValid(); +} + +bool DBlockDevice::watchChanges() const +{ + Q_D(const DBlockDevice); + + return d->watchChanges; +} + +/*! + * \brief Get the block device (patition) DBus path. + * + * \return the DBus path + */ +QString DBlockDevice::path() const +{ + Q_D(const DBlockDevice); + + return d->dbus->path(); +} + +QList > DBlockDevice::configuration() const +{ + Q_D(const DBlockDevice); + + return d->dbus->configuration(); +} + +QString DBlockDevice::cryptoBackingDevice() const +{ + Q_D(const DBlockDevice); + + return d->dbus->cryptoBackingDevice().path(); +} + +/*! + * \brief Get the device path, like `/dev/sda1` + * + * \return Device path in QByteArray. + */ +QByteArray DBlockDevice::device() const +{ + Q_D(const DBlockDevice); + + return d->dbus->device(); +} + +qulonglong DBlockDevice::deviceNumber() const +{ + Q_D(const DBlockDevice); + + return d->dbus->deviceNumber(); +} + +/*! + * \brief Get the disk device dbus path + * + * \return a dbus path in QString + */ +QString DBlockDevice::drive() const +{ + Q_D(const DBlockDevice); + + return d->dbus->drive().path(); +} + +bool DBlockDevice::hintAuto() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintAuto(); +} + +QString DBlockDevice::hintIconName() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintIconName(); +} + +bool DBlockDevice::hintIgnore() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintIgnore(); +} + +QString DBlockDevice::hintName() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintName(); +} + +bool DBlockDevice::hintPartitionable() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintPartitionable(); +} + +QString DBlockDevice::hintSymbolicIconName() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintSymbolicIconName(); +} + +bool DBlockDevice::hintSystem() const +{ + Q_D(const DBlockDevice); + + return d->dbus->hintSystem(); +} + +QString DBlockDevice::id() const +{ + Q_D(const DBlockDevice); + + return d->dbus->id(); +} + +QString DBlockDevice::idLabel() const +{ + Q_D(const DBlockDevice); + + return d->dbus->idLabel(); +} + +QString DBlockDevice::idType() const +{ + Q_D(const DBlockDevice); + + return d->dbus->idType(); +} + +DBlockDevice::FSType DBlockDevice::fsType() const +{ + const QString &fs_type = idType(); + + if (fs_type.isEmpty()) + return InvalidFS; + + if (fs_type == "hfs+") + return hfs_plus; + + bool ok = false; + const QMetaEnum me = QMetaEnum::fromType(); + + int value = me.keyToValue(fs_type.toLatin1().constData(), &ok); + + if (!ok) { + return UnknowFS; + } + + return static_cast(value); +} + +QString DBlockDevice::idUUID() const +{ + Q_D(const DBlockDevice); + + return d->dbus->idUUID(); +} + +QString DBlockDevice::idUsage() const +{ + Q_D(const DBlockDevice); + + return d->dbus->idUsage(); +} + +QString DBlockDevice::idVersion() const +{ + Q_D(const DBlockDevice); + + return d->dbus->idVersion(); +} + +QString DBlockDevice::mDRaid() const +{ + Q_D(const DBlockDevice); + + return d->dbus->mDRaid().path(); +} + +QString DBlockDevice::mDRaidMember() const +{ + Q_D(const DBlockDevice); + + return d->dbus->mDRaidMember().path(); +} + +QByteArray DBlockDevice::preferredDevice() const +{ + Q_D(const DBlockDevice); + + return d->dbus->preferredDevice(); +} + +bool DBlockDevice::readOnly() const +{ + Q_D(const DBlockDevice); + + return d->dbus->readOnly(); +} + +qulonglong DBlockDevice::size() const +{ + Q_D(const DBlockDevice); + + return d->dbus->size(); +} + +QByteArrayList DBlockDevice::symlinks() const +{ + Q_D(const DBlockDevice); + + return d->dbus->symlinks(); +} + +QStringList DBlockDevice::userspaceMountOptions() const +{ + Q_D(const DBlockDevice); + + return d->dbus->userspaceMountOptions(); +} + +bool DBlockDevice::hasFileSystem() const +{ + Q_D(const DBlockDevice); + + return hasFileSystem(d->dbus->path()); +} + +bool DBlockDevice::hasPartitionTable() const +{ + Q_D(const DBlockDevice); + + return hasPartitionTable(d->dbus->path()); +} + +bool DBlockDevice::hasPartition() const +{ + Q_D(const DBlockDevice); + + return hasPartition(d->dbus->path()); +} + +bool DBlockDevice::isEncrypted() const +{ + Q_D(const DBlockDevice); + + return isEncrypted(d->dbus->path()); +} + +bool DBlockDevice::isLoopDevice() const +{ + Q_D(const DBlockDevice); + + return UDisks2::interfaceExists(d->dbus->path(), UDISKS2_SERVICE ".Loop"); +} + +bool DBlockDevice::hasFileSystem(const QString &path) +{ + return UDisks2::interfaceExists(path, UDISKS2_SERVICE ".Filesystem"); +} + +bool DBlockDevice::hasPartitionTable(const QString &path) +{ + return UDisks2::interfaceExists(path, UDISKS2_SERVICE ".PartitionTable"); +} + +bool DBlockDevice::hasPartition(const QString &path) +{ + return UDisks2::interfaceExists(path, UDISKS2_SERVICE ".Partition"); +} + +bool DBlockDevice::isEncrypted(const QString &path) +{ + return UDisks2::interfaceExists(path, UDISKS2_SERVICE ".Encrypted"); +} + +QByteArrayList DBlockDevice::mountPoints() const +{ + if (!hasFileSystem()) + return QByteArrayList(); + + Q_D(const DBlockDevice); + + OrgFreedesktopUDisks2FilesystemInterface fsif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + return fsif.mountPoints(); +} + +DBlockDevice::PTType DBlockDevice::ptType() const +{ + Q_D(const DBlockDevice); + + if (!UDisks2::interfaceExists(d->dbus->path(), UDISKS2_SERVICE ".PartitionTable")) { + return InvalidPT; + } + + OrgFreedesktopUDisks2PartitionTableInterface ptif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + + const QString &type = ptif.type(); + + if (type.isEmpty()) { + return InvalidPT; + } + + if (type == "dos") { + return MBR; + } + + if (type == "gpt") { + return GPT; + } + + return UnknowPT; +} + +QList > DBlockDevice::childConfiguration() const +{ + Q_D(const DBlockDevice); + + if (!isEncrypted()) { + return QList>(); + } + + OrgFreedesktopUDisks2EncryptedInterface eif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + return eif.childConfiguration(); +} + +QDBusError DBlockDevice::lastError() const +{ + Q_D(const DBlockDevice); + return d->err; +} + +void DBlockDevice::setWatchChanges(bool watchChanges) +{ + Q_D(DBlockDevice); + + if (d->watchChanges == watchChanges) + return; + + d->watchChanges = watchChanges; + + OrgFreedesktopDBusObjectManagerInterface *object_manager = UDisks2::objectManager(); + auto sb = QDBusConnection::systemBus(); + + if (watchChanges) { + connect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, + this, &DBlockDevice::onInterfacesAdded); + connect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &DBlockDevice::onInterfacesRemoved); + + sb.connect(UDISKS2_SERVICE, d->dbus->path(), "org.freedesktop.DBus.Properties", + "PropertiesChanged", this, SLOT(onPropertiesChanged(const QString &, const QVariantMap &))); + } else { + disconnect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, + this, &DBlockDevice::onInterfacesAdded); + disconnect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &DBlockDevice::onInterfacesRemoved); + + sb.disconnect(UDISKS2_SERVICE, d->dbus->path(), "org.freedesktop.DBus.Properties", + "PropertiesChanged", this, SLOT(onPropertiesChanged(const QString &, const QVariantMap &))); + } +} + +void DBlockDevice::addConfigurationItem(const QPair &item, const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->AddConfigurationItem(item, options); + r.waitForFinished(); + d->err = r.error(); +} + +void DBlockDevice::format(const QString &type, const QVariantMap &options) +{ + Q_D(DBlockDevice); + + d->dbus->setTimeout(INT_MAX); + auto r = d->dbus->Format(type, options); + r.waitForFinished(); + d->err = r.error(); + d->dbus->setTimeout(-1); +} + +void DBlockDevice::format(const DBlockDevice::FSType &type, const QVariantMap &options) +{ + if (type < ext2) + return; + + format(QString::fromLatin1(QMetaEnum::fromType().valueToKey(type)), options); +} + +QList > DBlockDevice::getSecretConfiguration(const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->GetSecretConfiguration(options); + r.waitForFinished(); + d->err = r.error(); + return r.value(); +} + +QDBusUnixFileDescriptor DBlockDevice::openDevice(const QString &mode, const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->OpenDevice(mode, options); + r.waitForFinished(); + d->err = r.error(); + return r.value(); +} + +QDBusUnixFileDescriptor DBlockDevice::openForBackup(const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->OpenForBackup(options); + r.waitForFinished(); + d->err = r.error(); + return r.value(); +} + +QDBusUnixFileDescriptor DBlockDevice::openForBenchmark(const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->OpenForBenchmark(options); + r.waitForFinished(); + d->err = r.error(); + return r.value(); +} + +QDBusUnixFileDescriptor DBlockDevice::openForRestore(const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->OpenForRestore(options); + r.waitForFinished(); + d->err = r.error(); + return r.value(); +} + +void DBlockDevice::removeConfigurationItem(const QPair &item, const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->RemoveConfigurationItem(item, options); + r.waitForFinished(); + d->err = r.error(); +} + +void DBlockDevice::rescan(const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->Rescan(options); + r.waitForFinished(); + d->err = r.error(); +} + +void DBlockDevice::updateConfigurationItem(const QPair &old_item, const QPair &new_item, const QVariantMap &options) +{ + Q_D(DBlockDevice); + + auto r = d->dbus->UpdateConfigurationItem(old_item, new_item, options); + r.waitForFinished(); + d->err = r.error(); +} + +/*! + * \brief Mount the block device. + * + * \param options please refer to \l {http://storaged.org/doc/udisks2-api/latest/gdbus-org.freedesktop.UDisks2.Filesystem.html#gdbus-method-org-freedesktop-UDisks2-Filesystem.Mount} {UDisks2.Filesystem Mount()} + * + * \return the mount point path. + * + * \sa unmount() + */ +QString DBlockDevice::mount(const QVariantMap &options) +{ + if (!hasFileSystem()) { + return QString(); + } + + Q_D(DBlockDevice); + + OrgFreedesktopUDisks2FilesystemInterface fsif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + + auto r = fsif.Mount(options); + r.waitForFinished(); + d->err = r.error(); + return r.value(); +} + +void DBlockDevice::unmount(const QVariantMap &options) +{ + if (!hasFileSystem()) { + return; + } + + Q_D(DBlockDevice); + + OrgFreedesktopUDisks2FilesystemInterface fsif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + auto r = fsif.Unmount(options); + r.waitForFinished(); + d->err = r.error(); +} + +/*! + * \brief Check if we can set the filesystem label. + * + * \return + */ +bool DBlockDevice::canSetLabel() const +{ + if (!hasFileSystem()) { + return false; + } + + // blumia: Since gvfs can't correctly mount a label-renamed patition + // we simply disable rename support if we don't unmount the + // patition. Will be add back when we switch to udisks2. + if (/*fsType() == ntfs && */!mountPoints().isEmpty()) { + return false; + } + + return true; +} + +/*! + * \brief Sets the filesystem label. + * + * \param options Options (currently unused except for standard options). + */ +void DBlockDevice::setLabel(const QString &label, const QVariantMap &options) +{ + if (!hasFileSystem()) { + return; + } + + Q_D(DBlockDevice); + + OrgFreedesktopUDisks2FilesystemInterface fsif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + auto r = fsif.SetLabel(label, options); + r.waitForFinished(); + d->err = r.error(); +} + +void DBlockDevice::changePassphrase(const QString &passphrase, const QString &new_passphrase, const QVariantMap &options) +{ + if (!isEncrypted()) { + return; + } + + Q_D(DBlockDevice); + + OrgFreedesktopUDisks2EncryptedInterface eif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + auto r = eif.ChangePassphrase(passphrase, new_passphrase, options); + r.waitForFinished(); + d->err = r.error(); +} + +void DBlockDevice::lock(const QVariantMap &options) +{ + if (!isEncrypted()) { + return; + } + + Q_D(DBlockDevice); + + OrgFreedesktopUDisks2EncryptedInterface eif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + QDBusPendingReply r = eif.Lock(options); + r.waitForFinished(); + d->err = r.error(); +} + +QString DBlockDevice::unlock(const QString &passphrase, const QVariantMap &options) +{ + if (!isEncrypted()) { + return QString(); + } + + Q_D(DBlockDevice); + + OrgFreedesktopUDisks2EncryptedInterface eif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + + auto r = eif.Unlock(passphrase, options); + r.waitForFinished(); + d->err = r.error(); + return r.value().path(); +} + +QString DBlockDevice::cleartextDevice() +{ + if (!isEncrypted()) { + return QString(); + } + + Q_D(const DBlockDevice); + + OrgFreedesktopUDisks2EncryptedInterface eif(UDISKS2_SERVICE, d->dbus->path(), QDBusConnection::systemBus()); + return eif.cleartextDevice().path(); +} + +DBlockDevice::DBlockDevice(const QString &path, QObject *parent) + : DBlockDevice(*new DBlockDevicePrivate(this), path, parent) +{ + +} + +DBlockDevice::DBlockDevice(DBlockDevicePrivate &dd, const QString &path, QObject *parent) + : QObject(parent) + , d_ptr(&dd) +{ + dd.dbus = new OrgFreedesktopUDisks2BlockInterface(UDISKS2_SERVICE, path, QDBusConnection::systemBus(), this); + + connect(this, &DBlockDevice::idTypeChanged, this, &DBlockDevice::fsTypeChanged); +} diff --git a/src/dblockdevice.h b/src/dblockdevice.h new file mode 100644 index 0000000..ceb8e0f --- /dev/null +++ b/src/dblockdevice.h @@ -0,0 +1,222 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DBLOCKDEVICE_H +#define DBLOCKDEVICE_H + +#include +#include +#include +#include + +class QDBusObjectPath; + +class DBlockDevicePrivate; +class DBlockDevice : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(DBlockDevice) + + Q_PROPERTY(QString path READ path CONSTANT FINAL) + Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges) + Q_PROPERTY(bool hasFileSystem READ hasFileSystem NOTIFY hasFileSystemChanged) + Q_PROPERTY(bool hasPartition READ hasPartition NOTIFY hasPartitionChanged) + Q_PROPERTY(bool isEncrypted READ isEncrypted NOTIFY isEncryptedChanged) + Q_PROPERTY(bool isLoopDevice READ isLoopDevice) + Q_PROPERTY(QList> configuration READ configuration NOTIFY configurationChanged) + Q_PROPERTY(QString cryptoBackingDevice READ cryptoBackingDevice NOTIFY cryptoBackingDeviceChanged) + Q_PROPERTY(QByteArray device READ device) + Q_PROPERTY(qulonglong deviceNumber READ deviceNumber) + Q_PROPERTY(QString drive READ drive) + Q_PROPERTY(bool hintAuto READ hintAuto NOTIFY hintAutoChanged) + Q_PROPERTY(QString hintIconName READ hintIconName NOTIFY hintIconNameChanged) + Q_PROPERTY(bool hintIgnore READ hintIgnore NOTIFY hintIgnoreChanged) + Q_PROPERTY(QString hintName READ hintName NOTIFY hintNameChanged) + Q_PROPERTY(bool hintPartitionable READ hintPartitionable NOTIFY hintPartitionableChanged) + Q_PROPERTY(QString hintSymbolicIconName READ hintSymbolicIconName NOTIFY hintSymbolicIconNameChanged) + Q_PROPERTY(bool hintSystem READ hintSystem) + Q_PROPERTY(QString id READ id) + Q_PROPERTY(QString idLabel READ idLabel NOTIFY idLabelChanged) + Q_PROPERTY(QString idType READ idType NOTIFY idTypeChanged) + Q_PROPERTY(FSType fsType READ fsType NOTIFY fsTypeChanged) + Q_PROPERTY(QString idUUID READ idUUID NOTIFY idUUIDChanged) + Q_PROPERTY(QString idUsage READ idUsage NOTIFY idUsageChanged) + Q_PROPERTY(QString idVersion READ idVersion NOTIFY idVersionChanged) + Q_PROPERTY(QString mDRaid READ mDRaid NOTIFY mDRaidChanged) + Q_PROPERTY(QString mDRaidMember READ mDRaidMember NOTIFY mDRaidMemberChanged) + Q_PROPERTY(QByteArray preferredDevice READ preferredDevice NOTIFY preferredDeviceChanged) + Q_PROPERTY(bool readOnly READ readOnly NOTIFY readOnlyChanged) + Q_PROPERTY(qulonglong size READ size NOTIFY sizeChanged) + Q_PROPERTY(QByteArrayList symlinks READ symlinks NOTIFY symlinksChanged) + Q_PROPERTY(QStringList userspaceMountOptions READ userspaceMountOptions NOTIFY userspaceMountOptionsChanged) + // of FileSystem + Q_PROPERTY(QByteArrayList mountPoints READ mountPoints NOTIFY mountPointsChanged) + // of ParitionTable + Q_PROPERTY(PTType ptType READ ptType NOTIFY ptTypeChanged) + // of Encrypted + Q_PROPERTY(QList> childConfiguration READ childConfiguration NOTIFY childConfigurationChanged) + Q_PROPERTY(QString cleartextDevice READ cleartextDevice NOTIFY cleartextDeviceChanged) + +public: + // partition table type + enum PTType { + InvalidPT, + MBR, + GPT, + UnknowPT + }; + + Q_ENUM(PTType) + + enum FSType { + InvalidFS, + UnknowFS, + ext2, + ext3, + ext4, + fat12, + fat16, + fat32, + btrfs, + f2fs, + hfs_plus, + minix, + nilfs2, + ntfs, + reiser4, + vfat, + iso9660, + jfs, + xfs, + swap, + LVM2_member, + crypto_LUKS + }; + + Q_ENUM(FSType) + + ~DBlockDevice(); + + bool isValid() const; + bool watchChanges() const; + + QString path() const; + QList> configuration() const; + QString cryptoBackingDevice() const; + QByteArray device() const; + qulonglong deviceNumber() const; + QString drive() const; + bool hintAuto() const; + QString hintIconName() const; + bool hintIgnore() const; + QString hintName() const; + bool hintPartitionable() const; + QString hintSymbolicIconName() const; + bool hintSystem() const; + QString id() const; + QString idLabel() const; + QString idType() const; + FSType fsType() const; + QString idUUID() const; + QString idUsage() const; + QString idVersion() const; + QString mDRaid() const; + QString mDRaidMember() const; + QByteArray preferredDevice() const; + bool readOnly() const; + qulonglong size() const; + QByteArrayList symlinks() const; + QStringList userspaceMountOptions() const; + + bool hasFileSystem() const; + bool hasPartitionTable() const; + bool hasPartition() const; + bool isEncrypted() const; + bool isLoopDevice() const; + + static bool hasFileSystem(const QString &path); + static bool hasPartitionTable(const QString &path); + static bool hasPartition(const QString &path); + static bool isEncrypted(const QString &path); + + QByteArrayList mountPoints() const; + PTType ptType() const; + + QList> childConfiguration() const; + + QDBusError lastError() const; + +public Q_SLOTS: + void setWatchChanges(bool watchChanges); + + void addConfigurationItem(const QPair &item, const QVariantMap &options); + void format(const QString &type, const QVariantMap &options); + void format(const FSType &type, const QVariantMap &options); + QList> getSecretConfiguration(const QVariantMap &options); + QDBusUnixFileDescriptor openDevice(const QString &mode, const QVariantMap &options); + QDBusUnixFileDescriptor openForBackup(const QVariantMap &options); + QDBusUnixFileDescriptor openForBenchmark(const QVariantMap &options); + QDBusUnixFileDescriptor openForRestore(const QVariantMap &options); + void removeConfigurationItem(const QPair &item, const QVariantMap &options); + void rescan(const QVariantMap &options); + void updateConfigurationItem(const QPair &old_item, const QPair &new_item, const QVariantMap &options); + + // of Filesystem + QString mount(const QVariantMap &options); + void unmount(const QVariantMap &options); + bool canSetLabel() const; + void setLabel(const QString &label, const QVariantMap &options); + + // of Encrypted + void changePassphrase(const QString &passphrase, const QString &new_passphrase, const QVariantMap &options); + void lock(const QVariantMap &options); + QString unlock(const QString &passphrase, const QVariantMap &options); + QString cleartextDevice(); + +Q_SIGNALS: + void hasFileSystemChanged(bool hasFileSystem); + void hasPartitionChanged(bool hasPartition); + void isEncryptedChanged(bool isEncrypted); + void configurationChanged(QList> configuration); + void cryptoBackingDeviceChanged(QString cryptoBackingDevice); + void hintAutoChanged(bool hintAuto); + void hintIconNameChanged(QString hintIconName); + void hintIgnoreChanged(bool hintIgnore); + void hintNameChanged(QString hintName); + void hintPartitionableChanged(bool hintPartitionable); + void hintSymbolicIconNameChanged(QString hintSymbolicIconName); + void idLabelChanged(QString idLabel); + void idTypeChanged(QString idType); + void fsTypeChanged(); + void idUUIDChanged(QString idUUID); + void idUsageChanged(QString idUsage); + void idVersionChanged(QString idVersion); + void mDRaidChanged(QString mDRaid); + void mDRaidMemberChanged(QString mDRaidMember); + void preferredDeviceChanged(QByteArray preferredDevice); + void readOnlyChanged(bool readOnly); + void sizeChanged(qulonglong size); + void symlinksChanged(QByteArrayList symlinks); + void userspaceMountOptionsChanged(QStringList userspaceMountOptions); + void ptTypeChanged(); + void mountPointsChanged(const QByteArrayList &mountPoints); + void childConfigurationChanged(QList> childConfiguration); + void cleartextDeviceChanged(const QString &cleartextDevice); + +protected: + explicit DBlockDevice(const QString &path, QObject *parent = nullptr); + explicit DBlockDevice(DBlockDevicePrivate &dd, const QString &path, QObject *parent = nullptr); + + QScopedPointer d_ptr; + +private Q_SLOTS: + void onInterfacesAdded(const QDBusObjectPath &object_path, const QMap &interfaces_and_properties); + void onInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces); + void onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties); +// Q_PRIVATE_SLOT(d_ptr, void _q_onPropertiesChanged(const QString &, const QVariantMap &)) + + friend class DDiskManager; +}; + +#endif // DBLOCKDEVICE_H diff --git a/src/dblockpartition.cpp b/src/dblockpartition.cpp new file mode 100644 index 0000000..0b4a78e --- /dev/null +++ b/src/dblockpartition.cpp @@ -0,0 +1,743 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dblockpartition.h" +#include "private/dblockdevice_p.h" +#include "udisks2_interface.h" + +class DBlockPartitionPrivate : public DBlockDevicePrivate +{ +public: + DBlockPartitionPrivate(DBlockPartition *qq); + + OrgFreedesktopUDisks2PartitionInterface *dbus; +}; + +DBlockPartitionPrivate::DBlockPartitionPrivate(DBlockPartition *qq) + : DBlockDevicePrivate(qq) +{ + +} + +qulonglong DBlockPartition::flags() const +{ + Q_D(const DBlockPartition); + + return d->dbus->flags(); +} + +bool DBlockPartition::isContained() const +{ + Q_D(const DBlockPartition); + + return d->dbus->isContained(); +} + +bool DBlockPartition::isContainer() const +{ + Q_D(const DBlockPartition); + + return d->dbus->isContainer(); +} + +QString DBlockPartition::name() const +{ + Q_D(const DBlockPartition); + + return d->dbus->name(); +} + +uint DBlockPartition::number() const +{ + Q_D(const DBlockPartition); + + return d->dbus->number(); +} + +qulonglong DBlockPartition::offset() const +{ + Q_D(const DBlockPartition); + + return d->dbus->offset(); +} + +qulonglong DBlockPartition::size() const +{ + Q_D(const DBlockPartition); + + return d->dbus->size(); +} + +QString DBlockPartition::table() const +{ + Q_D(const DBlockPartition); + + return d->dbus->table().path(); +} + +QString DBlockPartition::type() const +{ + Q_D(const DBlockPartition); + + return d->dbus->type(); +} + +DBlockPartition::Type DBlockPartition::eType() const +{ + const QString &type = this->type(); + + if (type.isEmpty()) + return Empty; + + bool ok = false; + int value = type.toInt(&ok, 16); + + if (!ok) { + return Unknow; + } + + return static_cast(value); +} + +QString DBlockPartition::UUID() const +{ + Q_D(const DBlockPartition); + + return d->dbus->uUID(); +} + +DBlockPartition::GUIDType DBlockPartition::guidType() const +{ + static QByteArrayList list; + + if (list.isEmpty()) { + // None + list << "00000000-0000-0000-0000-000000000000" + << "024DEE41-33E7-11D3-9D69-0008C781F39F" + << "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" + << "21686148-6449-6E6F-744E-656564454649" + << "D3BFE2DE-3DAF-11DF-BA40-E3A556D89593" + << "F4019732-066E-4E12-8273-346C5641494F" + << "BFBFAFE7-A34F-448A-9A5B-6213EB736C22" + // Windows + << "E3C9E316-0B5C-4DB8-817D-F92DF00215AE" + << "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" + << "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3" + << "AF9B60A0-1431-4F62-BC68-3311714A69AD" + << "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC" + << "37AFFC90-EF7D-4e96-91C3-2D7AE055B174" + << "E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D" + // HP-UX + << "75894C1E-3AEB-11D3-B7C1-7B03A0000000" + << "E2A1E728-32E3-11D6-A682-7B03A0000000" + // Linux + << "0FC63DAF-8483-4772-8E79-3D69D8477DE4" + << "A19D880F-05FC-4D3B-A006-743F0F84911E" + << "44479540-F297-41B2-9AF7-D131D5F0458A" + << "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709" + << "69DAD710-2CE4-4E3C-B16C-21A1D49ABED3" + << "B921B045-1DF0-41C3-AF44-4C6F280D3FAE" + << "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" + << "E6D6D379-F507-44C2-A23C-238F2A3DF928" + << "933AC7E1-2EB4-4F13-B844-0E14E2AEF915" + << "3B8F8425-20E0-4F3B-907F-1A25A76F98E8" + << "7FFEC5C9-2D00-49B7-8941-3EA10A5586B7" + << "CA7D7CCB-63ED-4C53-861C-1742536059CC" + << "8DA63339-0007-60C0-C436-083AC8230908" + // FreeBSD + << "83BD6B9D-7F41-11DC-BE0B-001560B84F0F" + << "516E7CB4-6ECF-11D6-8FF8-00022D09712B" + << "516E7CB5-6ECF-11D6-8FF8-00022D09712B" + << "516E7CB6-6ECF-11D6-8FF8-00022D09712B" + << "516E7CB8-6ECF-11D6-8FF8-00022D09712B" + << "516E7CBA-6ECF-11D6-8FF8-00022D09712B" + // macOS Darwin + << "48465300-0000-11AA-AA11-00306543ECAC" + << "55465300-0000-11AA-AA11-00306543ECAC" + << "6A898CC3-1DD2-11B2-99A6-080020736631" + << "52414944-0000-11AA-AA11-00306543ECAC" + << "52414944-5F4F-11AA-AA11-00306543ECAC" + << "426F6F74-0000-11AA-AA11-00306543ECAC" + << "4C616265-6C00-11AA-AA11-00306543ECAC" + << "5265636F-7665-11AA-AA11-00306543ECAC" + << "53746F72-6167-11AA-AA11-00306543ECAC" + << "B6FA30DA-92D2-4A9A-96F1-871EC6486200" + << "2E313465-19B9-463F-8126-8A7993773801" + << "FA709C7E-65B1-4593-BFD5-E71D61DE9B02" + << "BBBA6DF5-F46F-4A89-8F59-8765B2727503" + // Solaris illumos + << "6A82CB45-1DD2-11B2-99A6-080020736631" + << "6A85CF4D-1DD2-11B2-99A6-080020736631" + << "6A87C46F-1DD2-11B2-99A6-080020736631" + << "6A8B642B-1DD2-11B2-99A6-080020736631" +// << "6A898CC3-1DD2-11B2-99A6-080020736631" + << "6A8EF2E9-1DD2-11B2-99A6-080020736631" + << "6A90BA39-1DD2-11B2-99A6-080020736631" + << "6A9283A5-1DD2-11B2-99A6-080020736631" + // reserved partition + << "6A945A3B-1DD2-11B2-99A6-080020736631" + << "6A9630D1-1DD2-11B2-99A6-080020736631" + << "6A980767-1DD2-11B2-99A6-080020736631" + << "6A96237F-1DD2-11B2-99A6-080020736631" + << "6A8D2AC7-1DD2-11B2-99A6-080020736631" + // NetBSD + << "49F48D32-B10E-11DC-B99B-0019D1879648" + << "49F48D5A-B10E-11DC-B99B-0019D1879648" + << "49F48D82-B10E-11DC-B99B-0019D1879648" + << "49F48DAA-B10E-11DC-B99B-0019D1879648" + << "2DB519C4-B10F-11DC-B99B-0019D1879648" + << "2DB519EC-B10F-11DC-B99B-0019D1879648" + // ChromeOS + << "FE3A2A5D-4F32-41A7-B725-ACCC3285A309" + << "3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC" + << "2E0A753D-9E48-43B0-8337-B15192CB1B5E" + // HaiKu + << "42465331-3BA3-10F1-802A-4861696B7521" + // MidnightBSD + << "85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7" + << "85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7" + << "85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7" + << "0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7" + << "85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7" + << "85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7" + // Ceph + << "45B0969E-9B03-4F30-B4C6-B4B80CEFF106" + << "45B0969E-9B03-4F30-B4C6-5EC00CEFF106" + << "4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D" + << "4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D" + << "89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE" + << "89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE" + // OpenBSD + << "824CC7A0-36A8-11E3-890A-952519AD3F61" + // QNX + << "CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1" + // Plan 9 + << "C91818F9-8025-47AF-89D2-F030D7000C2C" + // VMware ESX + << "9D275380-40AD-11DB-BF97-000C2911D1B8" + << "AA31E02A-400F-11DB-9590-000C2911D1B8" + << "9198EFFC-31C0-11DB-8F78-000C2911D1B8" + // Android-IA + << "2568845D-2332-4675-BC39-8FA5A4748D15" + << "114EAFFE-1552-4022-B26E-9B053604CF84" + << "49A4D17F-93A3-45C1-A0DE-F50B2EBE2599" + << "4177C722-9E92-4AAB-8644-43502BFD5506" + << "EF32A33B-A409-486C-9141-9FFB711F6266" + << "20AC26BE-20B7-11E3-84C5-6CFDB94711E9" + << "38F428E6-D326-425D-9140-6E0EA133647C" + << "A893EF21-E428-470A-9E55-0668FD91A2D9" + << "DC76DDA9-5AC1-491C-AF42-A82591580C0D" + << "EBC597D0-2053-4B15-8B64-E0AAC75F4DB1" + << "8F68CC74-C5E5-48DA-BE91-A0C8C15E9C80" + << "767941D0-2085-11E3-AD3B-6CFDB94711E9" + << "AC6D7924-EB71-4DF8-B48D-E267B27148FF" + // Open Network Install Environment (ONIE) + << "7412F7D5-A156-4B13-81DC-867174929325" + << "D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149" + // PowerPC + << "9E1A2D38-C612-4316-AA26-8B49521E5A8B" + // freedesktop.org OSes (Linux, etc.) + << "BC13C2FF-59E6-4262-A352-B275FD6F7172" + // Atari IOS + << "734E5AFE-F61A-11E6-BC64-92361F002671"; + } + + const QString &guid = this->type(); + + if (guid.isEmpty()) + return InvalidUUID; + + int index = list.indexOf(guid.toLatin1()); + + if (index < 0) + return UnknowUUID; + + return static_cast((index + GUIDTypeBegin)); +} + +QString DBlockPartition::typeDescription(DBlockPartition::Type type) +{ + switch (type) { + case Empty: + return "Empty"; + case FAT12Type: + return "FAT12"; + case XENIX_root: + return "XENIX root"; + case XENIX_usr: + return "XENIX usr"; + case FAT16_Less_32M: + return "FAT16 <32M"; + case Extended: + return "Extended"; + case FAT16Type: + return "FAT16"; + case HPFS_NTFS: + return "HPFS/NTFS"; + case AIX: + return "AIX"; + case AIX_bootable: + return "AIX bootable"; + case OS2_Boot_Manager: + return "OS2 Boot Manager"; + case Win95_FAT32: + return "Win95 FAT32"; + case Win95_FAT32_LBA: + return "Win95 FAT32 (LBA)"; + case Win95_FAT16_LBA: + return "Win95 FAT16 (LBA)"; + case Win95_Extended_LBA: + return "Win95 Ext'd (LBA)"; + case OPUS: + return "OPUS"; + case Hidden_FAT12: + return "Hidden FAT12"; + case Compaq_diagnostics: + return "Compaq diagnostics"; + case Hidden_FAT16_Less_32M: + return "Hidden FAT16 <32M"; + case Hidden_FAT16: + return "Hidden FAT16"; + case Hidden_HPFS_or_NTFS: + return "Hidden HPFS/NTFS"; + case AST_SmartSleep: + return "AST SmartSleep"; + case Hidden_Win95_FAT32: + return "Hidden Win95 FAT32"; + case Hidden_Win95_FAT32_LBA: + return "Hidden Win95 FAT32 (LBA)"; + case Hidden_Win95_FAT16_LBA: + return "Hidden Win95 FAT16"; + case NEC_DOS: + return "NEC DOS"; + case Plan9: + return "Plan 9"; + case PartitionMagic_recovery: + return "PartitionMagic recovery"; + case Venix_80286: + return "Venix 80286"; + case PPC_PReP_Boot: + return "PPC PReP Boot"; + case SFS: + return "SFS"; + case QNX4_dot_x: + return "QNX4.x"; + case QNX4_dot_x_2nd_part: + return "QNX4.x.2nd part"; + case QNX4_dot_x_3rd_part: + return "QNX4.x 3rd part"; + case OnTrack_DM: + return "OnTrack DM"; + case OnTrack_DM6_Aux1: + return "OnTrack DM6 Aux1"; + case CP_M: + return "CP/M"; + case OnTrack_DM6_Aux3: + return "OnTrack DM6 Aux3"; + case OnTrackDM6: + return "OnTrackDM6"; + case EZ_Drive: + return "EZ-Drive"; + case Golden_Bow: + return "Golden Bow"; + case Priam_Edisk: + return "Priam Edisk"; + case SpeedStor: + return "SpeedStor"; + case GNU_HURD_or_SysV: + return "GNU HURD or SysV"; + case Novell_Netware_286: + return "Novell Netware 286"; + case Novell_Netware_386: + return "Novell Netware 386"; + case DiskSecure_Multi_Boot: + return "DiskSecure Multi-Boot"; + case PC_IX: + return "PC/IX"; + case Old_Minix: + return "Old Minix"; + case Minix_old_Linux: + return "Minix / old Linux"; + case Linux_swap: + return "Linux swap"; + case Linux: + return "Linux"; + case OS2_hidden_C_drive: + return "OS/2 hidden C: drive"; + case Linux_extended: + return "Linux extended"; + case NTFS_volume_set_1: + return "NTFS volume set"; + case NTFS_volume_set_2: + return "NTFS volume set"; + case Linux_LVM: + return "Linux LVM"; + case Amoeba: + return "Amoeba"; + case Amoeba_BBT: + return "Amoeba BBT"; + case BSD_OS: + return "BSD/OS"; + case IBM_Thinkpad_hibernation: + return "IBM Thinkpad hibernation"; + case FreeBSD: + return "FreeBSD"; + case OpenBSD: + return "OpenBSD"; + case NeXTSTEP: + return "NeXTSTEP"; + case NetBSD: + return "NetBSD"; + case BSDI_fs: + return "BSDI fs"; + case BSDI_swap: + return "BSDI swap"; + case Boot_Wizard_hidden: + return "Boot Wizard hidden"; + case DRDOS_sec_FAT12: + return "DRDOS/sec (FAT-12)"; + case DRDOS_sec_FAT16_Less_32M: + return "DRDOS/sec (FAT-16 < 32M)"; + case DRDOS_sec_FAT16: + return "DRDOS/sec (FAT-16)"; + case Syrinx: + return "Syrinx"; + case Non_FS_data: + return "Non-FS data"; + case CP_M_CTOS_dot_dot_dot: + return "CP/M / CTOS / ..."; + case Dell_Utility: + return "Dell Utility"; + case BootIt: + return "BootIt"; + case DOS_access: + return "DOS access"; + case DOS_R_O: + return "DOS R/O"; + case SpeedStor_1: + return "SpeedStor"; + case BeOS_fs: + return "BeOS fs"; + case EFI_GPT: + return "EFI GPT"; + case EFI_FAT12_16_32: + return "EFI (FAT-12/16/32)"; + case Linux_PA_RISC_boot: + return "Linux/PA-RISC boot"; + case SpeedStor_2: + return "SpeedStor"; + case SeppdStor_3: + return "SpeedStor"; + case DOS_secondary: + return "DOS secondary"; + case Linux_raid_autodetect: + return "Linux raid autodetect"; + case LANstep: + return "LANstep"; + case BBT: + return "BBT"; + default: + break; + } + + return QString(); +} + +QString DBlockPartition::guidTypeDescription(GUIDType type) +{ + switch ((int)type) { + case Unused_None: + return "Unused entry"; + case MBR_PS_None: + return "MBR partition scheme"; + case EFI_SP_None: + return "EFI System partition"; + case BIOS_BP_None: + return "BIOS boot partition"; + case iFFS_None: + return "Intel Fast Flash (iFFS) partition (for Intel Rapid Start technology)"; + case Sony_BP_None: + return "Sony boot partition"; + case Lenove_BP_None: + return "Lenovo boot partition"; + // Windows + case MSR_Win: + return "Microsoft Reserved Partition (MSR)"; + case BasicData_Win: + return "Basic data partition of Windows"; + case LDM_Win: + return "Logical Disk Manager (LDM) metadata partition of Windows"; + case LDM_DP_Win: + return "Logical Disk Manager data partition of Windows"; + case WRE_Win: + return "Windows Recovery Environment"; + case IBM_GPFS_Win: + return "IBM General Parallel File System (GPFS) partition of Windows"; + case SSP_Win: + return "Storage Spaces partition of Windows"; + // HP-UX + case DP_HPUX: + return "Data partition of HP-UX"; + case SP_HPUX: + return "Service Partition of HP-UX"; + // Linux + case LFD_Linux: + return "Linux filesystem data"; + case RAID_P_Linux: + return "RAID partition of Linux"; + case RP_x86_Linux: + return "Root partition (x86) of Linux"; + case RP_x86_64_Linux: + return "Root partition (x86-64) of Linux"; + case RP_32bit_ARM_Linux: + return "Root partition (32-bit ARM) of Linux"; + case RP_64bit_ARM_Linux: + return "Root partition (64-bit ARM/AArch64) of Linux"; + case SP_Linux: + return "Swap partition of Linux"; + case LVM_P_Linux: + return "Logical Volume Manager (LVM) partition of Linux"; + case Home_P_Linux: + return "/home partition of Linux"; + case Srv_P_Linux: + return "/srv (server data) partition of Linux"; + case Plain_DC_P_Linux: + return "Plain dm-crypt partition of Linux"; + case LUKS_P_Linux: + return "LUKS partition of Linux"; + case Reserved_Linux: + return "Reserved of Linux"; + // FreeBSD + case BP_FreeBSD: + return "Boot partition of FreeBSD"; + case DP_FreeBSD: + return "Data partition of FreeBSD"; + case SP_FreeBSD: + return "Swap partition of FreeBSD"; + case UFS_P_FreeBSD: + return "Unix File System (UFS) partition of FreeBSD"; + case VVM_P_FreeBSD: + return "Vinum volume manager partition of FreeBSD"; + case ZFS_P_FreeBSD: + return "ZFS partition of FreeBSD"; + // macOS Darwin + case HFS_PLUS_P_Mac: + return "Hierarchical File System Plus (HFS+) partition of macOS"; + case UFS_Mac: + return "Apple UFS"; + case ZFS_Mac: + return "ZFS of macOS(Or /usr partition of Solaris illumos)"; + case RAID_P_Mac: + return "Apple RAID partition"; + case RAID_P_Offline_Mac: + return "Apple RAID partition, offline"; + case BP_Mac: + return "Apple Boot partition (Recovery HD)"; + case Label_Mac: + return "Apple Label"; + case TV_RP_Mac: + return "Apple TV Recovery partition"; + case CS_P_Mac: + return "Apple Core Storage (i.e. Lion FileVault) partition"; + case SoftRAID_Status_Mac: + return "SoftRAID_Status of macOS"; + case SoftRAID_Scratch_Mac: + return "SoftRAID_Scratch of macOS"; + case SoftRAID_Volume_Mac: + return "SoftRAID_Volume of macOS"; + case SoftRAID_Cache_Mac: + return "SoftRAID_Cache of macOS"; + // Solaris illumos + case BP_Solaris: + return "Boot partition of Solaris illumos"; + case RP_Solaris: + return "Root partition of Solaris illumos"; + case SP_Solaris: + return "Swap partition of Solaris illumos"; + case Backup_P_Solaris: + return "Backup partition of Solaris illumos"; + case Var_P_Solaris: + return "/var partition of Solaris illumos"; + case Home_P_Solaris: + return "/home partition of Solaris illumos"; + case AS_Solaris: + return "Alternate sector os Solaris illumos"; + case Reserved_Solaris: + return "Reserved partition os Solaris illumos"; + // NetBSD + case SP_NetBSD: + return "Swap partition of NetBSD"; + case FFS_P_NetBSD: + return "FFS partition of NetBSD"; + case LFS_P_NetBSD: + return "LFS partition of NetBSD"; + case RAID_P_NetBSD: + return "RAID partition of NetBSD"; + case CP_NetBSD: + return "Concatenated partition of NetBSD"; + case EP_NetBSD: + return "Encrypted partition of NetBSD"; + // ChromeOS + case Kernel_ChromeOS: + return "ChromeOS kernel"; + case Rootfs_ChromeOS: + return "ChromeOS rootfs"; + case FU_ChromeOS: + return "ChromeOS future use"; + // Haiku + case BFS_Haiku: + return "Haiku BFS"; + // MidnightBSD + case BP_MidnightBSD: + return "Boot partition of MidnightBSD"; + case DP_MidnightBSD: + return "Data partition of MidnightBSD"; + case SP_MidnightBSD: + return "Swap partition of MidnightBSD"; + case UFS_P_MidnightBSD: + return "Unix File System (UFS) partition of MidnightBSD"; + case VVM_P_MidnightBSD: + return "Vinum volume manager partition of MidnightBSD"; + case ZFS_P_MidnightBSD: + return "ZFS partition of MidnightBSD"; + // Ceph + case Journal_Ceph: + return "Ceph Journal"; + case DC_EJ_Ceph: + return "Ceph dm-crypt Encrypted Journal"; + case OSD_Ceph: + return "Ceph OSD"; + case DC_OSD_Ceph: + return "Ceph dm-crypt OSD"; + case DIC_Ceph: + return "Ceph disk in creation"; + case DC_DIC_Ceph: + return "Ceph dm-crypt disk in creation"; + // OpenBSD + case DP_OpenBSD: + return "Data partition of OpenBSD"; + // QNX + case PAFS_QNX: + return "Power-safe (QNX6) file system of QNX"; + // Plan9 + case Partition_Plan9: + return "Plan 9 partition of Plan9"; + // VMware ESX + case Vmkcore_VMware: + return "vmkcore (coredump partition)"; + case VMFS_VMware: + return "VMFS filesystem partition"; + case Reserved_VMware: + return "VMware Reserved"; + // Android-IA + case Bootloader_Android: + return "Android Bootloader"; + case Bottloader2_Android: + return "Android Bootloader2"; + case Boot_Android: + return "Android Boot"; + case Recovery_Android: + return "Android Recovery"; + case Misc_Android: + return "Android Misc"; + case Metadata_Android: + return "Android Metadata"; + case System_Android: + return "Android System"; + case Cache_Android: + return "Android Cache"; + case Data_Android: + return "Android Data"; + case Persistent_Android: + return "Android Persistent"; + case Factory_Android: + return "Android Factory"; + case Fastboot_Android: + return "Android Fastboot"; + case OEM_Android: + return "Android OEM"; + // Open Network Install Environment (ONIE) + case Boot_ONIE: + return "Open Network Install Environment Boot"; + case Config_ONIE: + return "Open Network Install Environment Config"; + // PowerPC + case Boot_PowerPC: + return "PowerPC PReP boot"; + // freedesktop.org OSes (Linux, etc.) + case SBLC_OSes: + return "Shared boot loader configuration of freedesktop.org OSes (Linux, etc.)"; + // Atari TOS + case BD_P_Atari: + return "Basic data partition (GEM, BGM, F32) of Atari TOS"; + case UnknowUUID: + return "Unknow GUID"; + } + + return "Invalid GUID type"; +} + +void DBlockPartition::deletePartition(const QVariantMap &options) +{ + Q_D(DBlockPartition); + + d->dbus->Delete(options); +} + +void DBlockPartition::resize(qulonglong size, const QVariantMap &options) +{ + Q_D(DBlockPartition); + + d->dbus->Resize(size, options); +} + +void DBlockPartition::setFlags(qulonglong flags, const QVariantMap &options) +{ + Q_D(DBlockPartition); + + d->dbus->SetFlags(flags, options); +} + +void DBlockPartition::setName(const QString &name, const QVariantMap &options) +{ + Q_D(DBlockPartition); + + d->dbus->SetName(name, options); +} + +void DBlockPartition::setType(const QString &type, const QVariantMap &options) +{ + Q_D(DBlockPartition); + + d->dbus->SetType(type, options); +} + +void DBlockPartition::setType(DBlockPartition::Type type, const QVariantMap &options) +{ + if (type == Unknow) + return; + + QString type_string = QString::asprintf("0x%.2s", QByteArray::number(type, 16).constData()); + + type_string.replace(" ", "0"); + setType(type_string, options); +} + +/*! + * \class DBlockPartition + * \inmodule dde-file-manager-lib + * + * \brief DBlockPartition class comment goes here + * + * \sa DDiskManager::createBlockPartition + */ + +DBlockPartition::DBlockPartition(const QString &path, QObject *parent) + : DBlockDevice(*new DBlockPartitionPrivate(this), path, parent) +{ + d_func()->dbus = new OrgFreedesktopUDisks2PartitionInterface(UDISKS2_SERVICE, path, QDBusConnection::systemBus(), this); + + connect(this, &DBlockPartition::typeChanged, this, &DBlockPartition::eTypeChanged); + connect(this, &DBlockPartition::UUIDChanged, this, &DBlockPartition::guidTypeChanged); +} diff --git a/src/dblockpartition.h b/src/dblockpartition.h new file mode 100644 index 0000000..43704b6 --- /dev/null +++ b/src/dblockpartition.h @@ -0,0 +1,305 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DBLOCKPARTITION_H +#define DBLOCKPARTITION_H + +#include + +class DBlockPartitionPrivate; +class DBlockPartition : public DBlockDevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(DBlockPartition) + + Q_PROPERTY(qulonglong flags READ flags NOTIFY flagsChanged) + Q_PROPERTY(bool isContained READ isContained NOTIFY isContainedChanged) + Q_PROPERTY(bool isContainer READ isContainer NOTIFY isContainerChanged) + Q_PROPERTY(QString name READ name NOTIFY nameChanged) + Q_PROPERTY(uint number READ number NOTIFY numberChanged) + Q_PROPERTY(qulonglong offset READ offset NOTIFY offsetChanged) + Q_PROPERTY(qulonglong size READ size NOTIFY sizeChanged) + Q_PROPERTY(QString table READ table) + Q_PROPERTY(QString type READ type NOTIFY typeChanged) + // MBR Partition Type + Q_PROPERTY(Type eType READ eType NOTIFY eTypeChanged) + // GPT Partition Type + Q_PROPERTY(GUIDType guidType READ guidType NOTIFY guidTypeChanged) + Q_PROPERTY(QString UUID READ UUID NOTIFY UUIDChanged) + +public: + enum Type { + Empty = 0x0, + FAT12Type = 0x1, + XENIX_root = 0x2, + XENIX_usr = 0x3, + FAT16_Less_32M = 0x4, + Extended = 0x5, + FAT16Type = 0x6, + HPFS_NTFS = 0x7, + AIX = 0x8, + AIX_bootable = 0x9, + OS2_Boot_Manager = 0xa, + Win95_FAT32 = 0xb, + Win95_FAT32_LBA = 0xc, + Win95_FAT16_LBA = 0xe, + Win95_Extended_LBA = 0xf, + OPUS = 0x10, + Hidden_FAT12 = 0x11, + Compaq_diagnostics = 0x12, + Hidden_FAT16_Less_32M = 0x14, + Hidden_FAT16 = 0x16, + Hidden_HPFS_or_NTFS = 0x17, + AST_SmartSleep = 0x18, + Hidden_Win95_FAT32 = 0x1b, + Hidden_Win95_FAT32_LBA = 0x1c, + Hidden_Win95_FAT16_LBA = 0x1e, + NEC_DOS = 0x24, + Plan9 = 0x39, + PartitionMagic_recovery = 0x3c, + Venix_80286 = 0x40, + PPC_PReP_Boot = 0x41, + SFS = 0x42, + QNX4_dot_x = 0x4d, + QNX4_dot_x_2nd_part = 0x4e, + QNX4_dot_x_3rd_part = 0x4f, + OnTrack_DM = 0x50, + OnTrack_DM6_Aux1 = 0x51, + CP_M = 0x52, + OnTrack_DM6_Aux3 = 0x53, + OnTrackDM6 = 0x54, + EZ_Drive = 0x55, + Golden_Bow = 0x56, + Priam_Edisk = 0x5c, + SpeedStor = 0x61, + GNU_HURD_or_SysV = 0x63, + Novell_Netware_286 = 0x64, + Novell_Netware_386 = 0x65, + DiskSecure_Multi_Boot = 0x70, + PC_IX = 0x75, + Old_Minix = 0x80, + Minix_old_Linux = 0x81, + Linux_swap = 0x82, + Linux = 0x83, + OS2_hidden_C_drive = 0x84, + Linux_extended = 0x85, + NTFS_volume_set_1 = 0x86, + NTFS_volume_set_2 = 0x87, + Linux_LVM = 0x8e, + Amoeba = 0x93, + Amoeba_BBT = 0x94, + BSD_OS = 0x9f, + IBM_Thinkpad_hibernation = 0xa0, + FreeBSD = 0xa5, + OpenBSD = 0xa6, + NeXTSTEP = 0xa7, + NetBSD = 0xa8, + BSDI_fs = 0xa9, + BSDI_swap = 0xb7, + Boot_Wizard_hidden = 0xb8, + DRDOS_sec_FAT12 = 0xbb, + DRDOS_sec_FAT16_Less_32M = 0xc1, + DRDOS_sec_FAT16 = 0xc4, + DRDOS_sec_extend = 0xc5, + Syrinx = 0xc6, + Non_FS_data = 0xc7, + Multiuser_DOS_extend = 0xd5, + CP_M_CTOS_dot_dot_dot = 0xda, + Dell_Utility = 0xdb, + BootIt = 0xde, + DOS_access = 0xdf, + DOS_R_O = 0xe1, + SpeedStor_1 = 0xe3, + BeOS_fs = 0xe4, + EFI_GPT = 0xeb, + EFI_FAT12_16_32 = 0xee, + Linux_PA_RISC_boot = 0xef, + SpeedStor_2 = 0xf0, + SeppdStor_3 = 0xf4, + DOS_secondary = 0xf2, + Linux_raid_autodetect = 0xfd, + LANstep = 0xfe, + BBT = 0xff, + Unknow + }; + + Q_ENUM(Type) + + enum GUIDType { + InvalidUUID = 0, + GUIDTypeBegin = 1, + // None + Unused_None = GUIDTypeBegin, + MBR_PS_None = 2, + EFI_SP_None = 3, + BIOS_BP_None = 4, + iFFS_None = 5, + Sony_BP_None = 6, + Lenove_BP_None = 7, + // Windows + MSR_Win = 8, + BasicData_Win = 9, + LDM_Win = 10, + LDM_DP_Win = 11, + WRE_Win = 12, + IBM_GPFS_Win = 13, + SSP_Win = 14, + // HP-UX + DP_HPUX = 15, + SP_HPUX = 16, + // Linux + LFD_Linux = 17, + RAID_P_Linux = 18, + RP_x86_Linux = 19, + RP_x86_64_Linux = 20, + RP_32bit_ARM_Linux = 21, + RP_64bit_ARM_Linux = 22, + SP_Linux = 23, + LVM_P_Linux = 24, + Home_P_Linux = 25, + Srv_P_Linux = 26, + Plain_DC_P_Linux = 27, + LUKS_P_Linux = 28, + Reserved_Linux = 29, + // FreeBSD + BP_FreeBSD = 30, + DP_FreeBSD = 31, + SP_FreeBSD = 32, + UFS_P_FreeBSD = 33, + VVM_P_FreeBSD = 34, + ZFS_P_FreeBSD = 35, + // macOS Darwin + HFS_PLUS_P_Mac = 36, + UFS_Mac = 37, + ZFS_Mac = 38, + RAID_P_Mac = 39, + RAID_P_Offline_Mac = 40, + BP_Mac = 41, + Label_Mac = 42, + TV_RP_Mac = 43, + CS_P_Mac = 44, + SoftRAID_Status_Mac = 45, + SoftRAID_Scratch_Mac = 46, + SoftRAID_Volume_Mac = 47, + SoftRAID_Cache_Mac = 48, + // Solaris illumos + BP_Solaris = 49, + RP_Solaris = 50, + SP_Solaris = 51, + Backup_P_Solaris = 52, + Usr_P_Solaris = ZFS_Mac, + Var_P_Solaris = 53, + Home_P_Solaris = 54, + AS_Solaris = 55, + Reserved_Solaris = 56, + // NetBSD + SP_NetBSD = 57, + FFS_P_NetBSD = 58, + LFS_P_NetBSD = 59, + RAID_P_NetBSD = 60, + CP_NetBSD = 61, + EP_NetBSD = 62, + // ChromeOS + Kernel_ChromeOS = 63, + Rootfs_ChromeOS = 64, + FU_ChromeOS = 65, + // Haiku + BFS_Haiku = 66, + // MidnightBSD + BP_MidnightBSD = 67, + DP_MidnightBSD = 68, + SP_MidnightBSD = 69, + UFS_P_MidnightBSD = 70, + VVM_P_MidnightBSD = 71, + ZFS_P_MidnightBSD = 72, + // Ceph + Journal_Ceph = 73, + DC_EJ_Ceph = 74, + OSD_Ceph = 75, + DC_OSD_Ceph = 76, + DIC_Ceph = 77, + DC_DIC_Ceph = 78, + // OpenBSD + DP_OpenBSD = 79, + // QNX + PAFS_QNX = 80, + // Plan9 + Partition_Plan9 = 81, + // VMware ESX + Vmkcore_VMware = 82, + VMFS_VMware = 83, + Reserved_VMware = 84, + // Android-IA + Bootloader_Android = 85, + Bottloader2_Android = 86, + Boot_Android = 87, + Recovery_Android = 88, + Misc_Android = 89, + Metadata_Android = 90, + System_Android = 91, + Cache_Android = 92, + Data_Android = 93, + Persistent_Android = 94, + Factory_Android = 95, + Fastboot_Android = 96, + OEM_Android = 97, + // Open Network Install Environment (ONIE) + Boot_ONIE = 98, + Config_ONIE = 99, + // PowerPC + Boot_PowerPC = 100, + // freedesktop.org OSes (Linux, etc.) + SBLC_OSes = 101, + // Atari TOS + BD_P_Atari = 102, + GUIDTypeEnd, + UnknowUUID + }; + + Q_ENUM(GUIDType) + + qulonglong flags() const; + bool isContained() const; + bool isContainer() const; + QString name() const; + uint number() const; + qulonglong offset() const; + qulonglong size() const; + QString table() const; + QString type() const; + Type eType() const; + GUIDType guidType() const; + QString UUID() const; + + static QString typeDescription(Type type); + static QString guidTypeDescription(GUIDType type); + +public Q_SLOTS: // METHODS + void deletePartition(const QVariantMap &options); + void resize(qulonglong size, const QVariantMap &options); + void setFlags(qulonglong flags, const QVariantMap &options); + void setName(const QString &name, const QVariantMap &options); + void setType(const QString &type, const QVariantMap &options); + void setType(Type type, const QVariantMap &options); + +Q_SIGNALS: + void flagsChanged(qulonglong flags); + void isContainedChanged(bool isContained); + void isContainerChanged(bool isContainer); + void nameChanged(const QString &name); + void numberChanged(uint number); + void offsetChanged(qulonglong offset); + void sizeChanged(qulonglong size); + void typeChanged(const QString &type); + void eTypeChanged(); + void UUIDChanged(const QString &UUID); + void guidTypeChanged(); + +private: + explicit DBlockPartition(const QString &path, QObject *parent = nullptr); + + friend class DDiskManager; +}; + +#endif // DBLOCKPARTITION_H diff --git a/src/ddiskdevice.cpp b/src/ddiskdevice.cpp new file mode 100644 index 0000000..fcbd7be --- /dev/null +++ b/src/ddiskdevice.cpp @@ -0,0 +1,210 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ddiskdevice.h" +#include "udisks2_interface.h" + +class DDiskDevicePrivate +{ +public: + OrgFreedesktopUDisks2DriveInterface *dbus = nullptr; + QDBusError err; +}; + +DDiskDevice::DDiskDevice(const QString &path, QObject *parent) + : QObject(parent) + , d_ptr(new DDiskDevicePrivate()) +{ + d_ptr->dbus = new OrgFreedesktopUDisks2DriveInterface(UDISKS2_SERVICE, path, QDBusConnection::systemBus(), this); +} + +DDiskDevice::~DDiskDevice() +{ + +} + +QString DDiskDevice::path() const +{ + Q_D(const DDiskDevice); + + return d->dbus->path(); +} + +bool DDiskDevice::canPowerOff() const +{ + return d_ptr->dbus->canPowerOff(); +} + +QVariantMap DDiskDevice::configuration() const +{ + return d_ptr->dbus->configuration(); +} + +QString DDiskDevice::connectionBus() const +{ + return d_ptr->dbus->connectionBus(); +} + +bool DDiskDevice::ejectable() const +{ + return d_ptr->dbus->ejectable(); +} + +QString DDiskDevice::id() const +{ + return d_ptr->dbus->id(); +} + +QString DDiskDevice::media() const +{ + return d_ptr->dbus->media(); +} + +bool DDiskDevice::mediaAvailable() const +{ + return d_ptr->dbus->mediaAvailable(); +} + +bool DDiskDevice::mediaChangeDetected() const +{ + return d_ptr->dbus->mediaChangeDetected(); +} + +QStringList DDiskDevice::mediaCompatibility() const +{ + return d_ptr->dbus->mediaCompatibility(); +} + +bool DDiskDevice::mediaRemovable() const +{ + return d_ptr->dbus->mediaRemovable(); +} + +QString DDiskDevice::model() const +{ + return d_ptr->dbus->model(); +} + +bool DDiskDevice::optical() const +{ + return d_ptr->dbus->optical(); +} + +bool DDiskDevice::opticalBlank() const +{ + return d_ptr->dbus->opticalBlank(); +} + +uint DDiskDevice::opticalNumAudioTracks() const +{ + return d_ptr->dbus->opticalNumAudioTracks(); +} + +uint DDiskDevice::opticalNumDataTracks() const +{ + return d_ptr->dbus->opticalNumDataTracks(); +} + +uint DDiskDevice::opticalNumSessions() const +{ + return d_ptr->dbus->opticalNumSessions(); +} + +uint DDiskDevice::opticalNumTracks() const +{ + return d_ptr->dbus->opticalNumTracks(); +} + +bool DDiskDevice::removable() const +{ + return d_ptr->dbus->removable(); +} + +QString DDiskDevice::revision() const +{ + return d_ptr->dbus->revision(); +} + +int DDiskDevice::rotationRate() const +{ + return d_ptr->dbus->rotationRate(); +} + +QString DDiskDevice::seat() const +{ + return d_ptr->dbus->seat(); +} + +QString DDiskDevice::serial() const +{ + return d_ptr->dbus->serial(); +} + +QString DDiskDevice::siblingId() const +{ + return d_ptr->dbus->siblingId(); +} + +qulonglong DDiskDevice::size() const +{ + return d_ptr->dbus->size(); +} + +QString DDiskDevice::sortKey() const +{ + return d_ptr->dbus->sortKey(); +} + +qulonglong DDiskDevice::timeDetected() const +{ + return d_ptr->dbus->timeDetected(); +} + +qulonglong DDiskDevice::timeMediaDetected() const +{ + return d_ptr->dbus->timeMediaDetected(); +} + +QString DDiskDevice::vendor() const +{ + return d_ptr->dbus->vendor(); +} + +QString DDiskDevice::WWN() const +{ + return d_ptr->dbus->wWN(); +} + +QDBusError DDiskDevice::lastError() const +{ + Q_D(const DDiskDevice); + return d->err; +} + +void DDiskDevice::eject(const QVariantMap &options) +{ + Q_D(DDiskDevice); + + auto r = d_ptr->dbus->Eject(options); + r.waitForFinished(); + d->err = r.error(); +} + +void DDiskDevice::powerOff(const QVariantMap &options) +{ + Q_D(DDiskDevice); + + auto r = d_ptr->dbus->PowerOff(options); + r.waitForFinished(); + d->err = r.error(); +} + +void DDiskDevice::setConfiguration(const QVariantMap &value, const QVariantMap &options) +{ + Q_D(DDiskDevice); + + auto r = d_ptr->dbus->SetConfiguration(value, options); + r.waitForFinished(); + d->err = r.error(); +} diff --git a/src/ddiskdevice.h b/src/ddiskdevice.h new file mode 100644 index 0000000..6559e5e --- /dev/null +++ b/src/ddiskdevice.h @@ -0,0 +1,97 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DDISKDEVICE_H +#define DDISKDEVICE_H + +#include +#include +#include + +class DDiskDevicePrivate; +class DDiskDevice : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(DDiskDevice) + + Q_PROPERTY(QString path READ path CONSTANT FINAL) + Q_PROPERTY(bool canPowerOff READ canPowerOff CONSTANT FINAL) + Q_PROPERTY(QVariantMap configuration READ configuration CONSTANT FINAL) + Q_PROPERTY(QString connectionBus READ connectionBus CONSTANT FINAL) + Q_PROPERTY(bool ejectable READ ejectable CONSTANT FINAL) + Q_PROPERTY(QString id READ id CONSTANT FINAL) + Q_PROPERTY(QString media READ media CONSTANT FINAL) + Q_PROPERTY(bool mediaAvailable READ mediaAvailable CONSTANT FINAL) + Q_PROPERTY(bool mediaChangeDetected READ mediaChangeDetected CONSTANT FINAL) + Q_PROPERTY(QStringList mediaCompatibility READ mediaCompatibility CONSTANT FINAL) + Q_PROPERTY(bool mediaRemovable READ mediaRemovable CONSTANT FINAL) + Q_PROPERTY(QString model READ model CONSTANT FINAL) + Q_PROPERTY(bool optical READ optical CONSTANT FINAL) + Q_PROPERTY(bool opticalBlank READ opticalBlank CONSTANT FINAL) + Q_PROPERTY(uint opticalNumAudioTracks READ opticalNumAudioTracks CONSTANT FINAL) + Q_PROPERTY(uint opticalNumDataTracks READ opticalNumDataTracks CONSTANT FINAL) + Q_PROPERTY(uint opticalNumSessions READ opticalNumSessions CONSTANT FINAL) + Q_PROPERTY(uint opticalNumTracks READ opticalNumTracks CONSTANT FINAL) + Q_PROPERTY(bool removable READ removable CONSTANT FINAL) + Q_PROPERTY(QString revision READ revision CONSTANT FINAL) + Q_PROPERTY(int rotationRate READ rotationRate CONSTANT FINAL) + Q_PROPERTY(QString seat READ seat CONSTANT FINAL) + Q_PROPERTY(QString serial READ serial CONSTANT FINAL) + Q_PROPERTY(QString siblingId READ siblingId CONSTANT FINAL) + Q_PROPERTY(qulonglong size READ size CONSTANT FINAL) + Q_PROPERTY(QString sortKey READ sortKey CONSTANT FINAL) + Q_PROPERTY(qulonglong timeDetected READ timeDetected CONSTANT FINAL) + Q_PROPERTY(qulonglong timeMediaDetected READ timeMediaDetected CONSTANT FINAL) + Q_PROPERTY(QString vendor READ vendor CONSTANT FINAL) + Q_PROPERTY(QString WWN READ WWN CONSTANT FINAL) + +public: + ~DDiskDevice(); + QString path() const; + bool canPowerOff() const; + QVariantMap configuration() const; + QString connectionBus() const; + bool ejectable() const; + QString id() const; + QString media() const; + bool mediaAvailable() const; + bool mediaChangeDetected() const; + QStringList mediaCompatibility() const; + bool mediaRemovable() const; + QString model() const; + bool optical() const; + bool opticalBlank() const; + uint opticalNumAudioTracks() const; + uint opticalNumDataTracks() const; + uint opticalNumSessions() const; + uint opticalNumTracks() const; + bool removable() const; + QString revision() const; + int rotationRate() const; + QString seat() const; + QString serial() const; + QString siblingId() const; + qulonglong size() const; + QString sortKey() const; + qulonglong timeDetected() const; + qulonglong timeMediaDetected() const; + QString vendor() const; + QString WWN() const; + + QDBusError lastError() const; + +public Q_SLOTS: // METHODS + void eject(const QVariantMap &options); + void powerOff(const QVariantMap &options); + void setConfiguration(const QVariantMap &value, const QVariantMap &options); + +private: + explicit DDiskDevice(const QString &path, QObject *parent = nullptr); + + QScopedPointer d_ptr; + + friend class DDiskManager; +}; + +#endif // DDISKDEVICE_H diff --git a/src/ddiskmanager.cpp b/src/ddiskmanager.cpp new file mode 100644 index 0000000..3bbbed0 --- /dev/null +++ b/src/ddiskmanager.cpp @@ -0,0 +1,504 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ddiskmanager.h" +#include "udisks2_dbus_common.h" +#include "udisks2_interface.h" +#include "objectmanager_interface.h" +#include "dblockdevice.h" +#include "dblockpartition.h" +#include "ddiskdevice.h" +#include "dudisksjob.h" + +#include +#include +#include +#include +#include +#include + +const QString ManagerPath = "/org/freedesktop/UDisks2/Manager"; + +static int udisks2VersionCompare(const QString &version) +{ + const QStringList &version_list = UDisks2::version().split("."); + const QStringList &v_v_list = version.split("."); + + for (int i = 0; i < version_list.count(); ++i) { + if (v_v_list.count() <= i) + return -1; + + int number_v = version_list[i].toInt(); + int number_v_v = v_v_list[i].toInt(); + + if (number_v == number_v_v) + continue; + + return number_v_v > number_v ? 1 : -1; + } + + return v_v_list.count() > version_list.count() ? 1 : 0; +} + +// 2.1.7版本的UDisks2在U盘插入时没有drive device added的信号 +// 当收到block device added信号后,通过diskDeviceAddSignalFlag +// 判断此块设备对应的磁盘设备信号是否已发送,未发送时补发信号 +// 风险:如果 diskDeviceAddSignalFlag 的值删除的不及时 +// 会导致设备再插入时不会再有信号发出 +static bool fixUDisks2DiskAddSignal() +{ + static bool fix = udisks2VersionCompare("2.1.7.1") > 0; + + return fix; +} + +class DDiskManagerPrivate +{ +public: + DDiskManagerPrivate(DDiskManager *qq); + + void updateBlockDeviceMountPointsMap(); + + bool watchChanges = false; + QMap blockDeviceMountPointsMap; + QSet diskDeviceAddSignalFlag; + + DDiskManager *q_ptr; +}; + +DDiskManagerPrivate::DDiskManagerPrivate(DDiskManager *qq) + : q_ptr(qq) +{ + +} + +void DDiskManagerPrivate::updateBlockDeviceMountPointsMap() +{ + blockDeviceMountPointsMap.clear(); + + auto om = UDisks2::objectManager(); + const QMap> &objects = om->GetManagedObjects().value(); + auto begin = objects.constBegin(); + + while (begin != objects.constEnd()) { + const QString path = begin.key().path(); + const QMap object = begin.value(); + + ++begin; + + if (!path.startsWith(QStringLiteral("/org/freedesktop/UDisks2/block_devices/"))) { + continue; + } + + const QVariantMap &filesystem = object.value(QStringLiteral(UDISKS2_SERVICE ".Filesystem")); + + if (filesystem.isEmpty()) { + continue; + } + + blockDeviceMountPointsMap[path] = qdbus_cast(filesystem.value("MountPoints")); + } +} + +void DDiskManager::onInterfacesAdded(const QDBusObjectPath &object_path, const QMap &interfaces_and_properties) +{ + const QString &path = object_path.path(); + const QString &path_drive = QStringLiteral("/org/freedesktop/UDisks2/drives/"); + const QString &path_device = QStringLiteral("/org/freedesktop/UDisks2/block_devices/"); + const QString &path_job = QStringLiteral("/org/freedesktop/UDisks2/jobs/"); + + Q_D(DDiskManager); + + if (path.startsWith(path_drive)) { + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Drive"))) { + if (fixUDisks2DiskAddSignal()) { + if (!d->diskDeviceAddSignalFlag.contains(path)) { + d->diskDeviceAddSignalFlag.insert(path); + // 防止flag未清除导致再也收不到此设备的信号 + QTimer::singleShot(1000, this, [d, path] { + d->diskDeviceAddSignalFlag.remove(path); + }); + + Q_EMIT diskDeviceAdded(path); + } + } else { + Q_EMIT diskDeviceAdded(path); + } + } + } else if (path.startsWith(path_device)) { + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Block"))) { + if (fixUDisks2DiskAddSignal()) { + QScopedPointer bd(createBlockDevice(path)); + const QString &drive = bd->drive(); + + if (!d->diskDeviceAddSignalFlag.contains(drive)) { + d->diskDeviceAddSignalFlag.insert(drive); + // 防止flag未清除导致再也收不到此设备的信号 + QTimer::singleShot(1000, this, [d, drive] { + d->diskDeviceAddSignalFlag.remove(drive); + }); + + Q_EMIT diskDeviceAdded(drive); + } + } + + Q_EMIT blockDeviceAdded(path); + } + + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Filesystem"))) { + Q_D(DDiskManager); + + d->blockDeviceMountPointsMap.remove(object_path.path()); + + Q_EMIT fileSystemAdded(path); + } + } else if (path.startsWith(path_job)) { + if (interfaces_and_properties.contains(QStringLiteral(UDISKS2_SERVICE ".Job"))) { + Q_EMIT jobAdded(path); + } + } +} + +void DDiskManager::onInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces) +{ + const QString &path = object_path.path(); + + Q_D(DDiskManager); + + for (const QString &i : interfaces) { + if (i == QStringLiteral(UDISKS2_SERVICE ".Drive")) { + d->diskDeviceAddSignalFlag.remove(path); + + Q_EMIT diskDeviceRemoved(path); + } else if (i == QStringLiteral(UDISKS2_SERVICE ".Filesystem")) { + d->blockDeviceMountPointsMap.remove(object_path.path()); + + Q_EMIT fileSystemRemoved(path); + } else if (i == QStringLiteral(UDISKS2_SERVICE ".Block")) { + Q_EMIT blockDeviceRemoved(path); + } + } +} + +void DDiskManager::onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QDBusMessage &message) +{ + Q_D(DDiskManager); + + const QString &path = message.path(); + + if (changed_properties.contains("Optical")) { + Q_EMIT opticalChanged(path); + } + + if (interface != UDISKS2_SERVICE ".Filesystem") { + return; + } + + if (!changed_properties.contains("MountPoints")) { + return; + } + + const QByteArrayList old_mount_points = d->blockDeviceMountPointsMap.value(path); + const QByteArrayList &new_mount_points = qdbus_cast(changed_properties.value("MountPoints")); + + d->blockDeviceMountPointsMap[path] = new_mount_points; + + Q_EMIT mountPointsChanged(path, old_mount_points, new_mount_points); + + if (old_mount_points.isEmpty()) { + if (!new_mount_points.isEmpty()) { + Q_EMIT mountAdded(path, new_mount_points.first()); + } + } else if (new_mount_points.isEmpty()) { + Q_EMIT mountRemoved(path, old_mount_points.first()); + } +} + +/*! + * \class DDiskManager + * \inmodule dde-file-manager-lib + * + * \brief DDiskManager provide severial ways to manage devices and partitions. + * + * \sa DBlockPartition, DBlockDevice, UDiskDeviceInfo + */ + +DDiskManager::DDiskManager(QObject *parent) + : QObject(parent) + , d_ptr(new DDiskManagerPrivate(this)) +{ + +} + +DDiskManager::~DDiskManager() +{ + +} + +static QStringList getDBusNodeNameList(const QString &service, const QString &path, const QDBusConnection &connection) +{ + QDBusInterface ud2(service, path, "org.freedesktop.DBus.Introspectable", connection); + QDBusReply reply = ud2.call("Introspect"); + QXmlStreamReader xml_parser(reply.value()); + QStringList nodeList; + + while (!xml_parser.atEnd()) { + xml_parser.readNext(); + + if (xml_parser.tokenType() == QXmlStreamReader::StartElement + && xml_parser.name().toString() == "node") { + const QString &name = xml_parser.attributes().value("name").toString(); + + if (!name.isEmpty()) { + nodeList << path + "/" + name; + } + } + } + + return nodeList; +} + +QStringList DDiskManager::blockDevices() const +{ + return getDBusNodeNameList(UDISKS2_SERVICE, "/org/freedesktop/UDisks2/block_devices", QDBusConnection::systemBus()); +} + +QStringList DDiskManager::diskDevices() const +{ + return getDBusNodeNameList(UDISKS2_SERVICE, "/org/freedesktop/UDisks2/drives", QDBusConnection::systemBus()); +} + +QStringList DDiskManager::blockDevices(QVariantMap options) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + + auto reply = udisksmgr.GetBlockDevices(options); + reply.waitForFinished(); + QList resultList = reply.value(); + QStringList dbusPaths; + for (const QDBusObjectPath &singleResult : resultList) { + dbusPaths << singleResult.path(); + } + return dbusPaths; +} + +bool DDiskManager::watchChanges() const +{ + Q_D(const DDiskManager); + + return d->watchChanges; +} + +QString DDiskManager::objectPrintable(const QObject *object) +{ + QString string; + QDebug debug(&string); + const QMetaObject *mo = object->metaObject(); + + debug << object; + + int property_count = mo->propertyCount(); + int base_property_count = QObject::staticMetaObject.propertyCount(); + + debug << "\n"; + + for (int i = base_property_count; i < property_count; ++i) { + const QMetaProperty &mp = mo->property(i); + + debug.nospace() << mp.name() << ": " << mp.read(object); + debug << "\n"; + } + + return string; +} + +DBlockDevice *DDiskManager::createBlockDevice(const QString &path, QObject *parent) +{ + return new DBlockDevice(path, parent); +} + +DBlockDevice *DDiskManager::createBlockDeviceByDevicePath(const QByteArray &path, QObject *parent) const +{ + for (const QString &block : blockDevices()) { + DBlockDevice *device = new DBlockDevice(block, parent); + + if (device->device() == path) { + return device; + } + + device->deleteLater(); + } + + return nullptr; +} + +DBlockPartition *DDiskManager::createBlockPartition(const QString &path, QObject *parent) +{ + return new DBlockPartition(path, parent); +} + +DBlockPartition *DDiskManager::createBlockPartitionByMountPoint(const QByteArray &path, QObject *parent) const +{ + for (const QString &block : blockDevices()) { + DBlockPartition *device = new DBlockPartition(block, parent); + + if (device->mountPoints().contains(path)) { + return device; + } + + device->deleteLater(); + } + + return nullptr; +} + +DBlockPartition *DDiskManager::createBlockPartition(const QStorageInfo &info, QObject *parent) const +{ + return createBlockPartitionByMountPoint(info.rootPath().toLocal8Bit() + '\0', parent); +} + +DDiskDevice *DDiskManager::createDiskDevice(const QString &path, QObject *parent) +{ + return new DDiskDevice(path, parent); +} + +DUDisksJob *DDiskManager::createJob(const QString &path, QObject *parent) +{ + return new DUDisksJob(path, parent); +} + +QStringList DDiskManager::supportedFilesystems() +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + return udisksmgr.supportedFilesystems(); +} + +QStringList DDiskManager::supportedEncryptionTypes() +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + return udisksmgr.supportedEncryptionTypes(); +} + +QStringList DDiskManager::resolveDevice(QVariantMap devspec, QVariantMap options) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + QStringList ret; + auto devices = udisksmgr.ResolveDevice(devspec, options); + devices.waitForFinished(); + if (!devices.isError()) { + for (auto &d : devices.value()) { + ret.push_back(d.path()); + } + } + return ret; +} + +QStringList DDiskManager::resolveDeviceNode(QString devnode, QVariantMap options) +{ + return resolveDevice({{"path", QVariant(devnode)}}, options); +} + +bool DDiskManager::canCheck(const QString &type, QString *requiredUtil) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + auto r = udisksmgr.CanCheck(type); + r.waitForFinished(); + if (r.isError()) { + return false; + } + if (requiredUtil) { + *requiredUtil = r.value().second; + } + return r.value().first; +} + +bool DDiskManager::canFormat(const QString &type, QString *requiredUtil) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + auto r = udisksmgr.CanFormat(type); + r.waitForFinished(); + if (r.isError()) { + return false; + } + if (requiredUtil) { + *requiredUtil = r.value().second; + } + return r.value().first; +} + +bool DDiskManager::canRepair(const QString &type, QString *requiredUtil) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + auto r = udisksmgr.CanRepair(type); + r.waitForFinished(); + if (r.isError()) { + return false; + } + if (requiredUtil) { + *requiredUtil = r.value().second; + } + return r.value().first; +} + +bool DDiskManager::canResize(const QString &type, QString *requiredUtil) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + auto r = udisksmgr.CanRepair(type); + r.waitForFinished(); + if (r.isError()) { + return false; + } + if (requiredUtil) { + *requiredUtil = r.value().second; + } + return r.value().first; +} + +QString DDiskManager::loopSetup(int fd, QVariantMap options) +{ + OrgFreedesktopUDisks2ManagerInterface udisksmgr(UDISKS2_SERVICE, ManagerPath, QDBusConnection::systemBus()); + QDBusUnixFileDescriptor dbusfd; + dbusfd.setFileDescriptor(fd); + auto r = udisksmgr.LoopSetup(dbusfd, options); + r.waitForFinished(); + return r.value().path(); +} + +QDBusError DDiskManager::lastError() +{ + return QDBusConnection::systemBus().lastError(); +} + +void DDiskManager::setWatchChanges(bool watchChanges) +{ + Q_D(DDiskManager); + + if (d->watchChanges == watchChanges) + return; + + OrgFreedesktopDBusObjectManagerInterface *object_manager = UDisks2::objectManager(); + auto sc = QDBusConnection::systemBus(); + + if (watchChanges) { + connect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, + this, &DDiskManager::onInterfacesAdded); + connect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &DDiskManager::onInterfacesRemoved); + + d->updateBlockDeviceMountPointsMap(); + + sc.connect(UDISKS2_SERVICE, QString(), "org.freedesktop.DBus.Properties", "PropertiesChanged", + this, SLOT(onPropertiesChanged(const QString &, const QVariantMap &, const QDBusMessage&))); + } else { + disconnect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, + this, &DDiskManager::onInterfacesAdded); + disconnect(object_manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &DDiskManager::onInterfacesRemoved); + + d->blockDeviceMountPointsMap.clear(); + + sc.disconnect(UDISKS2_SERVICE, QString(), "org.freedesktop.DBus.Properties", "PropertiesChanged", + this, SLOT(onPropertiesChanged(const QString &, const QVariantMap &, const QDBusMessage&))); + } +} diff --git a/src/ddiskmanager.h b/src/ddiskmanager.h new file mode 100644 index 0000000..dd57acd --- /dev/null +++ b/src/ddiskmanager.h @@ -0,0 +1,88 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DDISKMANAGER_H +#define DDISKMANAGER_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QDBusObjectPath; +class QStorageInfo; +QT_END_NAMESPACE + +class DBlockDevice; +class DBlockPartition; +class DDiskDevice; +class DUDisksJob; +class DDiskManagerPrivate; +class DDiskManager : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(DDiskManager) + + Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges) + +public: + explicit DDiskManager(QObject *parent = nullptr); + ~DDiskManager(); + + Q_DECL_DEPRECATED_X("Use the static variant instead") QStringList blockDevices() const; + QStringList diskDevices() const; + + static QStringList blockDevices(QVariantMap options); + + bool watchChanges() const; + + static QString objectPrintable(const QObject *object); + static DBlockDevice *createBlockDevice(const QString &path, QObject *parent = nullptr); + // device 路径以 '\0' 结尾 + DBlockDevice *createBlockDeviceByDevicePath(const QByteArray &path, QObject *parent = nullptr) const; + static DBlockPartition *createBlockPartition(const QString &path, QObject *parent = nullptr); + // 挂载点以 '\0' 结尾 + DBlockPartition *createBlockPartitionByMountPoint(const QByteArray &path, QObject *parent = nullptr) const; + DBlockPartition *createBlockPartition(const QStorageInfo &info, QObject *parent = nullptr) const; + static DDiskDevice *createDiskDevice(const QString &path, QObject *parent = nullptr); + static DUDisksJob *createJob(const QString &path, QObject *parent = nullptr); + + static QStringList supportedFilesystems(); + static QStringList supportedEncryptionTypes(); + static QStringList resolveDevice(QVariantMap devspec, QVariantMap options); + static QStringList resolveDeviceNode(QString devnode, QVariantMap options); + static bool canCheck(const QString &type, QString *requiredUtil = nullptr); + static bool canFormat(const QString &type, QString *requiredUtil = nullptr); + static bool canRepair(const QString &type, QString *requiredUtil = nullptr); + static bool canResize(const QString &type, QString *requiredUtil = nullptr); + static QString loopSetup(int fd, QVariantMap options); + + static QDBusError lastError(); + +public Q_SLOTS: + void setWatchChanges(bool watchChanges); + +Q_SIGNALS: + void blockDeviceAdded(const QString &path); + void blockDeviceRemoved(const QString &path); + void diskDeviceAdded(const QString &path); + void diskDeviceRemoved(const QString &path); + void fileSystemAdded(const QString &blockDevicePath); + void fileSystemRemoved(const QString &blockDevicePath); + void mountAdded(const QString &blockDevicePath, const QByteArray &mountPoint); + void mountRemoved(const QString &blockDevicePath, const QByteArray &mountPoint); + void mountPointsChanged(const QString &blockDevicePath, const QByteArrayList &oldMountPoints, const QByteArrayList &newMountPoints); + void jobAdded(const QString &jobPath); + void opticalChanged(const QString &path); + +private: + QScopedPointer d_ptr; + +private Q_SLOTS: + void onInterfacesAdded(const QDBusObjectPath &, const QMap &); + void onInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces); + void onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QDBusMessage &message); +}; + +#endif // DDISKMANAGER_H diff --git a/src/dudisksjob.cpp b/src/dudisksjob.cpp new file mode 100644 index 0000000..b0deb1c --- /dev/null +++ b/src/dudisksjob.cpp @@ -0,0 +1,139 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dudisksjob.h" +#include "udisks2_interface.h" + +#include + +class DUDisksJobPrivate +{ + DUDisksJobPrivate(DUDisksJob *) + { + + } + DUDisksJob *q_ptr; + OrgFreedesktopUDisks2JobInterface *dbusif; + + Q_DECLARE_PUBLIC(DUDisksJob) +}; + +DUDisksJob::~DUDisksJob() +{ +} + +QString DUDisksJob::path() const +{ + Q_D(const DUDisksJob); + return d->dbusif->path(); +} + +QStringList DUDisksJob::objects() const +{ + Q_D(const DUDisksJob); + QStringList ret; + for (auto &o : d->dbusif->objects()) { + ret.push_back(o.path()); + } + return ret; +} + +bool DUDisksJob::cancelable() const +{ + Q_D(const DUDisksJob); + return d->dbusif->cancelable(); +} + +bool DUDisksJob::progressValid() const +{ + Q_D(const DUDisksJob); + return d->dbusif->progressValid(); +} + +double DUDisksJob::progress() const +{ + Q_D(const DUDisksJob); + return d->dbusif->progress(); +} + +QString DUDisksJob::operation() const +{ + Q_D(const DUDisksJob); + return d->dbusif->operation(); +} + +quint32 DUDisksJob::startedByUid() const +{ + Q_D(const DUDisksJob); + return d->dbusif->startedByUID(); +} + +quint64 DUDisksJob::bytes() const +{ + Q_D(const DUDisksJob); + return d->dbusif->bytes(); +} + +quint64 DUDisksJob::expectedEndTime() const +{ + Q_D(const DUDisksJob); + return d->dbusif->expectedEndTime(); +} + +quint64 DUDisksJob::rate() const +{ + Q_D(const DUDisksJob); + return d->dbusif->rate(); +} + +quint64 DUDisksJob::startTime() const +{ + Q_D(const DUDisksJob); + return d->dbusif->startTime(); +} + +void DUDisksJob::cancel(const QVariantMap &options) +{ + Q_D(DUDisksJob); + d->dbusif->Cancel(options).waitForFinished(); +} + +DUDisksJob::DUDisksJob(QString path, QObject *parent) + : QObject(parent) + , d_ptr(new DUDisksJobPrivate(this)) +{ + Q_D(DUDisksJob); + d->dbusif = new OrgFreedesktopUDisks2JobInterface(UDISKS2_SERVICE, path, QDBusConnection::systemBus()); + QDBusConnection::systemBus().connect(UDISKS2_SERVICE, d->dbusif->path(), "org.freedesktop.DBus.Properties", + "PropertiesChanged", this, SLOT(onPropertiesChanged(const QString &, const QVariantMap &))); + connect(d->dbusif, &OrgFreedesktopUDisks2JobInterface::Completed, this, &DUDisksJob::completed); +} + +void DUDisksJob::onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties) +{ + Q_UNUSED(interface) + + auto begin = changed_properties.begin(); + + for (; begin != changed_properties.constEnd(); ++begin) { + QString property_name = begin.key(); + + int pindex = this->metaObject()->indexOfProperty(property_name.toLatin1().constData()); + + if (pindex < 0) { + property_name[0] = property_name.at(0).toLower(); + pindex = this->metaObject()->indexOfProperty(property_name.toLatin1().constData()); + } + + if (pindex < 0) + continue; + + const QMetaProperty &mp = this->metaObject()->property(pindex); + + if (!mp.hasNotifySignal()) + continue; + + mp.notifySignal().invoke(this, QGenericArgument(begin.value().typeName(), begin.value().constData())); + } +} diff --git a/src/dudisksjob.h b/src/dudisksjob.h new file mode 100644 index 0000000..917f902 --- /dev/null +++ b/src/dudisksjob.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DUDISKSJOB_H +#define DUDISKSJOB_H + +#include + +class DUDisksJobPrivate; +class DUDisksJob : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(DUDisksJob) + + Q_PROPERTY(QString path READ path CONSTANT FINAL) + Q_PROPERTY(QStringList objects READ objects CONSTANT FINAL) + Q_PROPERTY(bool cancelable READ cancelable CONSTANT FINAL) + Q_PROPERTY(bool progressValid READ progressValid CONSTANT FINAL) + Q_PROPERTY(double progress READ progress NOTIFY progressChanged FINAL) + Q_PROPERTY(QString operation READ operation CONSTANT FINAL) + Q_PROPERTY(quint32 startedByUid READ startedByUid CONSTANT FINAL) + Q_PROPERTY(quint64 bytes READ bytes CONSTANT FINAL) + Q_PROPERTY(quint64 expectedEndTime READ expectedEndTime NOTIFY expectedEndTimeChanged FINAL) + Q_PROPERTY(quint64 rate READ rate NOTIFY rateChanged FINAL) + Q_PROPERTY(quint64 startTime READ startTime CONSTANT FINAL) + +public: + ~DUDisksJob(); + QString path() const; + QStringList objects() const; + bool cancelable() const; + bool progressValid() const; + double progress() const; + QString operation() const; + quint32 startedByUid() const; + quint64 bytes() const; + quint64 expectedEndTime() const; + quint64 rate() const; + quint64 startTime() const; + +public Q_SLOTS: + void cancel(const QVariantMap &options); + +Q_SIGNALS: + void completed(bool success, QString message); + void progressChanged(double progress); + void rateChanged(quint64 rate); + void expectedEndTimeChanged(quint64 expectedEndTime); + +private: + QScopedPointer d_ptr; + + explicit DUDisksJob(QString path, QObject *parent = nullptr); + +private Q_SLOTS: + void onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties); + + friend class DDiskManager; +}; +#endif diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt new file mode 100644 index 0000000..f3c5914 --- /dev/null +++ b/src/modules/CMakeLists.txt @@ -0,0 +1,15 @@ +# CMakeLists for UDisks2-QT5 lib extra modules + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/udisks2qt5-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/udisks2qt5-config.cmake + @ONLY +) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/udisks2qt5-config-version.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/udisks2qt5-config-version.cmake + @ONLY +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/udisks2qt5-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/udisks2qt5-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/udisks2-qt5/ +) diff --git a/src/modules/udisks2qt5-config-version.cmake.in b/src/modules/udisks2qt5-config-version.cmake.in new file mode 100644 index 0000000..78200a1 --- /dev/null +++ b/src/modules/udisks2qt5-config-version.cmake.in @@ -0,0 +1,12 @@ +SET(PACKAGE_VERSION @VERSION@) +IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) + SET(PACKAGE_VERSION_EXACT "true") +ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) +IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + SET(PACKAGE_VERSION_COMPATIBLE "true") +ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + SET(PACKAGE_VERSION_UNSUITABLE "true") +ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) +IF (PACKAGE_VERSION_UNSUITABLE) + MESSAGE("VERSION CHECK FAILED FOR ${PACKAGE_FIND_NAME}. WANTED ${PACKAGE_FIND_VERSION}, HAVE ${PACKAGE_VERSION}") +ENDIF(PACKAGE_VERSION_UNSUITABLE) diff --git a/src/modules/udisks2qt5-config.cmake.in b/src/modules/udisks2qt5-config.cmake.in new file mode 100644 index 0000000..3009c47 --- /dev/null +++ b/src/modules/udisks2qt5-config.cmake.in @@ -0,0 +1,11 @@ +# - Config information for UDisks2-Qt5 +# This file defines: +# +# UDisks2Qt5_INCLUDE_DIR - the UDisks2Qt5 include directory +# UDisks2Qt5_LIBRARIES - Link these to use UDisks2-Qt5 + +SET(prefix "@CMAKE_INSTALL_PREFIX@") +SET(exec_prefix "@CMAKE_INSTALL_PREFIX@") +SET(UDisks2Qt5_LIBRARIES "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/libudisks2-qt5.so" CACHE FILEPATH "Libraries for UDisks2-Qt5") +SET(UDisks2Qt5_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/udisks2-qt5/" CACHE PATH "Include path for UDisks2-Qt5") +SET(UDisks2Qt5_FOUND "TRUE") diff --git a/src/org.freedesktop.UDisks2.ObjectManager.xml b/src/org.freedesktop.UDisks2.ObjectManager.xml new file mode 100644 index 0000000..a1bc847 --- /dev/null +++ b/src/org.freedesktop.UDisks2.ObjectManager.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org.freedesktop.UDisks2.xml b/src/org.freedesktop.UDisks2.xml new file mode 100644 index 0000000..b53e0c3 --- /dev/null +++ b/src/org.freedesktop.UDisks2.xml @@ -0,0 +1,2769 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/private/dblockdevice_p.h b/src/private/dblockdevice_p.h new file mode 100644 index 0000000..48b032e --- /dev/null +++ b/src/private/dblockdevice_p.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DBLOCKDEVICE_P_H +#define DBLOCKDEVICE_P_H + +#include "dblockdevice.h" + +QT_BEGIN_NAMESPACE +class QDBusObjectPath; +QT_END_NAMESPACE + +class OrgFreedesktopUDisks2BlockInterface; + +class DBlockDevicePrivate +{ +public: + explicit DBlockDevicePrivate(DBlockDevice *qq); + + OrgFreedesktopUDisks2BlockInterface *dbus; + bool watchChanges = false; + DBlockDevice *q_ptr; + QDBusError err; + + void _q_onInterfacesAdded(const QDBusObjectPath &object_path, const QMap &interfaces_and_properties); + void _q_onInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces); + void _q_onPropertiesChanged(const QString &interface, const QVariantMap &changed_properties); + + Q_DECLARE_PUBLIC(DBlockDevice) +}; + +#endif // DBLOCKDEVICE_P_H diff --git a/src/private/private.pri b/src/private/private.pri new file mode 100644 index 0000000..d13cb40 --- /dev/null +++ b/src/private/private.pri @@ -0,0 +1,2 @@ +HEADERS += \ + $$PWD/dblockdevice_p.h diff --git a/src/udisks2-qt5.pc.in b/src/udisks2-qt5.pc.in new file mode 100644 index 0000000..7e1d369 --- /dev/null +++ b/src/udisks2-qt5.pc.in @@ -0,0 +1,11 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include/udisks2-qt5 + + +Name: udisks2-qt5 +Description: UDisks2 Library with Qt5 +Version: 0.0.1 +Libs: -ludisks2-qt5 +Cflags: -I${includedir} diff --git a/src/udisks2_dbus_common.cpp b/src/udisks2_dbus_common.cpp new file mode 100644 index 0000000..1130651 --- /dev/null +++ b/src/udisks2_dbus_common.cpp @@ -0,0 +1,126 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "udisks2_dbus_common.h" +#include "objectmanager_interface.h" +#include "udisks2_interface.h" + +#include +#include +#include +#include +#include + +namespace UDisks2 { +Q_GLOBAL_STATIC_WITH_ARGS(OrgFreedesktopDBusObjectManagerInterface, omGlobal, (UDISKS2_SERVICE, "/org/freedesktop/UDisks2", QDBusConnection::systemBus())) +Q_GLOBAL_STATIC_WITH_ARGS(OrgFreedesktopUDisks2ManagerInterface, umGlobal, (UDISKS2_SERVICE, "/org/freedesktop/UDisks2/Manager", QDBusConnection::systemBus())) + +bool interfaceExists(const QString &path, const QString &interface) +{ + QDBusInterface ud2(UDISKS2_SERVICE, path, "org.freedesktop.DBus.Introspectable", QDBusConnection::systemBus()); + QDBusReply reply = ud2.call("Introspect"); + QXmlStreamReader xml_parser(reply.value()); + + while (!xml_parser.atEnd()) { + xml_parser.readNext(); + + if (xml_parser.tokenType() == QXmlStreamReader::StartElement + && xml_parser.name().toString() == "interface") { + const QString &name = xml_parser.attributes().value("name").toString(); + + if (name == interface) { + return true; + } + } + } + + return false; +} + +OrgFreedesktopDBusObjectManagerInterface *objectManager() +{ + if (!omGlobal.exists()) { + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>>(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>>(); + + QMetaType::registerDebugStreamOperator>>(); + } + + return omGlobal; +} + +QString version() +{ + return umGlobal->version(); +} + +QStringList supportedFilesystems() +{ + return umGlobal->supportedFilesystems(); +} + +} + +QDBusArgument &operator<<(QDBusArgument &argument, const UDisks2::SmartAttribute &mystruct) +{ + argument.beginStructure(); + argument << mystruct.id + << mystruct.name + << mystruct.flags + << mystruct.value + << mystruct.worst + << mystruct.threshold + << mystruct.pretty + << mystruct.pretty_unit + << mystruct.expansion; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, UDisks2::SmartAttribute &mystruct) +{ + argument.beginStructure(); + argument >> mystruct.id + >> mystruct.name + >> mystruct.flags + >> mystruct.value + >> mystruct.worst + >> mystruct.threshold + >> mystruct.pretty + >> mystruct.pretty_unit + >> mystruct.expansion; + argument.endStructure(); + + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const UDisks2::ActiveDeviceInfo &mystruct) +{ + argument.beginStructure(); + argument << mystruct.block + << mystruct.slot + << mystruct.state + << mystruct.num_read_errors + << mystruct.expansion; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, UDisks2::ActiveDeviceInfo &mystruct) +{ + argument.beginStructure(); + argument >> mystruct.block + >> mystruct.slot + >> mystruct.state + >> mystruct.num_read_errors + >> mystruct.expansion; + argument.endStructure(); + + return argument; +} diff --git a/src/udisks2_dbus_common.h b/src/udisks2_dbus_common.h new file mode 100644 index 0000000..ebb92ea --- /dev/null +++ b/src/udisks2_dbus_common.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef UDISK2_DBUS_COMMON_H +#define UDISK2_DBUS_COMMON_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QDBusArgument; +QT_END_NAMESPACE + +class OrgFreedesktopDBusObjectManagerInterface; + +#define UDISKS2_SERVICE "org.freedesktop.UDisks2" + +namespace UDisks2 { +/// by: http://storaged.org/doc/udisks2-api/2.7.2/gdbus-org.freedesktop.UDisks2.Drive.Ata.html#gdbus-method-org-freedesktop-UDisks2-Drive-Ata.SmartGetAttributes +struct SmartAttribute +{ + uchar id; // Attribute Identifier + QString name; // The identifier as a string. + quint16 flags; // 16-bit attribute flags (bit 0 is prefail/oldage, bit 1 is online/offline). + qint32 value; // The current value or -1 if unknown. + qint32 worst; // The worst value of -1 if unknown. + qint32 threshold; // The threshold or -1 if unknown. + qint64 pretty; // An interpretation of the value - must be ignored if pretty_unit is 0. + qint32 pretty_unit; // The unit of the pretty value - the following units are known: 0 (unknown), 1 (dimensionless), 2 (milliseconds), 3 (sectors), 4 (millikelvin). + QVariantMap expansion; // Currently unused. Intended for future expansion. +}; + +/// by: http://storaged.org/doc/udisks2-api/2.7.2/gdbus-org.freedesktop.UDisks2.MDRaid.html#gdbus-property-org-freedesktop-UDisks2-MDRaid.ActiveDevices +struct ActiveDeviceInfo +{ + QDBusObjectPath block; // The object path for the underlying block device (guaranteed to implement the org.freedesktop.UDisks2.Block interface) + qint32 slot; // -1 if the device is not currently part of the array (ie. spare or faulty), otherwise the slot number the device currently fills (between 0 and "NumDevices") + QStringList state; // The state of the device - known elements include faulty, in_sync, write_mostly, blocked and spare + quint64 num_read_errors; // An ongoing count of read errors that have been detected on this device but have not caused the device to be evicted from the array + QVariantMap expansion; // Currently unused. Intended for future expansion. +}; + +/// by: http://storaged.org/doc/udisks2-api/2.7.2/udisks-std-options.html +// default options +// Many method calls take a parameter of type 'a{sv}' that is normally called options. The following table lists well-known options: +// "auth.no_user_interaction" bool // If set to TRUE, then no user interaction will happen when checking if the method call is authorized. + +bool interfaceExists(const QString &path, const QString &interface); +OrgFreedesktopDBusObjectManagerInterface *objectManager(); +QStringList supportedFilesystems(); +QString version(); +} + +Q_DECLARE_METATYPE(UDisks2::SmartAttribute) + +QDBusArgument &operator<<(QDBusArgument &argument, const UDisks2::SmartAttribute &mystruct); +const QDBusArgument &operator>>(const QDBusArgument &argument, UDisks2::SmartAttribute &mystruct); + +Q_DECLARE_METATYPE(UDisks2::ActiveDeviceInfo) + +QDBusArgument &operator<<(QDBusArgument &argument, const UDisks2::ActiveDeviceInfo &mystruct); +const QDBusArgument &operator>>(const QDBusArgument &argument, UDisks2::ActiveDeviceInfo &mystruct); + +#endif // UDISK2_DBUS_COMMON_H