AuroraRuntime/Source/Process/ProcessSectionView.Unix.cpp

190 lines
5.9 KiB
C++
Raw Normal View History

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ProcessSectionView.Unix.hpp
Date: 2022-08-10
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "ProcessSectionView.Unix.hpp"
#include "Process.hpp"
#include <Source/IO/FS/FileStream.Unix.hpp>
#include "ProcessSectionFileMapView.Unix.hpp"
#include <Source/IO/IPC/IPCHandle.hpp>
#include <Source/IO/IPC/IPCMemory.Unix.hpp>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
namespace Aurora::Process
{
AuSPtr<IProcessSectionMapView> ProcessSectionView::Allocate(AuUInt length)
{
auto map = ::mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (map == MAP_FAILED)
{
SysPushErrorIO();
return {};
}
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map),
length,
false);
if (!newObject)
{
SysPushErrorMem();
::munmap(map, length);
return {};
}
return newObject;
}
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByPath(const AuString &str,
AuUInt64 offset,
AuUInt length,
AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel sectionLock)
{
auto file = AuFS::OpenShared(str, mode, AuFS::EFileAdvisoryLockLevel::eNoSafety);
return file ? this->MapFileByObject(file, offset, length, mode, sectionLock) : AuSPtr<IProcessSectionMapView> {};
}
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByObject(const AuSPtr<AuFS::IFileStream> &stream,
AuUInt64 offset,
AuUInt length,
AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel processLockLevel)
{
if (!stream)
{
return {};
}
auto ok = AuStaticCast<AuFS::PosixFileStream>(stream);
int fd = ::dup(ok->GetHandle());
if (fd == -1)
{
SysPushErrorIO();
return {};
}
// TODO (Reece): lock garbage
int prot {};
switch (mode)
{
case AuFS::EFileOpenMode::eRead:
{
prot = PROT_READ;
break;
}
case AuFS::EFileOpenMode::eWrite:
case AuFS::EFileOpenMode::eReadWrite:
{
prot = PROT_READ | PROT_WRITE;
break;
}
default:
SysPushErrorGeneric();
return {};
};
auto map = ::mmap(nullptr, length, prot, MAP_SHARED, fd, offset);
if (map == MAP_FAILED)
{
SysPushErrorIO();
::close(fd);
return {};
}
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map),
length,
true,
fd);
if (!newObject)
{
SysPushErrorMem();
::close(fd);
::munmap(map, length);
return {};
}
return newObject;
}
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapIPCMemory(const AuString &handleString,
AuUInt64 offset,
AuFS::EFileOpenMode mode)
{
AuIPC::IPCHandle handle;
if (!handle.FromString(handleString))
{
SysPushErrorParseError("Invalid handle: {}", handleString);
return {};
}
auto val = handle.GetToken(AuIPC::EIPCHandleType::eIPCMemory, 0);
if (!val)
{
SysPushErrorParseError("Invalid handle: {}", handleString);
return {};
}
auto path = AuIPC::GetServerPath(val->token);
int fd = ::shm_open(path.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1)
{
SysPushErrorIO();
return {};
}
int prot {};
switch (mode)
{
case AuFS::EFileOpenMode::eRead:
{
prot = PROT_READ;
break;
}
case AuFS::EFileOpenMode::eWrite:
case AuFS::EFileOpenMode::eReadWrite:
{
prot = PROT_READ | PROT_WRITE;
break;
}
default:
SysPushErrorGeneric();
return {};
};
auto map = ::mmap(nullptr, val->token.word, prot, MAP_SHARED, fd, offset);
if (map == MAP_FAILED)
{
SysPushErrorIO();
::close(fd);
return {};
}
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map),
val->token.word,
true,
fd);
if (!newObject)
{
SysPushErrorMem();
::close(fd);
::munmap(map, val->token.word);
return {};
}
return newObject;
}
AUKN_SYM AuSPtr<IProcessSectionView> GetGlobalProcessSpace()
{
static ProcessSectionView gSingleton;
return AuUnsafeRaiiToShared(&gSingleton);
}
}