/*** Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuProcAddresses.UNIX.cpp Date: 2024-3-5 Author: Reece ***/ #include "RuntimeInternal.hpp" #include "AuProcAddresses.UNIX.hpp" #if defined(AURORA_IS_LINUX_DERIVED) #include "AuProcAddresses.Linux.hpp" #endif #include #include #include namespace Aurora::Process { void PosixForkResetLocks(); } namespace Aurora::Memory { AuUInt32 RoundPageUp(AuUInt32 value); } namespace Aurora { int PosixOpen(const char *pathname, int flags, mode_t mode) { return ::open(pathname, flags, mode); } void PosixDoForkHooks() { Process::PosixForkResetLocks(); Debug::DeinitSignalHandlers(); } void PosixShutup() { int fd = PosixOpen("/dev/null", O_RDWR); ::dup2(fd, STDERR_FILENO); ::dup2(fd, STDOUT_FILENO); ::dup2(fd, STDIN_FILENO); ::close(fd); } void PosixFDYeetus() { #if defined(AURORA_IS_BSD_DERIVED) closefrom(STDERR_FILENO + 1); #elif defined(AURORA_IS_LINUX_DERIVED) close_range(STDERR_FILENO + 1, UINT_MAX, 0); #endif } void PosixTerminate() { ::killpg(0, SIGKILL); } static bool PosixLseek63(int fd, AuUInt64 offset, int whence, AuUInt64 *pOffset) { if (offset > std::numeric_limits::max()) { SysPushErrorIO("int overflow exploit?"); return false; } #if defined(AURORA_IS_LINUX_DERIVED) auto ret = lseek64(fd, offset, whence); #elif defined(AURORA_IS_64BIT) static_assert(std::numeric_limits::max() >= std::numeric_limits::max(), "unsupported posix os"); auto ret = lseek(fd, offset, whence); #elif defined(AURORA_FORCE_32BIT_FILESYSTEMS_ONLY) auto ret = lseek(fd, (off_t)offset, whence); #else #error ancient 32-bit posix operating systems require 64-bit file awareness #endif if (ret < 0) { // Intentionally omitted (thank linuxs' mess of incomplete filesystems) // SysPushErrorIO("PosixLseek63 IO Error: {}", ret); return false; } if (pOffset) { *pOffset = ret; } return true; } AuUInt64 PosixGetLength(int fd) { AuUInt64 ret {}, old {}; bool status {}; if (!PosixLseek63(fd, 0, SEEK_CUR, &old)) { return 0; } status = PosixLseek63(fd, 0, SEEK_END, &ret); status &= PosixLseek63(fd, old, SEEK_SET, nullptr); return status ? ret : 0; } AuUInt64 PosixGetOffset(int fd) { AuUInt64 ret; if (!PosixLseek63(fd, 0, SEEK_CUR, &ret)) { return 0; } return ret; } bool PosixSetOffset(int fd, AuUInt64 offset) { return PosixLseek63(fd, offset, SEEK_SET, nullptr); } bool PosixRead(int fd, void *buf, AuUInt32 count, AuUInt32 *pRead) { AuSInt ret; do { ret = ::read(fd, buf, count); } while ((ret == -1 && errno == EINTR)); if (ret < 0) { SysPushErrorIO("PosixRead IO Error: {}", errno); return false; } if (pRead) { *pRead = ret; } return true; } bool PosixWrite(int fd, const void *buf, AuUInt32 count, AuUInt32 *pWritten) { AuSInt ret; do { ret = ::write(fd, buf, count); } while ((ret == -1 && errno == EINTR)); if (ret < 0) { SysPushErrorIO("PosixWrite IO Error: {}", errno); return false; } if (pWritten) { *pWritten = ret; } return true; } void PosixWriteEoS(int fd) { ::ftruncate(fd, PosixGetOffset(fd)); } void SysWriteEoS(AuUInt uOSHandle) { PosixWriteEoS(uOSHandle); } void SysCloseHandle(AuUInt uOSHandle) { ::close(uOSHandle); } bool SysHandleIsNonZero(AuUInt uOSHandle) { #if defined(AURORA_IS_64BIT) return uOSHandle && (uOSHandle != 0xFFFFFFFFull) && (uOSHandle != 0xFFFFFFFFFFFFFFFFull); #else return uOSHandle && (uOSHandle != 0xFFFFFFFF); #endif } void SysFlushHandle(AuUInt uOSHandle) { ::fsync(uOSHandle); } int PosixUnlink(const char *pathname) { return ::unlink(pathname); } AuUInt64 SysGetFileLength(AuUInt uOSHandle) { return PosixGetLength(uOSHandle); } void *SysAllocateLarge(AuUInt uLength) { uLength = AuMemory::RoundPageUp(uLength); return ::mmap(0, uLength, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } void SysAllocateFree(void *pBuffer, AuUInt uLength) { uLength = AuMemory::RoundPageUp(uLength); ::munmap(pBuffer, uLength); } bool SysMemoryLockPages(const void *pVoid, AuUInt uLength) { return ::mlock(pVoid, uLength) == 0; } bool SysMemoryUnlockPages(const void *pVoid, AuUInt uLength) { return ::munlock(pVoid, uLength) == 0; } }