bring back dynamic load of VFS plugins

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
Matthieu Gallien 2021-06-11 19:17:10 +02:00 committed by Matthieu Gallien (Rebase PR Action)
parent fe925d8f36
commit 8ad6f89fed
24 changed files with 353 additions and 73 deletions

View file

@ -52,9 +52,6 @@
<Property Id="INSTALLDIR">
<RegistrySearch Id="RegistryInstallDir" Type="raw" Root="HKLM" Key="Software\$(var.AppVendor)\$(var.AppName)" Win64="no" />
</Property>
<Property Id="WINDOWSRELEASEID">
<RegistrySearch Id="RegistryWindowsReleaseId" Type="raw" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion" Name="ReleaseId"/>
</Property>
<!-- Detect legacy NSIS installation -->
<Property Id="NSIS_UNINSTALLEXE">

View file

@ -11,6 +11,8 @@ set(common_SOURCES
${CMAKE_CURRENT_LIST_DIR}/remotepermissions.cpp
${CMAKE_CURRENT_LIST_DIR}/vfs.cpp
${CMAKE_CURRENT_LIST_DIR}/pinstate.cpp
${CMAKE_CURRENT_LIST_DIR}/plugin.cpp
${CMAKE_CURRENT_LIST_DIR}/syncfilestatus.cpp
)
configure_file(${CMAKE_CURRENT_LIST_DIR}/vfspluginmetadata.json.in ${CMAKE_CURRENT_BINARY_DIR}/vfspluginmetadata.json)

33
src/common/plugin.cpp Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "plugin.h"
#include "config.h"
namespace OCC {
PluginFactory::~PluginFactory() = default;
QString pluginFileName(const QString &type, const QString &name)
{
return QStringLiteral("%1sync_%2_%3")
.arg(QStringLiteral(APPLICATION_EXECUTABLE), type, name);
}
}

48
src/common/plugin.h Normal file
View file

@ -0,0 +1,48 @@
/*
* Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "ocsynclib.h"
#include <QObject>
namespace OCC {
class OCSYNC_EXPORT PluginFactory
{
public:
virtual ~PluginFactory();
virtual QObject* create(QObject* parent) = 0;
};
template<class PluginClass>
class DefaultPluginFactory : public PluginFactory
{
public:
QObject* create(QObject *parent) override
{
return new PluginClass(parent);
}
};
/// Return the expected name of a plugin, for use with QPluginLoader
QString pluginFileName(const QString &type, const QString &name);
}
Q_DECLARE_INTERFACE(OCC::PluginFactory, "org.owncloud.PluginFactory")

View file

@ -17,6 +17,7 @@
*/
#include "vfs.h"
#include "plugin.h"
#include "version.h"
#include "syncjournaldb.h"
@ -27,15 +28,6 @@
using namespace OCC;
using MetaObjectHash = QHash<QString, Vfs::Factory>;
Q_GLOBAL_STATIC(MetaObjectHash, vfsFactoryHash);
void Vfs::registerPlugin(const QString &name, Factory factory)
{
Q_ASSERT(!vfsFactoryHash()->contains(name));
vfsFactoryHash()->insert(name, factory);
}
Vfs::Vfs(QObject* parent)
: QObject(parent)
{
@ -83,7 +75,8 @@ Result<bool, QString> Vfs::checkAvailability(const QString &path)
}
}
#else
Q_UNUSED(path);
Q_UNUSED(mode)
Q_UNUSED(path)
#endif
return true;
}
@ -146,7 +139,7 @@ static QString modeToPluginName(Vfs::Mode mode)
if (mode == Vfs::WithSuffix)
return QStringLiteral("suffix");
if (mode == Vfs::WindowsCfApi)
return QStringLiteral("win");
return QStringLiteral("cfapi");
if (mode == Vfs::XAttr)
return QStringLiteral("xattr");
return QString();
@ -157,14 +150,41 @@ Q_LOGGING_CATEGORY(lcPlugin, "plugins", QtInfoMsg)
bool OCC::isVfsPluginAvailable(Vfs::Mode mode)
{
// TODO: cache plugins available?
if (mode == Vfs::Off)
if (mode == Vfs::Off) {
return true;
auto name = modeToPluginName(mode);
if (name.isEmpty())
return false;
}
if (!vfsFactoryHash()->contains(name)) {
qCDebug(lcPlugin) << "Plugin isn't registered:" << name;
auto name = modeToPluginName(mode);
if (name.isEmpty()) {
return false;
}
QPluginLoader loader(pluginFileName(QStringLiteral("vfs"), name));
const auto baseMetaData = loader.metaData();
if (baseMetaData.isEmpty() || !baseMetaData.contains(QStringLiteral("IID"))) {
qCDebug(lcPlugin) << "Plugin doesn't exist" << loader.fileName();
return false;
}
if (baseMetaData[QStringLiteral("IID")].toString() != QStringLiteral("org.owncloud.PluginFactory")) {
qCWarning(lcPlugin) << "Plugin has wrong IID" << loader.fileName() << baseMetaData[QStringLiteral("IID")];
return false;
}
const auto metadata = baseMetaData[QStringLiteral("MetaData")].toObject();
if (metadata[QStringLiteral("type")].toString() != QStringLiteral("vfs")) {
qCWarning(lcPlugin) << "Plugin has wrong type" << loader.fileName() << metadata[QStringLiteral("type")];
return false;
}
if (metadata[QStringLiteral("version")].toString() != QStringLiteral(MIRALL_VERSION_STRING)) {
qCWarning(lcPlugin) << "Plugin has wrong version" << loader.fileName() << metadata[QStringLiteral("version")];
return false;
}
// Attempting to load the plugin is essential as it could have dependencies that
// can't be resolved and thus not be available after all.
if (!loader.load()) {
qCWarning(lcPlugin) << "Plugin failed to load:" << loader.errorString();
return false;
}
@ -210,26 +230,36 @@ std::unique_ptr<Vfs> OCC::createVfsFromPlugin(Vfs::Mode mode)
return std::unique_ptr<Vfs>(new VfsOff);
auto name = modeToPluginName(mode);
if (name.isEmpty())
if (name.isEmpty()) {
return nullptr;
}
const auto pluginPath = pluginFileName(QStringLiteral("vfs"), name);
if (!isVfsPluginAvailable(mode)) {
qCCritical(lcPlugin) << "Could not load plugin: not existant" << name;
qCCritical(lcPlugin) << "Could not load plugin: not existant or bad metadata" << pluginPath;
return nullptr;
}
const auto factory = vfsFactoryHash()->value(name);
QPluginLoader loader(pluginPath);
auto plugin = loader.instance();
if (!plugin) {
qCCritical(lcPlugin) << "Could not load plugin" << pluginPath << loader.errorString();
return nullptr;
}
auto factory = qobject_cast<PluginFactory *>(plugin);
if (!factory) {
qCCritical(lcPlugin) << "Could not load plugin" << name;
qCCritical(lcPlugin) << "Plugin" << loader.fileName() << "does not implement PluginFactory";
return nullptr;
}
auto vfs = std::unique_ptr<Vfs>(qobject_cast<Vfs *>(factory()));
auto vfs = std::unique_ptr<Vfs>(qobject_cast<Vfs *>(factory->create(nullptr)));
if (!vfs) {
qCCritical(lcPlugin) << "Plugin" << name << "does not create a Vfs instance";
qCCritical(lcPlugin) << "Plugin" << loader.fileName() << "does not create a Vfs instance";
return nullptr;
}
qCInfo(lcPlugin) << "Created VFS instance for:" << name;
qCInfo(lcPlugin) << "Created VFS instance from plugin" << pluginPath;
return vfs;
}

View file

@ -14,7 +14,6 @@
#pragma once
#include <QObject>
#include <QCoreApplication>
#include <QScopedPointer>
#include <QSharedPointer>
@ -126,9 +125,6 @@ public:
using AvailabilityResult = Result<VfsItemAvailability, AvailabilityError>;
public:
using Factory = Vfs* (*)();
static void registerPlugin(const QString &name, Factory factory);
explicit Vfs(QObject* parent = nullptr);
virtual ~Vfs();

View file

@ -58,26 +58,8 @@ set(libsync_SRCS
creds/abstractcredentials.cpp
creds/credentialscommon.cpp
creds/keychainchunk.cpp
vfs/suffix/vfs_suffix.cpp
)
if (WIN32)
set(libsync_SRCS ${libsync_SRCS}
vfs/cfapi/cfapiwrapper.cpp
vfs/cfapi/hydrationjob.cpp
vfs/cfapi/vfs_cfapi.cpp
)
add_definitions(-D_WIN32_WINNT=_WIN32_WINNT_WIN10)
list(APPEND OS_SPECIFIC_LINK_LIBRARIES cldapi)
elseif(LINUX) # elseif(LINUX OR APPLE)
set(libsync_SRCS ${libsync_SRCS} vfs/xattr/vfs_xattr.cpp)
if (APPLE)
set(libsync_SRCS ${libsync_SRCS} vfs/xattr/xattrwrapper_mac.cpp)
else()
set(libsync_SRCS ${libsync_SRCS} vfs/xattr/xattrwrapper_linux.cpp)
endif()
endif()
if(TOKEN_AUTH_ONLY)
set (libsync_SRCS ${libsync_SRCS} creds/tokencredentials.cpp)
else()
@ -159,3 +141,6 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
else()
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
endif()
add_subdirectory(vfs)

View file

@ -13,6 +13,7 @@
*/
#pragma once
#include "owncloudlib.h"
#include "owncloudpropagator.h"
#include "networkjobs.h"
#include "clientsideencryption.h"
@ -27,7 +28,7 @@ class PropagateDownloadEncrypted;
* @brief The GETFileJob class
* @ingroup libsync
*/
class GETFileJob : public AbstractNetworkJob
class OWNCLOUDSYNC_EXPORT GETFileJob : public AbstractNetworkJob
{
Q_OBJECT
QIODevice *_device;

View file

@ -0,0 +1,30 @@
# Globbing for plugins has a problem with in-source builds
# that create directories for the build.
#file(GLOB VIRTUAL_FILE_SYSTEM_PLUGINS RELATIVE ${CMAKE_CURRENT_LIST_DIR} "*")
list(APPEND VIRTUAL_FILE_SYSTEM_PLUGINS "suffix" "cfapi" "xattr")
message("list of plugins ${VIRTUAL_FILE_SYSTEM_PLUGINS}")
foreach(vfsPlugin ${VIRTUAL_FILE_SYSTEM_PLUGINS})
set(vfsPluginPath ${vfsPlugin})
get_filename_component(vfsPluginName ${vfsPlugin} NAME)
message("discovery ${vfsPlugin}")
if (NOT IS_ABSOLUTE ${vfsPlugin})
set(vfsPluginPath "${CMAKE_CURRENT_SOURCE_DIR}/${vfsPlugin}")
message("${vfsPluginPath}")
endif()
if(NOT IS_DIRECTORY ${vfsPluginPath})
continue()
endif()
message("${vfsPluginPath} ${vfsPluginName}")
add_subdirectory(${vfsPluginPath} ${vfsPluginName})
if(UNIT_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()

View file

@ -0,0 +1,36 @@
if (WIN32)
add_definitions(-D_WIN32_WINNT=_WIN32_WINNT_WIN10)
add_library("${synclib_NAME}_vfs_cfapi" SHARED
cfapiwrapper.cpp
hydrationjob.cpp
vfs_cfapi.cpp
)
target_link_libraries("${synclib_NAME}_vfs_cfapi"
"${synclib_NAME}"
cldapi
)
set_target_properties("${synclib_NAME}_vfs_cfapi" PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
PREFIX ""
AUTOMOC TRUE
)
target_include_directories("${synclib_NAME}_vfs_cfapi" BEFORE PUBLIC ${CMAKE_CURRENT_BINARY_DIR} INTERFACE ${CMAKE_BINARY_DIR})
set(vfs_installdir "${PLUGINDIR}")
GENERATE_EXPORT_HEADER( "${synclib_NAME}_vfs_cfapi"
BASE_NAME "${synclib_NAME}_vfs_cfapi"
EXPORT_MACRO_NAME NEXTCLOUD_CFAPI_EXPORT
EXPORT_FILE_NAME cfapiexport.h
)
INSTALL(TARGETS "${synclib_NAME}_vfs_cfapi"
LIBRARY DESTINATION "${vfs_installdir}"
RUNTIME DESTINATION "${vfs_installdir}"
)
endif()

View file

@ -19,6 +19,8 @@
#include "hydrationjob.h"
#include "vfs_cfapi.h"
#include <QCoreApplication>
#include <QEventLoop>
#include <QDir>
#include <QFileInfo>
#include <QLocalSocket>

View file

@ -15,7 +15,7 @@
#include <memory>
#include "owncloudlib.h"
#include "cfapiexport.h"
#include "common/pinstate.h"
#include "common/result.h"
#include "common/vfs.h"
@ -29,7 +29,7 @@ class VfsCfApi;
namespace CfApiWrapper
{
class OWNCLOUDSYNC_EXPORT ConnectionKey
class NEXTCLOUD_CFAPI_EXPORT ConnectionKey
{
public:
ConnectionKey();
@ -39,7 +39,7 @@ private:
std::unique_ptr<void, void(*)(void *)> _data;
};
class OWNCLOUDSYNC_EXPORT FileHandle
class NEXTCLOUD_CFAPI_EXPORT FileHandle
{
public:
using Deleter = void (*)(void *);
@ -54,7 +54,7 @@ private:
std::unique_ptr<void, void(*)(void *)> _data;
};
class OWNCLOUDSYNC_EXPORT PlaceHolderInfo
class NEXTCLOUD_CFAPI_EXPORT PlaceHolderInfo
{
public:
using Deleter = void (*)(CF_PLACEHOLDER_BASIC_INFO *);
@ -72,17 +72,17 @@ private:
std::unique_ptr<CF_PLACEHOLDER_BASIC_INFO, Deleter> _data;
};
OWNCLOUDSYNC_EXPORT Result<void, QString> registerSyncRoot(const QString &path, const QString &providerName, const QString &providerVersion, const QString &folderAlias, const QString &displayName, const QString &accountDisplayName);
OWNCLOUDSYNC_EXPORT Result<void, QString> unregisterSyncRoot(const QString &path, const QString &providerName, const QString &accountDisplayName);
NEXTCLOUD_CFAPI_EXPORT Result<void, QString> registerSyncRoot(const QString &path, const QString &providerName, const QString &providerVersion, const QString &folderAlias, const QString &displayName, const QString &accountDisplayName);
NEXTCLOUD_CFAPI_EXPORT Result<void, QString> unregisterSyncRoot(const QString &path, const QString &providerName, const QString &accountDisplayName);
OWNCLOUDSYNC_EXPORT Result<ConnectionKey, QString> connectSyncRoot(const QString &path, VfsCfApi *context);
OWNCLOUDSYNC_EXPORT Result<void, QString> disconnectSyncRoot(ConnectionKey &&key);
NEXTCLOUD_CFAPI_EXPORT Result<ConnectionKey, QString> connectSyncRoot(const QString &path, VfsCfApi *context);
NEXTCLOUD_CFAPI_EXPORT Result<void, QString> disconnectSyncRoot(ConnectionKey &&key);
OWNCLOUDSYNC_EXPORT bool isSparseFile(const QString &path);
NEXTCLOUD_CFAPI_EXPORT bool isSparseFile(const QString &path);
OWNCLOUDSYNC_EXPORT FileHandle handleForPath(const QString &path);
NEXTCLOUD_CFAPI_EXPORT FileHandle handleForPath(const QString &path);
OWNCLOUDSYNC_EXPORT PlaceHolderInfo findPlaceholderInfo(const FileHandle &handle);
PlaceHolderInfo findPlaceholderInfo(const FileHandle &handle);
enum SetPinRecurseMode {
NoRecurse = 0,
@ -90,10 +90,10 @@ enum SetPinRecurseMode {
ChildrenOnly
};
OWNCLOUDSYNC_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> setPinState(const FileHandle &handle, PinState state, SetPinRecurseMode mode);
OWNCLOUDSYNC_EXPORT Result<void, QString> createPlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId);
OWNCLOUDSYNC_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderInfo(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath = QString());
OWNCLOUDSYNC_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath);
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> setPinState(const FileHandle &handle, PinState state, SetPinRecurseMode mode);
NEXTCLOUD_CFAPI_EXPORT Result<void, QString> createPlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId);
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderInfo(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath = QString());
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath);
}

View file

@ -25,7 +25,7 @@ class GETFileJob;
class SyncJournalDb;
class VfsCfApi;
class OWNCLOUDSYNC_EXPORT HydrationJob : public QObject
class HydrationJob : public QObject
{
Q_OBJECT
public:

View file

@ -119,7 +119,7 @@ Result<void, QString> VfsCfApi::updateMetadata(const QString &filePath, time_t m
}
} else {
qCWarning(lcCfApi) << "Couldn't update metadata for non existing file" << localPath;
return QStringLiteral("Couldn't update metadata");
return {QStringLiteral("Couldn't update metadata")};
}
}
@ -460,5 +460,3 @@ VfsCfApi::HydratationAndPinStates VfsCfApi::computeRecursiveHydrationAndPinState
}
} // namespace OCC
OCC_DEFINE_VFS_FACTORY("win", OCC::VfsCfApi)

View file

@ -17,6 +17,7 @@
#include <QScopedPointer>
#include "common/vfs.h"
#include "common/plugin.h"
namespace OCC {
class HydrationJob;
@ -87,4 +88,11 @@ private:
QScopedPointer<VfsCfApiPrivate> d;
};
class CfApiVfsPluginFactory : public QObject, public DefaultPluginFactory<VfsCfApi>
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.owncloud.PluginFactory" FILE "vfspluginmetadata.json")
Q_INTERFACES(OCC::PluginFactory)
};
} // namespace OCC

View file

@ -0,0 +1,34 @@
add_library("${synclib_NAME}_vfs_suffix" SHARED
vfs_suffix.cpp
)
target_link_libraries("${synclib_NAME}_vfs_suffix"
"${synclib_NAME}"
)
set_target_properties("${synclib_NAME}_vfs_suffix" PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
PREFIX ""
AUTOMOC TRUE
)
if(APPLE)
# for being loadable when client run from build dir
set(vfs_buildoutputdir "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns/")
set_target_properties("${synclib_NAME}_vfs_suffix"
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${vfs_buildoutputdir}
RUNTIME_OUTPUT_DIRECTORY ${vfs_buildoutputdir}
)
# For being loadable when client run from install dir (after make macdeployqt)
set(vfs_installdir "${LIB_INSTALL_DIR}/../PlugIns")
else()
set(vfs_installdir "${PLUGINDIR}")
endif()
INSTALL(TARGETS "${synclib_NAME}_vfs_suffix"
LIBRARY DESTINATION "${vfs_installdir}"
RUNTIME DESTINATION "${vfs_installdir}"
)

View file

@ -151,5 +151,3 @@ Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath)
}
} // namespace OCC
OCC_DEFINE_VFS_FACTORY("suffix", OCC::VfsSuffix)

View file

@ -17,6 +17,7 @@
#include <QScopedPointer>
#include "common/vfs.h"
#include "common/plugin.h"
namespace OCC {
@ -60,4 +61,11 @@ protected:
void startImpl(const VfsSetupParams &params) 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

View file

@ -0,0 +1,50 @@
if (UNIX)
set(vfs_xattr_SRCS vfs_xattr.cpp)
if (APPLE)
set(vfs_xattr_SRCS ${vfs_xattr_SRCS} xattrwrapper_mac.cpp)
else()
set(vfs_xattr_SRCS ${vfs_xattr_SRCS} xattrwrapper_linux.cpp)
endif()
add_library("${synclib_NAME}_vfs_xattr" SHARED
${vfs_xattr_SRCS}
)
target_link_libraries("${synclib_NAME}_vfs_xattr"
"${synclib_NAME}"
)
set_target_properties("${synclib_NAME}_vfs_xattr" PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
PREFIX ""
AUTOMOC TRUE
)
target_include_directories("${synclib_NAME}_vfs_xattr" BEFORE PUBLIC ${CMAKE_CURRENT_BINARY_DIR} INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
if(APPLE)
# for being loadable when client run from build dir
set(vfs_buildoutputdir "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns/")
set_target_properties("${synclib_NAME}_vfs_xattr"
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${vfs_buildoutputdir}
RUNTIME_OUTPUT_DIRECTORY ${vfs_buildoutputdir}
)
# For being loadable when client run from install dir (after make macdeployqt)
set(vfs_installdir "${LIB_INSTALL_DIR}/../PlugIns")
else()
set(vfs_installdir "${PLUGINDIR}")
endif()
GENERATE_EXPORT_HEADER( "${synclib_NAME}_vfs_xattr"
BASE_NAME "${synclib_NAME}_vfs_xattr"
EXPORT_MACRO_NAME NEXTCLOUD_XATTR_EXPORT
EXPORT_FILE_NAME xattrexport.h
)
INSTALL(TARGETS "${synclib_NAME}_vfs_xattr"
LIBRARY DESTINATION "${vfs_installdir}"
RUNTIME DESTINATION "${vfs_installdir}"
)
endif()

View file

@ -182,5 +182,3 @@ void VfsXAttr::fileStatusChanged(const QString &, SyncFileStatus)
}
} // namespace OCC
OCC_DEFINE_VFS_FACTORY("xattr", OCC::VfsXAttr)

View file

@ -17,6 +17,7 @@
#include <QScopedPointer>
#include "common/vfs.h"
#include "common/plugin.h"
namespace OCC {
@ -58,4 +59,11 @@ protected:
void startImpl(const VfsSetupParams &params) override;
};
class XattrVfsPluginFactory : public QObject, public DefaultPluginFactory<VfsXAttr>
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.owncloud.PluginFactory" FILE "vfspluginmetadata.json")
Q_INTERFACES(OCC::PluginFactory)
};
} // namespace OCC

View file

@ -18,6 +18,8 @@
#include "owncloudlib.h"
#include "common/result.h"
#include "xattrexport.h"
namespace OCC {
namespace XAttrWrapper

View file

@ -63,6 +63,10 @@ if( UNIX AND NOT APPLE )
endif(UNIX AND NOT APPLE)
if (WIN32)
include_directories(
${CMAKE_BINARY_DIR}/src/libsync/vfs/cfapi
)
nextcloud_add_test(LongWinPath)
nextcloud_add_test(SyncCfApi)
elseif(LINUX) # elseif(LINUX OR APPLE)

View file

@ -17,6 +17,18 @@ macro(nextcloud_add_test test_class)
Qt5::Quick
)
if (WIN32)
target_link_libraries(${OWNCLOUD_TEST_CLASS}Test
"${synclib_NAME}_vfs_cfapi"
)
endif()
if (UNIX)
target_link_libraries(${OWNCLOUD_TEST_CLASS}Test
"${synclib_NAME}_vfs_xattr"
)
endif()
IF(BUILD_UPDATER)
target_link_libraries(${OWNCLOUD_TEST_CLASS}Test
updater