From 95b68b9542e61679956ede403979feb6ea647014 Mon Sep 17 00:00:00 2001 From: asypost Date: Tue, 14 Jul 2026 21:28:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 + include/seafile/api/account_info.hpp | 2 +- include/seafile/api/auth_token.hpp | 2 +- include/seafile/api/cached_seafile_api.hpp | 203 ++++++++++++++++++ include/seafile/api/default_repo.hpp | 2 +- include/seafile/api/dir_info.hpp | 2 +- include/seafile/api/exception.hpp | 2 +- include/seafile/api/file_info.hpp | 2 +- include/seafile/api/repo_entry.hpp | 2 +- include/seafile/api/repo_info.hpp | 2 +- include/seafile/api/seafile_api.hpp | 25 +-- include/seafile/api/seafile_api_interface.hpp | 116 ++++++++++ include/seafile/api/server_info.hpp | 2 +- include/seafile/api/token_type.hpp | 2 +- include/seafile/cache/cache.hpp | 4 +- include/seafile/fs/seafile_file_system.hpp | 16 +- src/seafile/fs/seafile_file_system.cpp | 200 ++++++++++------- src/seafile/fs/winfsp_adapter.cpp | 1 - 18 files changed, 481 insertions(+), 107 deletions(-) create mode 100644 include/seafile/api/cached_seafile_api.hpp create mode 100644 include/seafile/api/seafile_api_interface.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a8b0bd..a95d434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,9 @@ add_executable(seadisk src/main.cpp include/seafile/fs/winfsp_adapter.hpp src/util/string_util.cpp include/seafile/cache/cache.hpp + include/seafile/api/seafile_api_interface.hpp + include/seafile/api/seafile_api_interface.hpp + include/seafile/api/cached_seafile_api.hpp ) target_compile_definitions(seadisk PRIVATE diff --git a/include/seafile/api/account_info.hpp b/include/seafile/api/account_info.hpp index ad83c5a..b39e3fa 100644 --- a/include/seafile/api/account_info.hpp +++ b/include/seafile/api/account_info.hpp @@ -7,7 +7,7 @@ #include #include -namespace seafile +namespace seafile::api { /** * @brief Seafile user profile information. diff --git a/include/seafile/api/auth_token.hpp b/include/seafile/api/auth_token.hpp index 3857e41..11b7a3b 100644 --- a/include/seafile/api/auth_token.hpp +++ b/include/seafile/api/auth_token.hpp @@ -7,7 +7,7 @@ #include #include -namespace seafile { +namespace seafile::api { struct AuthToken final { std::string token; diff --git a/include/seafile/api/cached_seafile_api.hpp b/include/seafile/api/cached_seafile_api.hpp new file mode 100644 index 0000000..99c9dec --- /dev/null +++ b/include/seafile/api/cached_seafile_api.hpp @@ -0,0 +1,203 @@ +// +// Created by Shell on 2026-07-14. +// + +#ifndef SEADISK_CACHED_SEAFILE_API_HPP +#define SEADISK_CACHED_SEAFILE_API_HPP +#include "seafile_api_interface.hpp" +#include "seafile/cache/cache.hpp" + +namespace seafile::api +{ + class CachedSeafileApi final : public ISeaFileApi + { + mutable cache::Cache file_info_cache; + mutable cache::Cache dir_info_cache; + mutable cache::Cache> repo_entries_cache; + mutable cache::Cache account_info_cache; + + std::shared_ptr underlayer_api; + std::chrono::seconds default_ttl = std::chrono::seconds(300); + + static std::string makeKey( + std::string_view prefix, + std::initializer_list args + ) + { + std::string key(prefix); + + for (auto& arg : args) + { + key += ":"; + key += arg; + } + + return key; + } + + public: + explicit CachedSeafileApi(std::shared_ptr api) : underlayer_api(std::move(api)) + { + }; + + tl::expected + authToken( + const std::string& username, + const std::string& password + ) override + { + return underlayer_api->authToken(username, password); + } + + + tl::expected + serverInfo() const override + { + return underlayer_api->serverInfo(); + } + + + tl::expected + defaultRepo( + const std::string& token, + TokenType type + ) const override + { + return underlayer_api->defaultRepo(token, type); + } + + + tl::expected + repoInfo( + const std::string& repo_id, + const std::string& token, + TokenType type + ) const override + { + return underlayer_api->repoInfo(repo_id, token, type); + } + + + tl::expected, SeafileException> + repoDir( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType type + ) const override + { + const auto key = makeKey("repoDir", {repo_id, path}); + + if (const auto value = repo_entries_cache.get(key)) + { + return *value; + } + + auto result = underlayer_api->repoDir(repo_id, path, token, type); + if (result) + { + repo_entries_cache.put(key, result.value(), default_ttl); + } + return result; + } + + + tl::expected + accountInfo( + const std::string& token, + TokenType type + ) const override + { + if (const auto info = account_info_cache.get(token); info.has_value()) + { + return *info; + } + const auto result = underlayer_api->accountInfo(token, type); + if (result) + { + account_info_cache.put(token, result.value(), default_ttl); + } + return result; + } + + + tl::expected + fileDetail( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType type + ) const override + { + const auto key = makeKey("file", {repo_id, path}); + + if (const auto value = file_info_cache.get(key)) + { + return *value; + } + + auto result = underlayer_api->fileDetail(repo_id, path, token, type); + + if (result) + { + file_info_cache.put(key, result.value(), default_ttl); + } + + + return result; + } + + + tl::expected + downloadFileUrl( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType type + ) const override + { + return underlayer_api->downloadFileUrl(repo_id, path, token, type); + } + + + tl::expected + downloadFile( + const std::string& repo_id, + const std::string& path, + std::optional start, + std::optional end, + const std::string& token, + TokenType type + ) const override + { + return underlayer_api->downloadFile(repo_id, path, start, end, token, type); + } + + + tl::expected + dirDetail( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType type + ) const override + { + const auto key = makeKey("dir", {repo_id, path}); + + if (auto value = dir_info_cache.get(key)) + { + return *value; + } + + auto result = underlayer_api->dirDetail(repo_id, path, token, type); + + if (result) + { + dir_info_cache.put(key, result.value(), default_ttl); + } + + return result; + } + }; +} +#endif //SEADISK_CACHED_SEAFILE_API_HPP diff --git a/include/seafile/api/default_repo.hpp b/include/seafile/api/default_repo.hpp index 8f12a88..8deb3b4 100644 --- a/include/seafile/api/default_repo.hpp +++ b/include/seafile/api/default_repo.hpp @@ -8,7 +8,7 @@ #include #include -namespace seafile +namespace seafile::api { /** * default repo response diff --git a/include/seafile/api/dir_info.hpp b/include/seafile/api/dir_info.hpp index 2b9fc38..e780095 100644 --- a/include/seafile/api/dir_info.hpp +++ b/include/seafile/api/dir_info.hpp @@ -6,7 +6,7 @@ #define SEADISK_DIR_INFO_HPP #include #include -namespace seafile +namespace seafile::api { /** * @brief Repository directory information. diff --git a/include/seafile/api/exception.hpp b/include/seafile/api/exception.hpp index 6e97abf..4f043ee 100644 --- a/include/seafile/api/exception.hpp +++ b/include/seafile/api/exception.hpp @@ -6,7 +6,7 @@ #define SEADISK_EXCEPTION_HPP #include -namespace seafile { +namespace seafile::api { class SeafileException : public std::runtime_error { public: explicit SeafileException(const std::string &msg) diff --git a/include/seafile/api/file_info.hpp b/include/seafile/api/file_info.hpp index 4b4f10d..d3a5eb5 100644 --- a/include/seafile/api/file_info.hpp +++ b/include/seafile/api/file_info.hpp @@ -8,7 +8,7 @@ #include #include -namespace seafile +namespace seafile::api { /** * @brief Detailed file metadata. diff --git a/include/seafile/api/repo_entry.hpp b/include/seafile/api/repo_entry.hpp index 0d4e605..50c1de6 100644 --- a/include/seafile/api/repo_entry.hpp +++ b/include/seafile/api/repo_entry.hpp @@ -8,7 +8,7 @@ #include #include -namespace seafile +namespace seafile::api { /** * @brief File or directory entry metadata. diff --git a/include/seafile/api/repo_info.hpp b/include/seafile/api/repo_info.hpp index 2a0e234..871665e 100644 --- a/include/seafile/api/repo_info.hpp +++ b/include/seafile/api/repo_info.hpp @@ -8,7 +8,7 @@ #include #include -namespace seafile +namespace seafile::api { /** *@brief Seafile repository metadata. diff --git a/include/seafile/api/seafile_api.hpp b/include/seafile/api/seafile_api.hpp index 371c6a9..6863448 100644 --- a/include/seafile/api/seafile_api.hpp +++ b/include/seafile/api/seafile_api.hpp @@ -20,11 +20,12 @@ #include "file_info.hpp" #include "repo_entry.hpp" #include "repo_info.hpp" +#include "seafile_api_interface.hpp" #include "server_info.hpp" #include "token_type.hpp" -namespace seafile { - class SeaFileApi final { +namespace seafile::api { + class SeaFileApi final:public ISeaFileApi { //base url of the seafile api server std::string base_url; @@ -104,7 +105,7 @@ namespace seafile { * @return token when success else SeafileException */ tl::expected - authToken(const std::string &username, const std::string &password) { + authToken(const std::string &username, const std::string &password) override { const nlohmann::json body = { {"username", username}, {"password", password} @@ -113,7 +114,7 @@ namespace seafile { } tl::expected - serverInfo() const { + serverInfo() const override{ const auto response = cpr::Get( cpr::Url{makeUrl("/api2/server-info/")}, cpr::Header{ @@ -130,7 +131,7 @@ namespace seafile { * @return default repo info */ tl::expected - defaultRepo(const std::string &token, const TokenType token_type) const { + defaultRepo(const std::string &token, const TokenType token_type) const override{ const auto auth = makeAuthToken(token, token_type); const auto url = makeUrl("/api2/default-repo/"); const auto response = cpr::Get(cpr::Url{url}, @@ -142,7 +143,7 @@ namespace seafile { } tl::expected - repoInfo(const std::string &repo_id, const std::string &token, const TokenType token_type) const { + repoInfo(const std::string &repo_id, const std::string &token, const TokenType token_type) const override{ const auto url = makeUrl(std::format("/api2/repos/{}/", repo_id)); const auto auth = makeAuthToken(token, token_type); @@ -164,7 +165,7 @@ namespace seafile { */ tl::expected, SeafileException> repoDir(const std::string &repo_id, const std::string &path, const std::string &token, - const TokenType token_type) const { + const TokenType token_type) const override{ const auto url = cpr::Url{makeUrl(std::format("/api2/repos/{}/dir/", repo_id))}; const auto auth = makeAuthToken(token, token_type); @@ -181,7 +182,7 @@ namespace seafile { tl::expected accountInfo(const std::string &token, - const TokenType token_type) const { + const TokenType token_type) const override{ const auto url = cpr::Url{makeUrl("/api2/account/info/")}; const auto auth = makeAuthToken(token, token_type); @@ -195,7 +196,7 @@ namespace seafile { tl::expected fileDetail(const std::string &repo_id, const std::string &path, const std::string &token, - const TokenType token_type) const { + const TokenType token_type) const override{ const auto url = cpr::Url{makeUrl(std::format("/api2/repos/{}/file/detail/", repo_id))}; const auto auth = makeAuthToken(token, token_type); @@ -211,7 +212,7 @@ namespace seafile { tl::expected downloadFileUrl(const std::string &repo_id, const std::string &path, const std::string &token, - const TokenType token_type) const { + const TokenType token_type) const override{ const auto auth = makeAuthToken(token, token_type); const auto url = cpr::Url{makeUrl(std::format("/api2/repos/{}/file/", repo_id))}; const auto response = cpr::Get(url, @@ -231,7 +232,7 @@ namespace seafile { const std::optional start, const std::optional end, const std::string &token, - const TokenType token_type) const { + const TokenType token_type) const override{ if (auto download_url = downloadFileUrl(repo_id, path, token, token_type); download_url.has_value()) { const auto auth = makeAuthToken(token, token_type); const auto url = cpr::Url{download_url.value()}; @@ -255,7 +256,7 @@ namespace seafile { } tl::expected dirDetail(const std::string &repo_id, const std::string &path, - const std::string &token, const TokenType token_type) const { + const std::string &token, const TokenType token_type) const override{ const auto auth = makeAuthToken(token, token_type); const auto url = cpr::Url{makeUrl(std::format("/api/v2.1/repos/{}/dir/detail/", repo_id))}; const auto response = cpr::Get(url, cpr::Header{ diff --git a/include/seafile/api/seafile_api_interface.hpp b/include/seafile/api/seafile_api_interface.hpp new file mode 100644 index 0000000..4477169 --- /dev/null +++ b/include/seafile/api/seafile_api_interface.hpp @@ -0,0 +1,116 @@ +// +// Created by Shell on 2026-07-14. +// + +#ifndef SEADISK_SEAFILE_API_INTERFACE_HPP +#define SEADISK_SEAFILE_API_INTERFACE_HPP + +#include +#include +#include +#include + +#include "exception.hpp" +#include "account_info.hpp" +#include "auth_token.hpp" +#include "default_repo.hpp" +#include "dir_info.hpp" +#include "file_info.hpp" +#include "repo_entry.hpp" +#include "repo_info.hpp" +#include "server_info.hpp" +#include "token_type.hpp" + + +namespace seafile::api { + +class ISeaFileApi { +public: + + virtual ~ISeaFileApi() = default; + + + virtual tl::expected + authToken( + const std::string& username, + const std::string& password + ) = 0; + + + virtual tl::expected + serverInfo() const = 0; + + + virtual tl::expected + defaultRepo( + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected + repoInfo( + const std::string& repo_id, + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected, SeafileException> + repoDir( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected + accountInfo( + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected + fileDetail( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected + downloadFileUrl( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected + downloadFile( + const std::string& repo_id, + const std::string& path, + std::optional start, + std::optional end, + const std::string& token, + TokenType token_type + ) const = 0; + + + virtual tl::expected + dirDetail( + const std::string& repo_id, + const std::string& path, + const std::string& token, + TokenType token_type + ) const = 0; + +}; + +} + +#endif //SEADISK_SEAFILE_API_INTERFACE_HPP diff --git a/include/seafile/api/server_info.hpp b/include/seafile/api/server_info.hpp index 1c49444..f4b407c 100644 --- a/include/seafile/api/server_info.hpp +++ b/include/seafile/api/server_info.hpp @@ -7,7 +7,7 @@ #include #include -namespace seafile { +namespace seafile::api { /** * seafile server info */ diff --git a/include/seafile/api/token_type.hpp b/include/seafile/api/token_type.hpp index 7899095..a74e14d 100644 --- a/include/seafile/api/token_type.hpp +++ b/include/seafile/api/token_type.hpp @@ -4,7 +4,7 @@ #ifndef SEADISK_TOKEN_TYPE_HPP #define SEADISK_TOKEN_TYPE_HPP -namespace seafile +namespace seafile::api { enum class TokenType { diff --git a/include/seafile/cache/cache.hpp b/include/seafile/cache/cache.hpp index 59a786a..80d6564 100644 --- a/include/seafile/cache/cache.hpp +++ b/include/seafile/cache/cache.hpp @@ -31,7 +31,7 @@ namespace seafile::cache { /// 获取缓存值 /// @param key 键 /// @return 缓存值 - std::optional get(const K &key) { + std::optional get(const K &key){ // 第一阶段:读锁 { std::shared_lock lock(mutex_); @@ -93,7 +93,7 @@ namespace seafile::cache { ///缓存大小 size_t size() const { - std::unique_lock lock(mutex_); + std::shared_lock lock(mutex_); return cache_.size(); } diff --git a/include/seafile/fs/seafile_file_system.hpp b/include/seafile/fs/seafile_file_system.hpp index 6912eba..0c830d6 100644 --- a/include/seafile/fs/seafile_file_system.hpp +++ b/include/seafile/fs/seafile_file_system.hpp @@ -9,24 +9,32 @@ #include "../api/seafile_api.hpp" #include "../api/token_type.hpp" +#include "seafile/api/cached_seafile_api.hpp" #include "seafile/cache/cache.hpp" namespace seafile::fs { class SeafileFileSystem final { + using SeafileException = api::SeafileException; + using TokenType = api::TokenType; + using ISeaFileApi = api::ISeaFileApi; + using RepoEntry = api::RepoEntry; + + std::string repo_id; std::string token; TokenType token_type = TokenType::TOKEN; - SeaFileApi api; + std::shared_ptr api; std::wstring volume_label; - cache::Cache> repo_dir_cache{}; - public: explicit SeafileFileSystem(const std::string& server, - const std::wstring& volume_label) : api(server), volume_label(volume_label) + const std::wstring& volume_label) : volume_label(volume_label) { + this->api = std::make_shared( + std::make_shared(server) + ); } tl::expected initialize(const std::string& username, const std::string& password); diff --git a/src/seafile/fs/seafile_file_system.cpp b/src/seafile/fs/seafile_file_system.cpp index 824d7d3..3b2fc7c 100644 --- a/src/seafile/fs/seafile_file_system.cpp +++ b/src/seafile/fs/seafile_file_system.cpp @@ -5,30 +5,36 @@ #include #include -namespace seafile::fs { - namespace { +namespace seafile::fs +{ + namespace + { constexpr int64_t UNIX_EPOCH_AS_FILETIME = 116444736000000000LL; constexpr int64_t HUNDREDS_OF_NANOSECONDS_PER_SECOND = 10000000LL; - int64_t UnixTimeToFileTime(const int64_t unix_time) { + int64_t UnixTimeToFileTime(const int64_t unix_time) + { return UNIX_EPOCH_AS_FILETIME + unix_time * HUNDREDS_OF_NANOSECONDS_PER_SECOND; } - std::string normalize_path(const std::string &path) { + std::string normalize_path(const std::string& path) + { std::string result = path; std::ranges::replace(result, '\\', '/'); return result; } - int64_t NowFileTime() { + int64_t NowFileTime() + { FILETIME ft; GetSystemTimeAsFileTime(&ft); return (static_cast(ft.dwHighDateTime) << 32) | ft.dwLowDateTime; } - void SetFileInfo(FSP_FSCTL_FILE_INFO *FileInfo, const uint32_t attributes, const uint64_t size, - const int64_t mtime) { + void SetFileInfo(FSP_FSCTL_FILE_INFO* FileInfo, const uint32_t attributes, const uint64_t size, + const int64_t mtime) + { FileInfo->FileAttributes = attributes; FileInfo->AllocationSize = size; FileInfo->FileSize = size; @@ -42,12 +48,15 @@ namespace seafile::fs { } - tl::expected SeafileFileSystem::initialize(const std::string &username, - const std::string &password) { - const auto authToken = api.authToken(username, password); - if (authToken.has_value()) { + tl::expected SeafileFileSystem::initialize(const std::string& username, + const std::string& password) + { + const auto authToken = api->authToken(username, password); + if (authToken.has_value()) + { this->token = authToken.value().token; - if (const auto repo = api.defaultRepo(this->token, this->token_type); repo.has_value()) { + if (const auto repo = api->defaultRepo(this->token, this->token_type); repo.has_value()) + { this->repo_id = repo.value().repo_id.value_or(""); return {}; } @@ -58,17 +67,23 @@ namespace seafile::fs { return tl::make_unexpected(authToken.error()); } - void SeafileFileSystem::Close(PVOID FileContext) { - delete static_cast(FileContext); + void SeafileFileSystem::Close(PVOID FileContext) + { + delete static_cast(FileContext); } NTSTATUS SeafileFileSystem::GetSecurityByName(PWSTR FileName, PUINT32 PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, - SIZE_T *PSecurityDescriptorSize) { - if (PFileAttributes) { - if (wcscmp(FileName, L"\\") == 0) { + SIZE_T* PSecurityDescriptorSize) + { + if (PFileAttributes) + { + if (wcscmp(FileName, L"\\") == 0) + { *PFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - } else { + } + else + { *PFileAttributes = FILE_ATTRIBUTE_NORMAL; } } @@ -79,17 +94,21 @@ namespace seafile::fs { } NTSTATUS SeafileFileSystem::Overwrite(PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, - UINT64 AllocationSize, FSP_FSCTL_FILE_INFO *FileInfo) { + UINT64 AllocationSize, FSP_FSCTL_FILE_INFO* FileInfo) + { return STATUS_MEDIA_WRITE_PROTECTED; } - NTSTATUS SeafileFileSystem::GetVolumeInfo(FSP_FSCTL_VOLUME_INFO *VolumeInfo) const { - if (const auto userInfo = api.accountInfo(this->token, this->token_type); userInfo.has_value()) { - const auto &info = userInfo.value(); + NTSTATUS SeafileFileSystem::GetVolumeInfo(FSP_FSCTL_VOLUME_INFO* VolumeInfo) const + { + if (const auto userInfo = api->accountInfo(this->token, this->token_type); userInfo.has_value()) + { + const auto& info = userInfo.value(); VolumeInfo->FreeSize = info.total - info.usage; VolumeInfo->TotalSize = info.total; - if (!this->volume_label.empty()) { + if (!this->volume_label.empty()) + { wcscpy_s(VolumeInfo->VolumeLabel, this->volume_label.data()); VolumeInfo->VolumeLabelLength = static_cast((wcslen(VolumeInfo->VolumeLabel) * sizeof(WCHAR))); } @@ -101,20 +120,24 @@ namespace seafile::fs { return STATUS_END_OF_MEDIA; } - void SeafileFileSystem::Cleanup(PVOID FileContext, PWSTR FileName, ULONG Flags) { + void SeafileFileSystem::Cleanup(PVOID FileContext, PWSTR FileName, ULONG Flags) + { } - NTSTATUS SeafileFileSystem::Open(PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, PVOID *PFileContext, - FSP_FSCTL_FILE_INFO *FileInfo) { + NTSTATUS SeafileFileSystem::Open(PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, PVOID* PFileContext, + FSP_FSCTL_FILE_INFO* FileInfo) + { const auto path = normalize_path(shell::util::StringUtil::utf16le_to_utf8(FileName)); - if (repo_id.empty()) { + if (repo_id.empty()) + { spdlog::error(std::format("can't open file: {}, repo id is empty", path)); return STATUS_OBJECT_NAME_NOT_FOUND; } - if (path == "/") { - auto repo = api.repoInfo(repo_id, token, token_type); + if (path == "/") + { + auto repo = api->repoInfo(repo_id, token, token_type); if (!repo.has_value()) return STATUS_OBJECT_NAME_NOT_FOUND; const auto ctx = new SeaFileContext{repo->id, path, SeaFileContext::Type::DIRECTORY, 0, ""}; @@ -124,8 +147,9 @@ namespace seafile::fs { return STATUS_SUCCESS; } - if (const auto dirInfo = api.dirDetail(repo_id, path, token, token_type); dirInfo.has_value()) { - const auto &info = dirInfo.value(); + if (const auto dirInfo = api->dirDetail(repo_id, path, token, token_type); dirInfo.has_value()) + { + const auto& info = dirInfo.value(); const auto ctx = new SeaFileContext{info.repo_id, info.path, SeaFileContext::Type::DIRECTORY, 0, ""}; *PFileContext = ctx; SetFileInfo(FileInfo,FILE_ATTRIBUTE_DIRECTORY, 0, 0); @@ -134,8 +158,9 @@ namespace seafile::fs { } - if (const auto fileInfo = api.fileDetail(repo_id, path, token, token_type); fileInfo.has_value()) { - const auto &info = fileInfo.value(); + if (const auto fileInfo = api->fileDetail(repo_id, path, token, token_type); fileInfo.has_value()) + { + const auto& info = fileInfo.value(); const auto ctx = new SeaFileContext(repo_id, path, SeaFileContext::Type::FILE, info.size, ""); *PFileContext = ctx; SetFileInfo(FileInfo,FILE_ATTRIBUTE_ARCHIVE, info.size, 0); @@ -147,14 +172,16 @@ namespace seafile::fs { } NTSTATUS SeafileFileSystem::Read(PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, - PULONG PBytesTransferred) { - const auto fc = static_cast(FileContext); - auto result = api.downloadFile( + PULONG PBytesTransferred) + { + const auto fc = static_cast(FileContext); + auto result = api->downloadFile( fc->repo_id, fc->path, Offset, Offset + Length - 1, token, token_type); - if (result.has_value()) { - const auto &data = result.value(); + if (result.has_value()) + { + const auto& data = result.value(); const auto copy_len = (std::min)(data.size(), static_cast(Length)); memcpy(Buffer, data.data(), copy_len); *PBytesTransferred = static_cast(copy_len); @@ -165,76 +192,87 @@ namespace seafile::fs { } NTSTATUS SeafileFileSystem::ReadDirectory(PVOID FileContext, PWSTR Pattern, PWSTR Marker, - PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) { - const auto fc = static_cast(FileContext); + PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) + { + const auto fc = static_cast(FileContext); *PBytesTransferred = 0; - const auto cache_key = std::format("{}_{}", fc->repo_id, fc->path); - auto repo_entries = repo_dir_cache.get(cache_key); - if (!repo_entries.has_value()) { - if (auto entries_result = api.repoDir(fc->repo_id, fc->path, token, token_type); entries_result.has_value()) { - repo_entries = entries_result.value(); - repo_dir_cache.put(cache_key, repo_entries.value(),std::chrono::seconds(60)); - }else { - spdlog::error(std::format("can't read directory {},due to {}", fc->path,entries_result.error().what())); - } - } - if (repo_entries.has_value()) { - const auto &entries = repo_entries.value(); + if (auto entries_result = api->repoDir(fc->repo_id, fc->path, token, token_type); entries_result.has_value()) + { + const auto& entries = entries_result.value(); size_t start = 0; - if (Marker) { + if (Marker) + { const auto marker = shell::util::StringUtil::utf16le_to_utf8(Marker); - for (auto i = 0; i < entries.size(); ++i) { - if (entries[i].name == marker) { + for (auto i = 0; i < entries.size(); ++i) + { + if (entries[i].name == marker) + { start = i + 1; break; } } } - for (auto i = start; i < entries.size(); ++i) { - const auto &entry = entries[i]; + for (auto i = start; i < entries.size(); ++i) + { + const auto& entry = entries[i]; const auto entry_name = shell::util::StringUtil::utf8_to_utf16le(entry.name); const auto size = sizeof(FSP_FSCTL_DIR_INFO) + ((entry_name.size() + 1) * sizeof(WCHAR)); - const auto dir_info = static_cast(std::malloc(size)); + const auto dir_info = static_cast(std::malloc(size)); std::memset(dir_info, 0, size); dir_info->Size = size; dir_info->FileInfo.FileSize = entry.size.value_or(0); - if (entry.type == "file") { + if (entry.type == "file") + { dir_info->FileInfo.FileAttributes = FILE_ATTRIBUTE_ARCHIVE; - } else { + } + else + { dir_info->FileInfo.FileAttributes = FILE_ATTRIBUTE_DIRECTORY; } wcscpy_s(dir_info->FileNameBuf, entry_name.size() + 1, entry_name.data()); - if (*PBytesTransferred + size < BufferLength) { - if (!FspFileSystemAddDirInfo(dir_info, Buffer, BufferLength, PBytesTransferred)) { + if (*PBytesTransferred + size < BufferLength) + { + if (!FspFileSystemAddDirInfo(dir_info, Buffer, BufferLength, PBytesTransferred)) + { break; } - } else { + } + else + { break; } } + return STATUS_SUCCESS; } + else + { + spdlog::error(std::format("read directory {} failed: {}", fc->path, entries_result.error().what())); + } return STATUS_UNSUCCESSFUL; } - NTSTATUS SeafileFileSystem::GetFileInfo(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo) { - auto fc = static_cast(Handle); - if (fc->repo_id.empty() || fc->path == "/" || fc->path.back() == '/') { - if (fc->repo_id.empty()) { + NTSTATUS SeafileFileSystem::GetFileInfo(HANDLE Handle, FSP_FSCTL_FILE_INFO* FileInfo) + { + auto fc = static_cast(Handle); + if (fc->repo_id.empty() || fc->path == "/" || fc->path.back() == '/') + { + if (fc->repo_id.empty()) + { SetFileInfo(FileInfo, FILE_ATTRIBUTE_DIRECTORY, 0, 0); return STATUS_SUCCESS; } - auto repo = api.repoInfo(fc->repo_id, token, token_type); + auto repo = api->repoInfo(fc->repo_id, token, token_type); if (!repo.has_value()) return STATUS_UNSUCCESSFUL; SetFileInfo(FileInfo, FILE_ATTRIBUTE_DIRECTORY, repo->size, repo->mtime); return STATUS_SUCCESS; } - auto fdetail = api.fileDetail(fc->repo_id, fc->path, token, token_type); + auto fdetail = api->fileDetail(fc->repo_id, fc->path, token, token_type); if (!fdetail.has_value()) return STATUS_UNSUCCESSFUL; SetFileInfo(FileInfo, FILE_ATTRIBUTE_NORMAL, fdetail->size, fdetail->mtime); @@ -244,16 +282,19 @@ namespace seafile::fs { NTSTATUS SeafileFileSystem::Create(PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, - UINT64 AllocationSize, PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo) { + UINT64 AllocationSize, PVOID* PFileContext, FSP_FSCTL_FILE_INFO* FileInfo) + { return Open(FileName, CreateOptions, GrantedAccess, PFileContext, FileInfo); } NTSTATUS SeafileFileSystem::GetDirInfoByName(PVOID FileContext, PWSTR FileName, - FSP_FSCTL_DIR_INFO *DirInfo) { - auto fc = static_cast(FileContext); + FSP_FSCTL_DIR_INFO* DirInfo) + { + auto fc = static_cast(FileContext); std::wstring name(FileName); - if (name == L"." || name == L"..") { + if (name == L"." || name == L"..") + { memset(DirInfo, 0, sizeof(FSP_FSCTL_DIR_INFO)); DirInfo->Size = sizeof(FSP_FSCTL_DIR_INFO) + (wcslen(FileName) + 1) * sizeof(WCHAR); SetFileInfo(&DirInfo->FileInfo, FILE_ATTRIBUTE_DIRECTORY, 0, 0); @@ -262,18 +303,20 @@ namespace seafile::fs { } std::string utf8_name; - for (const auto c: name) + for (const auto c : name) utf8_name += static_cast(c); - if (fc->repo_id.empty()) { + if (fc->repo_id.empty()) + { return STATUS_OBJECT_NAME_NOT_FOUND; } - auto entries = api.repoDir(fc->repo_id, fc->path, token, token_type); + auto entries = api->repoDir(fc->repo_id, fc->path, token, token_type); if (!entries.has_value()) return STATUS_OBJECT_NAME_NOT_FOUND; - for (const auto &entry: entries.value()) { + for (const auto& entry : entries.value()) + { if (entry.name != utf8_name) continue; memset(DirInfo, 0, sizeof(FSP_FSCTL_DIR_INFO)); @@ -288,7 +331,8 @@ namespace seafile::fs { return STATUS_OBJECT_NAME_NOT_FOUND; } - NTSTATUS SeafileFileSystem::SetVolumeLabel_(PWSTR VolumeLabel, FSP_FSCTL_VOLUME_INFO *VolumeInfo) { + NTSTATUS SeafileFileSystem::SetVolumeLabel_(PWSTR VolumeLabel, FSP_FSCTL_VOLUME_INFO* VolumeInfo) + { return STATUS_ACCESS_DENIED; } } diff --git a/src/seafile/fs/winfsp_adapter.cpp b/src/seafile/fs/winfsp_adapter.cpp index 294ae6c..3e6e7fd 100644 --- a/src/seafile/fs/winfsp_adapter.cpp +++ b/src/seafile/fs/winfsp_adapter.cpp @@ -100,7 +100,6 @@ namespace seafile::fs FspFileSystemSetDebugLog( FileSystem, TRUE); - std::cout << Result << std::endl; return Result; }