1
0

UI changes

This commit is contained in:
Scott E. Graves
2017-03-21 01:32:21 -05:00
parent 92cc4bd769
commit c187ac45a3
10 changed files with 315 additions and 100 deletions

View File

@@ -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;