8#include "udisksdevice.h"
9#include "udisks_debug.h"
10#include "udisksblock.h"
11#include "udisksdevicebackend.h"
12#include "udisksdeviceinterface.h"
13#include "udisksgenericinterface.h"
14#include "udisksopticaldisc.h"
15#include "udisksopticaldrive.h"
16#include "udisksstorageaccess.h"
17#include "udisksstoragevolume.h"
19#include <solid/device.h>
20#include <solid/genericinterface.h>
23#include <QMimeDatabase>
25using namespace Solid::Backends::UDisks2;
28static QString formatByteSize(
double size)
40 if (size >= 1073741824.0) {
49 else if (size >= 1048576.0) {
54 else if (size >= 1024.0) {
69static QString concatBlockDeviceDescription(
const QString &name, qulonglong size,
bool isExternal)
73 const QString sizeStr = formatByteSize(size);
75 description =
QObject::tr(
"%1 External Drive (%2)",
"%1 is the size, %2 is the block device name e.g. sda, sda1").
arg(sizeStr, name);
77 description =
QObject::tr(
"%1 Internal Drive (%2)",
"%1 is the size, %2 is the block device name e.g. sda, sda1").
arg(sizeStr, name);
81 description =
QObject::tr(
"External Drive (%1)",
"%1 is the block device name e.g. sda, sda1").
arg(name);
83 description =
QObject::tr(
"Internal Drive (%1)",
"%1 is the block device name e.g. sda, sda1").
arg(name);
90Device::Device(
const QString &udi)
91 : Solid::Ifaces::Device()
92 , m_backend(DeviceBackend::backendForUDI(udi))
95 connect(m_backend, &DeviceBackend::changed,
this, &Device::changed);
96 connect(m_backend, &DeviceBackend::propertyChanged,
this, &Device::propertyChanged);
98 qCDebug(UDISKS2) <<
"Created invalid Device for udi" << udi;
109 return m_backend->udi();
118 return m_backend->prop(key);
124bool Device::propertyExists(
const QString &key)
const
127 return m_backend->propertyExists(key);
133QVariantMap Device::allProperties()
const
136 return m_backend->allProperties();
139 return QVariantMap();
142bool Device::hasInterface(
const QString &name)
const
145 return m_backend->interfaces().contains(name);
154 return m_backend->interfaces();
160void Device::invalidateCache()
163 return m_backend->invalidateProperties();
169 if (!queryDeviceInterface(type)) {
173 DeviceInterface *iface =
nullptr;
175 case Solid::DeviceInterface::GenericInterface:
176 iface =
new GenericInterface(
this);
178 case Solid::DeviceInterface::Block:
179 iface =
new Block(
this);
181 case Solid::DeviceInterface::StorageAccess:
182 iface =
new StorageAccess(
this);
184 case Solid::DeviceInterface::StorageDrive:
185 iface =
new StorageDrive(
this);
187 case Solid::DeviceInterface::OpticalDrive:
188 iface =
new OpticalDrive(
this);
190 case Solid::DeviceInterface::StorageVolume:
191 iface =
new StorageVolume(
this);
193 case Solid::DeviceInterface::OpticalDisc:
194 iface =
new OpticalDisc(
this);
205 case Solid::DeviceInterface::GenericInterface:
207 case Solid::DeviceInterface::Block:
208 return isBlock() || isDrive();
209 case Solid::DeviceInterface::StorageVolume:
210 return isStorageVolume();
211 case Solid::DeviceInterface::StorageAccess:
212 return isStorageAccess();
213 case Solid::DeviceInterface::StorageDrive:
215 case Solid::DeviceInterface::OpticalDrive:
216 return isOpticalDrive();
217 case Solid::DeviceInterface::OpticalDisc:
218 return isOpticalDisc();
226 if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess)) {
227 const UDisks2::StorageAccess accessIface(
const_cast<Device *
>(
this));
228 if (accessIface.isAccessible()) {
229 if (isEncryptedContainer()) {
230 return {QStringLiteral(
"emblem-encrypted-unlocked")};
233 if (isEncryptedContainer()) {
234 return {QStringLiteral(
"emblem-encrypted-locked")};
236 return {QStringLiteral(
"emblem-unmounted")};
244QString Device::description()
const
252 return loopDescription();
253 }
else if (isSwap()) {
254 return tr(
"Swap Space");
255 }
else if (queryDeviceInterface(Solid::DeviceInterface::StorageDrive)) {
256 return storageDescription();
257 }
else if (queryDeviceInterface(Solid::DeviceInterface::StorageVolume)) {
258 return volumeDescription();
264QString Device::loopDescription()
const
271 const QString backingFile = prop(QStringLiteral(
"BackingFile")).
toString();
276 return tr(
"Loop Device");
279QString Device::storageDescription()
const
282 const UDisks2::StorageDrive storageDrive(
const_cast<Device *
>(
this));
284 const bool drive_is_hotpluggable = storageDrive.isHotpluggable();
286 if (drive_type == Solid::StorageDrive::CdromDrive) {
287 const UDisks2::OpticalDrive opticalDrive(
const_cast<Device *
>(
this));
292 first =
tr(
"CD-ROM",
"First item of %1%2 Drive sentence");
293 if (mediumTypes & Solid::OpticalDrive::Cdr) {
294 first =
tr(
"CD-R",
"First item of %1%2 Drive sentence");
296 if (mediumTypes & Solid::OpticalDrive::Cdrw) {
297 first =
tr(
"CD-RW",
"First item of %1%2 Drive sentence");
300 if (mediumTypes & Solid::OpticalDrive::Dvd) {
301 second =
tr(
"/DVD-ROM",
"Second item of %1%2 Drive sentence");
303 if (mediumTypes & Solid::OpticalDrive::Dvdplusr) {
304 second =
tr(
"/DVD+R",
"Second item of %1%2 Drive sentence");
306 if (mediumTypes & Solid::OpticalDrive::Dvdplusrw) {
307 second =
tr(
"/DVD+RW",
"Second item of %1%2 Drive sentence");
309 if (mediumTypes & Solid::OpticalDrive::Dvdr) {
310 second =
tr(
"/DVD-R",
"Second item of %1%2 Drive sentence");
312 if (mediumTypes & Solid::OpticalDrive::Dvdrw) {
313 second =
tr(
"/DVD-RW",
"Second item of %1%2 Drive sentence");
315 if (mediumTypes & Solid::OpticalDrive::Dvdram) {
316 second =
tr(
"/DVD-RAM",
"Second item of %1%2 Drive sentence");
318 if ((mediumTypes & Solid::OpticalDrive::Dvdr) && (mediumTypes & Solid::OpticalDrive::Dvdplusr)) {
319 if (mediumTypes & Solid::OpticalDrive::Dvdplusdl) {
320 second =
tr(
"/DVD±R DL",
"Second item of %1%2 Drive sentence");
322 second =
tr(
"/DVD±R",
"Second item of %1%2 Drive sentence");
325 if ((mediumTypes & Solid::OpticalDrive::Dvdrw) && (mediumTypes & Solid::OpticalDrive::Dvdplusrw)) {
326 if ((mediumTypes & Solid::OpticalDrive::Dvdplusdl) || (mediumTypes & Solid::OpticalDrive::Dvdplusdlrw)) {
327 second =
tr(
"/DVD±RW DL",
"Second item of %1%2 Drive sentence");
329 second =
tr(
"/DVD±RW",
"Second item of %1%2 Drive sentence");
332 if (mediumTypes & Solid::OpticalDrive::Bd) {
333 second =
tr(
"/BD-ROM",
"Second item of %1%2 Drive sentence");
335 if (mediumTypes & Solid::OpticalDrive::Bdr) {
336 second =
tr(
"/BD-R",
"Second item of %1%2 Drive sentence");
338 if (mediumTypes & Solid::OpticalDrive::Bdre) {
339 second =
tr(
"/BD-RE",
"Second item of %1%2 Drive sentence");
341 if (mediumTypes & Solid::OpticalDrive::HdDvd) {
342 second =
tr(
"/HD DVD-ROM",
"Second item of %1%2 Drive sentence");
344 if (mediumTypes & Solid::OpticalDrive::HdDvdr) {
345 second =
tr(
"/HD DVD-R",
"Second item of %1%2 Drive sentence");
347 if (mediumTypes & Solid::OpticalDrive::HdDvdrw) {
348 second =
tr(
"/HD DVD-RW",
"Second item of %1%2 Drive sentence");
351 if (drive_is_hotpluggable) {
352 description =
tr(
"External %1%2 Drive",
"%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").
arg(first, second);
354 description =
tr(
"%1%2 Drive",
"%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").
arg(first, second);
360 if (drive_type == Solid::StorageDrive::Floppy) {
361 if (drive_is_hotpluggable) {
362 description =
tr(
"External Floppy Drive");
364 description =
tr(
"Floppy Drive");
370 const bool drive_is_removable = storageDrive.isRemovable();
372 if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable) {
373 QString devName = storageDrive.device();
375 description = concatBlockDeviceDescription(devName, storageDrive.size(), drive_is_hotpluggable);
386 vendormodel_str = model;
390 vendormodel_str = vendor_str;
394 vendormodel_str = model;
396 vendormodel_str =
tr(
"%1 %2",
"%1 is the vendor, %2 is the model of the device").
arg(vendor_str, model);
401 if (vendormodel_str.
isEmpty()) {
402 description =
tr(
"Drive");
404 description = vendormodel_str;
410QString Device::volumeDescription()
const
413 const UDisks2::StorageVolume storageVolume(
const_cast<Device *
>(
this));
416 volume_label = prop(QStringLiteral(
"Name")).
toString();
422 UDisks2::Device storageDevice(drivePath());
423 const UDisks2::StorageDrive storageDrive(&storageDevice);
427 if (drive_type == Solid::StorageDrive::CdromDrive) {
428 const UDisks2::OpticalDisc disc(
const_cast<Device *
>(
this));
429 switch (disc.discType()) {
430 case Solid::OpticalDisc::UnknownDiscType:
431 case Solid::OpticalDisc::CdRom:
432 description =
tr(
"CD-ROM");
435 case Solid::OpticalDisc::CdRecordable:
436 if (disc.isBlank()) {
437 description =
tr(
"Blank CD-R");
439 description =
tr(
"CD-R");
443 case Solid::OpticalDisc::CdRewritable:
444 if (disc.isBlank()) {
445 description =
tr(
"Blank CD-RW");
447 description =
tr(
"CD-RW");
451 case Solid::OpticalDisc::DvdRom:
452 description =
tr(
"DVD-ROM");
455 case Solid::OpticalDisc::DvdRam:
456 if (disc.isBlank()) {
457 description =
tr(
"Blank DVD-RAM");
459 description =
tr(
"DVD-RAM");
463 case Solid::OpticalDisc::DvdRecordable:
464 if (disc.isBlank()) {
465 description =
tr(
"Blank DVD-R");
467 description =
tr(
"DVD-R");
471 case Solid::OpticalDisc::DvdPlusRecordableDuallayer:
472 if (disc.isBlank()) {
473 description =
tr(
"Blank DVD+R Dual-Layer");
475 description =
tr(
"DVD+R Dual-Layer");
479 case Solid::OpticalDisc::DvdRewritable:
480 if (disc.isBlank()) {
481 description =
tr(
"Blank DVD-RW");
483 description =
tr(
"DVD-RW");
487 case Solid::OpticalDisc::DvdPlusRecordable:
488 if (disc.isBlank()) {
489 description =
tr(
"Blank DVD+R");
491 description =
tr(
"DVD+R");
495 case Solid::OpticalDisc::DvdPlusRewritable:
496 if (disc.isBlank()) {
497 description =
tr(
"Blank DVD+RW");
499 description =
tr(
"DVD+RW");
503 case Solid::OpticalDisc::DvdPlusRewritableDuallayer:
504 if (disc.isBlank()) {
505 description =
tr(
"Blank DVD+RW Dual-Layer");
507 description =
tr(
"DVD+RW Dual-Layer");
511 case Solid::OpticalDisc::BluRayRom:
512 description =
tr(
"BD-ROM");
515 case Solid::OpticalDisc::BluRayRecordable:
516 if (disc.isBlank()) {
517 description =
tr(
"Blank BD-R");
519 description =
tr(
"BD-R");
523 case Solid::OpticalDisc::BluRayRewritable:
524 if (disc.isBlank()) {
525 description =
tr(
"Blank BD-RE");
527 description =
tr(
"BD-RE");
531 case Solid::OpticalDisc::HdDvdRom:
532 description =
tr(
"HD DVD-ROM");
535 case Solid::OpticalDisc::HdDvdRecordable:
536 if (disc.isBlank()) {
537 description =
tr(
"Blank HD DVD-R");
539 description =
tr(
"HD DVD-R");
543 case Solid::OpticalDisc::HdDvdRewritable:
544 if (disc.isBlank()) {
545 description =
tr(
"Blank HD DVD-RW");
547 description =
tr(
"HD DVD-RW");
553 if (disc.availableContent() == Solid::OpticalDisc::Audio) {
554 description =
tr(
"Audio CD");
560 const bool drive_is_removable = storageDrive.isRemovable();
562 QString size_str = formatByteSize(storageVolume.size());
563 QString volumeName = storageVolume.device();
565 if (isEncryptedContainer()) {
566 if (storageVolume.size() > 0) {
567 description =
tr(
"%1 Encrypted Drive",
"%1 is the size").
arg(size_str);
569 description =
tr(
"Encrypted Drive");
571 }
else if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable) {
572 description = concatBlockDeviceDescription(volumeName, storageVolume.size(), storageDrive.isHotpluggable());
573 }
else if (drive_type == Solid::StorageDrive::Floppy) {
574 description =
tr(
"Floppy Disk");
576 if (drive_is_removable) {
577 if (storageVolume.size() > 0) {
578 description =
tr(
"%1 Removable Media",
"%1 is the size").
arg(size_str);
580 description =
tr(
"Removable Media");
583 if (storageVolume.size() > 0) {
584 description =
tr(
"%1 Media",
"%1 is the size").
arg(size_str);
586 description =
tr(
"Storage Media");
600 }
else if (isRoot()) {
601 return QStringLiteral(
"drive-harddisk-root");
602 }
else if (isLoop()) {
603 const QString backingFile = prop(QStringLiteral(
"BackingFile")).
toString();
606 if (!
type.isDefault()) {
607 return type.iconName();
610 return QStringLiteral(
"drive-harddisk");
611 }
else if (isSwap()) {
612 return QStringLiteral(
"drive-harddisk");
613 }
else if (isDrive()) {
614 const bool isRemovable = prop(QStringLiteral(
"Removable")).
toBool();
617 if (isOpticalDrive()) {
618 return QStringLiteral(
"drive-optical");
619 }
else if (isRemovable && !prop(QStringLiteral(
"Optical")).toBool()) {
621 return QStringLiteral(
"drive-removable-media-usb");
623 return QStringLiteral(
"drive-removable-media");
626 }
else if (isBlock()) {
627 const QString drv = drivePath();
629 return QStringLiteral(
"drive-harddisk");
635 const QString media = drive.prop(QStringLiteral(
"Media")).toString();
638 if (drive.prop(QStringLiteral(
"Optical")).toBool()) {
639 bool isWritable = drive.prop(QStringLiteral(
"OpticalBlank")).toBool();
641 const UDisks2::OpticalDisc disc(
const_cast<Device *
>(
this));
644 if (availContent & Solid::OpticalDisc::VideoDvd) {
645 return QStringLiteral(
"media-optical-dvd-video");
646 }
else if ((availContent & Solid::OpticalDisc::VideoCd) || (availContent & Solid::OpticalDisc::SuperVideoCd)) {
647 return QStringLiteral(
"media-optical-video");
648 }
else if ((availContent & Solid::OpticalDisc::Data) && (availContent & Solid::OpticalDisc::Audio)) {
649 return QStringLiteral(
"media-optical-mixed-cd");
650 }
else if (availContent & Solid::OpticalDisc::Audio) {
651 return QStringLiteral(
"media-optical-audio");
652 }
else if (availContent & Solid::OpticalDisc::Data) {
653 return QStringLiteral(
"media-optical-data");
654 }
else if (isWritable) {
655 return QStringLiteral(
"media-optical-recordable");
657 if (media.
startsWith(QStringLiteral(
"optical_dvd")) || media.
startsWith(QStringLiteral(
"optical_hddvd"))) {
658 return QStringLiteral(
"media-optical-dvd");
659 }
else if (media.
startsWith(QStringLiteral(
"optical_bd"))) {
660 return QStringLiteral(
"media-optical-blu-ray");
665 return QStringLiteral(
"media-optical");
669 return QStringLiteral(
"media-flash-memory-stick");
674 return QStringLiteral(
"media-flash-sd-mmc");
676 return QStringLiteral(
"media-flash-smart-media");
678 return QStringLiteral(
"drive-removable-media-usb-pendrive");
679 }
else if (media.
startsWith(QStringLiteral(
"flash"))) {
680 return QStringLiteral(
"media-flash");
682 return QStringLiteral(
"media-floppy");
687 return QStringLiteral(
"media-flash-sd-mmc");
693 return QStringLiteral(
"drive-harddisk");
699 Device drive(drivePath());
700 return drive.prop(QStringLiteral(
"Model")).toString();
703 return prop(QStringLiteral(
"Model")).
toString();
709 Device drive(drivePath());
710 return drive.prop(QStringLiteral(
"Vendor")).toString();
713 return prop(QStringLiteral(
"Vendor")).
toString();
716QString Device::parentUdi()
const
720 if (propertyExists(QStringLiteral(
"Drive"))) {
722 }
else if (propertyExists(QStringLiteral(
"Table"))) {
725 parent = QStringLiteral(UD2_UDI_DISKS_PREFIX);
733 return tr(
"You are not authorized to perform this operation");
735 return tr(
"The device is currently busy");
737 return tr(
"The requested operation has failed");
739 return tr(
"The requested operation has been canceled");
740 }
else if (error ==
QLatin1String(UD2_ERROR_INVALID_OPTION)) {
741 return tr(
"An invalid or malformed option has been given");
742 }
else if (error ==
QLatin1String(UD2_ERROR_MISSING_DRIVER)) {
743 return tr(
"The kernel driver for this filesystem type is not available");
744 }
else if (error ==
QLatin1String(UD2_ERROR_ALREADY_MOUNTED)) {
745 return tr(
"The device is already mounted");
747 return tr(
"The device is not mounted");
748 }
else if (error ==
QLatin1String(UD2_ERROR_MOUNTED_BY_OTHER_USER)) {
749 return tr(
"The device is mounted by another user");
750 }
else if (error ==
QLatin1String(UD2_ERROR_ALREADY_UNMOUNTING)) {
751 return tr(
"The device is already unmounting");
753 return tr(
"The operation timed out");
755 return tr(
"The operation would wake up a disk that is in a deep-sleep state");
756 }
else if (error ==
QLatin1String(UD2_ERROR_ALREADY_CANCELLED)) {
757 return tr(
"The operation has already been canceled");
758 }
else if (error ==
QLatin1String(UD2_ERROR_NOT_AUTHORIZED_CAN_OBTAIN)) {
759 return tr(
"Cannot request authentication for this action. The PolicyKit authentication system appears to be not available.");
760 }
else if (error ==
QLatin1String(UD2_ERROR_NOT_AUTHORIZED_DISMISSED)) {
761 return tr(
"The authentication prompt was canceled");
763 return tr(
"An unspecified error has occurred");
767Solid::ErrorType Device::errorToSolidError(
const QString &error)
const
770 return Solid::DeviceBusy;
772 return Solid::OperationFailed;
774 return Solid::UserCanceled;
775 }
else if (error ==
QLatin1String(UD2_ERROR_INVALID_OPTION)) {
776 return Solid::InvalidOption;
777 }
else if (error ==
QLatin1String(UD2_ERROR_MISSING_DRIVER)) {
778 return Solid::MissingDriver;
779 }
else if (error ==
QLatin1String(UD2_ERROR_NOT_AUTHORIZED_DISMISSED)) {
780 return Solid::UserCanceled;
782 return Solid::UnauthorizedOperation;
786bool Device::isBlock()
const
788 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_BLOCK));
791bool Device::isPartition()
const
793 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_PARTITION));
796bool Device::isPartitionTable()
const
798 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_PARTITIONTABLE));
801bool Device::isStorageVolume()
const
803 return isPartition() || isPartitionTable() || isStorageAccess() || isOpticalDisc();
806bool Device::isStorageAccess()
const
808 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_FILESYSTEM)) || isEncryptedContainer();
811bool Device::isDrive()
const
813 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_DRIVE));
816bool Device::isOpticalDrive()
const
818 return isDrive() && !prop(QStringLiteral(
"MediaCompatibility")).
toStringList().
filter(QStringLiteral(
"optical_")).
isEmpty();
821bool Device::isOpticalDisc()
const
823 const QString drv = drivePath();
829 return drive.prop(QStringLiteral(
"Optical")).toBool();
832bool Device::mightBeOpticalDisc()
const
834 const QString drv = drivePath();
840 return drive.isOpticalDrive();
843bool Device::isMounted()
const
845 QVariant mountPoints = prop(QStringLiteral(
"MountPoints"));
846 return mountPoints.
isValid() && !qdbus_cast<QByteArrayList>(mountPoints).isEmpty();
849bool Device::isEncryptedContainer()
const
851 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_ENCRYPTED));
854bool Device::isEncryptedCleartext()
const
864bool Device::isRoot()
const
866 if (isStorageAccess()) {
867 const UDisks2::StorageAccess accessIface(
const_cast<Device *
>(
this));
873bool Device::isSwap()
const
875 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_SWAP));
878bool Device::isLoop()
const
880 return hasInterface(QStringLiteral(UD2_DBUS_INTERFACE_LOOP));
883QString Device::drivePath()
const
888#include "moc_udisksdevice.cpp"
Type
This enum type defines the type of device interface that a Device can have.
DriveType
This enum type defines the type of drive a storage device can be.
Type type(const QSqlDatabase &db)
char * toString(const EngineQuery &query)
QString path(const QString &relativePath)
QString label(StandardShortcut id)
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
QMimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const const
QObject * parent() const const
QVariant property(const char *name) const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
bool isEmpty() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QStringList filter(QStringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isValid() const const
bool toBool() const const
QString toString() const const
QStringList toStringList() const const