diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 3964eb3e6..fd3a678c3 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -77,6 +77,14 @@ set( libSources utils/Yaml.cpp ) +### OPTIONAL Automount support (requires dbus) +# +# +if( Qt5DBus_FOUND) + list( APPEND libSources partition/AutoMount.cpp ) + list( APPEND OPTIONAL_PRIVATE_LIBRARIES Qt5::DBus ) +endif() + ### OPTIONAL Python support # # diff --git a/src/libcalamares/partition/AutoMount.cpp b/src/libcalamares/partition/AutoMount.cpp new file mode 100644 index 000000000..29fbfea5f --- /dev/null +++ b/src/libcalamares/partition/AutoMount.cpp @@ -0,0 +1,89 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + */ + +#include "AutoMount.h" + +#include "utils/Logger.h" + +#include + +namespace CalamaresUtils +{ +namespace Partition +{ + +struct AutoMountInfo +{ + bool wasSolidModuleAutoLoaded = false; +}; + +static inline QDBusMessage +kdedCall( const QString& method ) +{ + return QDBusMessage::createMethodCall( + QStringLiteral( "org.kde.kded5" ), QStringLiteral( "/kded" ), QStringLiteral( "org.kde.kded5" ), method ); +} + +// This code comes, roughly, from the KCM for removable devices. +static void +enableSolidAutoMount( QDBusConnection& dbus, bool enable ) +{ + const auto moduleName = QVariant( QStringLiteral( "device_automounter" ) ); + + // Stop module from auto-loading + { + auto msg = kdedCall( QStringLiteral( "setModuleAutoloading" ) ); + msg.setArguments( { moduleName, QVariant( enable ) } ); + dbus.call( msg, QDBus::NoBlock ); + } + + // Stop module + { + auto msg = kdedCall( enable ? QStringLiteral( "loadModule" ) : QStringLiteral( "unloadModule" ) ); + msg.setArguments( { moduleName } ); + dbus.call( msg, QDBus::NoBlock ); + } +} + +static void +querySolidAutoMount( QDBusConnection& dbus, AutoMountInfo& info ) +{ + const auto moduleName = QVariant( QStringLiteral( "device_automounter" ) ); + + // Find previous setting; this **does** need to block + auto msg = kdedCall( QStringLiteral( "isModuleAutoloaded" ) ); + msg.setArguments( { moduleName } ); + QDBusMessage r = dbus.call( msg, QDBus::Block ); + if ( r.type() == QDBusMessage::ReplyMessage ) + { + auto arg = r.arguments(); + cDebug() << arg; + info.wasSolidModuleAutoLoaded = false; + } +} + +std::unique_ptr< AutoMountInfo > +automountDisable() +{ + auto u = std::make_unique< AutoMountInfo >(); + QDBusConnection dbus = QDBusConnection::sessionBus(); + querySolidAutoMount( dbus, *u ); + enableSolidAutoMount( dbus, false ); + return u; +} + + +void +automountRestore( std::unique_ptr< AutoMountInfo >&& t ) +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + enableSolidAutoMount( dbus, t->wasSolidModuleAutoLoaded ); +} + +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/libcalamares/partition/AutoMount.h b/src/libcalamares/partition/AutoMount.h new file mode 100644 index 000000000..ecb1780a0 --- /dev/null +++ b/src/libcalamares/partition/AutoMount.h @@ -0,0 +1,48 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + * + */ + +#ifndef PARTITION_AUTOMOUNT_H +#define PARTITION_AUTOMOUNT_H + +#include "DllMacro.h" + +#include + +namespace CalamaresUtils +{ +namespace Partition +{ + +struct AutoMountInfo; + +/** @brief Disable automount + * + * Various subsystems can do "agressive automount", which can get in the + * way of partitioning actions. In particular, Solid can be configured + * to automount every device it sees, and partitioning happens in multiple + * steps (create table, create partition, set partition flags) which are + * blocked if the partition gets mounted partway through the operation. + * + * Returns an opaque structure which can be passed to automountRestore() + * to return the system to the previously-configured automount settings. + */ +DLLEXPORT std::unique_ptr< AutoMountInfo > automountDisable(); + +/** @brief Restore automount settings + * + * Pass the value returned from automountDisable() to restore the + * previous settings. + */ +DLLEXPORT void automountRestore( std::unique_ptr< AutoMountInfo >&& t ); + +} // namespace Partition +} // namespace CalamaresUtils + +#endif