/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: FS.Unix.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "FS.hpp" #include "FS.Generic.hpp" #include #if !defined(_AURUNTIME_GENERICFS) #include #include #include #include #if defined(AURORA_IS_LINUX_DERIVED) #include #endif namespace Aurora::IO::FS { bool _MkDir(const AuString &path) { return mkdir(path.c_str(), 0760) == 0; } 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 = OpenWriteUnique(path); SysCheckReturn(file, false); AuUInt written = length; if (!file->Write(Memory::MemoryViewStreamRead(data, written))) { SysPushErrorMem(); return false; } if (written != length) { SysPushErrorIO(); return false; } return false; } AUKN_SYM bool ReadFile(const AuString &path, AuList &buffer) { auto file = OpenReadUnique(path); SysCheckReturn(file, false); auto len = file->GetLength(); if (!AuTryResize(buffer, len)) { SysPushErrorMem(); return false; } AuUInt read; if (!file->Read(Memory::MemoryViewStreamWrite {buffer, read})) { SysPushErrorIO(); return false; } if (read != buffer.size()) { SysPushErrorIO(); return false; } return false; } static bool UnixExists(const AuString &path, bool dir) { struct stat s; int err = stat(path.c_str(), &s); if (-1 == err) { SysAssert(ENOENT == errno, "General File IO Error, path {}", path); return false; } return dir ? S_ISDIR(s.st_mode) : S_ISREG(s.st_mode); } AUKN_SYM bool FileExists(const AuString &path) { return UnixExists(NormalizePathRet(path), false); } AUKN_SYM bool DirExists(const AuString &path) { return UnixExists(NormalizePathRet(path), true); } AUKN_SYM bool DirMk(const AuString &path) { return CreateDirectories(NormalizePathRet(path), false); } AUKN_SYM bool Remove(const AuString &path) { return remove(NormalizePathRet(path).c_str()) != -1; } AUKN_SYM bool Relink(const AuString &src, const AuString &dest) { return rename(NormalizePathRet(src).c_str(), NormalizePathRet(dest).c_str()) != -1; } #if defined(AURORA_IS_LINUX_DERIVED) AUKN_SYM bool Copy(const AuString &src, const AuString &dest) { auto normalizedSrcPath = NormalizePathRet(src); auto normalizedDestPath = NormalizePathRet(dest); int input, output; if ((input = open(normalizedSrcPath.c_str(), O_RDONLY)) == -1) { return false; } struct stat fileinfo = { 0 }; if (fstat(input, &fileinfo) != 0) { close(input); return false; } if ((output = creat(normalizedDestPath.c_str(), fileinfo.st_mode)) == -1) { close(input); return false; } off_t bytesCopied = 0; auto result = sendfile(output, input, &bytesCopied, fileinfo.st_size) != -1; close(input); close(output); return result; } #elif defined(AURORA_IS_BSD_DERIVED) AUKN_SYM bool Copy(const AuString &src, const AuString &dest) { auto normalizedSrcPath = NormalizePathRet(src); auto normalizedDestPath = NormalizePathRet(dest); int input, output; if ((input = open(normalizedSrcPath.c_str(), O_RDONLY)) == -1) { return false; } struct stat fileinfo = { 0 }; if (fstat(input, &fileinfo) != 0) { close(input) return false; } if ((output = creat(normalizedDestPath.c_str(), fileinfo.st_mode)) == -1) { close(input); return false; } auto result = fcopyfile(input, output, 0, COPYFILE_ALL) == 0; close(input); close(output); return result; } #else AUKN_SYM bool Copy(const AuString &src, const AuString &dest) { // TODO: not that i care return false; } #endif 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 = Time::CTimeToMS(s.st_ctime); stat.modified = Time::CTimeToMS(s.st_mtime); stat.accessed = Time::CTimeToMS(s.st_atime); err = lstat(path.c_str(), &s); if (err != -1) { stat.symLink = S_ISLNK(s.st_mode); } return true; } } #endif