From c739ae6af89cbe2c34848a10ac554f907f8e6757 Mon Sep 17 00:00:00 2001 From: V3n3RiX Date: Sun, 16 Oct 2016 18:24:22 +0100 Subject: prepare calamares 2.4.2 with dracut luks support --- .../files/calamares-2.4.2-dracut-luks-fde.patch | 1918 ++++++++++++++++++++ 1 file changed, 1918 insertions(+) create mode 100644 app-admin/calamares/files/calamares-2.4.2-dracut-luks-fde.patch (limited to 'app-admin/calamares/files') diff --git a/app-admin/calamares/files/calamares-2.4.2-dracut-luks-fde.patch b/app-admin/calamares/files/calamares-2.4.2-dracut-luks-fde.patch new file mode 100644 index 00000000..55669822 --- /dev/null +++ b/app-admin/calamares/files/calamares-2.4.2-dracut-luks-fde.patch @@ -0,0 +1,1918 @@ +From 03c7357dbcb70c047c0aac0a2566c50aaaed1168 Mon Sep 17 00:00:00 2001 +From: Kevin Kofler +Date: Sun, 25 Sep 2016 03:20:50 +0200 +Subject: [PATCH] Add support for LUKS full disk encryption with dracut. + +Add support for C++/Qt batch job plugins + +These job plugins work similarly to view modules, with the following +differences: + +* These jobs need to link only libcalamares, not libcalamaresui. For + this reason, PluginFactory was moved from libcalamaresui to + libcalamares. (It depends only on QtCore.) + +* Instead of deriving from ViewModule, derive from CppJob (which is a + subclass of Job). + +* Like process and Python jobs, a job plugin is a single job, whereas a + ViewModule can generate a whole list of jobs. + +The CppJob and CppJobModule classes are new. In Module::fromDescriptor, +the combination type=job, intf=qtplugin is now supported and mapped to +CppJobModule. + +[fstab] Do not omit "/" from crypttab. + +At least the Debian update-initramfs needs the entry to be there (see +pull request #254). Dracut will probably need it too. And logically, it +should be there. + +[fstab] Write configurable options to crypttab (default: luks). + +fstab.conf: Add a new "crypttabOptions" option that defaults to "luks". + Document that for Debian and Debian-based distributions, the + setting should be changed to "luks,keyscript=/bin/cat". + +main.py: Append the options from the above setting to the end of every + line in crypttab. + +At least the "luks" option should always be there, because there may be +different encryption types. The Debian initramfs-tools also require the +Debian-specific keyscript option and will otherwise ignore the keyfile +entirely (see pull request #254). + +[dracutlukscfg] New module: pre-configuration for dracut+LUKS. + +Add a dracutlukscfg module to write a +/etc/dracut.conf.d/calamares-luks.conf file for LUKS full disk +encryption support with Dracut. + +You should run: + +* partition +* luksbootkeyfile +* dracutlukscfg +* dracut + +in that order (not necessarily in immediate sequence). The +luksopenswaphook module is not used with Dracut. +--- + settings.conf | 1 + + src/libcalamares/CMakeLists.txt | 2 + + src/libcalamares/CppJob.cpp | 45 +++ + src/libcalamares/CppJob.h | 51 ++++ + src/libcalamares/utils/PluginFactory.cpp | 123 ++++++++ + src/libcalamares/utils/PluginFactory.h | 370 +++++++++++++++++++++++ + src/libcalamares/utils/PluginFactory_p.h | 54 ++++ + src/libcalamaresui/CMakeLists.txt | 3 +- + src/libcalamaresui/modulesystem/CppJobModule.cpp | 128 ++++++++ + src/libcalamaresui/modulesystem/CppJobModule.h | 53 ++++ + src/libcalamaresui/modulesystem/Module.cpp | 7 +- + src/libcalamaresui/utils/PluginFactory.cpp | 123 -------- + src/libcalamaresui/utils/PluginFactory.h | 370 ----------------------- + src/libcalamaresui/utils/PluginFactory_p.h | 54 ---- + src/modules/dracutlukscfg/CMakeLists.txt | 9 + + src/modules/dracutlukscfg/DracutLuksCfgJob.cpp | 143 +++++++++ + src/modules/dracutlukscfg/DracutLuksCfgJob.h | 56 ++++ + src/modules/dracutlukscfg/module.desc | 7 + + src/modules/fstab/fstab.conf | 3 + + src/modules/fstab/main.py | 21 +- + 20 files changed, 1064 insertions(+), 559 deletions(-) + create mode 100644 src/libcalamares/CppJob.cpp + create mode 100644 src/libcalamares/CppJob.h + create mode 100644 src/libcalamares/utils/PluginFactory.cpp + create mode 100644 src/libcalamares/utils/PluginFactory.h + create mode 100644 src/libcalamares/utils/PluginFactory_p.h + create mode 100644 src/libcalamaresui/modulesystem/CppJobModule.cpp + create mode 100644 src/libcalamaresui/modulesystem/CppJobModule.h + delete mode 100644 src/libcalamaresui/utils/PluginFactory.cpp + delete mode 100644 src/libcalamaresui/utils/PluginFactory.h + delete mode 100644 src/libcalamaresui/utils/PluginFactory_p.h + create mode 100644 src/modules/dracutlukscfg/CMakeLists.txt + create mode 100644 src/modules/dracutlukscfg/DracutLuksCfgJob.cpp + create mode 100644 src/modules/dracutlukscfg/DracutLuksCfgJob.h + create mode 100644 src/modules/dracutlukscfg/module.desc + +diff --git a/settings.conf b/settings.conf +index 0721098..d4439a7 100644 +--- a/settings.conf ++++ b/settings.conf +@@ -79,6 +79,7 @@ sequence: + - localecfg + # - luksbootkeyfile + # - luksopenswaphookcfg ++# - dracutlukscfg + - initcpiocfg + - initcpio + - users +diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt +index 966ca9c..b1f6c48 100644 +--- a/src/libcalamares/CMakeLists.txt ++++ b/src/libcalamares/CMakeLists.txt +@@ -11,6 +11,7 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../calamares/CalamaresVersion.h.in + ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersion.h ) + + set( libSources ++ CppJob.cpp + GlobalStorage.cpp + Job.cpp + JobQueue.cpp +@@ -24,6 +25,7 @@ set( libSources + utils/CalamaresUtils.cpp + utils/CalamaresUtilsSystem.cpp + utils/Logger.cpp ++ utils/PluginFactory.cpp + utils/Retranslator.cpp + ) + +diff --git a/src/libcalamares/CppJob.cpp b/src/libcalamares/CppJob.cpp +new file mode 100644 +index 0000000..1925e39 +--- /dev/null ++++ b/src/libcalamares/CppJob.cpp +@@ -0,0 +1,45 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2014, Teo Mrnjavac ++ * Copyright 2016, Kevin Kofler ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#include "CppJob.h" ++ ++namespace Calamares ++{ ++ ++CppJob::CppJob( QObject* parent ) ++ : Job( parent ) ++{} ++ ++ ++CppJob::~CppJob() ++{} ++ ++ ++void ++CppJob::setModuleInstanceKey( const QString& instanceKey ) ++{ ++ m_instanceKey = instanceKey; ++} ++ ++ ++void ++CppJob::setConfigurationMap( const QVariantMap& configurationMap ) ++{} ++ ++} +diff --git a/src/libcalamares/CppJob.h b/src/libcalamares/CppJob.h +new file mode 100644 +index 0000000..a6e6735 +--- /dev/null ++++ b/src/libcalamares/CppJob.h +@@ -0,0 +1,51 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2014-2015, Teo Mrnjavac ++ * Copyright 2016, Kevin Kofler ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#ifndef CALAMARES_CPPJOB_H ++#define CALAMARES_CPPJOB_H ++ ++#include ++#include ++ ++#include "DllMacro.h" ++#include "Typedefs.h" ++#include "Job.h" ++ ++namespace Calamares ++{ ++ ++class DLLEXPORT CppJob : public Job ++{ ++ Q_OBJECT ++public: ++ explicit CppJob( QObject* parent = nullptr ); ++ virtual ~CppJob(); ++ ++ void setModuleInstanceKey( const QString& instanceKey ); ++ QString moduleInstanceKey() const { return m_instanceKey; } ++ ++ virtual void setConfigurationMap( const QVariantMap& configurationMap ); ++ ++protected: ++ QString m_instanceKey; ++}; ++ ++} ++ ++#endif // CALAMARES_CPPJOB_H +diff --git a/src/libcalamares/utils/PluginFactory.cpp b/src/libcalamares/utils/PluginFactory.cpp +new file mode 100644 +index 0000000..30a5bf4 +--- /dev/null ++++ b/src/libcalamares/utils/PluginFactory.cpp +@@ -0,0 +1,123 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2015, Teo Mrnjavac ++ * ++ * Based on KPluginFactory from KCoreAddons, KDE project ++ * Copyright 2007, Matthias Kretz ++ * Copyright 2007, Bernhard Loos ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#include "PluginFactory.h" ++#include "PluginFactory_p.h" ++ ++#include ++#include ++ ++Q_GLOBAL_STATIC(QObjectCleanupHandler, factorycleanup) ++ ++extern int kLibraryDebugArea(); ++ ++namespace Calamares ++{ ++ ++PluginFactory::PluginFactory() ++ : d_ptr(new PluginFactoryPrivate) ++{ ++ Q_D(PluginFactory); ++ d->q_ptr = this; ++ ++ factorycleanup()->add(this); ++} ++ ++PluginFactory::PluginFactory(PluginFactoryPrivate &d) ++ : d_ptr(&d) ++{ ++ factorycleanup()->add(this); ++} ++ ++PluginFactory::~PluginFactory() ++{ ++ delete d_ptr; ++} ++ ++void PluginFactory::doRegisterPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction) ++{ ++ Q_D(PluginFactory); ++ ++ Q_ASSERT(metaObject); ++ ++ // we allow different interfaces to be registered without keyword ++ if (!keyword.isEmpty()) { ++ if (d->createInstanceHash.contains(keyword)) { ++ qWarning() << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!"; ++ } ++ d->createInstanceHash.insert(keyword, PluginFactoryPrivate::Plugin(metaObject, instanceFunction)); ++ } else { ++ const QList clashes(d->createInstanceHash.values(keyword)); ++ const QMetaObject *superClass = metaObject->superClass(); ++ if (superClass) { ++ for (const PluginFactoryPrivate::Plugin &plugin : clashes) { ++ for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; ++ otherSuper = otherSuper->superClass()) { ++ if (superClass == otherSuper) { ++ qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; ++ } ++ } ++ } ++ } ++ for (const PluginFactoryPrivate::Plugin &plugin : clashes) { ++ superClass = plugin.first->superClass(); ++ if (superClass) { ++ for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; ++ otherSuper = otherSuper->superClass()) { ++ if (superClass == otherSuper) { ++ qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; ++ } ++ } ++ } ++ } ++ d->createInstanceHash.insertMulti(keyword, PluginFactoryPrivate::Plugin(metaObject, instanceFunction)); ++ } ++} ++ ++QObject *PluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QString &keyword) ++{ ++ Q_D(PluginFactory); ++ ++ QObject *obj = 0; ++ ++ const QList candidates(d->createInstanceHash.values(keyword)); ++ // for !keyword.isEmpty() candidates.count() is 0 or 1 ++ ++ for (const PluginFactoryPrivate::Plugin &plugin : candidates) { ++ for (const QMetaObject *current = plugin.first; current; current = current->superClass()) { ++ if (0 == qstrcmp(iface, current->className())) { ++ if (obj) { ++ qWarning() << "ambiguous interface requested from a DSO containing more than one plugin"; ++ } ++ obj = plugin.second(parentWidget, parent); ++ break; ++ } ++ } ++ } ++ ++ if (obj) { ++ emit objectCreated(obj); ++ } ++ return obj; ++} ++ ++} +diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h +new file mode 100644 +index 0000000..c0053ba +--- /dev/null ++++ b/src/libcalamares/utils/PluginFactory.h +@@ -0,0 +1,370 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2015, Teo Mrnjavac ++ * ++ * Based on KPluginFactory from KCoreAddons, KDE project ++ * Copyright 2007, Matthias Kretz ++ * Copyright 2007, Bernhard Loos ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#ifndef CALAMARESPLUGINFACTORY_H ++#define CALAMARESPLUGINFACTORY_H ++ ++#include "DllMacro.h" ++ ++#include ++#include ++#include ++ ++namespace Calamares ++{ ++class PluginFactoryPrivate; ++} ++ ++#define CalamaresPluginFactory_iid "io.calamares.PluginFactory" ++ ++#define CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, ...) \ ++ class name : public Calamares::PluginFactory \ ++ { \ ++ Q_OBJECT \ ++ Q_INTERFACES(Calamares::PluginFactory) \ ++ __VA_ARGS__ \ ++ public: \ ++ explicit name(); \ ++ ~name(); \ ++ private: \ ++ void init(); \ ++ }; ++ ++#define CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \ ++ CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid)) ++ ++#define CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \ ++ name::name() \ ++ { \ ++ pluginRegistrations \ ++ } \ ++ name::~name() {} ++ ++#define CALAMARES_PLUGIN_FACTORY_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \ ++ CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \ ++ CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) ++ ++#define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, Calamares::PluginFactory) ++#define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, Calamares::PluginFactory, pluginRegistrations) ++ ++/** ++ * \relates PluginFactory ++ * ++ * Create a PluginFactory subclass and export it as the root plugin object. ++ * ++ * \param name The name of the PluginFactory derived class. ++ * ++ * \param pluginRegistrations Code to be inserted into the constructor of the ++ * class. Usually a series of registerPlugin() calls. ++ * ++ * Example: ++ * \code ++ * #include ++ * #include ++ * ++ * class MyPlugin : public PluginInterface ++ * { ++ * public: ++ * MyPlugin(QObject *parent, const QVariantList &args) ++ * : PluginInterface(parent) ++ * {} ++ * }; ++ * ++ * CALAMARES_PLUGIN_FACTORY(MyPluginFactory, ++ * registerPlugin(); ++ * ) ++ * ++ * #include ++ * \endcode ++ * ++ * \see CALAMARES_PLUGIN_FACTORY_DECLARATION ++ * \see CALAMARES_PLUGIN_FACTORY_DEFINITION ++ */ ++#define CALAMARES_PLUGIN_FACTORY(name, pluginRegistrations) CALAMARES_PLUGIN_FACTORY_WITH_BASEFACTORY(name, Calamares::PluginFactory, pluginRegistrations) ++ ++/** ++ * \relates PluginFactory ++ * ++ * CALAMARES_PLUGIN_FACTORY_DECLARATION declares the PluginFactory subclass. This macro ++ * can be used in a header file. ++ * ++ * \param name The name of the PluginFactory derived class. ++ * ++ * \see CALAMARES_PLUGIN_FACTORY ++ * \see CALAMARES_PLUGIN_FACTORY_DEFINITION ++ */ ++#define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, Calamares::PluginFactory) ++ ++/** ++ * \relates PluginFactory ++ * CALAMARES_PLUGIN_FACTORY_DEFINITION defines the PluginFactory subclass. This macro ++ * can not be used in a header file. ++ * ++ * \param name The name of the PluginFactory derived class. ++ * ++ * \param pluginRegistrations Code to be inserted into the constructor of the ++ * class. Usually a series of registerPlugin() calls. ++ * ++ * \see CALAMARES_PLUGIN_FACTORY ++ * \see CALAMARES_PLUGIN_FACTORY_DECLARATION ++ */ ++#define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, Calamares::PluginFactory, pluginRegistrations) ++ ++namespace Calamares ++{ ++ ++/** ++ * \class PluginFactory PluginFactory.h ++ * ++ * PluginFactory provides a convenient way to provide factory-style plugins. ++ * Qt plugins provide a singleton object, but a common pattern is for plugins ++ * to generate as many objects of a particular type as the application requires. ++ * By using PluginFactory, you can avoid implementing the factory pattern ++ * yourself. ++ * ++ * PluginFactory also allows plugins to provide multiple different object ++ * types, indexed by keywords. ++ * ++ * The objects created by PluginFactory must inherit QObject, and must have a ++ * standard constructor pattern: ++ * \li if the object is a KPart::Part, it must be of the form ++ * \code ++ * T(QWidget *parentWidget, QObject *parent, const QVariantList &args) ++ * \endcode ++ * \li if it is a QWidget, it must be of the form ++ * \code ++ * T(QWidget *parent, const QVariantList &args) ++ * \endcode ++ * \li otherwise it must be of the form ++ * \code ++ * T(QObject *parent, const QVariantList &args) ++ * \endcode ++ * ++ * You should typically use either CALAMARES_PLUGIN_FACTORY() or ++ * CALAMARES_PLUGIN_FACTORY_WITH_JSON() in your plugin code to create the factory. The ++ * typical pattern is ++ * ++ * \code ++ * #include ++ * #include ++ * ++ * class MyPlugin : public PluginInterface ++ * { ++ * public: ++ * MyPlugin(QObject *parent, const QVariantList &args) ++ * : PluginInterface(parent) ++ * {} ++ * }; ++ * ++ * CALAMARES_PLUGIN_FACTORY(MyPluginFactory, ++ * registerPlugin(); ++ * ) ++ * #include ++ * \endcode ++ * ++ * If you want to load a library use KPluginLoader. ++ * The application that wants to instantiate plugin classes can do the following: ++ * \code ++ * PluginFactory *factory = KPluginLoader("libraryname").factory(); ++ * if (factory) { ++ * PluginInterface *p1 = factory->create(parent); ++ * OtherInterface *p2 = factory->create(parent); ++ * NextInterface *p3 = factory->create("keyword1", parent); ++ * NextInterface *p3 = factory->create("keyword2", parent); ++ * } ++ * \endcode ++ * ++ * \author Matthias Kretz ++ * \author Bernhard Loos ++ */ ++class DLLEXPORT PluginFactory : public QObject ++{ ++ Q_OBJECT ++ Q_DECLARE_PRIVATE(PluginFactory) ++public: ++ /** ++ * This constructor creates a factory for a plugin. ++ */ ++ explicit PluginFactory(); ++ ++ /** ++ * This destroys the PluginFactory. ++ */ ++ virtual ~PluginFactory(); ++ ++ /** ++ * Use this method to create an object. It will try to create an object which inherits ++ * \p T. If it has multiple choices, you will get a fatal error (kFatal()), so be careful ++ * to request a unique interface or use keywords. ++ * ++ * \tparam T The interface for which an object should be created. The object will inherit \p T. ++ * \param parent The parent of the object. If \p parent is a widget type, it will also passed ++ * to the parentWidget argument of the CreateInstanceFunction for the object. ++ * \returns A pointer to the created object is returned, or 0 if an error occurred. ++ */ ++ template ++ T *create(QObject *parent = 0); ++ ++ /** ++ * Use this method to create an object. It will try to create an object which inherits ++ * \p T and was registered with \p keyword. ++ * ++ * \tparam T The interface for which an object should be created. The object will inherit \p T. ++ * \param keyword The keyword of the object. ++ * \param parent The parent of the object. If \p parent is a widget type, it will also passed ++ * to the parentWidget argument of the CreateInstanceFunction for the object. ++ * \returns A pointer to the created object is returned, or 0 if an error occurred. ++ */ ++ template ++ T *create(const QString &keyword, QObject *parent = 0); ++ ++Q_SIGNALS: ++ void objectCreated(QObject *object); ++ ++protected: ++ /** ++ * Function pointer type to a function that instantiates a plugin. ++ */ ++ typedef QObject *(*CreateInstanceFunction)(QWidget *, QObject *); ++ ++ /** ++ * This is used to detect the arguments need for the constructor of plugin classes. ++ * You can inherit it, if you want to add new classes and still keep support for the old ones. ++ */ ++ template ++ struct InheritanceChecker { ++ CreateInstanceFunction createInstanceFunction(QWidget *) ++ { ++ return &createInstance; ++ } ++ CreateInstanceFunction createInstanceFunction(...) ++ { ++ return &createInstance; ++ } ++ }; ++ ++ explicit PluginFactory(PluginFactoryPrivate &dd); ++ ++ /** ++ * Registers a plugin with the factory. Call this function from the constructor of the ++ * PluginFactory subclass to make the create function able to instantiate the plugin when asked ++ * for an interface the plugin implements. ++ * ++ * \tparam T the name of the plugin class ++ * ++ * \param keyword An optional keyword as unique identifier for the plugin. This allows you to ++ * put more than one plugin with the same interface into the same library using the same ++ * factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file. ++ * ++ * \param instanceFunction A function pointer to a function that creates an instance of the ++ * plugin. The default function that will be used depends on the type of interface. If the ++ * interface inherits from ++ * \li \c KParts::Part the function will call ++ * \code ++ * new T(QWidget *parentWidget, QObject *parent) ++ * \endcode ++ * \li \c QWidget the function will call ++ * \code ++ * new T(QWidget *parent) ++ * \endcode ++ * \li else the function will call ++ * \code ++ * new T(QObject *parent) ++ * \endcode ++ */ ++ template ++ void registerPlugin(const QString &keyword = QString(), ++ CreateInstanceFunction instanceFunction ++ = InheritanceChecker().createInstanceFunction(reinterpret_cast(0))) ++ { ++ doRegisterPlugin(keyword, &T::staticMetaObject, instanceFunction); ++ } ++ ++ PluginFactoryPrivate *const d_ptr; ++ ++ /** ++ * This function is called when the factory asked to create an Object. ++ * ++ * You may reimplement it to provide a very flexible factory. This is especially useful to ++ * provide generic factories for plugins implemeted using a scripting language. ++ * ++ * \param iface The staticMetaObject::className() string identifying the plugin interface that ++ * was requested. E.g. for KCModule plugins this string will be "KCModule". ++ * \param parentWidget Only used if the requested plugin is a KPart. ++ * \param parent The parent object for the plugin object. ++ * \param args A plugin specific list of arbitrary arguments. ++ * \param keyword A string that uniquely identifies the plugin. If a KService is used this ++ * keyword is read from the X-KDE-PluginKeyword entry in the .desktop file. ++ */ ++ virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QString &keyword); ++ ++ template ++ static QObject *createInstance(QWidget *parentWidget, QObject *parent) ++ { ++ Q_UNUSED(parentWidget); ++ ParentType *p = 0; ++ if (parent) { ++ p = qobject_cast(parent); ++ Q_ASSERT(p); ++ } ++ return new impl(p); ++ } ++ ++private: ++ void doRegisterPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction); ++}; ++ ++template ++inline T *PluginFactory::create(QObject *parent) ++{ ++ QObject *o = create(T::staticMetaObject.className(), ++ parent && parent->isWidgetType() ? reinterpret_cast(parent) : 0, ++ parent, ++ QString()); ++ ++ T *t = qobject_cast(o); ++ if (!t) { ++ delete o; ++ } ++ return t; ++} ++ ++template ++inline T *PluginFactory::create(const QString &keyword, QObject *parent) ++{ ++ QObject *o = create(T::staticMetaObject.className(), ++ parent && parent->isWidgetType() ? reinterpret_cast(parent) : 0, ++ parent, ++ keyword); ++ ++ T *t = qobject_cast(o); ++ if (!t) { ++ delete o; ++ } ++ return t; ++} ++ ++} ++ ++Q_DECLARE_INTERFACE(Calamares::PluginFactory, CalamaresPluginFactory_iid) ++ ++#endif // CALAMARESPLUGINFACTORY_H +diff --git a/src/libcalamares/utils/PluginFactory_p.h b/src/libcalamares/utils/PluginFactory_p.h +new file mode 100644 +index 0000000..a0b4a1c +--- /dev/null ++++ b/src/libcalamares/utils/PluginFactory_p.h +@@ -0,0 +1,54 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2015, Teo Mrnjavac ++ * ++ * Based on KPluginFactory from KCoreAddons, KDE project ++ * Copyright 2007, Matthias Kretz ++ * Copyright 2007, Bernhard Loos ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#ifndef CALAMARESPLUGINFACTORY_P_H ++#define CALAMARESPLUGINFACTORY_P_H ++ ++#include "PluginFactory.h" ++ ++#include ++ ++namespace Calamares ++{ ++ ++class PluginFactoryPrivate ++{ ++ Q_DECLARE_PUBLIC(PluginFactory) ++protected: ++ typedef QPair Plugin; ++ ++ PluginFactoryPrivate() ++ : catalogInitialized( false ) ++ , q_ptr( nullptr ) ++ {} ++ ~PluginFactoryPrivate() {} ++ ++ QHash createInstanceHash; ++ QString catalogName; ++ bool catalogInitialized; ++ ++ PluginFactory *q_ptr; ++}; ++ ++} ++ ++#endif // CALAMARESPLUGINFACTORY_P_H +diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt +index 939d05a..478034b 100644 +--- a/src/libcalamaresui/CMakeLists.txt ++++ b/src/libcalamaresui/CMakeLists.txt +@@ -1,6 +1,7 @@ + set( CALAMARESUI_LIBRARY_TARGET calamaresui ) + + list( APPEND ${CALAMARESUI_LIBRARY_TARGET}_SOURCES ++ modulesystem/CppJobModule.cpp + modulesystem/Module.cpp + modulesystem/ModuleManager.cpp + modulesystem/ProcessJobModule.cpp +@@ -14,8 +15,6 @@ list( APPEND ${CALAMARESUI_LIBRARY_TARGET}_SOURCES + utils/qjsonmodel.cpp + utils/qjsonitem.cpp + +- utils/PluginFactory.cpp +- + viewpages/AbstractPage.cpp + viewpages/ViewStep.cpp + +diff --git a/src/libcalamaresui/modulesystem/CppJobModule.cpp b/src/libcalamaresui/modulesystem/CppJobModule.cpp +new file mode 100644 +index 0000000..15e41c2 +--- /dev/null ++++ b/src/libcalamaresui/modulesystem/CppJobModule.cpp +@@ -0,0 +1,128 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2014, Teo Mrnjavac ++ * Copyright 2016, Kevin Kofler ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#include "CppJobModule.h" ++ ++#include "utils/PluginFactory.h" ++#include "utils/Logger.h" ++#include "CppJob.h" ++ ++#include ++#include ++ ++namespace Calamares { ++ ++ ++Module::Type ++CppJobModule::type() const ++{ ++ return Job; ++} ++ ++ ++Module::Interface ++CppJobModule::interface() const ++{ ++ return QtPlugin; ++} ++ ++ ++void ++CppJobModule::loadSelf() ++{ ++ if ( m_loader ) ++ { ++ PluginFactory* pf = qobject_cast< PluginFactory* >( m_loader->instance() ); ++ if ( !pf ) ++ { ++ cDebug() << Q_FUNC_INFO << m_loader->errorString(); ++ return; ++ } ++ ++ CppJob *cppJob = pf->create< Calamares::CppJob >(); ++ if ( !cppJob ) ++ { ++ cDebug() << Q_FUNC_INFO << m_loader->errorString(); ++ return; ++ } ++// cDebug() << "CppJobModule loading self for instance" << instanceKey() ++// << "\nCppJobModule at address" << this ++// << "\nCalamares::PluginFactory at address" << pf ++// << "\nCppJob at address" << cppJob; ++ ++ cppJob->setModuleInstanceKey( instanceKey() ); ++ cppJob->setConfigurationMap( m_configurationMap ); ++ m_job = Calamares::job_ptr( static_cast< Calamares::Job * >( cppJob ) ); ++ m_loaded = true; ++ cDebug() << "CppJobModule" << instanceKey() << "loading complete."; ++ } ++} ++ ++ ++QList< job_ptr > ++CppJobModule::jobs() const ++{ ++ return QList< job_ptr >() << m_job; ++} ++ ++ ++void ++CppJobModule::initFrom( const QVariantMap& moduleDescriptor ) ++{ ++ Module::initFrom( moduleDescriptor ); ++ QDir directory( location() ); ++ QString load; ++ if ( !moduleDescriptor.value( "load" ).toString().isEmpty() ) ++ { ++ load = moduleDescriptor.value( "load" ).toString(); ++ load = directory.absoluteFilePath( load ); ++ } ++ // If a load path is not specified, we look for a plugin to load in the directory. ++ if ( load.isEmpty() || !QLibrary::isLibrary( load ) ) ++ { ++ const QStringList ls = directory.entryList( QStringList{ "*.so" } ); ++ if ( !ls.isEmpty() ) ++ { ++ for ( QString entry : ls ) ++ { ++ entry = directory.absoluteFilePath( entry ); ++ if ( QLibrary::isLibrary( entry ) ) ++ { ++ load = entry; ++ break; ++ } ++ } ++ } ++ } ++ ++ m_loader = new QPluginLoader( load ); ++} ++ ++CppJobModule::CppJobModule() ++ : Module() ++ , m_loader( nullptr ) ++{ ++} ++ ++CppJobModule::~CppJobModule() ++{ ++ delete m_loader; ++} ++ ++} // namespace Calamares +diff --git a/src/libcalamaresui/modulesystem/CppJobModule.h b/src/libcalamaresui/modulesystem/CppJobModule.h +new file mode 100644 +index 0000000..127614e +--- /dev/null ++++ b/src/libcalamaresui/modulesystem/CppJobModule.h +@@ -0,0 +1,53 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2014, Teo Mrnjavac ++ * Copyright 2016, Kevin Kofler ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#ifndef CALAMARES_CPPJOBMODULE_H ++#define CALAMARES_CPPJOBMODULE_H ++ ++#include "UiDllMacro.h" ++#include "Module.h" ++ ++class QPluginLoader; ++ ++namespace Calamares { ++ ++class UIDLLEXPORT CppJobModule : public Module ++{ ++public: ++ Type type() const override; ++ Interface interface() const override; ++ ++ void loadSelf() override; ++ QList< job_ptr > jobs() const override; ++ ++protected: ++ void initFrom( const QVariantMap& moduleDescriptor ) override; ++ ++private: ++ friend class Module; //so only the superclass can instantiate ++ explicit CppJobModule(); ++ virtual ~CppJobModule(); ++ ++ QPluginLoader* m_loader; ++ job_ptr m_job; ++}; ++ ++} // namespace Calamares ++ ++#endif // CALAMARES_CPPJOBMODULE_H +diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp +index 7809754..2a2fe77 100644 +--- a/src/libcalamaresui/modulesystem/Module.cpp ++++ b/src/libcalamaresui/modulesystem/Module.cpp +@@ -19,6 +19,7 @@ + #include "Module.h" + + #include "ProcessJobModule.h" ++#include "CppJobModule.h" + #include "ViewModule.h" + #include "utils/CalamaresUtils.h" + #include "utils/YamlUtils.h" +@@ -76,7 +77,11 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, + } + else if ( typeString == "job" ) + { +- if ( intfString == "process" ) ++ if ( intfString == "qtplugin" ) ++ { ++ m = new CppJobModule(); ++ } ++ else if ( intfString == "process" ) + { + m = new ProcessJobModule(); + } +diff --git a/src/libcalamaresui/utils/PluginFactory.cpp b/src/libcalamaresui/utils/PluginFactory.cpp +deleted file mode 100644 +index 30a5bf4..0000000 +--- a/src/libcalamaresui/utils/PluginFactory.cpp ++++ /dev/null +@@ -1,123 +0,0 @@ +-/* === This file is part of Calamares - === +- * +- * Copyright 2015, Teo Mrnjavac +- * +- * Based on KPluginFactory from KCoreAddons, KDE project +- * Copyright 2007, Matthias Kretz +- * Copyright 2007, Bernhard Loos +- * +- * Calamares is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Calamares is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Calamares. If not, see . +- */ +- +-#include "PluginFactory.h" +-#include "PluginFactory_p.h" +- +-#include +-#include +- +-Q_GLOBAL_STATIC(QObjectCleanupHandler, factorycleanup) +- +-extern int kLibraryDebugArea(); +- +-namespace Calamares +-{ +- +-PluginFactory::PluginFactory() +- : d_ptr(new PluginFactoryPrivate) +-{ +- Q_D(PluginFactory); +- d->q_ptr = this; +- +- factorycleanup()->add(this); +-} +- +-PluginFactory::PluginFactory(PluginFactoryPrivate &d) +- : d_ptr(&d) +-{ +- factorycleanup()->add(this); +-} +- +-PluginFactory::~PluginFactory() +-{ +- delete d_ptr; +-} +- +-void PluginFactory::doRegisterPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction) +-{ +- Q_D(PluginFactory); +- +- Q_ASSERT(metaObject); +- +- // we allow different interfaces to be registered without keyword +- if (!keyword.isEmpty()) { +- if (d->createInstanceHash.contains(keyword)) { +- qWarning() << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!"; +- } +- d->createInstanceHash.insert(keyword, PluginFactoryPrivate::Plugin(metaObject, instanceFunction)); +- } else { +- const QList clashes(d->createInstanceHash.values(keyword)); +- const QMetaObject *superClass = metaObject->superClass(); +- if (superClass) { +- for (const PluginFactoryPrivate::Plugin &plugin : clashes) { +- for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; +- otherSuper = otherSuper->superClass()) { +- if (superClass == otherSuper) { +- qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; +- } +- } +- } +- } +- for (const PluginFactoryPrivate::Plugin &plugin : clashes) { +- superClass = plugin.first->superClass(); +- if (superClass) { +- for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; +- otherSuper = otherSuper->superClass()) { +- if (superClass == otherSuper) { +- qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; +- } +- } +- } +- } +- d->createInstanceHash.insertMulti(keyword, PluginFactoryPrivate::Plugin(metaObject, instanceFunction)); +- } +-} +- +-QObject *PluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QString &keyword) +-{ +- Q_D(PluginFactory); +- +- QObject *obj = 0; +- +- const QList candidates(d->createInstanceHash.values(keyword)); +- // for !keyword.isEmpty() candidates.count() is 0 or 1 +- +- for (const PluginFactoryPrivate::Plugin &plugin : candidates) { +- for (const QMetaObject *current = plugin.first; current; current = current->superClass()) { +- if (0 == qstrcmp(iface, current->className())) { +- if (obj) { +- qWarning() << "ambiguous interface requested from a DSO containing more than one plugin"; +- } +- obj = plugin.second(parentWidget, parent); +- break; +- } +- } +- } +- +- if (obj) { +- emit objectCreated(obj); +- } +- return obj; +-} +- +-} +diff --git a/src/libcalamaresui/utils/PluginFactory.h b/src/libcalamaresui/utils/PluginFactory.h +deleted file mode 100644 +index a77d959..0000000 +--- a/src/libcalamaresui/utils/PluginFactory.h ++++ /dev/null +@@ -1,370 +0,0 @@ +-/* === This file is part of Calamares - === +- * +- * Copyright 2015, Teo Mrnjavac +- * +- * Based on KPluginFactory from KCoreAddons, KDE project +- * Copyright 2007, Matthias Kretz +- * Copyright 2007, Bernhard Loos +- * +- * Calamares is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Calamares is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Calamares. If not, see . +- */ +- +-#ifndef CALAMARESPLUGINFACTORY_H +-#define CALAMARESPLUGINFACTORY_H +- +-#include "UiDllMacro.h" +- +-#include +-#include +-#include +- +-namespace Calamares +-{ +-class PluginFactoryPrivate; +-} +- +-#define CalamaresPluginFactory_iid "io.calamares.PluginFactory" +- +-#define CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, ...) \ +- class name : public Calamares::PluginFactory \ +- { \ +- Q_OBJECT \ +- Q_INTERFACES(Calamares::PluginFactory) \ +- __VA_ARGS__ \ +- public: \ +- explicit name(); \ +- ~name(); \ +- private: \ +- void init(); \ +- }; +- +-#define CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \ +- CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid)) +- +-#define CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \ +- name::name() \ +- { \ +- pluginRegistrations \ +- } \ +- name::~name() {} +- +-#define CALAMARES_PLUGIN_FACTORY_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \ +- CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \ +- CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) +- +-#define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, Calamares::PluginFactory) +-#define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, Calamares::PluginFactory, pluginRegistrations) +- +-/** +- * \relates PluginFactory +- * +- * Create a PluginFactory subclass and export it as the root plugin object. +- * +- * \param name The name of the PluginFactory derived class. +- * +- * \param pluginRegistrations Code to be inserted into the constructor of the +- * class. Usually a series of registerPlugin() calls. +- * +- * Example: +- * \code +- * #include +- * #include +- * +- * class MyPlugin : public PluginInterface +- * { +- * public: +- * MyPlugin(QObject *parent, const QVariantList &args) +- * : PluginInterface(parent) +- * {} +- * }; +- * +- * CALAMARES_PLUGIN_FACTORY(MyPluginFactory, +- * registerPlugin(); +- * ) +- * +- * #include +- * \endcode +- * +- * \see CALAMARES_PLUGIN_FACTORY_DECLARATION +- * \see CALAMARES_PLUGIN_FACTORY_DEFINITION +- */ +-#define CALAMARES_PLUGIN_FACTORY(name, pluginRegistrations) CALAMARES_PLUGIN_FACTORY_WITH_BASEFACTORY(name, Calamares::PluginFactory, pluginRegistrations) +- +-/** +- * \relates PluginFactory +- * +- * CALAMARES_PLUGIN_FACTORY_DECLARATION declares the PluginFactory subclass. This macro +- * can be used in a header file. +- * +- * \param name The name of the PluginFactory derived class. +- * +- * \see CALAMARES_PLUGIN_FACTORY +- * \see CALAMARES_PLUGIN_FACTORY_DEFINITION +- */ +-#define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) CALAMARES_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, Calamares::PluginFactory) +- +-/** +- * \relates PluginFactory +- * CALAMARES_PLUGIN_FACTORY_DEFINITION defines the PluginFactory subclass. This macro +- * can not be used in a header file. +- * +- * \param name The name of the PluginFactory derived class. +- * +- * \param pluginRegistrations Code to be inserted into the constructor of the +- * class. Usually a series of registerPlugin() calls. +- * +- * \see CALAMARES_PLUGIN_FACTORY +- * \see CALAMARES_PLUGIN_FACTORY_DECLARATION +- */ +-#define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) CALAMARES_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, Calamares::PluginFactory, pluginRegistrations) +- +-namespace Calamares +-{ +- +-/** +- * \class PluginFactory PluginFactory.h +- * +- * PluginFactory provides a convenient way to provide factory-style plugins. +- * Qt plugins provide a singleton object, but a common pattern is for plugins +- * to generate as many objects of a particular type as the application requires. +- * By using PluginFactory, you can avoid implementing the factory pattern +- * yourself. +- * +- * PluginFactory also allows plugins to provide multiple different object +- * types, indexed by keywords. +- * +- * The objects created by PluginFactory must inherit QObject, and must have a +- * standard constructor pattern: +- * \li if the object is a KPart::Part, it must be of the form +- * \code +- * T(QWidget *parentWidget, QObject *parent, const QVariantList &args) +- * \endcode +- * \li if it is a QWidget, it must be of the form +- * \code +- * T(QWidget *parent, const QVariantList &args) +- * \endcode +- * \li otherwise it must be of the form +- * \code +- * T(QObject *parent, const QVariantList &args) +- * \endcode +- * +- * You should typically use either CALAMARES_PLUGIN_FACTORY() or +- * CALAMARES_PLUGIN_FACTORY_WITH_JSON() in your plugin code to create the factory. The +- * typical pattern is +- * +- * \code +- * #include +- * #include +- * +- * class MyPlugin : public PluginInterface +- * { +- * public: +- * MyPlugin(QObject *parent, const QVariantList &args) +- * : PluginInterface(parent) +- * {} +- * }; +- * +- * CALAMARES_PLUGIN_FACTORY(MyPluginFactory, +- * registerPlugin(); +- * ) +- * #include +- * \endcode +- * +- * If you want to load a library use KPluginLoader. +- * The application that wants to instantiate plugin classes can do the following: +- * \code +- * PluginFactory *factory = KPluginLoader("libraryname").factory(); +- * if (factory) { +- * PluginInterface *p1 = factory->create(parent); +- * OtherInterface *p2 = factory->create(parent); +- * NextInterface *p3 = factory->create("keyword1", parent); +- * NextInterface *p3 = factory->create("keyword2", parent); +- * } +- * \endcode +- * +- * \author Matthias Kretz +- * \author Bernhard Loos +- */ +-class UIDLLEXPORT PluginFactory : public QObject +-{ +- Q_OBJECT +- Q_DECLARE_PRIVATE(PluginFactory) +-public: +- /** +- * This constructor creates a factory for a plugin. +- */ +- explicit PluginFactory(); +- +- /** +- * This destroys the PluginFactory. +- */ +- virtual ~PluginFactory(); +- +- /** +- * Use this method to create an object. It will try to create an object which inherits +- * \p T. If it has multiple choices, you will get a fatal error (kFatal()), so be careful +- * to request a unique interface or use keywords. +- * +- * \tparam T The interface for which an object should be created. The object will inherit \p T. +- * \param parent The parent of the object. If \p parent is a widget type, it will also passed +- * to the parentWidget argument of the CreateInstanceFunction for the object. +- * \returns A pointer to the created object is returned, or 0 if an error occurred. +- */ +- template +- T *create(QObject *parent = 0); +- +- /** +- * Use this method to create an object. It will try to create an object which inherits +- * \p T and was registered with \p keyword. +- * +- * \tparam T The interface for which an object should be created. The object will inherit \p T. +- * \param keyword The keyword of the object. +- * \param parent The parent of the object. If \p parent is a widget type, it will also passed +- * to the parentWidget argument of the CreateInstanceFunction for the object. +- * \returns A pointer to the created object is returned, or 0 if an error occurred. +- */ +- template +- T *create(const QString &keyword, QObject *parent = 0); +- +-Q_SIGNALS: +- void objectCreated(QObject *object); +- +-protected: +- /** +- * Function pointer type to a function that instantiates a plugin. +- */ +- typedef QObject *(*CreateInstanceFunction)(QWidget *, QObject *); +- +- /** +- * This is used to detect the arguments need for the constructor of plugin classes. +- * You can inherit it, if you want to add new classes and still keep support for the old ones. +- */ +- template +- struct InheritanceChecker { +- CreateInstanceFunction createInstanceFunction(QWidget *) +- { +- return &createInstance; +- } +- CreateInstanceFunction createInstanceFunction(...) +- { +- return &createInstance; +- } +- }; +- +- explicit PluginFactory(PluginFactoryPrivate &dd); +- +- /** +- * Registers a plugin with the factory. Call this function from the constructor of the +- * PluginFactory subclass to make the create function able to instantiate the plugin when asked +- * for an interface the plugin implements. +- * +- * \tparam T the name of the plugin class +- * +- * \param keyword An optional keyword as unique identifier for the plugin. This allows you to +- * put more than one plugin with the same interface into the same library using the same +- * factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file. +- * +- * \param instanceFunction A function pointer to a function that creates an instance of the +- * plugin. The default function that will be used depends on the type of interface. If the +- * interface inherits from +- * \li \c KParts::Part the function will call +- * \code +- * new T(QWidget *parentWidget, QObject *parent) +- * \endcode +- * \li \c QWidget the function will call +- * \code +- * new T(QWidget *parent) +- * \endcode +- * \li else the function will call +- * \code +- * new T(QObject *parent) +- * \endcode +- */ +- template +- void registerPlugin(const QString &keyword = QString(), +- CreateInstanceFunction instanceFunction +- = InheritanceChecker().createInstanceFunction(reinterpret_cast(0))) +- { +- doRegisterPlugin(keyword, &T::staticMetaObject, instanceFunction); +- } +- +- PluginFactoryPrivate *const d_ptr; +- +- /** +- * This function is called when the factory asked to create an Object. +- * +- * You may reimplement it to provide a very flexible factory. This is especially useful to +- * provide generic factories for plugins implemeted using a scripting language. +- * +- * \param iface The staticMetaObject::className() string identifying the plugin interface that +- * was requested. E.g. for KCModule plugins this string will be "KCModule". +- * \param parentWidget Only used if the requested plugin is a KPart. +- * \param parent The parent object for the plugin object. +- * \param args A plugin specific list of arbitrary arguments. +- * \param keyword A string that uniquely identifies the plugin. If a KService is used this +- * keyword is read from the X-KDE-PluginKeyword entry in the .desktop file. +- */ +- virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QString &keyword); +- +- template +- static QObject *createInstance(QWidget *parentWidget, QObject *parent) +- { +- Q_UNUSED(parentWidget); +- ParentType *p = 0; +- if (parent) { +- p = qobject_cast(parent); +- Q_ASSERT(p); +- } +- return new impl(p); +- } +- +-private: +- void doRegisterPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction); +-}; +- +-template +-inline T *PluginFactory::create(QObject *parent) +-{ +- QObject *o = create(T::staticMetaObject.className(), +- parent && parent->isWidgetType() ? reinterpret_cast(parent) : 0, +- parent, +- QString()); +- +- T *t = qobject_cast(o); +- if (!t) { +- delete o; +- } +- return t; +-} +- +-template +-inline T *PluginFactory::create(const QString &keyword, QObject *parent) +-{ +- QObject *o = create(T::staticMetaObject.className(), +- parent && parent->isWidgetType() ? reinterpret_cast(parent) : 0, +- parent, +- keyword); +- +- T *t = qobject_cast(o); +- if (!t) { +- delete o; +- } +- return t; +-} +- +-} +- +-Q_DECLARE_INTERFACE(Calamares::PluginFactory, CalamaresPluginFactory_iid) +- +-#endif // CALAMARESPLUGINFACTORY_H +diff --git a/src/libcalamaresui/utils/PluginFactory_p.h b/src/libcalamaresui/utils/PluginFactory_p.h +deleted file mode 100644 +index a0b4a1c..0000000 +--- a/src/libcalamaresui/utils/PluginFactory_p.h ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* === This file is part of Calamares - === +- * +- * Copyright 2015, Teo Mrnjavac +- * +- * Based on KPluginFactory from KCoreAddons, KDE project +- * Copyright 2007, Matthias Kretz +- * Copyright 2007, Bernhard Loos +- * +- * Calamares is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Calamares is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Calamares. If not, see . +- */ +- +-#ifndef CALAMARESPLUGINFACTORY_P_H +-#define CALAMARESPLUGINFACTORY_P_H +- +-#include "PluginFactory.h" +- +-#include +- +-namespace Calamares +-{ +- +-class PluginFactoryPrivate +-{ +- Q_DECLARE_PUBLIC(PluginFactory) +-protected: +- typedef QPair Plugin; +- +- PluginFactoryPrivate() +- : catalogInitialized( false ) +- , q_ptr( nullptr ) +- {} +- ~PluginFactoryPrivate() {} +- +- QHash createInstanceHash; +- QString catalogName; +- bool catalogInitialized; +- +- PluginFactory *q_ptr; +-}; +- +-} +- +-#endif // CALAMARESPLUGINFACTORY_P_H +diff --git a/src/modules/dracutlukscfg/CMakeLists.txt b/src/modules/dracutlukscfg/CMakeLists.txt +new file mode 100644 +index 0000000..a239521 +--- /dev/null ++++ b/src/modules/dracutlukscfg/CMakeLists.txt +@@ -0,0 +1,9 @@ ++calamares_add_plugin( dracutlukscfg ++ TYPE job ++ EXPORT_MACRO PLUGINDLLEXPORT_PRO ++ SOURCES ++ DracutLuksCfgJob.cpp ++ LINK_LIBRARIES ++ calamares ++ SHARED_LIB ++) +diff --git a/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp b/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp +new file mode 100644 +index 0000000..273ff98 +--- /dev/null ++++ b/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp +@@ -0,0 +1,143 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2016, Kevin Kofler ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#include "DracutLuksCfgJob.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "CalamaresVersion.h" ++#include "JobQueue.h" ++#include "GlobalStorage.h" ++ ++#include "utils/Logger.h" ++ ++// static ++const QString DracutLuksCfgJob::CONFIG_FILE = QStringLiteral( "/etc/dracut.conf.d/calamares-luks.conf" ); ++ ++// static ++const char *DracutLuksCfgJob::CONFIG_FILE_CONTENTS = ++ "# Configuration file automatically written by the Calamares system installer\n" ++ "# (This file is written once at install time and should be safe to edit.)\n" ++ "# Enables support for LUKS full disk encryption with single sign on from GRUB.\n" ++ "\n" ++ "# force installing /etc/crypttab even if hostonly=\"no\", install the keyfile\n" ++ "install_items+=\" /etc/crypttab /crypto_keyfile.bin \"\n"; ++ ++// static ++const QString DracutLuksCfgJob::CONFIG_FILE_SWAPLINE = QStringLiteral( "# enable automatic resume from swap\nadd_device+=\" /dev/disk/by-uuid/%1 \"\n" ); ++ ++// static ++QString ++DracutLuksCfgJob::rootMountPoint() ++{ ++ Calamares::GlobalStorage *globalStorage = Calamares::JobQueue::instance()->globalStorage(); ++ return globalStorage->value( QStringLiteral( "rootMountPoint" ) ).toString(); ++} ++ ++// static ++QVariantList ++DracutLuksCfgJob::partitions() ++{ ++ Calamares::GlobalStorage *globalStorage = Calamares::JobQueue::instance()->globalStorage(); ++ return globalStorage->value( QStringLiteral( "partitions" ) ).toList(); ++} ++ ++// static ++bool ++DracutLuksCfgJob::isRootEncrypted() ++{ ++ const QVariantList partitions = DracutLuksCfgJob::partitions(); ++ for ( const QVariant &partition : partitions ) ++ { ++ QVariantMap partitionMap = partition.toMap(); ++ QString mountPoint = partitionMap.value( QStringLiteral( "mountPoint" ) ).toString(); ++ if ( mountPoint == QStringLiteral( "/" ) ) ++ return partitionMap.contains( QStringLiteral( "luksMapperName" ) ); ++ } ++ return false; ++} ++ ++// static ++QString ++DracutLuksCfgJob::swapOuterUuid() ++{ ++ const QVariantList partitions = DracutLuksCfgJob::partitions(); ++ for ( const QVariant &partition : partitions ) ++ { ++ QVariantMap partitionMap = partition.toMap(); ++ QString fsType = partitionMap.value( QStringLiteral( "fs" ) ).toString(); ++ if ( fsType == QStringLiteral( "linuxswap" ) && partitionMap.contains( QStringLiteral( "luksMapperName" ) ) ) ++ return partitionMap.value( QStringLiteral( "luksUuid" ) ).toString(); ++ } ++ return QString(); ++} ++ ++DracutLuksCfgJob::DracutLuksCfgJob( QObject* parent ) ++ : Calamares::CppJob( parent ) ++{ ++} ++ ++ ++DracutLuksCfgJob::~DracutLuksCfgJob() ++{ ++} ++ ++ ++QString ++DracutLuksCfgJob::prettyName() const ++{ ++ if ( isRootEncrypted() ) ++ return tr( "Write LUKS configuration for Dracut to %1" ).arg( CONFIG_FILE ); ++ else ++ return tr( "Skip writing LUKS configuration for Dracut: \"/\" partition is not encrypted" ); ++} ++ ++ ++Calamares::JobResult ++DracutLuksCfgJob::exec() ++{ ++ if ( isRootEncrypted() ) ++ { ++ const QString realConfigFilePath = rootMountPoint() + CONFIG_FILE; ++ cDebug() << "[DRACUTLUKSCFG]: Writing" << realConfigFilePath; ++ QDir( QStringLiteral( "/" ) ).mkpath( QFileInfo( realConfigFilePath ).absolutePath() ); ++ QFile configFile( realConfigFilePath ); ++ if ( ! configFile.open( QIODevice::WriteOnly | QIODevice::Text ) ) ++ { ++ cDebug() << "[DRACUTLUKSCFG]: Failed to open" << realConfigFilePath; ++ return Calamares::JobResult::error( tr( "Failed to open %1" ).arg( realConfigFilePath ) ); ++ } ++ QTextStream outStream( &configFile ); ++ outStream << CONFIG_FILE_CONTENTS; ++ const QString swapOuterUuid = DracutLuksCfgJob::swapOuterUuid(); ++ if ( ! swapOuterUuid.isEmpty() ) ++ { ++ cDebug() << "[DRACUTLUKSCFG]: Swap outer UUID" << swapOuterUuid; ++ outStream << CONFIG_FILE_SWAPLINE.arg( swapOuterUuid ).toLatin1(); ++ } ++ cDebug() << "[DRACUTLUKSCFG]: Wrote config to" << realConfigFilePath; ++ } else ++ cDebug() << "[DRACUTLUKSCFG]: / not encrypted, skipping"; ++ ++ return Calamares::JobResult::ok(); ++} ++ ++CALAMARES_PLUGIN_FACTORY_DEFINITION( DracutLuksCfgJobFactory, registerPlugin(); ) +diff --git a/src/modules/dracutlukscfg/DracutLuksCfgJob.h b/src/modules/dracutlukscfg/DracutLuksCfgJob.h +new file mode 100644 +index 0000000..bfedb85 +--- /dev/null ++++ b/src/modules/dracutlukscfg/DracutLuksCfgJob.h +@@ -0,0 +1,56 @@ ++/* === This file is part of Calamares - === ++ * ++ * Copyright 2016, Kevin Kofler ++ * ++ * Calamares is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * Calamares is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Calamares. If not, see . ++ */ ++ ++#ifndef DRACUTLUKSCFGJOB_H ++#define DRACUTLUKSCFGJOB_H ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++class PLUGINDLLEXPORT DracutLuksCfgJob : public Calamares::CppJob ++{ ++ Q_OBJECT ++ ++public: ++ explicit DracutLuksCfgJob( QObject* parent = nullptr ); ++ virtual ~DracutLuksCfgJob(); ++ ++ QString prettyName() const override; ++ ++ Calamares::JobResult exec() override; ++ ++private: ++ static const QString CONFIG_FILE; ++ static const char *CONFIG_FILE_CONTENTS; ++ static const QString CONFIG_FILE_SWAPLINE; ++ ++ static QString rootMountPoint(); ++ static QVariantList partitions(); ++ static bool isRootEncrypted(); ++ static QString swapOuterUuid(); ++}; ++ ++CALAMARES_PLUGIN_FACTORY_DECLARATION( DracutLuksCfgJobFactory ) ++ ++#endif // DRACUTLUKSCFGJOB_H +diff --git a/src/modules/dracutlukscfg/module.desc b/src/modules/dracutlukscfg/module.desc +new file mode 100644 +index 0000000..10d9b78 +--- /dev/null ++++ b/src/modules/dracutlukscfg/module.desc +@@ -0,0 +1,7 @@ ++# Module metadata file for dracutlukscfg job ++# Syntax is YAML 1.2 ++--- ++type: "job" ++name: "dracutlukscfg" ++interface: "qtplugin" ++load: "libcalamares_job_dracutlukscfg.so" +diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf +index 7dbf529..c3dbfc3 100644 +--- a/src/modules/fstab/fstab.conf ++++ b/src/modules/fstab/fstab.conf +@@ -8,3 +8,6 @@ ssdExtraMountOptions: + xfs: discard + swap: discard + btrfs: discard,compress=lzo ++crypttabOptions: luks ++# For Debian and Debian-based distributions, change the above line to: ++# crypttabOptions: luks,keyscript=/bin/cat +diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py +index 65f483b..05b094f 100644 +--- a/src/modules/fstab/main.py ++++ b/src/modules/fstab/main.py +@@ -102,11 +102,13 @@ class FstabGenerator(object): + :param mount_options: + :param ssd_extra_mount_options: + """ +- def __init__(self, partitions, root_mount_point, mount_options, ssd_extra_mount_options): ++ def __init__(self, partitions, root_mount_point, mount_options, ++ ssd_extra_mount_options, crypttab_options): + self.partitions = partitions + self.root_mount_point = root_mount_point + self.mount_options = mount_options + self.ssd_extra_mount_options = ssd_extra_mount_options ++ self.crypttab_options = crypttab_options + self.ssd_disks = set() + self.root_is_ssd = False + +@@ -152,21 +154,20 @@ class FstabGenerator(object): + if not mapper_name or not luks_uuid: + return None + +- if mount_point == "/": +- return None +- + return dict( + name=mapper_name, + device="UUID=" + luks_uuid, + password="/crypto_keyfile.bin", ++ options=self.crypttab_options, + ) + + def print_crypttab_line(self, dct, file=None): + """ Prints line to '/etc/crypttab' file. """ +- line = "{:21} {:<45} {}".format(dct["name"], +- dct["device"], +- dct["password"], +- ) ++ line = "{:21} {:<45} {} {}".format(dct["name"], ++ dct["device"], ++ dct["password"], ++ dct["options"], ++ ) + + print(line, file=file) + +@@ -258,9 +259,11 @@ def run(): + root_mount_point = global_storage.value("rootMountPoint") + mount_options = conf["mountOptions"] + ssd_extra_mount_options = conf.get("ssdExtraMountOptions", {}) ++ crypttab_options = conf.get("crypttabOptions", "luks") + generator = FstabGenerator(partitions, + root_mount_point, + mount_options, +- ssd_extra_mount_options) ++ ssd_extra_mount_options, ++ crypttab_options) + + return generator.run() +-- +2.1.0 + -- cgit v1.2.3