276 lines
7.1 KiB
C++
276 lines
7.1 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: FS.NT.cpp
|
|
Date: 2021-6-12
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "FS.hpp"
|
|
#include "FS.Generic.hpp"
|
|
#include <Source/Time/Time.hpp>
|
|
|
|
#if !defined(_AURUNTIME_GENERICFS)
|
|
namespace Aurora::IO::FS
|
|
{
|
|
static const AuUInt64 kFileCopyBlock = 0xFFFF; // 64KiB
|
|
|
|
bool _MkDir(const AuString &str)
|
|
{
|
|
return CreateDirectoryW(Locale::ConvertFromUTF8(str).c_str(), NULL);
|
|
}
|
|
|
|
AUKN_SYM bool FilesInDirectory(const AuString &string, AuList<AuString> &files)
|
|
{
|
|
if (IterateDirEntriesSTL(string, true, files))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// TODO: Implement a fast path for NT. std::filesystem is unusably slow
|
|
|
|
return false;
|
|
}
|
|
|
|
AUKN_SYM bool DirsInDirectory(const AuString &string, AuList<AuString> &dirs)
|
|
{
|
|
if (IterateDirEntriesSTL(string, false, dirs))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// TODO: Implement a fast path for NT. std::filesystem is unusably slow
|
|
|
|
return false;
|
|
}
|
|
|
|
AUKN_SYM bool WriteFile(const AuString &path, const Memory::MemoryViewRead &blob)
|
|
{
|
|
bool status;
|
|
size_t offset;
|
|
HANDLE fileHandle;
|
|
std::wstring win32Path;
|
|
AuString pathNormalized;
|
|
AuUInt length;
|
|
|
|
status = false;
|
|
pathNormalized = NormalizePathRet(path);
|
|
|
|
if (pathNormalized.empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
win32Path = Locale::ConvertFromUTF8(pathNormalized);
|
|
|
|
if (win32Path.empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CreateDirectories(pathNormalized, true);
|
|
|
|
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorIO("Couldn't open handle: {}", path);
|
|
return false;
|
|
}
|
|
|
|
length = blob.length;
|
|
offset = 0;
|
|
while (length)
|
|
{
|
|
DWORD written;
|
|
|
|
int blockSize = AuMin(static_cast<AuUInt64>(kFileCopyBlock), static_cast<AuUInt64>(length));
|
|
|
|
if (!::WriteFile(fileHandle, &reinterpret_cast<const char *>(blob.ptr)[offset], blockSize, &written, NULL))
|
|
{
|
|
SysPushErrorIO();
|
|
goto out;
|
|
}
|
|
|
|
if (written != blockSize)
|
|
{
|
|
SysPushErrorIO();
|
|
goto out;
|
|
}
|
|
|
|
offset += written;
|
|
length -= written;
|
|
}
|
|
|
|
status = true;
|
|
|
|
out:
|
|
AuWin32CloseHandle(fileHandle);
|
|
return status;
|
|
}
|
|
|
|
AUKN_SYM bool ReadFile(const AuString &path, AuByteBuffer &buffer)
|
|
{
|
|
std::wstring win32Path;
|
|
LARGE_INTEGER length;
|
|
bool status;
|
|
size_t offset;
|
|
|
|
status = false;
|
|
offset = 0;
|
|
win32Path = Locale::ConvertFromUTF8(NormalizePathRet(path));
|
|
|
|
if (win32Path.empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
auto fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorIO("Couldn't open handle: {}", path);
|
|
return false;
|
|
}
|
|
|
|
if (!GetFileSizeEx(fileHandle, &length))
|
|
{
|
|
SysPushErrorIO();
|
|
goto out;
|
|
}
|
|
|
|
if (!AuTryResize(buffer, length.QuadPart))
|
|
{
|
|
SysPushErrorMem();
|
|
goto out;
|
|
}
|
|
|
|
while (length.QuadPart)
|
|
{
|
|
DWORD read;
|
|
|
|
int blockSize = AuMin(static_cast<AuUInt64>(kFileCopyBlock), static_cast<AuUInt64>(length.QuadPart));
|
|
|
|
if (!::ReadFile(fileHandle, &buffer[offset], blockSize, &read, NULL))
|
|
{
|
|
AuLogWarn("ReadFile IO Error: 0x{:x} {}", GetLastError(), path);
|
|
SysPushErrorIO();
|
|
goto out;
|
|
}
|
|
|
|
offset += read;
|
|
length.QuadPart -= read;
|
|
}
|
|
|
|
status = true;
|
|
|
|
out:
|
|
AuWin32CloseHandle(fileHandle);
|
|
return status;
|
|
}
|
|
|
|
AUKN_SYM bool FileExists(const AuString &path)
|
|
{
|
|
try
|
|
{
|
|
DWORD dwAttrib = GetFileAttributesW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
|
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) &&
|
|
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM bool DirExists(const AuString &path)
|
|
{
|
|
try
|
|
{
|
|
DWORD dwAttrib = GetFileAttributesW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
|
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) &&
|
|
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM bool DirMk(const AuString &path)
|
|
{
|
|
try
|
|
{
|
|
return CreateDirectories(NormalizePathRet(path), false);
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM bool Remove(const AuString &path)
|
|
{
|
|
try
|
|
{
|
|
auto translatedPath = Locale::ConvertFromUTF8(NormalizePathRet(path));
|
|
if (!DeleteFileW(translatedPath.c_str()))
|
|
{
|
|
return RemoveDirectoryW(translatedPath.c_str());
|
|
}
|
|
return false;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM bool Relink(const AuString &src, const AuString &dest)
|
|
{
|
|
try
|
|
{
|
|
return MoveFileW(Locale::ConvertFromUTF8(NormalizePathRet(src)).c_str(), Locale::ConvertFromUTF8(NormalizePathRet(dest)).c_str());
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM bool Copy(const AuString &src, const AuString &dest)
|
|
{
|
|
try
|
|
{
|
|
return CopyFileW(Locale::ConvertFromUTF8(NormalizePathRet(src)).c_str(), Locale::ConvertFromUTF8(NormalizePathRet(dest)).c_str(), true);
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM bool StatFile(const AuString &path, Stat &stat)
|
|
{
|
|
WIN32_FILE_ATTRIBUTE_DATA data;
|
|
|
|
stat = {};
|
|
|
|
if (!GetFileAttributesExW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str(), GetFileExInfoStandard, &data))
|
|
{
|
|
stat.exists = false;
|
|
return false;
|
|
}
|
|
|
|
stat.exists = true;
|
|
stat.existsDirectory = data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
|
stat.existsFile = !stat.existsDirectory;
|
|
stat.symLink = data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT;
|
|
|
|
stat.size = AuUInt64(data.nFileSizeLow) | (AuUInt64(data.nFileSizeHigh) << 32);
|
|
|
|
stat.created = Time::ConvertTimestamp(data.ftCreationTime);
|
|
stat.modified = Time::ConvertTimestamp(data.ftLastWriteTime);
|
|
stat.accessed = Time::ConvertTimestamp(data.ftLastAccessTime);
|
|
return true;
|
|
}
|
|
}
|
|
#endif |