Skip to content

Commit

Permalink
[nemo-storage] Rescan block after formatting encrypted sd card. Fixes…
Browse files Browse the repository at this point in the history
… JB#43396
  • Loading branch information
rainemak committed Nov 22, 2018
1 parent c0ab8b7 commit 969443b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 48 deletions.
110 changes: 72 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 @@ -345,6 +314,48 @@ void UDisks2::Block::removeInterface(const QString &interface)
}
}

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 @@ -482,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();
});
}
7 changes: 6 additions & 1 deletion src/udisks2block_p.h
Expand Up @@ -49,7 +49,6 @@ class Block : public QObject

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

virtual ~Block();

Expand Down Expand Up @@ -83,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 +102,8 @@ class Block : public QObject
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,8 @@ private slots:
void updateProperties(const QDBusMessage &message);

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

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

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
38 changes: 29 additions & 9 deletions src/udisks2monitor.cpp
Expand Up @@ -226,9 +226,7 @@ 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)) {
Expand All @@ -238,8 +236,8 @@ void UDisks2::Monitor::interfacesAdded(const QDBusObjectPath &objectPath, const
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 @@ -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 969443b

Please sign in to comment.