UI changes
This commit is contained in:
@@ -2,18 +2,12 @@
|
||||
#include <filesystem>
|
||||
#include <uploadmanager.h>
|
||||
#include <dokan.h>
|
||||
#include <filepath.h>
|
||||
|
||||
using namespace Sia::Api;
|
||||
using namespace Sia::Api::Dokan;
|
||||
|
||||
// TODO Handle paths greater than MAX_PATH!!
|
||||
static SString StdConstructPath(const SString& part1, const SString& part2)
|
||||
{
|
||||
SString path = part1;
|
||||
path.Resize(MAX_PATH + 1);
|
||||
::PathAppend(&path[0], part2.str().c_str());
|
||||
return path;
|
||||
}
|
||||
|
||||
// The general idea is that normal file I/O occurs in a local cache folder and once the file is closed, it is scheduled for upload into Sia.
|
||||
// Files requested to be openned that are not cached will be downloaded first. If the file is not found in Sia, it will be treated as new.
|
||||
@@ -24,8 +18,8 @@ class SIADRIVE_DOKAN_EXPORTABLE DokanImpl
|
||||
private:
|
||||
typedef struct
|
||||
{
|
||||
SString SiaPath;
|
||||
SString CacheFilePath;
|
||||
FilePath SiaPath;
|
||||
FilePath CacheFilePath;
|
||||
bool ReadOnly;
|
||||
} OpenFileInfo;
|
||||
|
||||
@@ -36,7 +30,7 @@ private:
|
||||
static std::unique_ptr<CUploadManager> _uploadManager;
|
||||
static DOKAN_OPERATIONS _dokanOps;
|
||||
static DOKAN_OPTIONS _dokanOptions;
|
||||
static SString _cacheLocation;
|
||||
static FilePath _cacheLocation;
|
||||
static std::unordered_map<ULONG64, OpenFileInfo> _openFileMap;
|
||||
static std::unique_ptr<std::thread> _fileListThread;
|
||||
static bool _fileListStopRequested;
|
||||
@@ -47,7 +41,7 @@ private:
|
||||
static SString _mountPoint;
|
||||
|
||||
private:
|
||||
inline static const SString& GetCacheLocation()
|
||||
inline static const FilePath& GetCacheLocation()
|
||||
{
|
||||
return _cacheLocation;
|
||||
}
|
||||
@@ -55,17 +49,17 @@ private:
|
||||
static bool AddFileToCache(const SString& siaPath, const SString& cacheLocation)
|
||||
{
|
||||
bool ret = false;
|
||||
std::wstring tempPath;
|
||||
tempPath.resize(MAX_PATH + 1);
|
||||
SString tempPath;
|
||||
tempPath.Resize(MAX_PATH + 1);
|
||||
if (::GetTempPath(MAX_PATH + 1, &tempPath[0]))
|
||||
{
|
||||
// Check cache size is large enough to hold new file
|
||||
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempPath));
|
||||
if (ret)
|
||||
{
|
||||
SString src = StdConstructPath(tempPath, L"");
|
||||
SString dest = StdConstructPath(GetCacheLocation(), siaPath);
|
||||
ret = ::MoveFile(src.str().c_str(), dest.str().c_str()) ? true : false;
|
||||
FilePath src(tempPath, L"");
|
||||
FilePath dest(GetCacheLocation(), siaPath);
|
||||
ret = src.MoveFile(dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +148,7 @@ private:
|
||||
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
// Probably not going to happen, but just in case
|
||||
if (PathIsUNC(FileName))
|
||||
if (FilePath(FileName).IsUNC())
|
||||
{
|
||||
ret = STATUS_ILLEGAL_ELEMENT_ADDRESS;
|
||||
}
|
||||
@@ -162,8 +156,8 @@ private:
|
||||
{
|
||||
// When filePath is a directory, needs to change the flag so that the file can
|
||||
// be opened.
|
||||
SString cacheFilePath = StdConstructPath(GetCacheLocation(), &FileName[1]);
|
||||
DWORD fileAttr = ::GetFileAttributes(cacheFilePath.str().c_str());
|
||||
FilePath cacheFilePath(GetCacheLocation(), &FileName[1]);
|
||||
DWORD fileAttr = ::GetFileAttributes(&cacheFilePath[0]);
|
||||
|
||||
if ((fileAttr != INVALID_FILE_ATTRIBUTES) &&
|
||||
(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
@@ -182,7 +176,7 @@ private:
|
||||
{
|
||||
if (creationDisposition == CREATE_NEW)
|
||||
{
|
||||
if (!::CreateDirectory(cacheFilePath.str().c_str(), &securityAttrib))
|
||||
if (!::CreateDirectory(&cacheFilePath[0], &securityAttrib))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
ret = DokanNtStatusFromWin32(error);
|
||||
@@ -190,7 +184,7 @@ private:
|
||||
}
|
||||
else if (creationDisposition == OPEN_ALWAYS)
|
||||
{
|
||||
if (!CreateDirectory(cacheFilePath.str().c_str(), &securityAttrib))
|
||||
if (!::CreateDirectory(&cacheFilePath[0], &securityAttrib))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
|
||||
@@ -212,7 +206,7 @@ private:
|
||||
}
|
||||
|
||||
// FILE_FLAG_BACKUP_SEMANTICS is required for opening directory handles
|
||||
HANDLE handle = CreateFile(cacheFilePath.str().c_str(), genericDesiredAccess, ShareAccess, &securityAttrib, OPEN_EXISTING, fileAttributesAndFlags | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
HANDLE handle = ::CreateFile(&cacheFilePath[0], genericDesiredAccess, ShareAccess, &securityAttrib, OPEN_EXISTING, fileAttributesAndFlags | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
@@ -227,11 +221,11 @@ private:
|
||||
else // File (cache and/or Sia operation)
|
||||
{
|
||||
// Formulate Sia path and cache path
|
||||
SString siaPath = CSiaApi::FormatToSiaPath(PathSkipRoot(FileName)); // Strip drive letter to get Sia path
|
||||
SString siaPath = CSiaApi::FormatToSiaPath(FilePath(FileName).RemoveFileName()); // Strip drive letter to get Sia path
|
||||
if (siaPath.Length())
|
||||
{
|
||||
// If cache file already exists and is a directory, requested file operation isn't valid
|
||||
DWORD attribs = ::GetFileAttributes(cacheFilePath.str().c_str());
|
||||
DWORD attribs = ::GetFileAttributes(&cacheFilePath[0]);
|
||||
if ((attribs != INVALID_FILE_ATTRIBUTES) && (attribs & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
ret = STATUS_OBJECT_NAME_COLLISION;
|
||||
@@ -310,7 +304,7 @@ private:
|
||||
{
|
||||
// Since this is a request to replace an existing file, make sure cache is deleted first.
|
||||
// If file isn't cached, delete from Sia only
|
||||
if (!::PathFileExists(cacheFilePath.str().c_str()) || ::DeleteFile(cacheFilePath.str().c_str()))
|
||||
if (!cacheFilePath.IsFile() || cacheFilePath.DeleteFile())
|
||||
{
|
||||
if (!ApiSuccess(_uploadManager->Remove(siaPath)))
|
||||
{
|
||||
@@ -327,7 +321,7 @@ private:
|
||||
{
|
||||
// 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.str().c_str()))
|
||||
if (!isCreateOp && !cacheFilePath.IsFile())
|
||||
{
|
||||
if (!AddFileToCache(siaPath, cacheFilePath))
|
||||
{
|
||||
@@ -339,7 +333,7 @@ private:
|
||||
{
|
||||
// Create file as specified
|
||||
HANDLE handle = ::CreateFile(
|
||||
cacheFilePath.str().c_str(),
|
||||
&cacheFilePath[0],
|
||||
genericDesiredAccess,
|
||||
ShareAccess,
|
||||
&securityAttrib,
|
||||
@@ -399,18 +393,18 @@ private:
|
||||
auto siaFileTree = _siaFileTree;
|
||||
if (siaFileTree)
|
||||
{
|
||||
SString siaQuery = CSiaApi::FormatToSiaPath(::PathSkipRoot(FileName));
|
||||
SString siaQuery = CSiaApi::FormatToSiaPath(FilePath(FileName).RemoveFileName());
|
||||
|
||||
SString cachePath;
|
||||
SString rootPath = siaQuery;
|
||||
if (wcscmp(FileName, L"\\") == 0)
|
||||
FilePath cachePath;
|
||||
FilePath rootPath = siaQuery;
|
||||
if (FilePath::DirSep == FileName)
|
||||
{
|
||||
cachePath = GetCacheLocation();
|
||||
siaQuery += L"/*.*";
|
||||
}
|
||||
else
|
||||
{
|
||||
cachePath = StdConstructPath(GetCacheLocation(), &FileName[1]);
|
||||
cachePath.Append(&FileName[1]);
|
||||
if (::GetFileAttributes(&cachePath[0]) & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
siaQuery += L"/*.*";
|
||||
@@ -418,8 +412,7 @@ private:
|
||||
else
|
||||
{
|
||||
rootPath = cachePath;
|
||||
::PathRemoveFileSpec(&rootPath[0]);
|
||||
rootPath = CSiaApi::FormatToSiaPath(rootPath);
|
||||
rootPath = CSiaApi::FormatToSiaPath(rootPath.RemoveFileName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,10 +425,10 @@ private:
|
||||
FillFindData(&fd, DokanFileInfo);
|
||||
|
||||
// Create cache sub-folder
|
||||
SString subCachePath = StdConstructPath(cachePath, dir);
|
||||
if (!::PathIsDirectory(subCachePath.str().c_str()))
|
||||
FilePath subCachePath(cachePath, dir);
|
||||
if (!subCachePath.IsDirectory())
|
||||
{
|
||||
::CreateDirectory(subCachePath.str().c_str(), nullptr);
|
||||
subCachePath.CreateDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,12 +487,10 @@ private:
|
||||
BOOL opened = FALSE;
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
|
||||
SString cachePath = GetCacheLocation();
|
||||
if (wcscmp(FileName, L"\\") != 0)
|
||||
FilePath cachePath = GetCacheLocation();
|
||||
if (FilePath::DirSep == FileName)
|
||||
{
|
||||
cachePath.Resize(MAX_PATH + 1);
|
||||
::PathAppend(&cachePath[0], FileName);
|
||||
cachePath = cachePath.str().c_str();
|
||||
cachePath.Append(FileName);
|
||||
}
|
||||
|
||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||
@@ -614,15 +605,14 @@ private:
|
||||
LONGLONG Offset,
|
||||
PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
SString filePath = StdConstructPath(GetCacheLocation(), FileName);
|
||||
FilePath filePath(GetCacheLocation(), FileName);
|
||||
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
||||
ULONG offset = static_cast<ULONG>(Offset);
|
||||
BOOL opened = FALSE;
|
||||
|
||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
handle = ::CreateFile(filePath.str().c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
handle = ::CreateFile(&filePath[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
@@ -664,7 +654,7 @@ private:
|
||||
LONGLONG Offset,
|
||||
PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
SString filePath = StdConstructPath(GetCacheLocation(), FileName);
|
||||
FilePath filePath(GetCacheLocation(), FileName);
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
||||
BOOL opened = FALSE;
|
||||
|
||||
@@ -672,7 +662,7 @@ private:
|
||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
// TODO Get from cache if not found
|
||||
handle = ::CreateFile(filePath.str().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
handle = ::CreateFile(&filePath[0], GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
@@ -681,10 +671,8 @@ private:
|
||||
opened = TRUE;
|
||||
}
|
||||
|
||||
UINT64 fileSize = 0;
|
||||
DWORD fileSizeLow = 0;
|
||||
DWORD fileSizeHigh = 0;
|
||||
fileSizeLow = ::GetFileSize(handle, &fileSizeHigh);
|
||||
DWORD fileSizeLow = ::GetFileSize(handle, &fileSizeHigh);
|
||||
if (fileSizeLow == INVALID_FILE_SIZE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
@@ -693,7 +681,7 @@ private:
|
||||
return DokanNtStatusFromWin32(error);
|
||||
}
|
||||
|
||||
fileSize = (static_cast<UINT64>(fileSizeHigh) << 32) | fileSizeLow;
|
||||
UINT64 fileSize = (static_cast<UINT64>(fileSizeHigh) << 32) | fileSizeLow;
|
||||
|
||||
LARGE_INTEGER distanceToMove;
|
||||
if (DokanFileInfo->WriteToEndOfFile)
|
||||
@@ -773,7 +761,6 @@ private:
|
||||
|
||||
static NTSTATUS DOKAN_CALLBACK Sia_SetEndOfFile(LPCWSTR FileName, LONGLONG ByteOffset, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
SString filePath = StdConstructPath(GetCacheLocation(), FileName);
|
||||
HANDLE handle;
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
@@ -801,8 +788,7 @@ private:
|
||||
|
||||
static void DOKAN_CALLBACK Sia_Cleanup(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
SString filePath = StdConstructPath(GetCacheLocation(), FileName);
|
||||
|
||||
FilePath filePath(GetCacheLocation(), FileName);
|
||||
if (DokanFileInfo->Context)
|
||||
{
|
||||
::CloseHandle(reinterpret_cast<HANDLE>(DokanFileInfo->Context));
|
||||
@@ -818,7 +804,7 @@ private:
|
||||
// if open with FILE_FLAG_DELETE_ON_CLOSE
|
||||
if (DokanFileInfo->IsDirectory)
|
||||
{
|
||||
if (::RemoveDirectory(filePath.str().c_str()))
|
||||
if (filePath.RemoveDirectory())
|
||||
{
|
||||
}
|
||||
else
|
||||
@@ -827,7 +813,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (::DeleteFile(filePath.str().c_str()) == 0)
|
||||
if (filePath.DeleteFile())
|
||||
{
|
||||
}
|
||||
else
|
||||
@@ -840,9 +826,7 @@ private:
|
||||
|
||||
static NTSTATUS DOKAN_CALLBACK Sia_FlushFileBuffers(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
SString filePath = StdConstructPath(GetCacheLocation(), FileName);
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
||||
|
||||
if (!handle || handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
@@ -954,7 +938,7 @@ CSiaDriveConfig* DokanImpl::_siaDriveConfig = nullptr;
|
||||
std::unique_ptr<CUploadManager> DokanImpl::_uploadManager;
|
||||
DOKAN_OPERATIONS DokanImpl::_dokanOps;
|
||||
DOKAN_OPTIONS DokanImpl::_dokanOptions;
|
||||
SString DokanImpl::_cacheLocation;
|
||||
FilePath DokanImpl::_cacheLocation;
|
||||
bool DokanImpl::_fileListStopRequested;
|
||||
CSiaFileTreePtr DokanImpl::_siaFileTree;
|
||||
std::mutex DokanImpl::_fileTreeMutex;
|
||||
|
Reference in New Issue
Block a user