1
0

Partial fix for delete directory

This commit is contained in:
Scott E. Graves
2017-04-02 13:21:46 -05:00
parent 30f562745b
commit e60653e9b4
2 changed files with 103 additions and 77 deletions

View File

@@ -196,11 +196,12 @@ class SIADRIVE_DOKAN_EXPORTABLE DokanFindFiles :
public CEvent public CEvent
{ {
public: public:
DokanFindFiles(const SString& cachePath, const SString& rootPath, const SString& siaQuery, const SString& findFile) : DokanFindFiles(const SString& cachePath, const SString& rootPath, const SString& siaQuery, const SString& findFile, const SString& fileName) :
_cachePath(cachePath), _cachePath(cachePath),
_rootPath(rootPath), _rootPath(rootPath),
_siaQuery(siaQuery), _siaQuery(siaQuery),
_findFile(findFile) _findFile(findFile),
_fileName(fileName)
{ {
} }
@@ -214,11 +215,12 @@ private:
const SString _rootPath; const SString _rootPath;
const SString _siaQuery; const SString _siaQuery;
const SString _findFile; const SString _findFile;
const SString _fileName;
public: public:
virtual std::shared_ptr<CEvent> Clone() const override virtual std::shared_ptr<CEvent> Clone() const override
{ {
return std::shared_ptr<CEvent>(new DokanFindFiles(_cachePath, _rootPath, _siaQuery, _findFile)); return std::shared_ptr<CEvent>(new DokanFindFiles(_cachePath, _rootPath, _siaQuery, _findFile, _fileName));
} }
virtual SString GetSingleLineMessage() const override virtual SString GetSingleLineMessage() const override
@@ -226,7 +228,8 @@ public:
return L"DokanFindFiles|PATH|" + _cachePath + return L"DokanFindFiles|PATH|" + _cachePath +
"|ROOT|" + _rootPath + "|ROOT|" + _rootPath +
"|QUERY|" + _siaQuery + "|QUERY|" + _siaQuery +
"|FIND|" + _findFile; "|FIND|" + _findFile +
"|FN|" + _fileName;
} }
}; };
@@ -265,8 +268,10 @@ class SIADRIVE_DOKAN_EXPORTABLE DokanGetFileInformation :
public CEvent public CEvent
{ {
public: public:
DokanGetFileInformation(const SString& cachePath) : DokanGetFileInformation(const SString& cachePath, const SString& fileName, const NTSTATUS& result) :
_cachePath(cachePath) _cachePath(cachePath),
_fileName(fileName),
_result(result)
{ {
} }
@@ -277,16 +282,18 @@ public:
private: private:
const SString _cachePath; const SString _cachePath;
const SString _fileName;
const NTSTATUS _result;
public: public:
virtual std::shared_ptr<CEvent> Clone() const override virtual std::shared_ptr<CEvent> Clone() const override
{ {
return std::shared_ptr<CEvent>(new DokanGetFileInformation(_cachePath)); return std::shared_ptr<CEvent>(new DokanGetFileInformation(_cachePath, _fileName, _result));
} }
virtual SString GetSingleLineMessage() const override virtual SString GetSingleLineMessage() const override
{ {
return L"DokanGetFileInformation|PATH|" + _cachePath; return L"DokanGetFileInformation|PATH|" + _cachePath + "|FN|" + _fileName + "|RES|" + SString::FromUInt32(_result);
} }
}; };

View File

@@ -274,7 +274,7 @@ private:
else else
{ {
// FILE_FLAG_BACKUP_SEMANTICS is required for opening directory handles // FILE_FLAG_BACKUP_SEMANTICS is required for opening directory handles
HANDLE handle = ::CreateFile(&cacheFilePath[0], 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 | FILE_FLAG_POSIX_SEMANTICS, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
{ {
DWORD error = GetLastError(); DWORD error = GetLastError();
@@ -295,7 +295,7 @@ private:
else // File (cache and/or Sia operation) else // File (cache and/or Sia operation)
{ {
// Formulate Sia path // Formulate Sia path
SString siaPath = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot()); // Strip drive letter to get Sia path SString siaPath = CSiaApi::FormatToSiaPath(fileName); // Strip drive letter to get Sia path
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
@@ -474,37 +474,36 @@ private:
static NTSTATUS DOKAN_CALLBACK Sia_FindFiles(LPCWSTR fileName, PFillFindData fillFindData, PDOKAN_FILE_INFO dokanFileInfo) static NTSTATUS DOKAN_CALLBACK Sia_FindFiles(LPCWSTR fileName, PFillFindData fillFindData, PDOKAN_FILE_INFO dokanFileInfo)
{ {
NTSTATUS ret = STATUS_SUCCESS; NTSTATUS ret = STATUS_INVALID_SERVER_STATE;
auto siaFileTree = GetFileTree(); auto siaFileTree = GetFileTree();
if (siaFileTree) if (siaFileTree)
{ {
SString siaFileQuery = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot()); SString siaFileQuery = CSiaApi::FormatToSiaPath(fileName);
SString siaRootPath = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot()); SString siaRootPath = CSiaApi::FormatToSiaPath(fileName);
FilePath siaDirQuery = siaFileQuery; FilePath siaDirQuery = siaFileQuery;
FilePath findFile = GetCacheLocation(); FilePath findFile = GetCacheLocation();
FilePath cachePath = GetCacheLocation(); FilePath cachePath = GetCacheLocation();
if (FilePath::DirSep == fileName) if (FilePath::DirSep == fileName)
{ {
siaFileQuery += L"/*.*"; siaFileQuery += L"/*.*";
findFile.Append("*.*"); findFile.Append("*");
} }
else else
{ {
cachePath.Append(fileName); cachePath.Append(fileName);
findFile.Append(fileName); findFile.Append(fileName);
if (cachePath.IsDirectory()) if (dokanFileInfo->IsDirectory)
{ {
siaFileQuery += L"/*.*"; siaFileQuery += L"/*.*";
findFile.Append("*.*"); findFile.Append("*");
} }
else else
{ {
siaDirQuery = cachePath; siaDirQuery = FilePath();
siaDirQuery = CSiaApi::FormatToSiaPath(siaDirQuery.RemoveFileName());
} }
} }
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanFindFiles(cachePath, siaDirQuery, siaFileQuery, findFile))); CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanFindFiles(cachePath, siaDirQuery, siaFileQuery, findFile, fileName)));
WIN32_FIND_DATA findData = { 0 }; WIN32_FIND_DATA findData = { 0 };
HANDLE findHandle = ::FindFirstFile(&findFile[0], &findData); HANDLE findHandle = ::FindFirstFile(&findFile[0], &findData);
@@ -525,62 +524,79 @@ private:
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{ {
dirs.insert({ findData.cFileName, 0 }); dirs.insert({ findData.cFileName, 0 });
}
bool exists;
if (!ApiSuccess(_siaApi->GetRenter()->FileExists(CSiaApi::FormatToSiaPath(FilePath(siaRootPath, findData.cFileName)), exists)))
{
::FindClose(findHandle);
return STATUS_INVALID_DEVICE_STATE;
}
if (findData.nFileSizeHigh || findData.nFileSizeLow || !exists)
{
fillFindData(&findData, dokanFileInfo); fillFindData(&findData, dokanFileInfo);
files.insert({ findData.cFileName, 1 }); }
else
{
bool exists;
if (!ApiSuccess(_siaApi->GetRenter()->FileExists(CSiaApi::FormatToSiaPath(FilePath(fileName, findData.cFileName)), exists)))
{
::FindClose(findHandle);
return STATUS_INVALID_DEVICE_STATE;
}
if (findData.nFileSizeHigh || findData.nFileSizeLow || !exists)
{
fillFindData(&findData, dokanFileInfo);
files.insert({ findData.cFileName, 1 });
}
} }
} }
} while (::FindNextFile(findHandle, &findData) != 0); } while (::FindNextFile(findHandle, &findData) != 0);
DWORD error = GetLastError();
::FindClose(findHandle); ::FindClose(findHandle);
// Find Sia directories if (error == ERROR_NO_MORE_FILES)
auto dirList = siaFileTree->QueryDirectories(siaDirQuery);
for (auto& dir : dirList)
{ {
if (dirs.find(dir) == dirs.end()) // Find Sia directories
if (!static_cast<SString>(siaDirQuery).IsNullOrEmpty())
{ {
WIN32_FIND_DATA fd = { 0 }; auto dirList = siaFileTree->QueryDirectories(siaDirQuery);
wcscpy_s(fd.cFileName, dir.str().c_str()); for (auto& dir : dirList)
fd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
fillFindData(&fd, dokanFileInfo);
// Create cache sub-folder
FilePath subCachePath(cachePath, dir);
if (!subCachePath.IsDirectory())
{ {
subCachePath.CreateDirectory(); if (dirs.find(dir) == dirs.end())
{
// Create cache sub-folder
FilePath subCachePath(cachePath, dir);
if (!subCachePath.IsDirectory())
{
subCachePath.CreateDirectory();
}
WIN32_FIND_DATA fd = { 0 };
wcscpy_s(fd.cFileName, dir.str().c_str());
fd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
fillFindData(&fd, dokanFileInfo);
}
} }
} }
}
// Find Sia files // Find Sia files
auto fileList = siaFileTree->Query(siaFileQuery); auto fileList = siaFileTree->Query(siaFileQuery);
for (auto& file : fileList) for (auto& file : fileList)
{
FilePath fp = file->GetSiaPath();
fp.StripToFileName();
if (files.find(fp) == files.end())
{ {
WIN32_FIND_DATA fd = { 0 }; FilePath fp = file->GetSiaPath();
wcscpy_s(fd.cFileName, &fp[0]); fp.StripToFileName();
if (files.find(fp) == files.end())
{
WIN32_FIND_DATA fd = { 0 };
wcscpy_s(fd.cFileName, &fp[0]);
LARGE_INTEGER li = { 0 }; LARGE_INTEGER li = { 0 };
li.QuadPart = file->GetFileSize(); li.QuadPart = file->GetFileSize();
fd.nFileSizeHigh = li.HighPart; fd.nFileSizeHigh = li.HighPart;
fd.nFileSizeLow = li.LowPart; fd.nFileSizeLow = li.LowPart;
fd.dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL; fd.dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL;
fillFindData(&fd, dokanFileInfo); fillFindData(&fd, dokanFileInfo);
}
} }
ret = STATUS_SUCCESS;
}
else
{
ret = DokanNtStatusFromWin32(error);
} }
} }
} }
@@ -612,17 +628,13 @@ private:
BOOL opened = FALSE; BOOL opened = FALSE;
NTSTATUS ret = STATUS_SUCCESS; NTSTATUS ret = STATUS_SUCCESS;
FilePath cachePath(GetCacheLocation(), fileName);
SString siaPath = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot());
auto siaFileTree = GetFileTree(); auto siaFileTree = GetFileTree();
auto siaFile = siaFileTree ? siaFileTree->GetFile(siaPath) : nullptr; auto siaFile = siaFileTree ? siaFileTree->GetFile(openFileInfo->SiaPath) : nullptr;
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanGetFileInformation(cachePath)));
HANDLE tempHandle = openFileInfo->FileHandle; HANDLE tempHandle = openFileInfo->FileHandle;
if (!siaFile && (!openFileInfo->FileHandle || (openFileInfo->FileHandle == INVALID_HANDLE_VALUE))) if (!siaFile && (!tempHandle || (tempHandle == INVALID_HANDLE_VALUE)))
{ {
tempHandle = ::CreateFile(&cachePath[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); tempHandle = ::CreateFile(&openFileInfo->CacheFilePath[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (tempHandle == INVALID_HANDLE_VALUE) if (tempHandle == INVALID_HANDLE_VALUE)
{ {
ret = DokanNtStatusFromWin32(::GetLastError()); ret = DokanNtStatusFromWin32(::GetLastError());
@@ -650,12 +662,12 @@ private:
// in this case, FindFirstFile can't get directory information // in this case, FindFirstFile can't get directory information
if (wcscmp(fileName, L"\\") == 0) if (wcscmp(fileName, L"\\") == 0)
{ {
handleFileInfo->dwFileAttributes = ::GetFileAttributes(&cachePath[0]); handleFileInfo->dwFileAttributes = ::GetFileAttributes(&openFileInfo->CacheFilePath[0]);
} }
else else
{ {
WIN32_FIND_DATAW find = { 0 }; WIN32_FIND_DATAW find = { 0 };
HANDLE findHandle = ::FindFirstFile(&cachePath[0], &find); HANDLE findHandle = ::FindFirstFile(&openFileInfo->CacheFilePath[0], &find);
if (findHandle == INVALID_HANDLE_VALUE) if (findHandle == INVALID_HANDLE_VALUE)
{ {
DWORD error = ::GetLastError(); DWORD error = ::GetLastError();
@@ -681,6 +693,8 @@ private:
::CloseHandle(tempHandle); ::CloseHandle(tempHandle);
} }
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanGetFileInformation(openFileInfo->CacheFilePath, fileName, ret)));
return ret; return ret;
} }
@@ -709,7 +723,7 @@ private:
UNREFERENCED_PARAMETER(dokanFileInfo); UNREFERENCED_PARAMETER(dokanFileInfo);
// TODO Implement this correctly // TODO Implement this correctly
*FreeBytesAvailable = static_cast<ULONGLONG>(512 * 1024 * 1024); *FreeBytesAvailable = static_cast<ULONGLONG>(1024 * 1024 * 1024);
*TotalNumberOfBytes = 9223372036854775807; *TotalNumberOfBytes = 9223372036854775807;
*TotalNumberOfFreeBytes = 9223372036854775807; *TotalNumberOfFreeBytes = 9223372036854775807;
@@ -724,7 +738,7 @@ private:
UNREFERENCED_PARAMETER(dokanFileInfo); UNREFERENCED_PARAMETER(dokanFileInfo);
wcscpy_s(VolumeNameBuffer, VolumeNameSize, L"SiaDrive"); wcscpy_s(VolumeNameBuffer, VolumeNameSize, L"SiaDrive");
*VolumeSerialNumber = 0x19831116; *VolumeSerialNumber = 0x19831186;
*MaximumComponentLength = 256; *MaximumComponentLength = 256;
*FileSystemFlags = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | *FileSystemFlags = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
FILE_SUPPORTS_REMOTE_STORAGE | FILE_UNICODE_ON_DISK | FILE_SUPPORTS_REMOTE_STORAGE | FILE_UNICODE_ON_DISK |
@@ -971,7 +985,7 @@ private:
// if open with FILE_FLAG_DELETE_ON_CLOSE // if open with FILE_FLAG_DELETE_ON_CLOSE
if (dokanFileInfo->IsDirectory) if (dokanFileInfo->IsDirectory)
{ {
if (filePath.RemoveDirectory()) if (RetryableAction(filePath.RemoveDirectory(), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
{ {
} }
else else
@@ -980,7 +994,7 @@ private:
} }
else else
{ {
if (filePath.DeleteFile()) if (RetryableAction(filePath.RemoveDirectory(), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
{ {
} }
else else
@@ -1040,11 +1054,13 @@ private:
} }
} }
while ((ret == STATUS_SUCCESS) && (::FindNextFile(findHandle, &findData) != 0)); while ((ret == STATUS_SUCCESS) && (::FindNextFile(findHandle, &findData) != 0));
if (ret != STATUS_DIRECTORY_NOT_EMPTY)
DWORD error = GetLastError();
if (error != ERROR_NO_MORE_FILES)
{ {
ret = DokanNtStatusFromWin32(error); DWORD error = GetLastError();
if (error != ERROR_NO_MORE_FILES)
{
ret = DokanNtStatusFromWin32(error);
}
} }
::FindClose(findHandle); ::FindClose(findHandle);
@@ -1321,6 +1337,9 @@ public:
_dokanOptions.ThreadCount = 0; // use default _dokanOptions.ThreadCount = 0; // use default
#ifdef _DEBUG #ifdef _DEBUG
_dokanOptions.Options = DOKAN_OPTION_DEBUG | DOKAN_OPTION_DEBUG_LOG_FILE; _dokanOptions.Options = DOKAN_OPTION_DEBUG | DOKAN_OPTION_DEBUG_LOG_FILE;
_dokanOptions.Timeout = (60 * 1000) * 60;
#else
_dokanOptions.Options = 0;
#endif #endif
} }