#include "mmap_utils.h" #include #include #include #include #include namespace fs = std::filesystem; namespace fetchml::common { MemoryMap::~MemoryMap() { unmap(); } MemoryMap::MemoryMap(MemoryMap&& other) noexcept : addr_(other.addr_), size_(other.size_), fd_(other.fd_), writable_(other.writable_) { other.addr_ = nullptr; other.fd_ = -1; } MemoryMap& MemoryMap::operator=(MemoryMap&& other) noexcept { if (this != &other) { unmap(); addr_ = other.addr_; size_ = other.size_; fd_ = other.fd_; writable_ = other.writable_; other.addr_ = nullptr; other.fd_ = -1; } return *this; } void MemoryMap::unmap() { if (addr_ && addr_ != reinterpret_cast(-1)) { munmap(addr_, size_); addr_ = nullptr; } if (fd_ >= 0) { close(fd_); fd_ = -1; } } void MemoryMap::sync() { if (addr_ && writable_) { msync(addr_, size_, MS_SYNC); } } std::optional MemoryMap::map_read(const char* path) { int fd = ::open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return std::nullopt; struct stat st; if (fstat(fd, &st) < 0) { ::close(fd); return std::nullopt; } if (st.st_size == 0) { ::close(fd); return MemoryMap(); // Empty file - valid but no mapping } void* addr = mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { ::close(fd); return std::nullopt; } MemoryMap mm; mm.addr_ = addr; mm.size_ = st.st_size; mm.fd_ = fd; mm.writable_ = false; return mm; } FileHandle::FileHandle(const char* path, int flags, int mode) { open(path, flags, mode); } FileHandle::~FileHandle() { close(); } FileHandle::FileHandle(FileHandle&& other) noexcept : fd_(other.fd_), path_(std::move(other.path_)) { other.fd_ = -1; } FileHandle& FileHandle::operator=(FileHandle&& other) noexcept { if (this != &other) { close(); fd_ = other.fd_; path_ = std::move(other.path_); other.fd_ = -1; } return *this; } bool FileHandle::open(const char* path, int flags, int mode) { fd_ = ::open(path, flags | O_CLOEXEC, mode); if (fd_ >= 0) { path_ = path; return true; } return false; } void FileHandle::close() { if (fd_ >= 0) { ::close(fd_); fd_ = -1; } } ssize_t FileHandle::read(void* buf, size_t count, off_t offset) { if (offset < 0) { return ::read(fd_, buf, count); } return pread(fd_, buf, count, offset); } ssize_t FileHandle::write(const void* buf, size_t count, off_t offset) { if (offset < 0) { return ::write(fd_, buf, count); } return pwrite(fd_, buf, count, offset); } int64_t file_size(const char* path) { struct stat st; if (stat(path, &st) < 0) return -1; return st.st_size; } bool ensure_dir(const char* path) { try { fs::create_directories(path); return true; } catch (...) { return false; } } } // namespace fetchml::common