From 0a865eb73e861e0e13744a0d7b694ec25af8e9fe Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 11 Feb 2017 12:20:17 -0600 Subject: [PATCH] Dokan changes --- SiaDrive.Api/SiaApi.h | 1 + SiaDrive.Api/SiaRenter.cpp | 5 ++ SiaDrive.Dokan.Api/SiaDokanDrive.cpp | 109 +++++++++++++++++++-------- SiaDrive.Dokan.Api/SiaDokanDrive.h | 2 + 4 files changed, 85 insertions(+), 32 deletions(-) diff --git a/SiaDrive.Api/SiaApi.h b/SiaDrive.Api/SiaApi.h index 98b6b9e..c2149e8 100644 --- a/SiaDrive.Api/SiaApi.h +++ b/SiaDrive.Api/SiaApi.h @@ -68,6 +68,7 @@ public: public: _SiaApiError FileExists(const String& siaPath, bool& exists) const; _SiaApiError DeleteFile(const String& siaPath); + _SiaApiError DownloadFile(const String& siaPath, const String& location) const; }; public: diff --git a/SiaDrive.Api/SiaRenter.cpp b/SiaDrive.Api/SiaRenter.cpp index ddb419f..092ed2e 100644 --- a/SiaDrive.Api/SiaRenter.cpp +++ b/SiaDrive.Api/SiaRenter.cpp @@ -19,6 +19,11 @@ SiaApiError CSiaApi::_CSiaRenter::FileExists(const String& siaPath, bool& exists } SiaApiError CSiaApi::_CSiaRenter::DeleteFile(const String& siaPath) +{ + return SiaApiError::NotImplemented; +} + +SiaApiError CSiaApi::_CSiaRenter::DownloadFile(const String& siaPath, const String& location) const { return SiaApiError::NotImplemented; } \ No newline at end of file diff --git a/SiaDrive.Dokan.Api/SiaDokanDrive.cpp b/SiaDrive.Dokan.Api/SiaDokanDrive.cpp index 397c88e..02346bb 100644 --- a/SiaDrive.Dokan.Api/SiaDokanDrive.cpp +++ b/SiaDrive.Dokan.Api/SiaDokanDrive.cpp @@ -16,6 +16,23 @@ private: static String _cacheLocation; private: + static bool AddFileToCache(const String& siaPath, const String& cachePath) + { + bool ret = false; + std::wstring tempPath; + tempPath.resize(MAX_PATH + 1); + if (GetTempPath(MAX_PATH + 1, &tempPath[0])) + { + ret = API_SUCCESS(SiaApiError, _siaApi->GetRenter()->DownloadFile(siaPath, tempPath)); + if (ret) + { + + } + } + + return ret; + } + static NTSTATUS DOKAN_CALLBACK SiaDrive_ZwCreateFile( LPCWSTR FileName, PDOKAN_IO_SECURITY_CONTEXT SecurityContext, @@ -38,17 +55,17 @@ private: ACCESS_MASK genericDesiredAccess = DokanMapStandardToGenericAccess(DesiredAccess); NTSTATUS ret = STATUS_SUCCESS; - bool isFile = (fileAttributesAndFlags & FILE_NON_DIRECTORY_FILE); + bool isFile = (FileAttributes & FILE_NON_DIRECTORY_FILE); + DokanFileInfo->IsDirectory = !isFile; if (isFile) { // Formulate Sia path and cache path String siaPath = PathSkipRoot(FileName); // Strip drive letter to get Sia path - String cacheFilePath; cacheFilePath.resize(MAX_PATH + 1); PathCombine(&cacheFilePath[0], _cacheLocation.c_str(), siaPath.c_str()); - // If cache file already exists and is a directory, file operation should fail + // If cache file already exists and is a directory, requested file operation doesn't make sense if (GetFileAttributes(cacheFilePath.c_str()) & FILE_ATTRIBUTE_DIRECTORY) { ret = STATUS_OBJECT_NAME_COLLISION; @@ -58,6 +75,9 @@ private: bool exists; if (API_SUCCESS(SiaApiError, _siaApi->GetRenter()->FileExists(siaPath, exists))) { + // Operations on existing files that are requested to be truncated, overwritten or re-created + // will first be deleted and then replaced if, after the file operation is done, the resulting file + // size is > 0. Sia doesn't support random access to files (upload/download/rename/delete). bool isCreateOp = false; bool isReplaceOp = false; switch (creationDisposition) @@ -118,6 +138,8 @@ private: { if (isReplaceOp) { + // Since this is a request to replace existing file, so make sure cache is deleted first. + // If file isn't cached, delete from Sia only if (!PathFileExists(cacheFilePath.c_str()) || ::DeleteFile(cacheFilePath.c_str())) { // Delete from Sia @@ -134,40 +156,45 @@ private: if (ret == STATUS_SUCCESS) { - // If file should exist, then check for it in cache location. If not found, + // If file must exist, then check for it in cache location. If not found, // it must be downloaded first and placed in cache if (!isCreateOp && !PathFileExists(cacheFilePath.c_str())) { - // Download to temp location - // Move to cache location + if (!AddFileToCache(siaPath, cacheFilePath)) + { + ret = STATUS_INVALID_SERVER_STATE; + } } - // Create file as specified - HANDLE handle = CreateFile( - cacheFilePath.c_str(), - genericDesiredAccess, - ShareAccess, - &securityAttrib, - creationDisposition, - fileAttributesAndFlags, - nullptr); - if (handle == INVALID_HANDLE_VALUE) + if (ret == STATUS_SUCCESS) { - ret = DokanNtStatusFromWin32(GetLastError()); - } - else - { - DokanFileInfo->Context = reinterpret_cast(handle); // save the file handle in Context - /*if (creationDisposition == OPEN_ALWAYS || - creationDisposition == CREATE_ALWAYS) { - error = GetLastError(); - if (error == ERROR_ALREADY_EXISTS) { - DbgPrint(L"\tOpen an already existing file\n"); - // Open succeed but we need to inform the driver - // that the file open and not created by returning STATUS_OBJECT_NAME_COLLISION - return STATUS_OBJECT_NAME_COLLISION; - } - }*/ + // Create file as specified + HANDLE handle = CreateFile( + cacheFilePath.c_str(), + genericDesiredAccess, + ShareAccess, + &securityAttrib, + creationDisposition, + fileAttributesAndFlags, + nullptr); + if (handle == INVALID_HANDLE_VALUE) + { + ret = DokanNtStatusFromWin32(GetLastError()); + } + else + { + DokanFileInfo->Context = reinterpret_cast(handle); // save the file handle in Context + /*if (creationDisposition == OPEN_ALWAYS || + creationDisposition == CREATE_ALWAYS) { + error = GetLastError(); + if (error == ERROR_ALREADY_EXISTS) { + DbgPrint(L"\tOpen an already existing file\n"); + // Open succeed but we need to inform the driver + // that the file open and not created by returning STATUS_OBJECT_NAME_COLLISION + return STATUS_OBJECT_NAME_COLLISION; + } + }*/ + } } } } @@ -194,12 +221,23 @@ private: return 0; } + static void DOKAN_CALLBACK Sia_CloseFile(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo) + { + if (DokanFileInfo->Context) + { + ::CloseHandle(reinterpret_cast(DokanFileInfo->Context)); + DokanFileInfo->Context = 0; + + QueueUploadIfChanged(FileName); + } + } + public: static void Initialize(CSiaApi* siaApi) { _siaApi = siaApi; _dokanOps.Cleanup = nullptr; - _dokanOps.CloseFile = nullptr; + _dokanOps.CloseFile = Sia_CloseFile; _dokanOps.DeleteDirectory = nullptr; _dokanOps.DeleteFileW = nullptr; _dokanOps.FindFiles = SiaDrive_FindFiles; @@ -267,8 +305,15 @@ CSiaDokanDrive::~CSiaDokanDrive() void CSiaDokanDrive::Mount(const wchar_t& driveLetter, const String& cacheLocation, const std::uint64_t& maxCacheSizeBytes) { + std::lock_guard l(DokanImpl::GetMutex()); } void CSiaDokanDrive::Unmount(const bool& clearCache) { + std::lock_guard l(DokanImpl::GetMutex()); +} + +void CSiaDokanDrive::ClearCache() +{ + } \ No newline at end of file diff --git a/SiaDrive.Dokan.Api/SiaDokanDrive.h b/SiaDrive.Dokan.Api/SiaDokanDrive.h index c229ae8..102120f 100644 --- a/SiaDrive.Dokan.Api/SiaDokanDrive.h +++ b/SiaDrive.Dokan.Api/SiaDokanDrive.h @@ -35,6 +35,8 @@ public: void Mount(const wchar_t& driveLetter, const String& cacheLocation, const std::uint64_t& maxCacheSizeBytes); void Unmount(const bool& clearCache = false); + + void ClearCache(); }; NS_END(3) \ No newline at end of file