Commit e1d9073b authored by Raine Makelainen's avatar Raine Makelainen

Merge branch 'jb43396' into 'master'

Rescan block after formatting encrypted sd card

See merge request mer-core/nemo-qml-plugin-systemsettings!90
parents b8d96da9 969443b0
......@@ -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()
......@@ -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
......@@ -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();
......@@ -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();
......@@ -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();
});
}
......@@ -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;
......@@ -72,10 +71,7 @@ public:
QString cryptoBackingDeviceObjectPath() const;
bool isEncrypted() const;
bool setEncrypted(bool encrypted);
bool isMountable() const;
bool setMountable(bool mountable);
bool isFormatting() const;
bool setFormatting(bool formatting);
......@@ -86,6 +82,8 @@ public:
bool isReadOnly() const;
bool isExternal() const;
bool isValid() const;
QString idType() const;
QString idVersion() const;
QString idLabel() const;
......@@ -101,6 +99,11 @@ public:
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();
......@@ -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();
......@@ -120,6 +128,8 @@ private:
void getEncryptedInterface();
void getDriveProperties();
void rescan(const QString &dbusObjectPath);
QString m_path;
UDisks2::InterfacePropertyMap m_interfacePropertyMap;
QVariantMap m_data;
......
......@@ -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")
......
......@@ -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);
......@@ -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;
......
......@@ -68,6 +68,8 @@ public:
QString message() const;
bool deviceBusy() const;
QStringList objects() const;
QString path() const;
QVariant value(const QString &key) const;
......
......@@ -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);
......@@ -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);
}
}
......@@ -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);
}
}
}
......@@ -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;
......@@ -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);
......@@ -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();
}
});
......@@ -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) {
......
......@@ -118,6 +118,7 @@ private:
void getBlockDevices();
Block *findBlock(const QString &devicePath) const;
void updateFormattingState(UDisks2::Block *block);
private:
static Monitor *sharedInstance;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment