From 500c927883e73aabe6124d6c61cc849800caced4 Mon Sep 17 00:00:00 2001 From: shell Date: Sun, 21 Jun 2026 20:56:29 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=8E=A5=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 7 +- include/seafile/fs/seafile_file_system.hpp | 46 +++--- include/seafile/fs/winfsp_adapter.hpp | 57 +++++++ src/main.cpp | 47 +----- src/seafile/fs/seafile_file_system.cpp | 56 ++++++- src/seafile/fs/winfsp_adapter.cpp | 175 +++++++++++++++++++++ vcpkg.json | 3 + 7 files changed, 316 insertions(+), 75 deletions(-) create mode 100644 include/seafile/fs/winfsp_adapter.hpp create mode 100644 src/seafile/fs/winfsp_adapter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 330bff8..6724f5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ find_package(date CONFIG REQUIRED) find_package(cpr CONFIG REQUIRED) find_package(argparse CONFIG REQUIRED) find_package(ada CONFIG REQUIRED) +find_package(spdlog CONFIG REQUIRED) cmake_host_system_information( RESULT WINFSP_DIR @@ -49,11 +50,12 @@ add_executable(seadisk src/main.cpp include/seafile/fs/file_context.hpp include/seafile/fs/seafile_file_system.hpp src/seafile/fs/seafile_file_system.cpp + src/seafile/fs/winfsp_adapter.cpp + include/seafile/fs/winfsp_adapter.hpp ) target_compile_definitions(seadisk PRIVATE - UNICODE - _UNICODE + NOMINMAX ) target_include_directories(seadisk PRIVATE @@ -75,6 +77,7 @@ target_link_libraries(seadisk PRIVATE cpr::cpr argparse::argparse ada::ada + spdlog::spdlog ) target_link_options(seadisk PRIVATE diff --git a/include/seafile/fs/seafile_file_system.hpp b/include/seafile/fs/seafile_file_system.hpp index fcac8f5..0f3868e 100644 --- a/include/seafile/fs/seafile_file_system.hpp +++ b/include/seafile/fs/seafile_file_system.hpp @@ -10,59 +10,55 @@ #include "seafile/seafile_api.hpp" #include "seafile/token_type.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; SeaFileApi api; std::wstring mount_point; - FSP_FILE_SYSTEM* FileSystem = nullptr; 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(SeafileFileSystem&&) = delete; - SeafileFileSystem& operator=(const SeafileFileSystem&) = delete; - SeafileFileSystem& operator=(SeafileFileSystem&&) = delete; + SeafileFileSystem(const SeafileFileSystem &) = delete; - NTSTATUS SvcStart(FSP_SERVICE* Service, ULONG argc, PWSTR* argv); + SeafileFileSystem(SeafileFileSystem &&) = delete; - NTSTATUS SvcStop(FSP_SERVICE* Service); + SeafileFileSystem &operator=(const SeafileFileSystem &) = delete; - NTSTATUS GetVolumeInfo(FSP_FSCTL_VOLUME_INFO* VolumeInfo); + SeafileFileSystem &operator=(SeafileFileSystem &&) = delete; + + 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 Open( PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, - PVOID* PFileContext, - FSP_FSCTL_FILE_INFO* FileInfo); + PVOID *PFileContext, + FSP_FSCTL_FILE_INFO *FileInfo); - NTSTATUS GetFileInfoInternal(HANDLE Handle, 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); - VOID Close(FSP_FILE_SYSTEM* FileSystem, - PVOID FileContext0); + VOID Close(PVOID FileContext0); - NTSTATUS ReadDirectory(FSP_FILE_SYSTEM* FileSystem, - PVOID FileContext0, PWSTR Pattern, PWSTR Marker, + NTSTATUS ReadDirectory(PVOID FileContext0, PWSTR Pattern, PWSTR Marker, PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred); }; } diff --git a/include/seafile/fs/winfsp_adapter.hpp b/include/seafile/fs/winfsp_adapter.hpp new file mode 100644 index 0000000..ae7a9fa --- /dev/null +++ b/include/seafile/fs/winfsp_adapter.hpp @@ -0,0 +1,57 @@ +// +// Created by Shell on 2026/6/20. +// + +#ifndef SEADISK_WINFSP_ADAPTER_HPP +#define SEADISK_WINFSP_ADAPTER_HPP +#include "seafile_file_system.hpp" + +namespace seafile::fs { + class WinFSPAdapter { + public: + static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_VOLUME_INFO *VolumeInfo); + + static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv); + + static NTSTATUS SvcStop(FSP_SERVICE *Service); + + + 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, + PSECURITY_DESCRIPTOR SecurityDescriptor, + 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 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); + + 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 VOID Close(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext0); + + static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext0, PWSTR Pattern, PWSTR Marker, + PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred); + + static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem, + PVOID FileContext, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ModificationDescriptor); + + static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem, + PVOID FileContext, + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize); + }; +} +#endif //SEADISK_WINFSP_ADAPTER_HPP diff --git a/src/main.cpp b/src/main.cpp index fec37df..944b7ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,52 +1,15 @@ #include "seafile/seafile_api.hpp" #include -#include "seafile/fs/seafile_file_system.hpp" +#include "seafile/fs/winfsp_adapter.hpp" + using namespace seafile::fs; -static std::shared_ptr file_system = nullptr; - -static NTSTATUS GetVolumeInfo( - FSP_FILE_SYSTEM* FileSystem, - FSP_FSCTL_VOLUME_INFO* VolumeInfo) -{ - const auto fs = static_cast(FileSystem->UserContext); - - return fs->GetVolumeInfo(VolumeInfo); -} - -static FSP_FILE_SYSTEM_INTERFACE seafile_interface = { - .GetVolumeInfo = GetVolumeInfo -}; - -static -NTSTATUS SvcStart(FSP_SERVICE* Service, ULONG argc, PWSTR* argv) // (2) -{ - if (file_system) - { - return file_system->SvcStart(Service, argc, argv); - } - return STATUS_NOT_IMPLEMENTED; -} - -static -NTSTATUS SvcStop(FSP_SERVICE* Service) // (3) -{ - if (file_system) - { - return file_system->SvcStop(Service); - } - return STATUS_NOT_IMPLEMENTED; -} - -int wmain(int argc, wchar_t** argv) -{ +int wmain(int argc, wchar_t **argv) { if (!NT_SUCCESS(FspLoad(nullptr))) return ERROR_DELAY_LOAD_FAILED; - file_system = std::make_shared(std::wstring("X:")); + FspDebugLogSetHandle(GetStdHandle(STD_ERROR_HANDLE)); - file_system->auth("asypost@yeah.net","Shell0805@china"); - - return FspServiceRun(const_cast(L"SeaDisk"), SvcStart, SvcStop, nullptr); + return FspServiceRun(const_cast(L"SeaDisk"), WinFSPAdapter::SvcStart, WinFSPAdapter::SvcStop, nullptr); } diff --git a/src/seafile/fs/seafile_file_system.cpp b/src/seafile/fs/seafile_file_system.cpp index d1b4c36..03ef1c3 100644 --- a/src/seafile/fs/seafile_file_system.cpp +++ b/src/seafile/fs/seafile_file_system.cpp @@ -4,13 +4,57 @@ #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()) - { +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; } } + + void SeafileFileSystem::Close(PVOID FileContext0) { + } + + NTSTATUS SeafileFileSystem::GetSecurityByName(PWSTR FileName, PUINT32 PFileAttributes, + PSECURITY_DESCRIPTOR SecurityDescriptor, + SIZE_T *PSecurityDescriptorSize) { + *PFileAttributes = FILE_ATTRIBUTE_NORMAL; + *PSecurityDescriptorSize = 0; + return STATUS_SUCCESS; + } + + 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(); + 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; + } + + NTSTATUS SeafileFileSystem::Read(PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, PULONG PBytesTransferred) { + return STATUS_NOT_IMPLEMENTED; + } + + NTSTATUS SeafileFileSystem::ReadDirectory(PVOID FileContext0, PWSTR Pattern, PWSTR Marker, PVOID Buffer, + ULONG BufferLength, PULONG PBytesTransferred) { + return STATUS_NOT_IMPLEMENTED; + } + + NTSTATUS SeafileFileSystem::SetVolumeLabel_(PWSTR VolumeLabel, FSP_FSCTL_VOLUME_INFO *VolumeInfo) { + return STATUS_NOT_IMPLEMENTED; + } + + NTSTATUS SeafileFileSystem::GetFileInfo(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo) { + return STATUS_NOT_IMPLEMENTED; + } } diff --git a/src/seafile/fs/winfsp_adapter.cpp b/src/seafile/fs/winfsp_adapter.cpp new file mode 100644 index 0000000..a07c9fc --- /dev/null +++ b/src/seafile/fs/winfsp_adapter.cpp @@ -0,0 +1,175 @@ +#include "seafile/fs/winfsp_adapter.hpp" + +#include "seafile/fs/seafile_file_system.hpp" +// +// Created by Shell on 2026/6/20. +// +#include "seafile/fs/winfsp_adapter.hpp" +#include + +namespace seafile::fs { + namespace { + FSP_FILE_SYSTEM_INTERFACE FsInterface = { + .GetVolumeInfo = WinFSPAdapter::GetVolumeInfo, + .SetVolumeLabel = WinFSPAdapter::SetVolumeLabel_, + .GetSecurityByName = WinFSPAdapter::GetSecurityByName, + .Create = WinFSPAdapter::Create, + .Open = WinFSPAdapter::Open, + .Close = WinFSPAdapter::Close, + .Read = WinFSPAdapter::Read, + .GetFileInfo = WinFSPAdapter::GetFileInfo, + .GetSecurity = WinFSPAdapter::GetSecurity, + .SetSecurity = WinFSPAdapter::SetSecurity, + .ReadDirectory = WinFSPAdapter::ReadDirectory, + + }; + std::unordered_map fstab; + + } + + NTSTATUS WinFSPAdapter::SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) { + DWORD LastError; + FILETIME CreationTime; + FSP_FSCTL_VOLUME_PARAMS VolumeParams = {}; + FSP_FILE_SYSTEM *FileSystem = nullptr; + + GetSystemTimeAsFileTime(&CreationTime); + + std::memset(&VolumeParams, 0, sizeof(VolumeParams)); + VolumeParams.SectorSize = 4096; + VolumeParams.SectorsPerAllocationUnit = 1; + VolumeParams.MaxComponentLength = 255; + VolumeParams.VolumeCreationTime = reinterpret_cast(&CreationTime)->QuadPart; + VolumeParams.VolumeSerialNumber = 0; + VolumeParams.FileInfoTimeout = 1000; + VolumeParams.CaseSensitiveSearch = 0; + VolumeParams.CasePreservedNames = 1; + VolumeParams.UnicodeOnDisk = 1; + VolumeParams.PersistentAcls = 1; + VolumeParams.PostCleanupWhenModifiedOnly = 1; // (4) + VolumeParams.UmFileContextIsUserContext2 = 1; // (4) + VolumeParams.ReadOnlyVolume = 1; + wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR), + L"SeafileFS"); + NTSTATUS Result = FspFileSystemCreate( + const_cast(L"" FSP_FSCTL_DISK_DEVICE_NAME), + &VolumeParams, + &FsInterface, + &FileSystem); + + if (!NT_SUCCESS(Result)) { + return Result; + } + const 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())); + + LastError = GetLastError(); + std::cout << LastError << std::endl; + + if (!NT_SUCCESS(Result)) { + FspFileSystemDelete(FileSystem); + fstab.erase(FileSystem); + + delete seafile_file_system; + return Result; + } + + Result = FspFileSystemStartDispatcher(FileSystem, 0); + + if (!NT_SUCCESS(Result)) { + FspFileSystemDelete(FileSystem); + fstab.erase(FileSystem); + + delete seafile_file_system; + } + FspFileSystemSetDebugLog( + FileSystem, + TRUE); + std::cout << Result << std::endl; + + FSP_FSCTL_VOLUME_INFO volumeInfo{}; + auto status = GetVolumeInfo(FileSystem, &volumeInfo); + + std::cout << "GetVolumeInfo direct call = " + << std::hex << status + << std::endl; + return Result; + } + + NTSTATUS WinFSPAdapter::SvcStop(FSP_SERVICE *Service) { + for (auto &[fileSystem, seafileFs]: fstab) { + FspFileSystemStopDispatcher(fileSystem); + fileSystem->UserContext = nullptr; + FspFileSystemDelete(fileSystem); + delete seafileFs; + } + + fstab.clear(); + return STATUS_SUCCESS; + } + + NTSTATUS WinFSPAdapter::GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_VOLUME_INFO *VolumeInfo) { + 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::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; + } + + 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); + return fs->ReadDirectory(FileContext0, Pattern, Marker, Buffer, BufferLength, PBytesTransferred); + } + + + NTSTATUS WinFSPAdapter::GetSecurityByName(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PUINT32 PFileAttributes, + PSECURITY_DESCRIPTOR SecurityDescriptor, + SIZE_T *PSecurityDescriptorSize) { + 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); + 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); + 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); + 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); + return fs->GetFileInfo(Handle, FileInfo); + } + + 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) { + return STATUS_NOT_IMPLEMENTED; + } +} diff --git a/vcpkg.json b/vcpkg.json index b4ac2bb..5b419f4 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -24,5 +24,8 @@ }, { "name" : "tl-expected", "version>=" : "1.3.1" + }, { + "name" : "spdlog", + "version>=" : "1.17.0" } ] } \ No newline at end of file