132 lines
3.7 KiB
C++
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);
|
|
}
|
|
} |