diff --git a/.gitignore b/.gitignore index 8e24b65..5dc6142 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea cmake-build-debug +build diff --git a/CMakeLists.txt b/CMakeLists.txt index 6724f5a..3f2a502 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ add_executable(seadisk src/main.cpp target_compile_definitions(seadisk PRIVATE NOMINMAX + UNICODE + _UNICODE ) target_include_directories(seadisk PRIVATE diff --git a/include/seafile/fs/file_context.hpp b/include/seafile/fs/file_context.hpp index aace52e..4b5cd0f 100644 --- a/include/seafile/fs/file_context.hpp +++ b/include/seafile/fs/file_context.hpp @@ -7,7 +7,7 @@ #include namespace seafile::fs { - struct FileContext final + struct SeaFileContext final { std::string repo_id; std::string path; diff --git a/include/seafile/fs/seafile_file_system.hpp b/include/seafile/fs/seafile_file_system.hpp index 0f3868e..9f3d229 100644 --- a/include/seafile/fs/seafile_file_system.hpp +++ b/include/seafile/fs/seafile_file_system.hpp @@ -9,9 +9,12 @@ #include "seafile/seafile_api.hpp" #include "seafile/token_type.hpp" +#include "seafile/fs/file_context.hpp" -namespace seafile::fs { - class SeafileFileSystem final { +namespace seafile::fs +{ + class SeafileFileSystem final + { std::string repo_id; std::string token; TokenType token_type = TokenType::TOKEN; @@ -19,47 +22,61 @@ namespace seafile::fs { std::wstring mount_point; public: - explicit SeafileFileSystem(const std::string &server, - const std::wstring &mount_point) : api(server), mount_point(mount_point) { + explicit SeafileFileSystem(const std::string& server, + const std::wstring& mount_point) : api(server), mount_point(mount_point) + { } - void auth(const std::string &username, const std::string &password); + void auth(const std::string& username, const std::string& password); - SeafileFileSystem(const SeafileFileSystem &) = delete; + SeafileFileSystem(const SeafileFileSystem&) = delete; - SeafileFileSystem(SeafileFileSystem &&) = delete; + SeafileFileSystem(SeafileFileSystem&&) = delete; - SeafileFileSystem &operator=(const SeafileFileSystem &) = delete; + SeafileFileSystem& operator=(const SeafileFileSystem&) = delete; - SeafileFileSystem &operator=(SeafileFileSystem &&) = delete; + SeafileFileSystem& operator=(SeafileFileSystem&&) = delete; - NTSTATUS GetVolumeInfo(FSP_FSCTL_VOLUME_INFO *VolumeInfo); + NTSTATUS GetVolumeInfo(FSP_FSCTL_VOLUME_INFO* VolumeInfo); NTSTATUS SetVolumeLabel_(PWSTR VolumeLabel, - FSP_FSCTL_VOLUME_INFO *VolumeInfo); + FSP_FSCTL_VOLUME_INFO* VolumeInfo); NTSTATUS GetSecurityByName(PWSTR FileName, PUINT32 PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, - SIZE_T *PSecurityDescriptorSize); + SIZE_T* PSecurityDescriptorSize); + + NTSTATUS Create(PWSTR FileName, UINT32 CreateOptions, + UINT32 GrantedAccess, UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, + UINT64 AllocationSize, PVOID* PFileContext, FSP_FSCTL_FILE_INFO* FileInfo); NTSTATUS Open( PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, - PVOID *PFileContext, - FSP_FSCTL_FILE_INFO *FileInfo); + PVOID* PFileContext, + FSP_FSCTL_FILE_INFO* FileInfo); NTSTATUS Read(PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, PULONG PBytesTransferred); - NTSTATUS GetFileInfo(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo); + NTSTATUS GetFileInfo(HANDLE Handle, FSP_FSCTL_FILE_INFO* FileInfo); VOID Close(PVOID FileContext0); - NTSTATUS ReadDirectory(PVOID FileContext0, PWSTR Pattern, PWSTR Marker, + VOID Cleanup(PVOID FileContext, PWSTR FileName, ULONG Flags); + + NTSTATUS Overwrite( + PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, + FSP_FSCTL_FILE_INFO* FileInfo); + + NTSTATUS ReadDirectory(PVOID FileContext, PWSTR Pattern, PWSTR Marker, PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred); + + NTSTATUS GetDirInfoByName(PVOID FileContext, PWSTR FileName, + FSP_FSCTL_DIR_INFO* DirInfo); }; } #endif //SEADISK_SEAFILE_FILE_SYSTEM_HPP diff --git a/include/seafile/fs/winfsp_adapter.hpp b/include/seafile/fs/winfsp_adapter.hpp index 543a548..1d5b56a 100644 --- a/include/seafile/fs/winfsp_adapter.hpp +++ b/include/seafile/fs/winfsp_adapter.hpp @@ -6,56 +6,64 @@ #define SEADISK_WINFSP_ADAPTER_HPP #include "seafile_file_system.hpp" -namespace seafile::fs { - class WinFSPAdapter { +namespace seafile::fs +{ + class WinFSPAdapter + { public: - static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_VOLUME_INFO *VolumeInfo); + static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM* FileSystem, FSP_FSCTL_VOLUME_INFO* VolumeInfo); - static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv); + static NTSTATUS SvcStart(FSP_SERVICE* Service, ULONG argc, PWSTR* argv); - static NTSTATUS SvcStop(FSP_SERVICE *Service); + static NTSTATUS SvcStop(FSP_SERVICE* Service); - static NTSTATUS SetVolumeLabel_(FSP_FILE_SYSTEM *FileSystem, PWSTR VolumeLabel, - FSP_FSCTL_VOLUME_INFO *VolumeInfo); + static NTSTATUS SetVolumeLabel_(FSP_FILE_SYSTEM* FileSystem, PWSTR VolumeLabel, + FSP_FSCTL_VOLUME_INFO* VolumeInfo); - static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PUINT32 PFileAttributes, + static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM* FileSystem, PWSTR FileName, PUINT32 PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, - SIZE_T *PSecurityDescriptorSize); + SIZE_T* PSecurityDescriptorSize); - static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, - PVOID *PFileContext, - FSP_FSCTL_FILE_INFO *FileInfo); + static NTSTATUS Open(FSP_FILE_SYSTEM* FileSystem, PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, + PVOID* PFileContext, + FSP_FSCTL_FILE_INFO* FileInfo); - static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem, + static NTSTATUS Create(FSP_FILE_SYSTEM* FileSystem, PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize, - PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo); + PVOID* PFileContext, FSP_FSCTL_FILE_INFO* FileInfo); - static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem, + static NTSTATUS Read(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, PULONG PBytesTransferred); - static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM *FileSystem, HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo); + static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem, + PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, + FSP_FSCTL_FILE_INFO *FileInfo); + + static VOID Cleanup(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, PWSTR FileName, ULONG Flags); + + static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM* FileSystem, HANDLE Handle, FSP_FSCTL_FILE_INFO* FileInfo); - static VOID Close(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext0); + static VOID Close(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext0); - static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext0, PWSTR Pattern, PWSTR Marker, + static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext0, PWSTR Pattern, PWSTR Marker, PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred); - static NTSTATUS GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem, - PVOID FileContext, PWSTR FileName, - FSP_FSCTL_DIR_INFO *DirInfo); + static NTSTATUS GetDirInfoByName(FSP_FILE_SYSTEM* FileSystem, + PVOID FileContext, PWSTR FileName, + FSP_FSCTL_DIR_INFO* DirInfo); - static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem, + static NTSTATUS SetSecurity(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor); - static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem, + static NTSTATUS GetSecurity(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, - PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize); + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T* PSecurityDescriptorSize); }; } #endif //SEADISK_WINFSP_ADAPTER_HPP diff --git a/include/seafile/seafile_api.hpp b/include/seafile/seafile_api.hpp index 143ba90..cfd7364 100644 --- a/include/seafile/seafile_api.hpp +++ b/include/seafile/seafile_api.hpp @@ -252,7 +252,7 @@ namespace seafile const std::string& token, const TokenType token_type) const { - if (const auto download_url = downloadFileUrl(repo_id, path, token, token_type); download_url.has_value()) + 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()}; @@ -263,7 +263,7 @@ namespace seafile "bytes={}-{}", start ? std::to_string(*start) : "", end ? std::to_string(*end) : ""); - header.emplace("range", std::move(range)); + header.emplace("range", range); const auto response = cpr::Get(url, header); return parseResponse(response); } diff --git a/src/seafile/fs/seafile_file_system.cpp b/src/seafile/fs/seafile_file_system.cpp index 03ef1c3..24f38a7 100644 --- a/src/seafile/fs/seafile_file_system.cpp +++ b/src/seafile/fs/seafile_file_system.cpp @@ -1,60 +1,319 @@ -// -// Created by Shell on 2026-06-18. -// - #include "seafile/fs/seafile_file_system.hpp" -namespace seafile::fs { - void SeafileFileSystem::auth(const std::string &username, const std::string &password) { - if (const auto authToken = api.authToken(username, password); authToken.has_value()) { - this->token = authToken.value().token; +namespace seafile::fs +{ + namespace + { + constexpr int64_t UNIX_EPOCH_AS_FILETIME = 116444736000000000LL; + constexpr int64_t HUNDREDS_OF_NANOSECONDS_PER_SECOND = 10000000LL; + + int64_t UnixTimeToFileTime(int64_t unix_time) + { + return UNIX_EPOCH_AS_FILETIME + unix_time * HUNDREDS_OF_NANOSECONDS_PER_SECOND; + } + + int64_t NowFileTime() + { + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + return (static_cast(ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + } + + void SetFileInfo(FSP_FSCTL_FILE_INFO* FileInfo, uint32_t attributes, uint64_t size, int64_t mtime) + { + FileInfo->FileAttributes = attributes; + FileInfo->AllocationSize = size; + FileInfo->FileSize = size; + const auto ft = mtime ? UnixTimeToFileTime(mtime) : NowFileTime(); + FileInfo->CreationTime = ft; + FileInfo->LastAccessTime = ft; + FileInfo->LastWriteTime = ft; + FileInfo->ChangeTime = ft; + FileInfo->IndexNumber = 0; + } + + void SplitPath(const std::wstring& path, std::string& repo_id, std::string& sub_path) + { + repo_id.clear(); + sub_path = "/"; + auto p = path; + while (!p.empty() && p[0] == L'\\') + p = p.substr(1); + if (p.empty()) + return; + + auto sep = p.find(L'\\'); + auto repo_id_w = (sep == std::wstring::npos) ? p : p.substr(0, sep); + repo_id.assign(repo_id_w.begin(), repo_id_w.end()); + + if (sep != std::wstring::npos) + { + auto rest = p.substr(sep); + sub_path.clear(); + for (auto c : rest) + sub_path += static_cast(c); + while (!sub_path.empty() && sub_path.front() == '\\') + sub_path = sub_path.substr(1); + sub_path = "/" + sub_path; + } } } - void SeafileFileSystem::Close(PVOID FileContext0) { + void SeafileFileSystem::auth(const std::string& username, const std::string& password) + { + if (const auto authToken = api.authToken(username, password); authToken.has_value()) + this->token = authToken.value().token; + } + + void SeafileFileSystem::Close(PVOID FileContext) + { + delete static_cast(FileContext); } NTSTATUS SeafileFileSystem::GetSecurityByName(PWSTR FileName, PUINT32 PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, - SIZE_T *PSecurityDescriptorSize) { - *PFileAttributes = FILE_ATTRIBUTE_NORMAL; - *PSecurityDescriptorSize = 0; + SIZE_T* PSecurityDescriptorSize) + { + + if (PFileAttributes) + { + if (wcscmp(FileName, L"\\") == 0) + { + *PFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + }else + { + *PFileAttributes = FILE_ATTRIBUTE_NORMAL; + } + } + + if (PSecurityDescriptorSize) + *PSecurityDescriptorSize = 0; return STATUS_SUCCESS; } - NTSTATUS SeafileFileSystem::GetVolumeInfo(FSP_FSCTL_VOLUME_INFO *VolumeInfo) { + NTSTATUS SeafileFileSystem::Overwrite(PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, FSP_FSCTL_FILE_INFO* FileInfo) + { + return STATUS_NOT_IMPLEMENTED; + } + + + NTSTATUS SeafileFileSystem::GetVolumeInfo(FSP_FSCTL_VOLUME_INFO* VolumeInfo) + { const auto userInfo = api.accountInfo(this->token, this->token_type); - if (userInfo.has_value()) { - const auto &info = userInfo.value(); + if (userInfo.has_value()) + { + const auto& info = userInfo.value(); VolumeInfo->FreeSize = info.total - info.usage; VolumeInfo->TotalSize = info.total; wcscpy(VolumeInfo->VolumeLabel, L"Seafile"); VolumeInfo->VolumeLabelLength = static_cast((wcslen(VolumeInfo->VolumeLabel) * sizeof(WCHAR))); - return STATUS_SUCCESS; } return STATUS_END_OF_MEDIA; } - NTSTATUS SeafileFileSystem::Open(PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, PVOID *PFileContext, - FSP_FSCTL_FILE_INFO *FileInfo) { - return STATUS_NOT_IMPLEMENTED; + void SeafileFileSystem::Cleanup(PVOID FileContext, PWSTR FileName, ULONG Flags) + { + } - NTSTATUS SeafileFileSystem::Read(PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, PULONG PBytesTransferred) { - return STATUS_NOT_IMPLEMENTED; + NTSTATUS SeafileFileSystem::Open(PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, PVOID* PFileContext, + FSP_FSCTL_FILE_INFO* FileInfo) + { + std::string repo_id, sub_path; + SplitPath(FileName, repo_id, sub_path); + + const bool expect_dir = (CreateOptions & FILE_DIRECTORY_FILE) != 0; + + if (repo_id.empty()) + { + auto ctx = new SeaFileContext{"", "/", 0, ""}; + *PFileContext = ctx; + SetFileInfo(FileInfo, FILE_ATTRIBUTE_DIRECTORY, 0, 0); + return STATUS_SUCCESS; + } + + if (sub_path == "/") + { + auto repo = api.repoInfo(repo_id, token, token_type); + if (!repo.has_value()) + return STATUS_OBJECT_NAME_NOT_FOUND; + auto ctx = new SeaFileContext{repo->id, "/", 0, ""}; + *PFileContext = ctx; + SetFileInfo(FileInfo, FILE_ATTRIBUTE_DIRECTORY, repo->size, repo->mtime); + return STATUS_SUCCESS; + } + + if (expect_dir) + { + auto entries = api.repoDir(repo_id, sub_path, token, token_type); + if (entries.has_value()) + { + auto ctx = new SeaFileContext{repo_id, sub_path, 0, ""}; + *PFileContext = ctx; + SetFileInfo(FileInfo, FILE_ATTRIBUTE_DIRECTORY, 0, 0); + return STATUS_SUCCESS; + } + auto fdetail = api.fileDetail(repo_id, sub_path, token, token_type); + if (fdetail.has_value()) + return STATUS_NOT_A_DIRECTORY; + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + auto fdetail = api.fileDetail(repo_id, sub_path, token, token_type); + if (fdetail.has_value()) + { + auto ctx = new SeaFileContext{repo_id, sub_path, fdetail->size, ""}; + *PFileContext = ctx; + SetFileInfo(FileInfo, FILE_ATTRIBUTE_NORMAL, fdetail->size, fdetail->mtime); + return STATUS_SUCCESS; + } + auto entries = api.repoDir(repo_id, sub_path, token, token_type); + if (entries.has_value()) + return STATUS_FILE_IS_A_DIRECTORY; + return STATUS_OBJECT_NAME_NOT_FOUND; } - NTSTATUS SeafileFileSystem::ReadDirectory(PVOID FileContext0, PWSTR Pattern, PWSTR Marker, PVOID Buffer, - ULONG BufferLength, PULONG PBytesTransferred) { - return STATUS_NOT_IMPLEMENTED; + NTSTATUS SeafileFileSystem::Read(PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, + 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(); + const auto copy_len = (std::min)(data.size(), static_cast(Length)); + memcpy(Buffer, data.data(), copy_len); + *PBytesTransferred = static_cast(copy_len); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; } - NTSTATUS SeafileFileSystem::SetVolumeLabel_(PWSTR VolumeLabel, FSP_FSCTL_VOLUME_INFO *VolumeInfo) { - return STATUS_NOT_IMPLEMENTED; + NTSTATUS SeafileFileSystem::ReadDirectory(PVOID FileContext, PWSTR Pattern, PWSTR Marker, + PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) + { + const auto fc = static_cast(FileContext); + *PBytesTransferred = 0; + + auto add_entry = [&](const std::wstring& name, UINT32 attrs, uint64_t size, int64_t mtime) -> bool + { + if (Marker && wcscmp(name.c_str(), Marker) <= 0) + return true; + + const auto name_bytes = (wcslen(name.c_str()) + 1) * sizeof(WCHAR); + const auto entry_size = static_cast(offsetof(FSP_FSCTL_DIR_INFO, FileNameBuf) + name_bytes); + if (*PBytesTransferred + entry_size > BufferLength) + return false; + + auto DirInfo = reinterpret_cast( + static_cast(Buffer) + *PBytesTransferred); + memset(DirInfo, 0, sizeof(FSP_FSCTL_DIR_INFO)); + DirInfo->Size = entry_size; + SetFileInfo(&DirInfo->FileInfo, attrs, size, mtime); + memcpy(DirInfo->FileNameBuf, name.c_str(), name_bytes); + *PBytesTransferred += entry_size; + return true; + }; + + if (fc->repo_id.empty()) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + bool ok = true; + auto entries = api.repoDir(fc->repo_id, fc->path, token, token_type); + if (!entries.has_value()) + return STATUS_UNSUCCESSFUL; + + for (const auto& entry : entries.value()) + { + auto wname = std::wstring(entry.name.begin(), entry.name.end()); + const auto attrs = (entry.type == "dir") ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + const auto sz = entry.size.value_or(0); + ok = add_entry(wname, attrs, sz, entry.mtime); + if (!ok) break; + } + + return STATUS_SUCCESS; } - NTSTATUS SeafileFileSystem::GetFileInfo(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo) { - return STATUS_NOT_IMPLEMENTED; + 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); + 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); + if (!fdetail.has_value()) + return STATUS_UNSUCCESSFUL; + SetFileInfo(FileInfo, FILE_ATTRIBUTE_NORMAL, fdetail->size, fdetail->mtime); + return STATUS_SUCCESS; + } + + NTSTATUS SeafileFileSystem::Create(PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize, PVOID* PFileContext, FSP_FSCTL_FILE_INFO* FileInfo) + { + return STATUS_SUCCESS; + } + + NTSTATUS SeafileFileSystem::GetDirInfoByName(PVOID FileContext, PWSTR FileName, + FSP_FSCTL_DIR_INFO* DirInfo) + { + auto fc = static_cast(FileContext); + std::wstring name(FileName); + + 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); + wcscpy_s(DirInfo->FileNameBuf, wcslen(FileName) + 1, FileName); + return STATUS_SUCCESS; + } + + std::string utf8_name; + for (const auto c : name) + utf8_name += static_cast(c); + + if (fc->repo_id.empty()) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + 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()) + { + if (entry.name != utf8_name) + continue; + memset(DirInfo, 0, sizeof(FSP_FSCTL_DIR_INFO)); + const auto name_bytes = (name.size() + 1) * sizeof(WCHAR); + DirInfo->Size = static_cast(offsetof(FSP_FSCTL_DIR_INFO, FileNameBuf) + name_bytes); + const auto attrs = (entry.type == "dir") ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + SetFileInfo(&DirInfo->FileInfo, attrs, entry.size.value_or(0), entry.mtime); + wcscpy_s(DirInfo->FileNameBuf, name.size() + 1, FileName); + return STATUS_SUCCESS; + } + + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + NTSTATUS SeafileFileSystem::SetVolumeLabel_(PWSTR VolumeLabel, FSP_FSCTL_VOLUME_INFO* VolumeInfo) + { + return STATUS_SUCCESS; } } diff --git a/src/seafile/fs/winfsp_adapter.cpp b/src/seafile/fs/winfsp_adapter.cpp index 2404210..1eafced 100644 --- a/src/seafile/fs/winfsp_adapter.cpp +++ b/src/seafile/fs/winfsp_adapter.cpp @@ -6,14 +6,18 @@ // #include -namespace seafile::fs { - namespace { +namespace seafile::fs +{ + namespace + { FSP_FILE_SYSTEM_INTERFACE FsInterface = { .GetVolumeInfo = WinFSPAdapter::GetVolumeInfo, .SetVolumeLabel = WinFSPAdapter::SetVolumeLabel_, .GetSecurityByName = WinFSPAdapter::GetSecurityByName, .Create = WinFSPAdapter::Create, .Open = WinFSPAdapter::Open, + .Overwrite = WinFSPAdapter::Overwrite, + .Cleanup = WinFSPAdapter::Cleanup, .Close = WinFSPAdapter::Close, .Read = WinFSPAdapter::Read, .GetFileInfo = WinFSPAdapter::GetFileInfo, @@ -22,15 +26,14 @@ namespace seafile::fs { .ReadDirectory = WinFSPAdapter::ReadDirectory, .GetDirInfoByName = WinFSPAdapter::GetDirInfoByName }; - std::unordered_map fstab; - + std::unordered_map fstab; } - NTSTATUS WinFSPAdapter::SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) { - DWORD LastError; + NTSTATUS WinFSPAdapter::SvcStart(FSP_SERVICE* Service, ULONG argc, PWSTR* argv) + { FILETIME CreationTime; FSP_FSCTL_VOLUME_PARAMS VolumeParams = {}; - FSP_FILE_SYSTEM *FileSystem = nullptr; + FSP_FILE_SYSTEM* FileSystem = nullptr; GetSystemTimeAsFileTime(&CreationTime); @@ -44,7 +47,7 @@ namespace seafile::fs { VolumeParams.CaseSensitiveSearch = 0; VolumeParams.CasePreservedNames = 1; VolumeParams.UnicodeOnDisk = 1; - VolumeParams.PersistentAcls = 1; + VolumeParams.PersistentAcls = 0; VolumeParams.PostCleanupWhenModifiedOnly = 1; // (4) VolumeParams.UmFileContextIsUserContext2 = 1; // (4) VolumeParams.ReadOnlyVolume = 1; @@ -56,21 +59,23 @@ namespace seafile::fs { &FsInterface, &FileSystem); - if (!NT_SUCCESS(Result)) { + if (!NT_SUCCESS(Result)) + { return Result; } - const auto mount_point = std::wstring(L"X:"); + auto mount_point = std::wstring(L"X:"); auto seafile_file_system = new SeafileFileSystem("https://pan.hanwangsoft.com", mount_point); seafile_file_system->auth("asypost@yeah.net", "Shell0805@china"); FileSystem->UserContext = seafile_file_system; fstab.insert({FileSystem, seafile_file_system}); - Result = FspFileSystemSetMountPoint(FileSystem, PWSTR(mount_point.data())); + Result = FspFileSystemSetMountPoint(FileSystem, static_cast(mount_point.data())); - LastError = GetLastError(); + DWORD LastError = GetLastError(); std::cout << LastError << std::endl; - if (!NT_SUCCESS(Result)) { + if (!NT_SUCCESS(Result)) + { FspFileSystemDelete(FileSystem); fstab.erase(FileSystem); @@ -80,11 +85,13 @@ namespace seafile::fs { Result = FspFileSystemStartDispatcher(FileSystem, 0); - if (!NT_SUCCESS(Result)) { + if (!NT_SUCCESS(Result)) + { FspFileSystemDelete(FileSystem); fstab.erase(FileSystem); - delete seafile_file_system; + + return Result; } FspFileSystemSetDebugLog( FileSystem, @@ -94,8 +101,10 @@ namespace seafile::fs { return Result; } - NTSTATUS WinFSPAdapter::SvcStop(FSP_SERVICE *Service) { - for (auto &[fileSystem, seafileFs]: fstab) { + NTSTATUS WinFSPAdapter::SvcStop(FSP_SERVICE* Service) + { + for (auto& [fileSystem, seafileFs] : fstab) + { FspFileSystemStopDispatcher(fileSystem); fileSystem->UserContext = nullptr; FspFileSystemDelete(fileSystem); @@ -106,70 +115,105 @@ namespace seafile::fs { return STATUS_SUCCESS; } - NTSTATUS WinFSPAdapter::GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_VOLUME_INFO *VolumeInfo) { - std::cout<<"Getting Volume Info" <(FileSystem->UserContext); + NTSTATUS WinFSPAdapter::GetVolumeInfo(FSP_FILE_SYSTEM* FileSystem, FSP_FSCTL_VOLUME_INFO* VolumeInfo) + { + std::cout << "Getting Volume Info" << std::endl; + const auto fs = static_cast(FileSystem->UserContext); return fs->GetVolumeInfo(VolumeInfo); } - void WinFSPAdapter::Close(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext0) { - auto fs = static_cast(FileSystem->UserContext); - fs->Close(FileContext0); + NTSTATUS WinFSPAdapter::Overwrite(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, UINT32 FileAttributes, + BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, + FSP_FSCTL_FILE_INFO* FileInfo) + { + const auto fs = static_cast(FileSystem->UserContext); + return fs->Overwrite(FileContext, FileAttributes, ReplaceFileAttributes, AllocationSize, FileInfo); } - NTSTATUS WinFSPAdapter::Create(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize, PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo) { - return STATUS_NOT_IMPLEMENTED; + void WinFSPAdapter::Close(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext) + { + const auto fs = static_cast(FileSystem->UserContext); + fs->Close(FileContext); } - NTSTATUS WinFSPAdapter::ReadDirectory(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext0, PWSTR Pattern, PWSTR Marker, - PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) { - auto fs = static_cast(FileSystem->UserContext); + NTSTATUS WinFSPAdapter::Create(FSP_FILE_SYSTEM* FileSystem, PWSTR FileName, UINT32 CreateOptions, + UINT32 GrantedAccess, UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, + UINT64 AllocationSize, PVOID* PFileContext, FSP_FSCTL_FILE_INFO* FileInfo) + { + const auto fs = static_cast(FileSystem->UserContext); + return fs->Create(FileName, CreateOptions, + GrantedAccess, FileAttributes, SecurityDescriptor, + AllocationSize, PFileContext, FileInfo); + } + + VOID WinFSPAdapter::Cleanup(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, PWSTR FileName, ULONG Flags) + { + const auto fs = static_cast(FileSystem->UserContext); + fs->Cleanup(FileContext, FileName, Flags); + } + + NTSTATUS WinFSPAdapter::ReadDirectory(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext0, PWSTR Pattern, PWSTR Marker, + PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) + { + const auto fs = static_cast(FileSystem->UserContext); return fs->ReadDirectory(FileContext0, Pattern, Marker, Buffer, BufferLength, PBytesTransferred); } - NTSTATUS WinFSPAdapter::GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem, - PVOID FileContext, PWSTR FileName, - FSP_FSCTL_DIR_INFO *DirInfo) { - return STATUS_NOT_IMPLEMENTED; + NTSTATUS WinFSPAdapter::GetDirInfoByName(FSP_FILE_SYSTEM* FileSystem, + PVOID FileContext, PWSTR FileName, + FSP_FSCTL_DIR_INFO* DirInfo) + { + const auto fs = static_cast(FileSystem->UserContext); + return fs->GetDirInfoByName(FileContext, FileName, DirInfo); } - NTSTATUS WinFSPAdapter::GetSecurityByName(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PUINT32 PFileAttributes, + NTSTATUS WinFSPAdapter::GetSecurityByName(FSP_FILE_SYSTEM* FileSystem, PWSTR FileName, PUINT32 PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, - SIZE_T *PSecurityDescriptorSize) { - auto fs = static_cast(FileSystem->UserContext); + SIZE_T* PSecurityDescriptorSize) + { + const auto fs = static_cast(FileSystem->UserContext); return fs->GetSecurityByName(FileName, PFileAttributes, SecurityDescriptor, PSecurityDescriptorSize); } - NTSTATUS WinFSPAdapter::SetVolumeLabel_(FSP_FILE_SYSTEM *FileSystem, PWSTR VolumeLabel, - FSP_FSCTL_VOLUME_INFO *VolumeInfo) { - auto fs = static_cast(FileSystem->UserContext); + NTSTATUS WinFSPAdapter::SetVolumeLabel_(FSP_FILE_SYSTEM* FileSystem, PWSTR VolumeLabel, + FSP_FSCTL_VOLUME_INFO* VolumeInfo) + { + const auto fs = static_cast(FileSystem->UserContext); return fs->SetVolumeLabel_(VolumeLabel, VolumeInfo); } - NTSTATUS WinFSPAdapter::Open(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, UINT32 CreateOptions, - UINT32 GrantedAccess, PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo) { - auto fs = static_cast(FileSystem->UserContext); + NTSTATUS WinFSPAdapter::Open(FSP_FILE_SYSTEM* FileSystem, PWSTR FileName, UINT32 CreateOptions, + UINT32 GrantedAccess, PVOID* PFileContext, FSP_FSCTL_FILE_INFO* FileInfo) + { + const auto fs = static_cast(FileSystem->UserContext); return fs->Open(FileName, CreateOptions, GrantedAccess, PFileContext, FileInfo); } - NTSTATUS WinFSPAdapter::Read(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext, PVOID Buffer, UINT64 Offset, - ULONG Length, PULONG PBytesTransferred) { - auto fs = static_cast(FileSystem->UserContext); + NTSTATUS WinFSPAdapter::Read(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, PVOID Buffer, UINT64 Offset, + ULONG Length, PULONG PBytesTransferred) + { + const auto fs = static_cast(FileSystem->UserContext); return fs->Read(FileContext, Buffer, Offset, Length, PBytesTransferred); } - NTSTATUS WinFSPAdapter::GetFileInfo(FSP_FILE_SYSTEM *FileSystem, HANDLE Handle, - FSP_FSCTL_FILE_INFO *FileInfo) { - auto fs = static_cast(FileSystem->UserContext); + NTSTATUS WinFSPAdapter::GetFileInfo(FSP_FILE_SYSTEM* FileSystem, HANDLE Handle, + FSP_FSCTL_FILE_INFO* FileInfo) + { + const auto fs = static_cast(FileSystem->UserContext); return fs->GetFileInfo(Handle, FileInfo); } - NTSTATUS WinFSPAdapter::SetSecurity(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor) { + NTSTATUS WinFSPAdapter::SetSecurity(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ModificationDescriptor) + { return STATUS_NOT_IMPLEMENTED; } - NTSTATUS WinFSPAdapter::GetSecurity(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext, PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) { + NTSTATUS WinFSPAdapter::GetSecurity(FSP_FILE_SYSTEM* FileSystem, PVOID FileContext, + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T* PSecurityDescriptorSize) + { return STATUS_NOT_IMPLEMENTED; } }