[+] IReadDir

[+] AuIOFS::ReadDir
[*] Fix erroneous return false under fs remove (NT)
This commit is contained in:
Reece Wilson 2022-07-23 07:41:47 +01:00
parent 2470cbc12a
commit b8bcab1bdc
4 changed files with 169 additions and 14 deletions

View File

@ -9,18 +9,24 @@
namespace Aurora::IO::FS
{
struct IReadDir;
/**
Lists files with respect to a given partial or full path of a directory
@param files relative address of an entry
@deprecate use ReadDir
*/
AUKN_SYM bool FilesInDirectory(const AuString &string, AuList<AuString> &files);
/**
Lists directories with respect to a given partial or full path of a directory
@param files relative address of an entry
@deprecate use ReadDir
*/
AUKN_SYM bool DirsInDirectory(const AuString &string, AuList<AuString> &dirs);
AUKN_SYM AuSPtr<IReadDir> ReadDir(const AuString &string);
AUKN_SYM bool WriteFile(const AuString &path, const Memory::MemoryViewRead &blob);
AUKN_SYM bool WriteString(const AuString &path, const AuString &str);
@ -56,3 +62,4 @@ namespace Aurora::IO::FS
#include "IAsyncFileStream.hpp"
#include "Async.hpp"
#include "Watcher.hpp"
#include "IReadDir.hpp"

View File

@ -0,0 +1,22 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IReadDir.hpp
Date: 2022-07-22
Author: Reece
***/
#pragma once
namespace Aurora::IO::FS
{
struct StatEx : Stat
{
AuString path;
AuString fileName;
};
struct IReadDir
{
virtual StatEx *Next() = 0;
};
}

View File

@ -30,6 +30,4 @@ namespace Aurora::IO
AUI_METHOD(bool, ApplyRateLimit, ())
);
}

View File

@ -20,29 +20,151 @@ namespace Aurora::IO::FS
return CreateDirectoryW(Locale::ConvertFromUTF8(str).c_str(), NULL);
}
AUKN_SYM bool FilesInDirectory(const AuString &string, AuList<AuString> &files)
struct ReadDirStructure : IReadDir
{
if (IterateDirEntriesSTL(string, true, files))
HANDLE hFind {INVALID_HANDLE_VALUE};
WIN32_FIND_DATAW ffd;
bool bFirstTick {true};
bool bDead {false};
StatEx stat;
AuString sPath;
~ReadDirStructure()
{
return true;
::FindClose(this->hFind);
}
// TODO: Implement a fast path for NT. std::filesystem is unusably slow
virtual StatEx *Next() override
{
if (!AuExchange(this->bFirstTick, false))
{
if (::FindNextFileW(this->hFind, &this->ffd) == 0)
{
return {};
}
}
if (this->bDead)
{
return {};
}
if (this->ffd.cFileName == std::wstring(L".") ||
this->ffd.cFileName == std::wstring(L".."))
{
return Next();
}
stat.exists = true;
stat.fileName = Locale::ConvertFromWChar(this->ffd.cFileName);
if (stat.fileName.empty())
{
this->bDead = true;
return {};
}
stat.path = NormalizePathRet(this->sPath + stat.fileName);
if (stat.path.empty())
{
this->bDead = true;
return {};
}
stat.existsDirectory = this->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
stat.existsFile = !stat.existsDirectory;
stat.symLink = this->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT;
stat.size = AuUInt64(this->ffd.nFileSizeLow) | (AuUInt64(this->ffd.nFileSizeHigh) << 32);
stat.created = Time::ConvertTimestamp(this->ffd.ftCreationTime);
stat.modified = Time::ConvertTimestamp(this->ffd.ftLastWriteTime);
stat.accessed = Time::ConvertTimestamp(this->ffd.ftLastAccessTime);
return &stat;
}
};
AUKN_SYM AuSPtr<IReadDir> ReadDir(const AuString &string)
{
auto pObj = AuMakeShared<ReadDirStructure>();
if (!pObj)
{
SysPushErrorMem();
return {};
}
if (!AuIOFS::NormalizePath(pObj->sPath, string))
{
SysPushErrorMem();
return {};
}
if (!AuTryInsert(pObj->sPath, '\\'))
{
SysPushErrorMem();
return {};
}
pObj->hFind = ::FindFirstFileW(AuLocale::ConvertFromUTF8(pObj->sPath + "*").c_str(), &pObj->ffd);
if (INVALID_HANDLE_VALUE == pObj->hFind)
{
SysPushErrorIO();
return {};
}
return pObj;
}
AUKN_SYM bool FilesInDirectory(const AuString &string, AuList<AuString> &files)
{
auto itr = ReadDir(string);
if (!itr)
{
return false;
}
// SECURITY(): if next fails, its indistinguishable from end of file list, and will return true. it kinda sucks
while (auto stat = itr->Next())
{
if (!stat->existsFile)
{
continue;
}
if (!AuTryInsert(files, stat->fileName))
{
return false;
}
}
return true;
}
AUKN_SYM bool DirsInDirectory(const AuString &string, AuList<AuString> &dirs)
{
if (IterateDirEntriesSTL(string, false, dirs))
auto itr = ReadDir(string);
if (!itr)
{
return true;
return false;
}
// TODO: Implement a fast path for NT. std::filesystem is unusably slow
// SECURITY(): if next fails, its indistinguishable from end of file list, and will return true. it kinda sucks
while (auto stat = itr->Next())
{
if (!stat->existsDirectory)
{
continue;
}
if (!AuTryInsert(dirs, stat->fileName))
{
return false;
}
}
return true;
}
AUKN_SYM bool WriteFile(const AuString &path, const Memory::MemoryViewRead &blob)
{
@ -212,10 +334,16 @@ namespace Aurora::IO::FS
try
{
auto translatedPath = Locale::ConvertFromUTF8(NormalizePathRet(path));
if (!DeleteFileW(translatedPath.c_str()))
if (::DeleteFileW(translatedPath.c_str()))
{
return RemoveDirectoryW(translatedPath.c_str());
return true;
}
if (::RemoveDirectoryW(translatedPath.c_str()))
{
return true;
}
return false;
}
catch (...)