diff options
author | Hannah von Reth <vonreth@kde.org> | 2022-05-05 13:16:49 +0300 |
---|---|---|
committer | Hannah von Reth <vonreth@kde.org> | 2022-05-10 12:04:09 +0300 |
commit | 64f3c376c345f5ba0c54f5f444bf04ca312752b7 (patch) | |
tree | a0df6c8f4490bf3c11110c429e36c7908150ae62 /src/plugins | |
parent | 3108ea863c55ddb861c8c9bc9202a0781ae08f38 (diff) |
Move vfs plugins out of libsync
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/plugins/vfs/CMakeLists.txt | 25 | ||||
-rw-r--r-- | src/plugins/vfs/off/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/plugins/vfs/off/vfs_off.cpp | 104 | ||||
-rw-r--r-- | src/plugins/vfs/off/vfs_off.h | 68 | ||||
-rw-r--r-- | src/plugins/vfs/suffix/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/plugins/vfs/suffix/vfs_suffix.cpp | 157 | ||||
-rw-r--r-- | src/plugins/vfs/suffix/vfs_suffix.h | 75 |
8 files changed, 452 insertions, 0 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt new file mode 100644 index 000000000..276f2be05 --- /dev/null +++ b/src/plugins/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(vfs) diff --git a/src/plugins/vfs/CMakeLists.txt b/src/plugins/vfs/CMakeLists.txt new file mode 100644 index 000000000..dadf1eed9 --- /dev/null +++ b/src/plugins/vfs/CMakeLists.txt @@ -0,0 +1,25 @@ +# Globbing for plugins has a problem with in-source builds +# that create directories for the build. + +foreach(vfsPlugin ${VIRTUAL_FILE_SYSTEM_PLUGINS}) + set(vfsPluginPath ${vfsPlugin}) + set(vfsPluginPathOut ${vfsPlugin}) + get_filename_component(vfsPluginName ${vfsPlugin} NAME) + if (NOT IS_ABSOLUTE ${vfsPlugin}) + set(vfsPluginPath "${CMAKE_CURRENT_LIST_DIR}/${vfsPlugin}") + else() + get_filename_component(vfsPluginPathOut ${vfsPluginPath} DIRECTORY) + endif() + if(NOT IS_DIRECTORY ${vfsPluginPath}) + continue() + endif() + + add_subdirectory(${vfsPluginPath} ${vfsPluginPathOut}) + + if(BUILD_TESTING AND IS_DIRECTORY "${vfsPluginPath}/test") + add_subdirectory("${vfsPluginPath}/test" "${vfsPluginName}_test") + message(STATUS "Added vfsPlugin with tests: ${vfsPluginName}") + else() + message(STATUS "Added vfsPlugin without tests: ${vfsPluginName}") + endif() +endforeach() diff --git a/src/plugins/vfs/off/CMakeLists.txt b/src/plugins/vfs/off/CMakeLists.txt new file mode 100644 index 000000000..08b539e36 --- /dev/null +++ b/src/plugins/vfs/off/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(owncloud_vfs_off MODULE + vfs_off.cpp +) + +set_target_properties(owncloud_vfs_off PROPERTIES OUTPUT_NAME "${synclib_NAME}_vfs_off") + +target_link_libraries(owncloud_vfs_off PRIVATE + libsync +) +INSTALL(TARGETS owncloud_vfs_off DESTINATION "${KDE_INSTALL_PLUGINDIR}") + diff --git a/src/plugins/vfs/off/vfs_off.cpp b/src/plugins/vfs/off/vfs_off.cpp new file mode 100644 index 000000000..cced0ca13 --- /dev/null +++ b/src/plugins/vfs/off/vfs_off.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ + +#include "vfs_off.h" + +#include "filesystem.h" +#include "syncfileitem.h" + +using namespace OCC; + +VfsOff::VfsOff(QObject *parent) + : Vfs(parent) +{ +} + +VfsOff::~VfsOff() = default; + +Vfs::Mode VfsOff::mode() const +{ + return Vfs::Off; +} + +QString VfsOff::fileSuffix() const +{ + return QString(); +} + +void VfsOff::stop() { } + +void VfsOff::unregisterFolder() { } + +bool VfsOff::socketApiPinStateActionsShown() const +{ + return false; +} + +bool OCC::VfsOff::isHydrating() const +{ + return false; +} + +Result<void, QString> VfsOff::createPlaceholder(const SyncFileItem &) +{ + return {}; +} + +bool VfsOff::needsMetadataUpdate(const SyncFileItem &) +{ + return false; +} + +bool VfsOff::isDehydratedPlaceholder(const QString &) +{ + return false; +} + +bool VfsOff::statTypeVirtualFile(csync_file_stat_t *, void *) +{ + return false; +} + +bool VfsOff::setPinState(const QString &, PinState) +{ + return true; +} + +Optional<PinState> VfsOff::pinState(const QString &) +{ + return PinState::AlwaysLocal; +} + +Vfs::AvailabilityResult VfsOff::availability(const QString &) +{ + return VfsItemAvailability::AlwaysLocal; +} + +void VfsOff::startImpl(const VfsSetupParams &) +{ + Q_EMIT started(); +} + +Result<Vfs::ConvertToPlaceholderResult, QString> VfsOff::updateMetadata(const SyncFileItem &item, const QString &filePath, const QString &replacesFile) +{ + if (!item.isDirectory()) { + const bool isReadOnly = !item._remotePerm.isNull() && !item._remotePerm.hasPermission(RemotePermissions::CanWrite); + FileSystem::setFileReadOnlyWeak(filePath, isReadOnly); + } + return { ConvertToPlaceholderResult::Ok }; +} + +void VfsOff::fileStatusChanged(const QString &, SyncFileStatus) +{ +}
\ No newline at end of file diff --git a/src/plugins/vfs/off/vfs_off.h b/src/plugins/vfs/off/vfs_off.h new file mode 100644 index 000000000..eec48cc07 --- /dev/null +++ b/src/plugins/vfs/off/vfs_off.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) by Christian Kamm <mail@ckamm.de> + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ +#pragma once + +#include <QObject> +#include <QScopedPointer> + +#include "common/plugin.h" +#include "common/vfs.h" + +namespace OCC { + +class VfsOff : public Vfs +{ + Q_OBJECT + +public: + VfsOff(QObject *parent = nullptr); + ~VfsOff() override; + + Mode mode() const override; + + QString fileSuffix() const override; + + void stop() override; + void unregisterFolder() override; + + bool socketApiPinStateActionsShown() const override; + bool isHydrating() const override; + + Result<void, QString> createPlaceholder(const SyncFileItem &) override; + + bool needsMetadataUpdate(const SyncFileItem &) override; + bool isDehydratedPlaceholder(const QString &) override; + bool statTypeVirtualFile(csync_file_stat_t *, void *) override; + + bool setPinState(const QString &, PinState) override; + Optional<PinState> pinState(const QString &) override; + AvailabilityResult availability(const QString &) override; + +public slots: + void fileStatusChanged(const QString &, SyncFileStatus) override; + +protected: + Result<ConvertToPlaceholderResult, QString> updateMetadata(const SyncFileItem &, const QString &, const QString &) override; + void startImpl(const VfsSetupParams &) override; +}; + + +class OffVfsPluginFactory : public QObject, public DefaultPluginFactory<VfsOff> +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.owncloud.PluginFactory" FILE "vfspluginmetadata.json") + Q_INTERFACES(OCC::PluginFactory) +}; + +} // namespace OCC diff --git a/src/plugins/vfs/suffix/CMakeLists.txt b/src/plugins/vfs/suffix/CMakeLists.txt new file mode 100644 index 000000000..bdc33cac4 --- /dev/null +++ b/src/plugins/vfs/suffix/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(owncloud_vfs_suffix MODULE + vfs_suffix.cpp +) + +set_target_properties(owncloud_vfs_suffix PROPERTIES OUTPUT_NAME "${synclib_NAME}_vfs_suffix") + +target_link_libraries(owncloud_vfs_suffix + libsync +) +INSTALL(TARGETS owncloud_vfs_suffix DESTINATION "${KDE_INSTALL_PLUGINDIR}") + diff --git a/src/plugins/vfs/suffix/vfs_suffix.cpp b/src/plugins/vfs/suffix/vfs_suffix.cpp new file mode 100644 index 000000000..c2ffd4b90 --- /dev/null +++ b/src/plugins/vfs/suffix/vfs_suffix.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) by Christian Kamm <mail@ckamm.de> + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ + +#include "vfs_suffix.h" + +#include <QFile> + +#include "common/syncjournaldb.h" +#include "filesystem.h" +#include "syncfileitem.h" + +namespace OCC { + +VfsSuffix::VfsSuffix(QObject *parent) + : Vfs(parent) +{ +} + +VfsSuffix::~VfsSuffix() +{ +} + +Vfs::Mode VfsSuffix::mode() const +{ + return WithSuffix; +} + +QString VfsSuffix::fileSuffix() const +{ + return QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX); +} + +void VfsSuffix::startImpl(const VfsSetupParams ¶ms) +{ + // It is unsafe for the database to contain any ".owncloud" file entries + // that are not marked as a virtual file. These could be real .owncloud + // files that were synced before vfs was enabled. + QByteArrayList toWipe; + params.journal->getFilesBelowPath("", [&toWipe](const SyncJournalFileRecord &rec) { + if (!rec.isVirtualFile() && rec._path.endsWith(APPLICATION_DOTVIRTUALFILE_SUFFIX)) + toWipe.append(rec._path); + }); + for (const auto &path : toWipe) { + params.journal->deleteFileRecord(QString::fromUtf8(path)); + } + Q_EMIT started(); +} + +void VfsSuffix::stop() +{ +} + +void VfsSuffix::unregisterFolder() +{ +} + +bool VfsSuffix::isHydrating() const +{ + return false; +} + +Result<Vfs::ConvertToPlaceholderResult, QString> VfsSuffix::updateMetadata(const SyncFileItem &item, const QString &filePath, const QString &) +{ + if (item._type == ItemTypeVirtualFileDehydration) { + SyncFileItem virtualItem(item); + virtualItem._file = item._renameTarget; + auto r = createPlaceholder(virtualItem); + if (!r) { + return r.error(); + } + // Move the item's pin state + auto pin = _setupParams.journal->internalPinStates().rawForPath(item._file.toUtf8()); + if (pin && *pin != PinState::Inherited) { + setPinState(item._renameTarget, *pin); + } + if (item._file != item._renameTarget) { // can be the same when renaming foo -> foo.owncloud to dehydrate + QString error; + if (!FileSystem::remove(_setupParams.filesystemPath + item._file, &error)) { + return error; + } + } + _setupParams.journal->deleteFileRecord(item._originalFile); + } else { + OC_ASSERT(FileSystem::setModTime(filePath, item._modtime)); + } + if (!item.isDirectory()) { + const bool isReadOnly = !item._remotePerm.isNull() && !item._remotePerm.hasPermission(RemotePermissions::CanWrite); + FileSystem::setFileReadOnlyWeak(filePath, isReadOnly); + } + return Vfs::ConvertToPlaceholderResult::Ok; +} + +Result<void, QString> VfsSuffix::createPlaceholder(const SyncFileItem &item) +{ + // The concrete shape of the placeholder is also used in isDehydratedPlaceholder() below + const QString fn = _setupParams.filesystemPath + item._file; + Q_ASSERT(fn.endsWith(fileSuffix())); + + QFile file(fn); + if (file.exists() && file.size() > 1 + && FileSystem::fileChanged(fn, item._size, item._modtime)) { + return tr("Cannot create a placeholder because a file with the placeholder name already exist"); + } + + if (!file.open(QFile::ReadWrite | QFile::Truncate)) { + return file.errorString(); + } + file.write(" "); + file.close(); + OC_ASSERT(FileSystem::setModTime(fn, item._modtime)); + return {}; +} + +bool VfsSuffix::isDehydratedPlaceholder(const QString &filePath) +{ + if (!filePath.endsWith(fileSuffix())) + return false; + QFileInfo fi(filePath); + return fi.exists() && fi.size() == 1; +} + +bool VfsSuffix::statTypeVirtualFile(csync_file_stat_t *stat, void *) +{ + if (stat->path.endsWith(fileSuffix().toUtf8())) { + stat->type = ItemTypeVirtualFile; + return true; + } + return false; +} + +Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath) +{ + return availabilityInDb(folderPath); +} + +QString VfsSuffix::underlyingFileName(const QString &fileName) const +{ + { + if (fileName.endsWith(fileSuffix())) { + return fileName.chopped(fileSuffix().size()); + } + return fileName; + } +} + +} // namespace OCC diff --git a/src/plugins/vfs/suffix/vfs_suffix.h b/src/plugins/vfs/suffix/vfs_suffix.h new file mode 100644 index 000000000..12ffe858b --- /dev/null +++ b/src/plugins/vfs/suffix/vfs_suffix.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) by Christian Kamm <mail@ckamm.de> + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ +#pragma once + +#include <QObject> +#include <QScopedPointer> + +#include "common/plugin.h" +#include "common/vfs.h" + +namespace OCC { + +class VfsSuffix : public Vfs +{ + Q_OBJECT + +public: + explicit VfsSuffix(QObject *parent = nullptr); + ~VfsSuffix() override; + + Mode mode() const override; + QString fileSuffix() const override; + QString underlyingFileName(const QString &fileName) const override; + + + void stop() override; + void unregisterFolder() override; + + bool socketApiPinStateActionsShown() const override { return true; } + bool isHydrating() const override; + + + Result<void, QString> createPlaceholder(const SyncFileItem &item) override; + + bool needsMetadataUpdate(const SyncFileItem &) override { return false; } + bool isDehydratedPlaceholder(const QString &filePath) override; + bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data) override; + + bool setPinState(const QString &folderPath, PinState state) override + { + return setPinStateInDb(folderPath, state); + } + Optional<PinState> pinState(const QString &folderPath) override + { + return pinStateInDb(folderPath); + } + AvailabilityResult availability(const QString &folderPath) override; + +public slots: + void fileStatusChanged(const QString &, SyncFileStatus) override { } + +protected: + Result<ConvertToPlaceholderResult, QString> updateMetadata(const SyncFileItem &item, const QString &filePath, const QString &replacesFile) override; + void startImpl(const VfsSetupParams ¶ms) override; +}; + +class SuffixVfsPluginFactory : public QObject, public DefaultPluginFactory<VfsSuffix> +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.owncloud.PluginFactory" FILE "vfspluginmetadata.json") + Q_INTERFACES(OCC::PluginFactory) +}; + +} // namespace OCC |