Directory listing changes
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
using namespace Sia::Api;
|
using namespace Sia::Api;
|
||||||
using namespace Sia::Api::Dokan;
|
using namespace Sia::Api::Dokan;
|
||||||
|
|
||||||
|
// TODO Handle paths greater than MAX_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.
|
// 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.
|
// 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.
|
||||||
// Keeping cache and Sia in synch will be a bit of a hastle, so it's strongly suggested to treat the cache folder as if it doesn't exist;
|
// Keeping cache and Sia in synch will be a bit of a hastle, so it's strongly suggested to treat the cache folder as if it doesn't exist;
|
||||||
@@ -48,8 +50,9 @@ private:
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
std::wstring tempPath;
|
std::wstring tempPath;
|
||||||
tempPath.resize(MAX_PATH + 1);
|
tempPath.resize(MAX_PATH + 1);
|
||||||
if (GetTempPath(MAX_PATH + 1, &tempPath[0]))
|
if (::GetTempPath(MAX_PATH + 1, &tempPath[0]))
|
||||||
{
|
{
|
||||||
|
// Check cache size is large enough to hold new file
|
||||||
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempPath));
|
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempPath));
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
@@ -148,14 +151,12 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OutputDebugString(FileName);
|
|
||||||
OutputDebugString(L"\n");
|
|
||||||
// When filePath is a directory, needs to change the flag so that the file can
|
// When filePath is a directory, needs to change the flag so that the file can
|
||||||
// be opened.
|
// be opened.
|
||||||
String cacheFilePath;
|
String cacheFilePath;
|
||||||
cacheFilePath.resize(MAX_PATH + 1);
|
cacheFilePath.resize(MAX_PATH + 1);
|
||||||
PathCombine(&cacheFilePath[0], GetCacheLocation().c_str(), &FileName[1]);
|
::PathCombine(&cacheFilePath[0], GetCacheLocation().c_str(), &FileName[1]);
|
||||||
DWORD fileAttr = GetFileAttributes(cacheFilePath.c_str());
|
DWORD fileAttr = ::GetFileAttributes(cacheFilePath.c_str());
|
||||||
|
|
||||||
if (fileAttr != INVALID_FILE_ATTRIBUTES &&
|
if (fileAttr != INVALID_FILE_ATTRIBUTES &&
|
||||||
(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
@@ -176,7 +177,7 @@ private:
|
|||||||
if (siaPath.length())
|
if (siaPath.length())
|
||||||
{
|
{
|
||||||
// If cache file already exists and is a directory, requested file operation isn't valid
|
// If cache file already exists and is a directory, requested file operation isn't valid
|
||||||
DWORD attribs = GetFileAttributes(cacheFilePath.c_str());
|
DWORD attribs = ::GetFileAttributes(cacheFilePath.c_str());
|
||||||
if ((attribs != INVALID_FILE_ATTRIBUTES) && (attribs & FILE_ATTRIBUTE_DIRECTORY))
|
if ((attribs != INVALID_FILE_ATTRIBUTES) && (attribs & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
{
|
{
|
||||||
ret = STATUS_OBJECT_NAME_COLLISION;
|
ret = STATUS_OBJECT_NAME_COLLISION;
|
||||||
@@ -243,6 +244,10 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Nothing to do
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == STATUS_SUCCESS)
|
if (ret == STATUS_SUCCESS)
|
||||||
@@ -251,7 +256,7 @@ private:
|
|||||||
{
|
{
|
||||||
// Since this is a request to replace an existing file, make sure cache is deleted first.
|
// 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 file isn't cached, delete from Sia only
|
||||||
if (!PathFileExists(cacheFilePath.c_str()) || ::DeleteFile(cacheFilePath.c_str()))
|
if (!::PathFileExists(cacheFilePath.c_str()) || ::DeleteFile(cacheFilePath.c_str()))
|
||||||
{
|
{
|
||||||
if (!ApiSuccess(_uploadManager->Remove(siaPath)))
|
if (!ApiSuccess(_uploadManager->Remove(siaPath)))
|
||||||
{
|
{
|
||||||
@@ -279,7 +284,7 @@ private:
|
|||||||
if (ret == STATUS_SUCCESS)
|
if (ret == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
// Create file as specified
|
// Create file as specified
|
||||||
HANDLE handle = CreateFile(
|
HANDLE handle = ::CreateFile(
|
||||||
cacheFilePath.c_str(),
|
cacheFilePath.c_str(),
|
||||||
genericDesiredAccess,
|
genericDesiredAccess,
|
||||||
ShareAccess,
|
ShareAccess,
|
||||||
@@ -346,10 +351,7 @@ private:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK SiaDrive_FindFiles(
|
static NTSTATUS DOKAN_CALLBACK SiaDrive_FindFiles(LPCWSTR FileName, PFillFindData FillFindData, PDOKAN_FILE_INFO DokanFileInfo)
|
||||||
LPCWSTR FileName,
|
|
||||||
PFillFindData FillFindData,
|
|
||||||
PDOKAN_FILE_INFO DokanFileInfo)
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(_dokanMutex);
|
std::lock_guard<std::mutex> l(_dokanMutex);
|
||||||
auto siaFileTree = _siaFileTree;
|
auto siaFileTree = _siaFileTree;
|
||||||
@@ -394,7 +396,7 @@ private:
|
|||||||
for (auto& file : fileList)
|
for (auto& file : fileList)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATA fd = { 0 };
|
WIN32_FIND_DATA fd = { 0 };
|
||||||
wcscpy_s(fd.cFileName, PathFindFileName(file->GetSiaPath().c_str()));
|
wcscpy_s(fd.cFileName, ::PathFindFileName(file->GetSiaPath().c_str()));
|
||||||
|
|
||||||
LARGE_INTEGER li = { 0 };
|
LARGE_INTEGER li = { 0 };
|
||||||
li.QuadPart = file->GetFileSize();
|
li.QuadPart = file->GetFileSize();
|
||||||
@@ -424,7 +426,7 @@ private:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LARGE_INTEGER li = { 0 };
|
LARGE_INTEGER li = { 0 };
|
||||||
BOOL sizeOk = GetFileSizeEx(handle, &li);
|
BOOL sizeOk = ::GetFileSizeEx(handle, &li);
|
||||||
|
|
||||||
::CloseHandle(handle);
|
::CloseHandle(handle);
|
||||||
|
|
||||||
@@ -440,6 +442,75 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS DOKAN_CALLBACK Sia_GetFileInformation(LPCWSTR FileName, LPBY_HANDLE_FILE_INFORMATION HandleFileInformation, PDOKAN_FILE_INFO DokanFileInfo)
|
||||||
|
{
|
||||||
|
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
||||||
|
BOOL opened = FALSE;
|
||||||
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
String cachePath = GetCacheLocation().c_str();
|
||||||
|
if (wcscmp(FileName, L"\\") != 0)
|
||||||
|
{
|
||||||
|
cachePath.resize(MAX_PATH + 1);
|
||||||
|
::PathAppend(&cachePath[0], FileName);
|
||||||
|
cachePath = cachePath.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
|
{
|
||||||
|
handle = ::CreateFile(&cachePath[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
ret = DokanNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opened = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!::GetFileInformationByHandle(handle, HandleFileInformation))
|
||||||
|
{
|
||||||
|
// FileName is a root directory
|
||||||
|
// in this case, FindFirstFile can't get directory information
|
||||||
|
if (wcslen(FileName) == 1)
|
||||||
|
{
|
||||||
|
HandleFileInformation->dwFileAttributes = ::GetFileAttributes(&cachePath[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATAW find = { 0 };
|
||||||
|
HANDLE findHandle = ::FindFirstFile(&cachePath[0], &find);
|
||||||
|
if (findHandle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
// TODO Not Cached, so manual attributes
|
||||||
|
ret = DokanNtStatusFromWin32(::GetLastError());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleFileInformation->dwFileAttributes = find.dwFileAttributes;
|
||||||
|
HandleFileInformation->ftCreationTime = find.ftCreationTime;
|
||||||
|
HandleFileInformation->ftLastAccessTime = find.ftLastAccessTime;
|
||||||
|
HandleFileInformation->ftLastWriteTime = find.ftLastWriteTime;
|
||||||
|
HandleFileInformation->nFileSizeHigh = find.nFileSizeHigh;
|
||||||
|
HandleFileInformation->nFileSizeLow = find.nFileSizeLow;
|
||||||
|
|
||||||
|
FindClose(findHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opened)
|
||||||
|
{
|
||||||
|
CloseHandle(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_Mounted(PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_Mounted(PDOKAN_FILE_INFO DokanFileInfo)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(_dokanMutex);
|
std::lock_guard<std::mutex> l(_dokanMutex);
|
||||||
@@ -505,7 +576,7 @@ public:
|
|||||||
_dokanOps.FindStreams = nullptr;
|
_dokanOps.FindStreams = nullptr;
|
||||||
_dokanOps.FlushFileBuffers = nullptr;
|
_dokanOps.FlushFileBuffers = nullptr;
|
||||||
_dokanOps.GetDiskFreeSpaceW = Sia_GetDiskFreeSpaceW;
|
_dokanOps.GetDiskFreeSpaceW = Sia_GetDiskFreeSpaceW;
|
||||||
_dokanOps.GetFileInformation = nullptr;
|
_dokanOps.GetFileInformation = Sia_GetFileInformation;
|
||||||
_dokanOps.GetFileSecurityW = nullptr;
|
_dokanOps.GetFileSecurityW = nullptr;
|
||||||
_dokanOps.GetVolumeInformationW = Sia_GetVolumeInformation;
|
_dokanOps.GetVolumeInformationW = Sia_GetVolumeInformation;
|
||||||
_dokanOps.LockFile = nullptr;
|
_dokanOps.LockFile = nullptr;
|
||||||
|
Reference in New Issue
Block a user