94 lines
2.8 KiB
C
94 lines
2.8 KiB
C
// POSIX compatibility support for mmap-style file mappings.
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <ntlite/syscall.h>
|
|
#include "posix_internal.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;
|
|
}
|
|
|
|
POSIX_OPEN_DESCRIPTION* description = PosixFdAcquire(fd);
|
|
if (!description) return MAP_FAILED;
|
|
if (description->Type != PosixFdFile) {
|
|
PosixFdRelease(description);
|
|
errno = EBADF;
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
uint64_t maxSize = (uint64_t)offset + (uint64_t)length;
|
|
if (maxSize < (uint64_t)offset) {
|
|
PosixFdRelease(description);
|
|
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;
|
|
SYS_CREATE_FILE_MAPPING_REQUEST createMapping = {
|
|
sizeof(SYS_CREATE_FILE_MAPPING_REQUEST), description->KHandle, protect,
|
|
SYS_MAP_FLAG_NONE, maxSize, &mapping
|
|
};
|
|
uint32_t s = SysCreateFileMapping(&createMapping);
|
|
PosixFdRelease(description);
|
|
if (s != NTLSTATUS_SUCCESS) {
|
|
errno = PosixStatusToErrno(s);
|
|
return MAP_FAILED;
|
|
}
|
|
|
|
void* base = (void*)0;
|
|
SYS_MAP_FILE_REQUEST mapFile = {
|
|
sizeof(SYS_MAP_FILE_REQUEST), mapping,
|
|
PosixProtToSysMapAccess(prot, flags), SYS_MAP_FLAG_NONE,
|
|
(uint64_t)offset, length, &base
|
|
};
|
|
s = SysMapFile(&mapFile);
|
|
SysCloseHandle(mapping);
|
|
if (s != NTLSTATUS_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 != NTLSTATUS_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;
|
|
}
|