Skip to content

Commit

Permalink
Merge branch 'jb43396' into 'master'
Browse files Browse the repository at this point in the history
Rescan block after formatting encrypted sd card

See merge request mer-core/nemo-qml-plugin-systemsettings!90
  • Loading branch information
rainemak committed Nov 22, 2018
2 parents b8d96da + 969443b commit e1d9073
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 59 deletions.
134 changes: 96 additions & 38 deletions src/udisks2block.cpp
Expand Up @@ -76,44 +76,8 @@ UDisks2::Block::Block(const QString &path, const UDisks2::InterfacePropertyMap &
});
}

// Use when morphing a block e.g. updating encrypted block to crypto backing block device (e.i. to a block that implements file system).
UDisks2::Block &UDisks2::Block::operator=(const UDisks2::Block &other)
UDisks2::Block &UDisks2::Block::operator=(const UDisks2::Block &)
{
if (&other == this)
return *this;

if (!this->m_connection.disconnect(
UDISKS2_SERVICE,
m_path,
DBUS_OBJECT_PROPERTIES_INTERFACE,
UDisks2::propertiesChangedSignal,
this,
SLOT(updateProperties(QDBusMessage)))) {
qCWarning(lcMemoryCardLog) << "Failed to disconnect to Block properties change interface" << m_path << m_connection.lastError().message();
}

this->m_path = other.m_path;

if (!this->m_connection.connect(
UDISKS2_SERVICE,
this->m_path,
DBUS_OBJECT_PROPERTIES_INTERFACE,
UDisks2::propertiesChangedSignal,
this,
SLOT(updateProperties(QDBusMessage)))) {
qCWarning(lcMemoryCardLog) << "Failed to connect to Block properties change interface" << m_path << m_connection.lastError().message();
}

m_interfacePropertyMap = other.m_interfacePropertyMap;
m_data = other.m_data;
m_drive = other.m_drive;
m_mountable = other.m_mountable;
m_mountPath = other.m_mountPath;
m_encrypted = other.m_encrypted;
m_formatting = other.m_formatting;
m_locking = other.m_locking;

return *this;
}

UDisks2::Block::~Block()
Expand Down Expand Up @@ -184,7 +148,7 @@ bool UDisks2::Block::isCryptoBlock() const
bool UDisks2::Block::hasCryptoBackingDevice() const
{
const QString cryptoBackingDev = cryptoBackingDeviceObjectPath();
return cryptoBackingDev != QLatin1String("/");
return !cryptoBackingDev.isEmpty() && cryptoBackingDev != QLatin1String("/");
}

QString UDisks2::Block::cryptoBackingDevicePath() const
Expand Down Expand Up @@ -264,6 +228,11 @@ bool UDisks2::Block::isExternal() const
return prefDevice != QStringLiteral("/dev/sailfish/home") && prefDevice != QStringLiteral("/dev/sailfish/root");
}

bool UDisks2::Block::isValid() const
{
return m_interfacePropertyMap.contains(UDISKS2_BLOCK_INTERFACE);
}

QString UDisks2::Block::idType() const
{
return value(QStringLiteral("IdType")).toString();
Expand Down Expand Up @@ -321,6 +290,72 @@ QString UDisks2::Block::cryptoBackingDevicePath(const QString &objectPath)
}
}

void UDisks2::Block::addInterface(const QString &interface, QVariantMap propertyMap)
{
m_interfacePropertyMap.insert(interface, propertyMap);
if (interface == UDISKS2_FILESYSTEM_INTERFACE) {
setMountable(true);
} else if (interface == UDISKS2_ENCRYPTED_INTERFACE) {
setEncrypted(true);
}
}

void UDisks2::Block::removeInterface(const QString &interface)
{
m_interfacePropertyMap.remove(interface);
if (interface == UDISKS2_BLOCK_INTERFACE) {
m_data.clear();
} else if (interface == UDISKS2_DRIVE_INTERFACE) {
m_drive.clear();
} else if (interface == UDISKS2_FILESYSTEM_INTERFACE) {
setMountable(false);
}else if (interface == UDISKS2_ENCRYPTED_INTERFACE) {
setEncrypted(false);
}
}

void UDisks2::Block::morph(const UDisks2::Block &other)
{
if (&other == this)
return;

if (!this->m_connection.disconnect(
UDISKS2_SERVICE,
m_path,
DBUS_OBJECT_PROPERTIES_INTERFACE,
UDisks2::propertiesChangedSignal,
this,
SLOT(updateProperties(QDBusMessage)))) {
qCWarning(lcMemoryCardLog) << "Failed to disconnect to Block properties change interface" << m_path << m_connection.lastError().message();
}

this->m_path = other.m_path;

if (!this->m_connection.connect(
UDISKS2_SERVICE,
this->m_path,
DBUS_OBJECT_PROPERTIES_INTERFACE,
UDisks2::propertiesChangedSignal,
this,
SLOT(updateProperties(QDBusMessage)))) {
qCWarning(lcMemoryCardLog) << "Failed to connect to Block properties change interface" << m_path << m_connection.lastError().message();
}

m_interfacePropertyMap = other.m_interfacePropertyMap;
m_data = other.m_data;
m_drive = other.m_drive;
m_mountPath = other.m_mountPath;
m_mountable = other.m_mountable;
m_encrypted = other.m_encrypted;
bool wasFormatting = m_formatting;
m_formatting = other.m_formatting;
m_locking = other.m_locking;

if (wasFormatting && hasCryptoBackingDevice()) {
rescan(cryptoBackingDeviceObjectPath());
}
}

void UDisks2::Block::updateProperties(const QDBusMessage &message)
{
QList<QVariant> arguments = message.arguments();
Expand Down Expand Up @@ -458,3 +493,26 @@ void UDisks2::Block::getDriveProperties()
complete();
});
}

void UDisks2::Block::rescan(const QString &dbusObjectPath)
{
QVariantList arguments;
QVariantMap options;
arguments << options;

QDBusInterface blockDeviceInterface(UDISKS2_SERVICE,
dbusObjectPath,
UDISKS2_BLOCK_INTERFACE,
m_connection);

QDBusPendingCall pendingCall = blockDeviceInterface.asyncCallWithArgumentList(UDISKS2_BLOCK_RESCAN, arguments);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
connect(watcher, &QDBusPendingCallWatcher::finished,
this, [dbusObjectPath](QDBusPendingCallWatcher *watcher) {
if (watcher->isError()) {
QDBusError error = watcher->error();
qCDebug(lcMemoryCardLog) << "UDisks failed to rescan object path" << dbusObjectPath << ", error type:" << error.type() << ",name:" << error.name() << ", message:" << error.message();
}
watcher->deleteLater();
});
}
20 changes: 15 additions & 5 deletions src/udisks2block_p.h
Expand Up @@ -49,9 +49,8 @@ class Block : public QObject

public:
Block(const QString &path, const UDisks2::InterfacePropertyMap &interfacePropertyMap, QObject *parent = nullptr);
Block& operator=(const Block& other);

~Block();
virtual ~Block();

QString path() const;

Expand All @@ -72,10 +71,7 @@ class Block : public QObject
QString cryptoBackingDeviceObjectPath() const;

bool isEncrypted() const;
bool setEncrypted(bool encrypted);

bool isMountable() const;
bool setMountable(bool mountable);

bool isFormatting() const;
bool setFormatting(bool formatting);
Expand All @@ -86,6 +82,8 @@ class Block : public QObject
bool isReadOnly() const;
bool isExternal() const;

bool isValid() const;

QString idType() const;
QString idVersion() const;
QString idLabel() const;
Expand All @@ -101,6 +99,11 @@ class Block : public QObject

static QString cryptoBackingDevicePath(const QString &objectPath);

void addInterface(const QString &interface, QVariantMap propertyMap);
void removeInterface(const QString &interface);

void morph(const Block& other);

signals:
void completed();
void updated();
Expand All @@ -111,6 +114,11 @@ private slots:
void updateProperties(const QDBusMessage &message);

private:
Block& operator=(const Block& other);

bool setEncrypted(bool encrypted);
bool setMountable(bool mountable);

bool isCompleted() const;
void updateMountPoint(const QVariant &mountPoints);
void complete();
Expand All @@ -120,6 +128,8 @@ private slots:
void getEncryptedInterface();
void getDriveProperties();

void rescan(const QString &dbusObjectPath);

QString m_path;
UDisks2::InterfacePropertyMap m_interfacePropertyMap;
QVariantMap m_data;
Expand Down
1 change: 1 addition & 0 deletions src/udisks2defines.h
Expand Up @@ -81,6 +81,7 @@ Q_DECLARE_METATYPE(UDisks2::InterfacePropertyMap)
#define UDISKS2_ENCRYPTED_UNLOCK QLatin1String("Unlock")
#define UDISKS2_FILESYSTEM_MOUNT QLatin1String("Mount")
#define UDISKS2_FILESYSTEM_UNMOUNT QLatin1String("Unmount")
#define UDISKS2_BLOCK_RESCAN QLatin1String("Rescan")

// Errors
#define UDISKS2_ERROR_DEVICE_BUSY QLatin1String("org.freedesktop.UDisks2.Error.DeviceBusy")
Expand Down
8 changes: 6 additions & 2 deletions src/udisks2job.cpp
Expand Up @@ -58,8 +58,7 @@ UDisks2::Job::Job(const QString &path, const QVariantMap &data, QObject *parent)
}

connect(Monitor::instance(), &Monitor::errorMessage, this, [this](const QString &objectPath, const QString &errorName) {
QStringList objects = value(UDISKS2_JOB_KEY_OBJECTS).toStringList();
if (objects.contains(objectPath) && errorName == UDISKS2_ERROR_DEVICE_BUSY) {
if (objects().contains(objectPath) && errorName == UDISKS2_ERROR_DEVICE_BUSY) {
m_message = errorName;
if (!isCompleted() && deviceBusy()) {
updateCompleted(false, m_message);
Expand Down Expand Up @@ -100,6 +99,11 @@ bool UDisks2::Job::deviceBusy() const
return m_message == UDISKS2_ERROR_TARGET_BUSY || m_message == UDISKS2_ERROR_DEVICE_BUSY;
}

QStringList UDisks2::Job::objects() const
{
return value(UDISKS2_JOB_KEY_OBJECTS).toStringList();
}

QString UDisks2::Job::path() const
{
return m_path;
Expand Down
2 changes: 2 additions & 0 deletions src/udisks2job_p.h
Expand Up @@ -68,6 +68,8 @@ class Job : public QObject
QString message() const;
bool deviceBusy() const;

QStringList objects() const;

QString path() const;
QVariant value(const QString &key) const;

Expand Down
48 changes: 34 additions & 14 deletions src/udisks2monitor.cpp
Expand Up @@ -226,20 +226,18 @@ void UDisks2::Monitor::interfacesAdded(const QDBusObjectPath &objectPath, const
// External device must have file system or partition so that it can added to the model.
// Devices without partition table have filesystem interface.

if ((interfaces.contains(UDISKS2_FILESYSTEM_INTERFACE) ||
interfaces.contains(UDISKS2_ENCRYPTED_INTERFACE)) && externalBlockDevice(path)) {

if (path.startsWith(QStringLiteral("/org/freedesktop/UDisks2/block_devices/")) && externalBlockDevice(path)) {
if (m_blockDevices.contains(path)) {
UDisks2::Block *block = m_blockDevices.value(path);
if (interfaces.contains(UDISKS2_FILESYSTEM_INTERFACE)) {
block->setMountable(true);
block->addInterface(UDISKS2_FILESYSTEM_INTERFACE, interfaces.value(UDISKS2_FILESYSTEM_INTERFACE));
}
if (interfaces.contains(UDISKS2_ENCRYPTED_INTERFACE)) {
block->setEncrypted(true);
block->addInterface(UDISKS2_ENCRYPTED_INTERFACE, interfaces.value(UDISKS2_ENCRYPTED_INTERFACE));
}
} else {
QVariantMap dict = interfaces.value(UDISKS2_BLOCK_INTERFACE);
createBlockDevice(path, interfaces);
UDisks2::Block *block = createBlockDevice(path, interfaces);
updateFormattingState(block);
}
} else if (path.startsWith(QStringLiteral("/org/freedesktop/UDisks2/jobs"))) {
QVariantMap dict = interfaces.value(UDISKS2_JOB_INTERFACE);
Expand All @@ -257,6 +255,17 @@ void UDisks2::Monitor::interfacesAdded(const QDBusObjectPath &objectPath, const
UDisks2::Job *job = qobject_cast<UDisks2::Job *>(sender());
updatePartitionStatus(job, success);
});

if (job->operation() == Job::Format) {
for (const QString &objectPath : job->objects()) {
if (UDisks2::Block *block = m_blockDevices.value(objectPath, nullptr)) {
block->blockSignals(true);
block->setFormatting(true);
block->blockSignals(false);
}
}
}

m_jobsToWait.insert(path, job);
}
}
Expand Down Expand Up @@ -296,10 +305,10 @@ void UDisks2::Monitor::interfacesRemoved(const QDBusObjectPath &objectPath, cons
} else if (m_blockDevices.contains(path)) {
UDisks2::Block *block = m_blockDevices.value(path);
if (interfaces.contains(UDISKS2_FILESYSTEM_INTERFACE)) {
block->setMountable(false);
block->removeInterface(UDISKS2_FILESYSTEM_INTERFACE);
}
if (interfaces.contains(UDISKS2_ENCRYPTED_INTERFACE)) {
block->setEncrypted(false);
block->removeInterface(UDISKS2_ENCRYPTED_INTERFACE);
}
}
}
Expand Down Expand Up @@ -369,7 +378,7 @@ void UDisks2::Monitor::updatePartitionStatus(const UDisks2::Job *job, bool succe
{
UDisks2::Job::Operation operation = job->operation();
PartitionManagerPrivate::Partitions affectedPartitions;
lookupPartitions(affectedPartitions, job->value(UDISKS2_JOB_KEY_OBJECTS).toStringList());
lookupPartitions(affectedPartitions, job->objects());
if (operation == UDisks2::Job::Lock || operation == UDisks2::Job::Unlock) {
for (auto partition : affectedPartitions) {
Partition::Status oldStatus = partition->status;
Expand Down Expand Up @@ -648,13 +657,10 @@ UDisks2::Block *UDisks2::Monitor::createBlockDevice(const QString &dbusObjectPat
if (completedBlock->hasCryptoBackingDevice() && m_blockDevices.contains(cryptoBackingDeviceObjectPath)) {
// Update crypto backing device to file system device.
UDisks2::Block *cryptoBackingDev = m_blockDevices.value(cryptoBackingDeviceObjectPath);
*cryptoBackingDev = *completedBlock;

cryptoBackingDev->morph(*completedBlock);
m_blockDevices.remove(cryptoBackingDeviceObjectPath);
m_blockDevices.insert(cryptoBackingDev->path(), cryptoBackingDev);

updatePartitionProperties(cryptoBackingDev);

completedBlock->deleteLater();
} else if (!m_blockDevices.contains(completedBlock->path())) {
m_blockDevices.insert(completedBlock->path(), completedBlock);
Expand All @@ -677,6 +683,7 @@ UDisks2::Block *UDisks2::Monitor::createBlockDevice(const QString &dbusObjectPat
} else {
// This is garbage block device that should not be exposed
// from the partition model.
completedBlock->removeInterface(UDISKS2_BLOCK_INTERFACE);
completedBlock->deleteLater();
}
});
Expand Down Expand Up @@ -809,6 +816,19 @@ UDisks2::Block *UDisks2::Monitor::findBlock(const QString &devicePath) const
return nullptr;
}

void UDisks2::Monitor::updateFormattingState(UDisks2::Block *block)
{
UDisks2::Block *cryptoBackingDevice = nullptr;
QString cryptoBackingDevicePath = block->cryptoBackingDeviceObjectPath();

// If we have crypto backing device, copy over formatting state.
if (cryptoBackingDevicePath != QLatin1String("/") && (cryptoBackingDevice = m_blockDevices.value(cryptoBackingDevicePath, nullptr))) {
block->blockSignals(true);
block->setFormatting(cryptoBackingDevice->isFormatting());
block->blockSignals(false);
}
}

QString UDisks2::Monitor::objectPath(const QString &devicePath) const
{
for (QMap<QString, Block *>::const_iterator i = m_blockDevices.begin(); i != m_blockDevices.end(); ++i) {
Expand Down
1 change: 1 addition & 0 deletions src/udisks2monitor_p.h
Expand Up @@ -118,6 +118,7 @@ private slots:
void getBlockDevices();

Block *findBlock(const QString &devicePath) const;
void updateFormattingState(UDisks2::Block *block);

private:
static Monitor *sharedInstance;
Expand Down

0 comments on commit e1d9073

Please sign in to comment.