/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: FS.Generic.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "FS.hpp" #include "FS.Generic.hpp" #include #if defined(_AURUNTIME_GENERICFS) #include // if your platform isn't supported, let's not assume we have these dino headers #if defined(__has_include) && __has_include() #define _AURUNTIME_HAS_STAT #include #endif // HAS_STD_FS might exist, who knows, let's hope namespace Aurora::IO::FS { AUKN_SYM bool FilesInDirectory(const AuString &string, AuList &files) { return IterateDirEntriesSTL(string, true, files); } AUKN_SYM bool DirsInDirectory(const AuString &string, AuList &dirs) { return IterateDirEntriesSTL(string, false, dirs); } AUKN_SYM bool WriteFile(const AuString &path, const void *data, AuUInt length) { auto file = fopen(NormalizePathRet(path).c_str(), "wb"); if (!file) { return false; } auto bytesWritten = fwrite(data, 1, length, file); fclose(file); return bytesWritten == length; } AUKN_SYM bool ReadFile(const AuString &path, AuByteBuffer &buffer) { auto file = fopen(NormalizePathRet(path).c_str(), "rb"); if (!file) { return false; } if (fseek(file, 0, SEEK_END) < 0) { return false; } auto size = ftell(file); if (fseek(file, 0, SEEK_CUR) < 0) { return false; } buffer.resize(size); auto bytesRead = fread(buffer.data(), 1, size, file); fclose(file); return bytesRead == size; } AUKN_SYM bool FileExists(const AuString &path) { auto file = fopen(NormalizePathRet(path).c_str(), "rb"); if (!file) return false; fclose(file); return true; } AUKN_SYM bool DirExists(const AuString &path) { #if defined(_AURUNTIME_HAS_STAT) Stat stat; if (!StatFile(path, stat)) { return false; } return stat.existsDirectory; #endif return false; } AUKN_SYM bool DirMk(const AuString &path) { return false; } AUKN_SYM bool Remove(const AuString &path) { #if defined(HAS_STD_FS) try { std::filesystem::remove(std::filesystem::u8path(NormalizePathRet(path))); return true; } catch (...) { return false; } #else return ::remove(NormalizePathRet(path).c_str()); #endif } AUKN_SYM bool Relink(const AuString &src, const AuString &dest) { #if defined(HAS_STD_FS) try { std::filesystem::rename(std::filesystem::u8path(NormalizePathRet(src)), std::filesystem::u8path(NormalizePathRet(dest))); return true; } catch (...) { return false; } #else if (!Copy(src, dest)) { return false; } return Remove(src); #endif } AUKN_SYM bool Copy(const AuString &src, const AuString &dest) { #if defined(HAS_STD_FS) try { std::filesystem::copy(std::filesystem::u8path(NormalizePathRet(src)), std::filesystem::u8path(NormalizePathRet(dest))); return true; } catch (...) { return false; } #else // im not even going to bother writing a crt stream copy here // what are you doing with this reference implemention? Memory::ByteBuffer buffered; if (!ReadFile(src, buffered)) { return false; } return WriteFile(dest, buffered); #endif } #if defined(_AURUNTIME_HAS_STAT) AUKN_SYM bool StatFile(const AuString &pathRel, Stat &stat) { stat = {}; auto path = NormalizePathRet(pathRel); struct stat s; auto err = stat(path.c_str(), &s); if (err == -1) { if (ENOENT == errno) { LogWarn("Critical IO error, errno = {}", path); } return false; } stat.existsFile = S_ISREG(s.st_mode); stat.existsDirectory = S_ISDIR(s.st_mode); stat.existsSystemResource = S_ISSOCK(s.st_mode); stat.exists = stat.existsFile || stat.existsDirectory || stat.existsSystemResource; if (!stat.exists) { LogWarn("Missing attribute type of path {}, stat mode {}", path, s.st_mode); return false; } stat.size = s.st_size; stat.created = ConvertUnixTimespecToMs(s.st_ctime); stat.modified = ConvertUnixTimespecToMs(s.st_mtime); stat.accessed = ConvertUnixTimespecToMs(s.st_atime); err = lstat(path.c_str(), &s); if (err != -1) { stat.symLink = S_ISLNK(s.st_mode); } return true; } #else AUKN_SYM bool StatFile(const AuString &path, Stat &stat) { stat = {}; stat.existsDirectory = DirExists(path); stat.existsFile = FileExists(path); stat.exists = stat.existsDirectory || stat.existsFile; if (stat.exists) { auto time = Time::CurrentClockMS(); stat.created = time; stat.modified = time; stat.accessed = time; } else { stat = {}; } return stat.exists; } #endif } #endif