AuroraRuntime/Source/IO/FS/FileAttrs.NT.cpp

132 lines
3.7 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FileAttrs.NT.cpp
Date: 2023-2-4
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "FS.hpp"
#include "FileAttrs.NT.hpp"
namespace Aurora::IO::FS
{
AUKN_SYM AuList<AuString> FileAttrsList(const AuString &path)
{
AuList<AuString> names;
WIN32_FIND_STREAM_DATA data;
if (path.empty())
{
SysPushErrorArg("Empty path provided");
return {};
}
auto pathex = NormalizePathRet(path);
if (pathex.empty())
{
return {};
}
auto win32Path = Locale::ConvertFromUTF8(pathex);
if (win32Path.empty())
{
return {};
}
if (!pFindFirstStreamW)
{
SysPushErrorUnavailableError();
return {};
}
auto hIterationHandle = pFindFirstStreamW(win32Path.c_str(),
FindStreamInfoStandard,
&data,
0);
if (hIterationHandle == INVALID_HANDLE_VALUE)
{
if (!AuFS::FileExists(pathex))
{
SysPushErrorResourceMissing("Missing file: {}", path);
return {};
}
SysPushErrorIO("Couldn't open a handle for: {}", path);
return {};
}
do
{
AuString currentName;
currentName = AuLocale::ConvertFromWChar(data.cStreamName, wcsnlen_s(data.cStreamName, AuArraySize(data.cStreamName)));
if (currentName.empty())
{
continue;
}
// meh, noise. doesnt prevent an explicit read for this attribute.
if (currentName == "::$DATA")
{
continue;
}
{
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/a82e9105-2405-4e37-b2c3-28c773902d85
// Seems like NTFS docs
// "A file's data is an attribute; the "Data Attribute" known as $DATA"
// ok, so, let's drop this suffix?
if (AuEndsWith(currentName, "$DATA"))
{
if (!AuTryResize(currentName, currentName.size() - 5))
{
SysPushErrorMemory();
continue;
}
}
}
int endRemoval = currentName.size() > 1 && currentName[currentName.size() - 1] == ':';
if (currentName[0] == ':')
{
auto endLen = currentName.size() - 1;
AuMemmove(currentName.data(), currentName.data() + 1, endLen);
currentName.resize(endLen - endRemoval);
}
else if (endRemoval)
{
currentName.pop_back();
}
names.push_back(currentName);
}
while (pFindNextStreamW(hIterationHandle, &data));
pFindClose(hIterationHandle);
return names;
}
AUKN_SYM AuResult<Memory::ByteBuffer> FileAttrsGet(const AuString &path, const AuString &attr)
{
AuByteBuffer temp;
if (!AuFS::ReadFile(path + ":" + attr, temp))
{
return {};
}
return AuMove(temp);
}
AUKN_SYM bool FileAttrsSet(const AuString &path, const AuString &attr, const Memory::MemoryViewRead &view)
{
return AuFS::WriteFile(path + ":" + attr, view);
}
AUKN_SYM bool FileAttrsDel(const AuString &path, const AuString &attr)
{
return AuFS::Remove(path + ":" + attr) || AuFS::FileExists(path);
}
}