2022-08-10 11:12:36 +00:00
|
|
|
/***
|
|
|
|
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,
|
2022-08-11 11:28:20 +00:00
|
|
|
AuUInt64 length,
|
2022-08-10 11:12:36 +00:00
|
|
|
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 {};
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:28:20 +00:00
|
|
|
auto actualLength = val->token.word;
|
|
|
|
auto path = AuIPC::GetServerPath(val->token);
|
|
|
|
|
|
|
|
if (actualLength < offset + length)
|
|
|
|
{
|
|
|
|
SysPushErrorIO("Out of range");
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-08-10 11:12:36 +00:00
|
|
|
int fd = ::shm_open(path.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
|
|
|
|
if (fd == -1)
|
|
|
|
{
|
|
|
|
SysPushErrorIO();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:28:20 +00:00
|
|
|
// TODO (Reece): lock garbage ( ??? )
|
|
|
|
|
2022-08-10 11:12:36 +00:00
|
|
|
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 {};
|
|
|
|
};
|
|
|
|
|
2022-08-13 23:23:12 +00:00
|
|
|
auto map = ::mmap(nullptr, length, prot, MAP_SHARED, fd, offset);
|
2022-08-10 11:12:36 +00:00
|
|
|
if (map == MAP_FAILED)
|
|
|
|
{
|
|
|
|
SysPushErrorIO();
|
|
|
|
::close(fd);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map),
|
2022-08-13 23:23:12 +00:00
|
|
|
length,
|
2022-08-10 11:12:36 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|