diff options
Diffstat (limited to 'compat/shm.cpp')
-rw-r--r-- | compat/shm.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/compat/shm.cpp b/compat/shm.cpp new file mode 100644 index 00000000..83a3260c --- /dev/null +++ b/compat/shm.cpp @@ -0,0 +1,199 @@ +/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl> + + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "shm.h" + +#if defined(_WIN32) + +#include <cstring> +#include <stdio.h> + +#include <accctrl.h> +#include <aclapi.h> + +struct secattr +{ + bool success; + SECURITY_DESCRIPTOR* pSD; + SECURITY_ATTRIBUTES attrs; + PSID pEveryoneSID; + PACL pACL; + + void cleanup() + { + if (pEveryoneSID) + FreeSid(pEveryoneSID); + if (pACL) + LocalFree(pACL); + if (pSD) + LocalFree(pSD); + success = false; + pSD = nullptr; + pEveryoneSID = nullptr; + pACL = nullptr; + } + + secattr(DWORD perms) : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) + { + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + EXPLICIT_ACCESS ea; + + if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID)) + { + fprintf(stderr, "AllocateAndInitializeSid: %d\n", (int) GetLastError()); + goto cleanup; + } + + memset(&ea, 0, sizeof(ea)); + + ea.grfAccessPermissions = perms; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + if (SetEntriesInAcl(1, &ea, NULL, &pACL) != ERROR_SUCCESS) + { + fprintf(stderr, "SetEntriesInAcl: %d\n", (int) GetLastError()); + goto cleanup; + } + + pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD == nullptr) + { + fprintf(stderr, "LocalAlloc: %d\n", (int) GetLastError()); + goto cleanup; + } + + if (!InitializeSecurityDescriptor(pSD, + SECURITY_DESCRIPTOR_REVISION)) + { + fprintf(stderr, "InitializeSecurityDescriptor: %d\n", (int) GetLastError()); + goto cleanup; + } + + if (!SetSecurityDescriptorDacl(pSD, + TRUE, + pACL, + FALSE)) + { + fprintf(stderr, "SetSecurityDescriptorDacl: %d\n", (int) GetLastError()); + goto cleanup; + } + + attrs.bInheritHandle = false; + attrs.lpSecurityDescriptor = pSD; + attrs.nLength = sizeof(SECURITY_ATTRIBUTES); + + fflush(stderr); + + return; +cleanup: + fflush(stderr); + cleanup(); + } + + ~secattr() + { + cleanup(); + } +}; + +PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize) +{ + secattr sa(GENERIC_ALL|SYNCHRONIZE); + + hMutex = CreateMutexA(sa.success ? &sa.attrs : nullptr, false, mutexName); + if (!hMutex) + { + fprintf(stderr, "CreateMutexA: %d\n", (int) GetLastError()); + fflush(stderr); + } + hMapFile = CreateFileMappingA( + INVALID_HANDLE_VALUE, + sa.success ? &sa.attrs : nullptr, + PAGE_READWRITE, + 0, + mapSize, + shmName); + if (!hMapFile) + { + fprintf(stderr, "CreateFileMappingA: %d\n", (int) GetLastError()); + fflush(stderr); + } + mem = MapViewOfFile(hMapFile, + FILE_MAP_WRITE, + 0, + 0, + mapSize); + if (!mem) + { + fprintf(stderr, "MapViewOfFile: %d\n", (int) GetLastError()); + fflush(stderr); + } +} + +PortableLockedShm::~PortableLockedShm() +{ + UnmapViewOfFile(mem); + CloseHandle(hMapFile); + CloseHandle(hMutex); +} + +void PortableLockedShm::lock() +{ + (void) WaitForSingleObject(hMutex, INFINITE); +} + +void PortableLockedShm::unlock() +{ + (void) ReleaseMutex(hMutex); +} +#else + +#include <limits.h> + +#pragma GCC diagnostic ignored "-Wunused-result" +PortableLockedShm::PortableLockedShm(const char *shmName, const char* /*mutexName*/, int mapSize) : size(mapSize) +{ + char filename[PATH_MAX+2] = {0}; + strcpy(filename, "/"); + strcat(filename, shmName); + fd = shm_open(filename, O_RDWR | O_CREAT, 0600); + (void) ftruncate(fd, mapSize); + mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0); +} + +PortableLockedShm::~PortableLockedShm() +{ + (void) munmap(mem, size); + (void) close(fd); +} + +void PortableLockedShm::lock() +{ + flock(fd, LOCK_EX); +} + +void PortableLockedShm::unlock() +{ + flock(fd, LOCK_UN); +} +#endif + +bool PortableLockedShm::success() +{ +#ifndef _WIN32 + return mem != (void*) -1; +#else + return mem != NULL; +#endif +} |