// Copyright 2021 The Mumble Developers. All rights reserved. // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file at the root of the // Mumble source tree or at . #include "SharedMemory.h" #ifdef _WIN32 #else // Note: Linking to the "rt" library is required # include # include # include # include # include #endif #include #include SharedMemory::SharedMemory() : m_data(nullptr), m_size(0), m_error(0), #ifdef _WIN32 m_handle(NULL) #else m_name() #endif { } SharedMemory::~SharedMemory() { close(); } std::size_t SharedMemory::size() { return m_size; } void SharedMemory::close() { #ifdef _WIN32 if (m_data) { UnmapViewOfFile(m_data); } if (m_handle != NULL) { CloseHandle(m_handle); } m_handle = NULL; #else if (m_data) { munmap(m_data, m_size); } if (!m_name.empty()) { shm_unlink(m_name.c_str()); } m_name.clear(); #endif m_data = nullptr; m_size = 0; m_error = 0; } int SharedMemory::lastError() const { return m_error; } void *SharedMemory::mapMemory(const char *name, std::size_t size) { close(); bool created = false; #ifdef _WIN32 m_handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, name); if (m_handle == NULL) { // Attaching failed, so we have to create it m_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, size, name); if (m_handle == NULL) { m_error = GetLastError(); return nullptr; } created = true; } m_data = MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (m_data == NULL) { m_error = GetLastError(); CloseHandle(m_handle); return nullptr; } #else m_name.clear(); // Create or attach to a shared memory region with the given name and make sure the user can read and write it int fd = shm_open(name, O_RDWR, S_IRUSR | S_IWUSR); if (fd < 0) { std::cout << "Attaching failed" << std::endl; // Attaching failed, so it seems we have to create it fd = shm_open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { m_error = errno; return nullptr; } // Truncate to specified size if (ftruncate(fd, size) != 0) { m_error = errno; ::close(fd); return nullptr; } created = true; } m_data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (m_data == reinterpret_cast< void * >(-1)) { m_data = nullptr; m_error = errno; ::close(fd); return nullptr; } // Quoting from the mmap manpage: // After the mmap() call has returned, the file descriptor, fd, can // be closed immediately without invalidating the mapping. ::close(fd); m_name.assign(name); #endif m_size = size; if (created) { std::memset(m_data, 0, m_size); } return m_data; }