/*** Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: FileAttrs.NT.cpp Date: 2023-2-4 Author: Reece ***/ #include #include "FS.hpp" #include "FileAttrs.NT.hpp" namespace Aurora::IO::FS { AUKN_SYM AuList FileAttrsList(const AuROString &path) { AuList 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 FileAttrsGet(const AuROString &path, const AuROString &attr) { try { AuByteBuffer temp; if (!AuFS::ReadFile(AuString(path) + ":" + AuString(attr), temp)) { return {}; } return AuMove(temp); } catch (...) { return {}; } } AUKN_SYM bool FileAttrsSet(const AuROString &path, const AuROString &attr, const Memory::MemoryViewRead &view) { try { return AuFS::WriteFile(AuString(path) + ":" + AuString(attr), view); } catch (...) { return false; } } AUKN_SYM bool FileAttrsDel(const AuROString &path, const AuROString &attr) { try { return AuFS::Remove(AuString(path) + ":" + AuString(attr)) || AuFS::FileExists(path); } catch (...) { return false; } } }