Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/craft_override.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ Packager/CreateCache = False
Paths/CCACHE_DIR = ${Env:HOME}/ccache
Compile/UseCCache = True

[BlueprintSettings]
# ignore for now
opencloud/openvfs.ignored=1

[linux-gcc-x86_64]
Environment/SourceCommand = export PKG_CONFIG_PATH=(/usr/bin/pkg-config --variable pc_path pkg-config) && source /opt/rh/gcc-toolset-14/enable

Expand Down
2 changes: 1 addition & 1 deletion cmake/modules/OCAddVfsPlugin.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function(add_vfs_plugin)

set_target_properties(vfs_${__PLUGIN_NAME} PROPERTIES OUTPUT_NAME "OpenCloud_vfs_${__PLUGIN_NAME}")

target_link_libraries(vfs_${__PLUGIN_NAME}
target_link_libraries(vfs_${__PLUGIN_NAME} PRIVATE
libsync
${__PLUGIN_LIBS}
)
Expand Down
1 change: 0 additions & 1 deletion src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ void Folder::startVfs()
OC_ENFORCE(_vfs->mode() == _definition.virtualFilesMode);

VfsSetupParams vfsParams(_accountState->account(), webDavUrl(), _definition.spaceId(), displayName(), _engine.get());
vfsParams.filesystemPath = path();
vfsParams.journal = &_journal;
vfsParams.providerDisplayName = Theme::instance()->appNameGUI();
vfsParams.providerName = Theme::instance()->appName();
Expand Down
2 changes: 2 additions & 0 deletions src/libsync/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ add_library(libsync SHARED
abstractcorejob.cpp

appprovider.cpp

path.cpp
)

if(WIN32)
Expand Down
11 changes: 6 additions & 5 deletions src/libsync/common/filesystembase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,13 @@ namespace OCC {

Q_LOGGING_CATEGORY(lcFileSystem, "sync.filesystem", QtInfoMsg)

std::filesystem::path FileSystem::toFilesystemPath(QString path)
std::filesystem::path FileSystem::toFilesystemPath(const QString &path)
{
#ifdef Q_OS_WIN
path = FileSystem::longWinPath(path);
return QtPrivate::toFilesystemPath(FileSystem::longWinPath(path));
#else
return QtPrivate::toFilesystemPath(path);
#endif
return std::filesystem::path(reinterpret_cast<const char16_t *>(path.cbegin()), reinterpret_cast<const char16_t *>(path.cend()));
}

QString FileSystem::fromFilesystemPath(const std::filesystem::path &path)
Expand All @@ -71,9 +72,9 @@ QString FileSystem::fromFilesystemPath(const std::filesystem::path &path)
return QDir::fromNativeSeparators(QString::fromWCharArray(view.data(), view.length()));
#elif defined(Q_OS_MACOS)
// based on QFile::decodeName
return QString::fromStdString(path.native()).normalized(QString::NormalizationForm_C);
return QtPrivate::fromFilesystemPath(path).normalized(QString::NormalizationForm_C);
#else
return QString::fromStdString(path.native());
return QtPrivate::fromFilesystemPath(path);
#endif
}

Expand Down
4 changes: 2 additions & 2 deletions src/libsync/common/filesystembase.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include <QString>

#include <cstdint>
#include <ctime>


class QFile;
Expand All @@ -48,9 +47,10 @@ OPENCLOUD_SYNC_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcFileSystem)
{
OPENCLOUD_SYNC_EXPORT Q_NAMESPACE;

OPENCLOUD_SYNC_EXPORT std::filesystem::path toFilesystemPath(QString path);
OPENCLOUD_SYNC_EXPORT std::filesystem::path toFilesystemPath(const QString &path);
OPENCLOUD_SYNC_EXPORT QString fromFilesystemPath(const std::filesystem::path &path);


/**
* List of characters not allowd in filenames on Windows
*/
Expand Down
3 changes: 1 addition & 2 deletions src/libsync/discoveryphase.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ class DiscoverySingleLocalDirectoryJob : public QObject, public QRunnable
private:
QString _localPath;
AccountPtr _account;
OCC::Vfs* _vfs;
public:
OCC::Vfs *_vfs;
};


Expand Down
6 changes: 4 additions & 2 deletions src/libsync/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ std::optional<QString> FileSystem::Tags::get(const QString &path, const QString
if (Utility::isLinux()) {
platformKey = QStringLiteral("user.") + platformKey;
}
return Xattr::getxattr(toFilesystemPath(path), platformKey);
if (const auto d = Xattr::getxattr(toFilesystemPath(path), platformKey)) {
return QString::fromUtf8(*d);
}
#elif defined(Q_OS_WIN)
QFile file(QStringLiteral("%1:%2").arg(path, key));
if (file.open(QIODevice::ReadOnly)) {
Expand All @@ -314,7 +316,7 @@ OCC::Result<void, QString> FileSystem::Tags::set(const QString &path, const QStr
if (Utility::isLinux()) {
platformKey = QStringLiteral("user.") + platformKey;
}
return Xattr::setxattr(toFilesystemPath(path), platformKey, value);
return Xattr::setxattr(toFilesystemPath(path), platformKey, value.toUtf8());
#elif defined(Q_OS_WIN)
QFile file(QStringLiteral("%1:%2").arg(path, key));
if (!file.open(QIODevice::WriteOnly)) {
Expand Down
31 changes: 31 additions & 0 deletions src/libsync/path.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2025 Hannah von Reth <h.vonreth@opencloud.eu>

#include "path.h"

#include "libsync/common/filesystembase.h"

OCC::FileSystem::Path::Path(QAnyStringView path)
: _path(toFilesystemPath(path.toString()))
{
}

OCC::FileSystem::Path::Path(const std::filesystem::path &path)
: _path(path)
{
}

OCC::FileSystem::Path::Path(std::filesystem::path &&path)
: _path(std::move(path))
{
}

OCC::FileSystem::Path OCC::FileSystem::Path::relative(QAnyStringView path)
{
return QtPrivate::toFilesystemPath(path.toString());
}

QString OCC::FileSystem::Path::toString() const
{
return fromFilesystemPath(_path);
}
68 changes: 68 additions & 0 deletions src/libsync/path.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2025 Hannah von Reth <h.vonreth@opencloud.eu>

#pragma once

#include "libsync/opencloudsynclib.h"

#include <QString>

#include <filesystem>

namespace OCC {
namespace FileSystem {
class OPENCLOUD_SYNC_EXPORT Path
{
public:
/**
* Will create an absolute path from the given QString.
* On Windows it will create a UNC path starting with "\\?\".
* For path segments use Path::relative.
* @param path
*/
explicit Path(QAnyStringView path);

Path(const std::filesystem::path &path);

Path(std::filesystem::path &&path);

/**
* Creates a relative path segment
* @param path
* @return A relative path
*/
static Path relative(QAnyStringView path);

const std::filesystem::path &get() const { return _path; }

[[nodiscard]] operator std::filesystem::path() const { return _path; }

explicit operator QString() const { return toString(); }

Path operator/(const Path &other) const { return _path / other._path; }
Path operator/(const std::filesystem::path &other) const { return _path / other; }
Path operator/(QAnyStringView other) const { return _path / relative(other); }

Path &operator/=(const Path &other)
{
_path /= other._path;
return *this;
}
Path &operator/=(const std::filesystem::path &other)
{
_path /= other;
return *this;
}
Path &operator/=(QAnyStringView other)
{
_path /= relative(other);
return *this;
}

QString toString() const;

private:
std::filesystem::path _path;
};
}
}
15 changes: 14 additions & 1 deletion src/libsync/vfs/vfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "libsync/common/syncjournaldb.h"
#include "libsync/common/version.h"
#include "libsync/filesystem.h"
#include "libsync/syncengine.h"

#include <QApplication>
#include <QCoreApplication>
Expand Down Expand Up @@ -100,7 +101,7 @@ void Vfs::wipeDehydratedVirtualFiles()

// If the local file is a dehydrated placeholder, wipe it too.
// Otherwise leave it to allow the next sync to have a new-new conflict.
const QString absolutePath = _setupParams->filesystemPath + relativePath;
const auto absolutePath = QString(_setupParams->root() / relativePath);
if (QFile::exists(absolutePath)) {
// according to our db this is a dehydrated file, check it to be sure
if (isDehydratedPlaceholder(absolutePath)) {
Expand Down Expand Up @@ -261,7 +262,9 @@ VfsSetupParams::VfsSetupParams(const AccountPtr &account, const QUrl &baseUrl, c
, _syncEngine(syncEngine)
, _spaceId(spaceId)
, _folderDisplayName(folderDisplayName)
, _root(syncEngine->localPath())
{
Q_ASSERT(filesystemPath().endsWith('/'_L1));
}

QString VfsSetupParams::folderDisplayName() const
Expand All @@ -273,3 +276,13 @@ SyncEngine *VfsSetupParams::syncEngine() const
{
return _syncEngine;
}

QString VfsSetupParams::filesystemPath() const
{
return _root.toString();
}

const FileSystem::Path &VfsSetupParams::root() const
{
return _root;
}
22 changes: 11 additions & 11 deletions src/libsync/vfs/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@
*/
#pragma once

#include "../common/pinstate.h"
#include "../common/result.h"
#include "../common/syncfilestatus.h"
#include "../common/utility.h"
#include "assert.h"
#include "filesystem.h"
#include "libsync/accountfwd.h"
#include "libsync/common/pinstate.h"
#include "libsync/common/result.h"
#include "libsync/common/syncfilestatus.h"
#include "libsync/common/utility.h"
#include "libsync/discoveryinfo.h"
#include "libsync/opencloudsynclib.h"
#include "libsync/path.h"

#include <QObject>
#include <QSharedPointer>
#include <QUrl>
#include <QVersionNumber>

#include <QFuture>
#include <filesystem>
#include <memory>

Expand All @@ -43,11 +43,7 @@ class HydrationJob;
struct OPENCLOUD_SYNC_EXPORT VfsSetupParams
{
explicit VfsSetupParams(const AccountPtr &account, const QUrl &baseUrl, const QString &spaceId, const QString &folderDisplayName, SyncEngine *syncEngine);
/** The full path to the folder on the local filesystem
*
* Always ends with /.
*/
QString filesystemPath;

QString folderDisplayName() const;

/// Account url, credentials etc for network calls
Expand All @@ -69,11 +65,15 @@ struct OPENCLOUD_SYNC_EXPORT VfsSetupParams

SyncEngine *syncEngine() const;

QString filesystemPath() const;
const FileSystem::Path &root() const;

private:
QUrl _baseUrl;
SyncEngine *_syncEngine;
QString _spaceId;
QString _folderDisplayName;
FileSystem::Path _root;
};

/** Interface describing how to deal with virtual/placeholder files.
Expand Down
7 changes: 3 additions & 4 deletions src/libsync/xattr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace FileSystem {
#endif
}

std::optional<QString> Xattr::getxattr(const std::filesystem::path &path, const QString &name)
std::optional<QByteArray> Xattr::getxattr(const std::filesystem::path &path, const QString &name)
{
QByteArray value;
ssize_t res = 0;
Expand All @@ -32,15 +32,14 @@ namespace FileSystem {
} while (res == -1 && errno == ERANGE);
if (res > 0) {
value.resize(res);
return QString::fromUtf8(value);
return value;
} else {
return {};
}
}

Result<void, QString> Xattr::setxattr(const std::filesystem::path &path, const QString &name, const QString &value)
Result<void, QString> Xattr::setxattr(const std::filesystem::path &path, const QString &name, const QByteArray &data)
{
const auto data = value.toUtf8();
#ifdef Q_OS_MAC
const auto result = ::setxattr(path.c_str(), name.toUtf8().constData(), data.constData(), data.size(), 0, XATTR_NOFOLLOW);
#else
Expand Down
5 changes: 2 additions & 3 deletions src/libsync/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ namespace OCC {
namespace FileSystem {
namespace Xattr {
OPENCLOUD_SYNC_EXPORT bool supportsxattr(const std::filesystem::path &path);
OPENCLOUD_SYNC_EXPORT std::optional<QString> getxattr(const std::filesystem::path &path, const QString &name);
OPENCLOUD_SYNC_EXPORT Result<void, QString> setxattr(const std::filesystem::path &path, const QString &name, const QString &value);

OPENCLOUD_SYNC_EXPORT std::optional<QByteArray> getxattr(const std::filesystem::path &path, const QString &name);
OPENCLOUD_SYNC_EXPORT Result<void, QString> setxattr(const std::filesystem::path &path, const QString &name, const QByteArray &value);
OPENCLOUD_SYNC_EXPORT Result<void, QString> removexattr(const std::filesystem::path &path, const QString &name);
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/plugins/vfs/cfapi/cfapiwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ void CALLBACK cfApiRename(const CF_CALLBACK_INFO *callbackInfo, const CF_CALLBAC
if (callbackParameters->Rename.Flags & (CF_CALLBACK_RENAME_FLAG_TARGET_IN_SCOPE | CF_CALLBACK_RENAME_FLAG_SOURCE_IN_SCOPE) &&
// CF_CALLBACK_RENAME_FLAG_TARGET_IN_SCOPE is also set for any other sync root we manage
// but in that case windows will hydrate the file before its moved
OCC::FileSystem::isChildPathOf(target, context.vfs->params().filesystemPath) && context.vfs->isDehydratedPlaceholder(context.path)
OCC::FileSystem::isChildPathOf(target, context.vfs->params().filesystemPath()) && context.vfs->isDehydratedPlaceholder(context.path)
&& context.vfs->params().syncEngine()->isExcluded(qtPath)) {
reject = true;
}
Expand Down Expand Up @@ -356,7 +356,7 @@ QString createSyncRootID(const QString &providerName, const QUuid &accountUUID,

void OCC::CfApiWrapper::registerSyncRoot(const VfsSetupParams &params, const std::function<void(QString)> &callback)
{
const auto nativePath = QDir::toNativeSeparators(params.filesystemPath);
const auto nativePath = QDir::toNativeSeparators(params.filesystemPath());
winrt::StorageFolder::GetFolderFromPathAsync(reinterpret_cast<const wchar_t *>(nativePath.utf16()))
.Completed([params, callback](const winrt::IAsyncOperation<winrt::StorageFolder> &result, winrt::AsyncStatus status) {
if (status != winrt::AsyncStatus::Completed) {
Expand All @@ -365,7 +365,7 @@ void OCC::CfApiWrapper::registerSyncRoot(const VfsSetupParams &params, const std
}
try {
const auto iconPath = QCoreApplication::applicationFilePath();
const auto id = createSyncRootID(params.providerName, params.account->uuid(), params.filesystemPath);
const auto id = createSyncRootID(params.providerName, params.account->uuid(), params.filesystemPath());
const auto version = params.providerVersion.toString();

winrt::StorageProviderSyncRootInfo info;
Expand Down Expand Up @@ -400,7 +400,7 @@ void OCC::CfApiWrapper::registerSyncRoot(const VfsSetupParams &params, const std
}
callback({});
} catch (const winrt::hresult_error &ex) {
callback(u"Failed to register sync root %1: %2"_s.arg(params.filesystemPath, Utility::formatWinError(ex.code())));
callback(u"Failed to register sync root %1: %2"_s.arg(params.filesystemPath(), Utility::formatWinError(ex.code())));
}
});
}
Expand Down Expand Up @@ -431,7 +431,7 @@ OCC::Result<void, QString> OCC::CfApiWrapper::unregisterSyncRoot(const VfsSetupP
try {
std::lock_guard lock(sRegister_mutex);
winrt::StorageProviderSyncRootManager::Unregister(
reinterpret_cast<const wchar_t *>(createSyncRootID(params.providerName, params.account->uuid(), params.filesystemPath).utf16()));
reinterpret_cast<const wchar_t *>(createSyncRootID(params.providerName, params.account->uuid(), params.filesystemPath()).utf16()));
} catch (winrt::hresult_error const &ex) {
return u"unregisterSyncRoot failed: %1"_s.arg(Utility::formatWinError(ex.code()));
}
Expand Down
Loading
Loading