Commit 5772467e authored by Raine Makelainen's avatar Raine Makelainen

[systemsettings] Cleanup unwanted partitions. Contributes to JB#40936

External block device are now read through udisks2 upon
PartitionModel creation. This guarantees that all block devices
will have also file system interface. For instance now memory sticks
that do not have partition table but formatted directly will be
shown as well.

In future, similar approach should be take for encrypted devices.
parent 27b75fc3
......@@ -71,8 +71,7 @@ PartitionManagerPrivate::PartitionManagerPrivate()
home->mountPath = QStringLiteral("/home");
m_partitions.append(home);
refresh();
refresh(m_partitions, m_partitions);
// Remove any prospective internal partitions that aren't mounted.
int internalPartitionCount = 0;
......@@ -105,8 +104,6 @@ PartitionManagerPrivate::PartitionManagerPrivate()
if (root->status == Partition::Mounted) {
m_root = Partition(QExplicitlySharedDataPointer<PartitionPrivate>(root));
}
m_udisksMonitor->getBlockDevices();
}
PartitionManagerPrivate::~PartitionManagerPrivate()
......@@ -147,85 +144,41 @@ QVector<Partition> PartitionManagerPrivate::partitions(const Partition::StorageT
return partitions;
}
void PartitionManagerPrivate::refresh()
void PartitionManagerPrivate::add(Partitions &partitions)
{
int index;
for (index = 0; index < m_partitions.count(); ++index) {
if (m_partitions.at(index)->storageType == Partition::External) {
break;
}
}
Partitions addedPartitions;
Partitions changedPartitions;
QFile partitionFile(QStringLiteral("/proc/partitions"));
if (partitionFile.open(QIODevice::ReadOnly)) {
// Read headers.
partitionFile.readLine();
partitionFile.readLine();
static const QRegularExpression whitespace(QStringLiteral("\\s+"));
static const QRegularExpression deviceRoot(QStringLiteral("^mmcblk\\d+$"));
m_partitions.append(partitions);
refresh(partitions, partitions);
while (!partitionFile.atEnd()) {
QStringList line = QString::fromUtf8(partitionFile.readLine()).split(whitespace, QString::SkipEmptyParts);
if (line.count() != 4) {
continue;
}
const QString deviceName = line.at(3);
for (const auto partition : partitions) {
emit partitionAdded(Partition(partition));
}
}
if (!externalMedia.match(deviceName).hasMatch()) {
continue;
void PartitionManagerPrivate::remove(const Partitions &partitions)
{
for (const auto removedPartition : partitions) {
for (int i = m_partitions.count() - 1; i >= 0 && m_partitions.at(i)->storageType == Partition::External; --i) {
const auto partition = m_partitions.at(i);
if (removedPartition->devicePath == partition->devicePath) {
m_partitions.removeAt(i);
}
const auto partition = [&]() {
for (int i = index; i < m_partitions.count(); ++i) {
const auto partition = m_partitions.at(i);
if (partition->deviceName == deviceName) {
if (index != i) {
m_partitions.removeAt(i);
m_partitions.insert(index, partition);
}
changedPartitions.append(partition);
return partition;
}
}
QExplicitlySharedDataPointer<PartitionPrivate> partition(new PartitionPrivate(this));
partition->storageType = Partition::External;
partition->deviceName = deviceName;
partition->devicePath = QStringLiteral("/dev/") + deviceName;
partition->deviceRoot = deviceRoot.match(deviceName).hasMatch();
m_partitions.insert(index, partition);
addedPartitions.append(partition);
return partition;
}();
partition->bytesTotal = line.at(2).toInt() * 1024;
++index;
}
}
const auto removedPartitions = m_partitions.mid(index);
m_partitions.resize(index);
refresh(m_partitions, changedPartitions);
for (const auto partition : removedPartitions) {
emit partitionRemoved(Partition(partition));
emit partitionRemoved(Partition(removedPartition));
}
}
for (const auto partition : addedPartitions) {
emit partitionAdded(Partition(partition));
void PartitionManagerPrivate::refresh()
{
Partitions changedPartitions;
for (int index = 0; index < m_partitions.count(); ++index) {
const auto partition = m_partitions.at(index);
if (partition->storageType == Partition::External) {
changedPartitions.append(partition);
}
}
refresh(m_partitions, changedPartitions);
for (const auto partition : changedPartitions) {
emit partitionChanged(Partition(partition));
}
......@@ -246,9 +199,11 @@ void PartitionManagerPrivate::refresh(const Partitions &partitions, Partitions &
partition->bytesFree = 0;
partition->bytesAvailable = 0;
if (!partition->valid) {
partition->status = partition->activeState == QStringLiteral("activating")
? Partition::Mounting
: Partition::Unmounted;
if (partition->status != Partition::Formatting) {
partition->status = partition->activeState == QStringLiteral("activating")
? Partition::Mounting
: Partition::Unmounted;
}
partition->canMount = false;
partition->readOnly = true;
partition->filesystemType.clear();
......@@ -266,7 +221,7 @@ void PartitionManagerPrivate::refresh(const Partitions &partitions, Partitions &
const QString mountPath = QString::fromUtf8(mountEntry.mnt_dir);
const QString devicePath = QString::fromUtf8(mountEntry.mnt_fsname);
const QString deviceName = devicePath.section(QChar('/'), 2);
for (auto partition : partitions) {
if (partition->valid || ((partition->status == Partition::Mounted || partition->status == Partition::Mounting) &&
......@@ -282,6 +237,10 @@ void PartitionManagerPrivate::refresh(const Partitions &partitions, Partitions &
&& partition->devicePath == devicePath)) {
partition->mountPath = mountPath;
partition->devicePath = devicePath;
// There two values wrong for system partitions as devicePath will not start with mmcblk.
// Currently deviceName and deviceRoot are merely informative data fields.
partition->deviceName = deviceName;
partition->deviceRoot = deviceRoot.match(deviceName).hasMatch();
partition->filesystemType = QString::fromUtf8(mountEntry.mnt_type);
partition->status = partition->activeState == QStringLiteral("deactivating")
? Partition::Unmounting
......@@ -292,7 +251,7 @@ void PartitionManagerPrivate::refresh(const Partitions &partitions, Partitions &
}
endmntent(mtab);
for (auto partition : partitions) {
if (partition->status == Partition::Mounted) {
struct statvfs64 stat;
......
......@@ -43,7 +43,7 @@ namespace UDisks2 {
class Monitor;
}
static const auto externalDevice = QStringLiteral("mmcblk(?!0)\\d+(?:p\\d+$)?|(sd[a-z]\\d+)");
static const auto externalDevice = QStringLiteral("mmcblk(?!0)\\d+(?:p\\d+$)?|(sd[a-z]\\d*)");
class PartitionManagerPrivate : public QObject, public QSharedData
{
......@@ -59,6 +59,9 @@ public:
Partition root() const;
QVector<Partition> partitions(Partition::StorageTypes types) const;
void add(Partitions &partitions);
void remove(const Partitions &partitions);
void refresh();
void refresh(PartitionPrivate *partition);
void refresh(const Partitions &partitions, Partitions &changedPartitions);
......
......@@ -12,6 +12,9 @@ UDisks2::Block::Block(const QString &path, const QVariantMap &data, QObject *par
, m_path(path)
, m_data(data)
, m_connection(QDBusConnection::systemBus())
, m_mountable(false)
, m_pendingFileSystem(nullptr)
, m_pendingBlock(nullptr)
{
if (!m_connection.connect(
UDISKS2_SERVICE,
......@@ -28,36 +31,42 @@ UDisks2::Block::Block(const QString &path, const QVariantMap &data, QObject *par
DBUS_OBJECT_PROPERTIES_INTERFACE,
m_connection);
QDBusPendingCall pendingCall = dbusPropertyInterface.asyncCall(DBUS_GET_ALL, UDISKS2_FILESYSTEM_INTERFACE);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
m_pendingFileSystem = new QDBusPendingCallWatcher(pendingCall, this);
connect(m_pendingFileSystem, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
if (watcher->isValid() && watcher->isFinished()) {
QDBusPendingReply<> reply = *watcher;
QDBusMessage message = reply.reply();
m_mountable = true;
updateMountPoint(message.arguments().at(0));
} else {
QDBusError error = watcher->error();
qCWarning(lcMemoryCardLog) << "Error reading filesystem properties:" << error.name() << error.message();
qCWarning(lcMemoryCardLog) << "Error reading filesystem properties:" << error.name() << error.message() << path;
}
watcher->deleteLater();
m_pendingFileSystem = nullptr;
complete();
});
if (data.isEmpty()) {
pendingCall = dbusPropertyInterface.asyncCall(DBUS_GET_ALL, UDISKS2_BLOCK_INTERFACE);
watcher = new QDBusPendingCallWatcher(pendingCall, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
m_pendingBlock = new QDBusPendingCallWatcher(pendingCall, this);
connect(m_pendingBlock, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
if (watcher->isValid() && watcher->isFinished()) {
QDBusPendingReply<> reply = *watcher;
QDBusMessage message = reply.reply();
QVariantMap blockProperties = NemoDBus::demarshallArgument<QVariantMap>(message.arguments().at(0));
qCInfo(lcMemoryCardLog) << "Block properties:" << blockProperties;
m_data = blockProperties;
emit blockUpdated();
} else {
QDBusError error = watcher->error();
qCWarning(lcMemoryCardLog) << "Error reading block properties:" << error.name() << error.message();
}
watcher->deleteLater();
m_pendingBlock = nullptr;
complete();
});
} else {
complete();
}
}
......@@ -102,6 +111,11 @@ qint64 UDisks2::Block::size() const
return value(QStringLiteral("Size")).toLongLong();
}
bool UDisks2::Block::isMountable() const
{
return m_mountable;
}
bool UDisks2::Block::isReadOnly() const
{
return value(QStringLiteral("ReadOnly")).toBool();
......@@ -152,8 +166,9 @@ void UDisks2::Block::updateProperties(const QDBusMessage &message)
for (QMap<QString, QVariant>::const_iterator i = changedProperties.begin(); i != changedProperties.end(); ++i) {
m_data.insert(i.key(), i.value());
}
emit blockUpdated();
emit updated();
} else if (interface == UDISKS2_FILESYSTEM_INTERFACE) {
m_mountable = true;
updateMountPoint(arguments.value(1));
}
}
......@@ -174,3 +189,10 @@ void UDisks2::Block::updateMountPoint(const QVariant &mountPoints)
qCInfo(lcMemoryCardLog) << "New file system mount points:" << mountPoints << "resolved mount path: " << m_mountPath;
emit mountPathChanged();
}
void UDisks2::Block::complete()
{
if (!m_pendingFileSystem && !m_pendingBlock) {
QMetaObject::invokeMethod(this, "completed", Qt::QueuedConnection);
}
}
......@@ -36,6 +36,8 @@
#include <QVariantMap>
#include <QDBusConnection>
class QDBusPendingCallWatcher;
namespace UDisks2 {
class Block : public QObject
......@@ -57,6 +59,8 @@ public:
qint64 size() const;
bool isMountable() const;
bool isReadOnly() const;
QString idType() const;
......@@ -71,7 +75,8 @@ public:
bool hasData() const;
signals:
void blockUpdated();
void completed();
void updated();
void mountPathChanged();
private slots:
......@@ -79,11 +84,16 @@ private slots:
private:
void updateMountPoint(const QVariant &mountPoints);
void complete();
QString m_path;
QVariantMap m_data;
QDBusConnection m_connection;
QString m_mountPath;
bool m_mountable;
QDBusPendingCallWatcher *m_pendingFileSystem;
QDBusPendingCallWatcher *m_pendingBlock;
};
}
......
......@@ -36,10 +36,12 @@
#define DBUS_OBJECT_PROPERTIES_INTERFACE QLatin1String("org.freedesktop.DBus.Properties")
#define DBUS_GET_ALL QLatin1String("GetAll")
#define UDISKS2_SERVICE QLatin1String("org.freedesktop.UDisks2")
#define UDISKS2_PATH QLatin1String("/org/freedesktop/UDisks2")
#define UDISKS2_SERVICE QLatin1String("org.freedesktop.UDisks2")
#define UDISKS2_PATH QLatin1String("/org/freedesktop/UDisks2")
#define UDISKS2_MANAGER_PATH QLatin1String("/org/freedesktop/UDisks2/Manager")
// Interfaces
#define UDISKS2_MANAGER_INTERFACE QLatin1String("org.freedesktop.UDisks2.Manager")
#define UDISKS2_BLOCK_INTERFACE QLatin1String("org.freedesktop.UDisks2.Block")
#define UDISKS2_FILESYSTEM_INTERFACE QLatin1String("org.freedesktop.UDisks2.Filesystem")
#define UDISKS2_PARTITION_INTERFACE QLatin1String("org.freedesktop.UDisks2.Partition")
......@@ -56,7 +58,7 @@
#define UDISKS2_JOB_KEY_OBJECTS QLatin1String("Objects")
// Mount, Unmount, Format
#define UDISKS2_BLOCK_DEVICE_PATH QString("/org/freedesktop/UDisks2/block_devices/%1")
#define UDISKS2_BLOCK_DEVICE_PATH QString(QLatin1String("/org/freedesktop/UDisks2/block_devices/%1"))
#define UDISKS2_BLOCK_FORMAT QLatin1String("Format")
#define UDISKS2_FILESYSTEM_MOUNT QLatin1String("Mount")
#define UDISKS2_FILESYSTEM_UNMOUNT QLatin1String("Unmount")
......
......@@ -32,9 +32,9 @@
#include "udisks2job_p.h"
#include "udisks2monitor_p.h"
#include "udisks2defines.h"
#include "logging_p.h"
#include <QDBusConnection>
#include <QDebug>
#include <nemo-dbus/dbus.h>
......@@ -54,7 +54,7 @@ UDisks2::Job::Job(const QString &path, const QVariantMap &data, QObject *parent)
QStringLiteral("Completed"),
this,
SLOT(updateCompleted(bool, QString)))) {
qWarning("Failed to connect to Job's at path %p completed signal: %s: ", qPrintable(m_path), qPrintable(m_connection.lastError().message()));
qCWarning(lcMemoryCardLog) << "Failed to connect to Job's at path" << qPrintable(m_path) << "completed signal" << qPrintable(m_connection.lastError().message());
}
connect(Monitor::instance(), &Monitor::errorMessage, this, [this](const QString &objectPath, const QString &errorName) {
......
This diff is collapsed.
......@@ -35,6 +35,7 @@
#include <QObject>
#include <QDBusObjectPath>
#include <QExplicitlySharedDataPointer>
#include <QRegularExpression>
#include <QQueue>
#include "partitionmodel.h"
......@@ -44,6 +45,8 @@ class PartitionManagerPrivate;
typedef QMap<QString, QVariantMap> InterfaceAndPropertyMap;
static const QRegularExpression deviceRoot(QStringLiteral("^mmcblk\\d+$"));
Q_DECLARE_METATYPE(InterfaceAndPropertyMap)
namespace UDisks2 {
......@@ -80,8 +83,6 @@ public:
void format(const QString &deviceName, const QString &type, const QString &label);
void getBlockDevices();
signals:
void status(const QString &deviceName, Partition::Status);
void errorMessage(const QString &objectPath, const QString &errorName);
......@@ -94,6 +95,7 @@ private slots:
void interfacesRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces);
private:
void setPartitionProperties(QExplicitlySharedDataPointer<PartitionPrivate> &partition, const UDisks2::Block *blockDevice);
void updatePartitionProperties(const UDisks2::Block *blockDevice);
void updatePartitionStatus(const UDisks2::Job *job, bool success);
bool externalBlockDevice(const QString &objectPathStr) const;
......@@ -101,9 +103,11 @@ private:
void startMountOperation(const QString &dbusMethod, const QString &deviceName, QVariantHash arguments);
void lookupPartitions(PartitionManagerPrivate::Partitions &affectedPartions, const QStringList &objects);
void addBlockDevice(const QString &path, const QVariantMap &dict);
void createPartition(const Block *block);
void createBlockDevice(const QString &path, const QVariantMap &dict);
void doFormat(const QString &deviceName, const QString &type, const QVariantHash &arguments);
void getBlockDevices();
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