86 lines
2.5 KiB
C
86 lines
2.5 KiB
C
// POSIX compatibility support for mmap-style file mappings.
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <ntlite/syscall.h>
|
|
#include "posix.h"
|
|
#include "posix_fd.h"
|
|
|
|
static uint32_t PosixProtToSysMapAccess(int prot, int flags) {
|
|
uint32_t access = 0;
|
|
if (prot & PROT_EXEC) access |= SYS_MAP_ACCESS_EXECUTE;
|
|
if (prot & PROT_WRITE) {
|
|
access |= (flags & MAP_SHARED) ? SYS_MAP_ACCESS_WRITE : SYS_MAP_ACCESS_COPY;
|
|
} else if (flags & MAP_PRIVATE) {
|
|
access |= SYS_MAP_ACCESS_COPY;
|
|
}
|
|
if (prot & PROT_READ) access |= SYS_MAP_ACCESS_READ;
|
|
if (!access) access = SYS_MAP_ACCESS_READ;
|
|
return access;
|
|
}
|
|
|
|
__declspec(dllexport) void* mmap(void* addr, size_t length, int prot,
|
|
int flags, int fd, off_t offset) {
|
|
if (addr || length == 0 || offset < 0 || ((uint64_t)offset & 0xFFFu)) {
|
|
errno = EINVAL;
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
if (!(flags & MAP_PRIVATE) && !(flags & MAP_SHARED)) {
|
|
errno = EINVAL;
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
uint32_t pid = SysGetCurrentPid();
|
|
FD_ENTRY* e = FdGet(pid, fd);
|
|
if (!e) return MAP_FAILED;
|
|
if (e->Type != FD_FILE) {
|
|
errno = EBADF;
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
uint64_t maxSize = (uint64_t)offset + (uint64_t)length;
|
|
if (maxSize < (uint64_t)offset) {
|
|
errno = EINVAL;
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
uint32_t protect = (prot & PROT_WRITE) ? SYS_VM_READWRITE : SYS_VM_READ;
|
|
if (prot & PROT_EXEC)
|
|
protect = (prot & PROT_WRITE) ? SYS_VM_EXECUTE_READWRITE : SYS_VM_EXECUTE_READ;
|
|
|
|
uint32_t mapping = 0;
|
|
uint32_t s = SysCreateFileMapping(e->KHandle, protect, SYS_MAP_FLAG_NONE,
|
|
maxSize, &mapping);
|
|
if (s != SYS_STATUS_SUCCESS) {
|
|
errno = PosixStatusToErrno(s);
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
void* base = (void*)0;
|
|
s = SysMapFile(mapping, (uint64_t)offset, length,
|
|
PosixProtToSysMapAccess(prot, flags),
|
|
SYS_MAP_FLAG_NONE, &base);
|
|
SysCloseHandle(mapping);
|
|
if (s != SYS_STATUS_SUCCESS) {
|
|
errno = PosixStatusToErrno(s);
|
|
return MAP_FAILED;
|
|
}
|
|
return base;
|
|
}
|
|
|
|
__declspec(dllexport) int munmap(void* addr, size_t length) {
|
|
(void)length;
|
|
if (!addr) { errno = EINVAL; return -1; }
|
|
uint32_t s = SysFreeVm(addr);
|
|
if (s != SYS_STATUS_SUCCESS) { errno = PosixStatusToErrno(s); return -1; }
|
|
return 0;
|
|
}
|
|
|
|
__declspec(dllexport) int msync(void* addr, size_t length, int flags) {
|
|
(void)addr;
|
|
(void)length;
|
|
(void)flags;
|
|
return 0;
|
|
}
|