File indexing completed on 2024-06-16 05:09:49

0001 /*
0002  *   SPDX-FileCopyrightText: 2017 Ivan Cukic <ivan.cukic (at) kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "encfsbackend.h"
0008 
0009 #include <QDir>
0010 #include <QProcess>
0011 #include <QRegularExpression>
0012 
0013 #include <KConfigGroup>
0014 #include <KLocalizedString>
0015 #include <KMountPoint>
0016 #include <KSharedConfig>
0017 
0018 #include <algorithm>
0019 
0020 #include <asynqt/basic/all.h>
0021 #include <asynqt/operations/collect.h>
0022 #include <asynqt/operations/transform.h>
0023 #include <asynqt/wrappers/process.h>
0024 
0025 #include <singleton_p.h>
0026 
0027 using namespace AsynQt;
0028 
0029 namespace PlasmaVault
0030 {
0031 EncFsBackend::EncFsBackend()
0032 {
0033 }
0034 
0035 EncFsBackend::~EncFsBackend()
0036 {
0037 }
0038 
0039 Backend::Ptr EncFsBackend::instance()
0040 {
0041     return singleton::instance<EncFsBackend>();
0042 }
0043 
0044 FutureResult<> EncFsBackend::mount(const Device &device, const MountPoint &mountPoint, const Vault::Payload &payload)
0045 {
0046     QDir dir;
0047 
0048     const auto password = payload[KEY_PASSWORD].toString();
0049 
0050     if (!dir.mkpath(device.data()) || !dir.mkpath(mountPoint.data())) {
0051         return errorResult(Error::BackendError, i18n("Failed to create directories, check your permissions"));
0052     }
0053     removeDotDirectory(mountPoint);
0054 
0055     auto process = encfs({
0056         "-S", // read password from stdin
0057         "--standard", // If creating a file system, use the default options
0058         device.data(), // source directory to initialize encfs in
0059         mountPoint.data() // where to mount the file system
0060     });
0061 
0062     auto result = makeFuture(process, hasProcessFinishedSuccessfully);
0063 
0064     // Writing the password
0065     process->write(password.toUtf8());
0066     process->write("\n");
0067 
0068     return result;
0069 }
0070 
0071 FutureResult<> EncFsBackend::validateBackend()
0072 {
0073     using namespace AsynQt::operators;
0074 
0075     // We need to check whether all the commands are installed
0076     // and whether the user has permissions to run them
0077     return collect(checkVersion(encfs({"--version"}), std::make_tuple(1, 9, 1)),
0078                    checkVersion(encfsctl({"--version"}), std::make_tuple(1, 9, 1)),
0079                    checkVersion(fusermount({"--version"}), std::make_tuple(2, 9, 7)))
0080 
0081         | transform([this](const QPair<bool, QString> &encfs, const QPair<bool, QString> &encfsctl, const QPair<bool, QString> &fusermount) {
0082                bool success = encfs.first && encfsctl.first && fusermount.first;
0083                QString message = formatMessageLine("encfs", encfs) + formatMessageLine("encfsctl", encfsctl) + formatMessageLine("fusermount", fusermount);
0084 
0085                return success ? Result<>::success() : Result<>::error(Error::BackendError, message);
0086            });
0087 }
0088 
0089 bool EncFsBackend::isInitialized(const Device &device) const
0090 {
0091     auto process = encfsctl({device.data()});
0092 
0093     process->start();
0094     process->waitForFinished();
0095 
0096     return process->exitCode() == 0;
0097 }
0098 
0099 QProcess *EncFsBackend::encfs(const QStringList &arguments) const
0100 {
0101     auto config = KSharedConfig::openConfig(PLASMAVAULT_CONFIG_FILE);
0102     KConfigGroup backendConfig(config, "EncfsBackend");
0103 
0104     return process("encfs", arguments + backendConfig.readEntry("extraMountOptions", QStringList{}), {});
0105 }
0106 
0107 QProcess *EncFsBackend::encfsctl(const QStringList &arguments) const
0108 {
0109     return process("encfsctl", arguments, {});
0110 }
0111 
0112 } // namespace PlasmaVault