From f441d633b266a4416dfb1dae24fca4576be073b4 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 15 Mar 2026 09:41:25 +0000 Subject: [PATCH] lib: c: implement mmap() --- lib/libc/io/unistd/mmap.c | 142 +++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/lib/libc/io/unistd/mmap.c b/lib/libc/io/unistd/mmap.c index e75fb6b..03e4d67 100644 --- a/lib/libc/io/unistd/mmap.c +++ b/lib/libc/io/unistd/mmap.c @@ -1,6 +1,146 @@ +#include +#include +#include +#include +#include +#include #include +static vm_prot_t vm_prot_from_mmap_prot(int prot) +{ + vm_prot_t vm_prot = VM_PROT_USER; + + if (prot & PROT_READ) { + vm_prot |= VM_PROT_READ; + } + + if (prot & PROT_WRITE) { + vm_prot |= VM_PROT_WRITE; + } + + if (prot & PROT_EXEC) { + vm_prot |= VM_PROT_EXEC; + } + + return vm_prot; +} + +static int get_vmo_anon( + int fd, + int prot, + int flags, + size_t length, + kern_handle_t *out) +{ + vm_prot_t vm_prot = vm_prot_from_mmap_prot(prot); + kern_status_t status = vm_object_create(NULL, 0, length, vm_prot, out); + return __errno_from_kern_status(status); +} + +static int get_vmo( + int fd, + int prot, + int flags, + size_t length, + kern_handle_t *out) +{ + if (fd == -1) { + return get_vmo_anon(fd, prot, flags, length, out); + } + + int err = 0; + kern_status_t status = fs_map(fd, prot, flags, &err, out); + if (status != KERN_OK) { + return __errno_from_kern_status(status); + } + + return err; +} + void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { - return NULL; + int tmp = 0; + + if (flags & MAP_SHARED) { + tmp++; + } + + if (flags & MAP_SHARED_VALIDATE) { + tmp++; + } + + if (flags & MAP_PRIVATE) { + tmp++; + } + + if (tmp != 1) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + if ((flags & MAP_ANONYMOUS) && fd != -1) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + if (!(flags & MAP_ANONYMOUS) && fd == -1) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + kern_status_t status = KERN_OK; + kern_handle_t self = KERN_HANDLE_INVALID, + address_space = KERN_HANDLE_INVALID; + + status = task_self(&self); + if (status != KERN_OK) { + __set_errno(__errno_from_kern_status(status)); + return MAP_FAILED; + } + + status = task_get_address_space(self, &address_space); + kern_handle_close(self); + if (status != KERN_OK) { + __set_errno(__errno_from_kern_status(status)); + return MAP_FAILED; + } + + kern_handle_t vmo = KERN_HANDLE_INVALID; + int err = get_vmo(fd, prot, flags, length, &vmo); + if (err != SUCCESS) { + kern_handle_close(address_space); + __set_errno(err); + return MAP_FAILED; + } + + virt_addr_t map_address = 0; + vm_prot_t vm_prot = vm_prot_from_mmap_prot(prot); + if (addr && (flags & MAP_FIXED)) { + status = address_space_map( + address_space, + (virt_addr_t)addr, + vmo, + offset, + length, + vm_prot, + &map_address); + } else { + status = address_space_map( + address_space, + MAP_ADDRESS_ANY, + vmo, + offset, + length, + vm_prot, + &map_address); + } + + kern_handle_close(vmo); + kern_handle_close(address_space); + if (status != KERN_OK) { + __set_errno(__errno_from_kern_status(status)); + return MAP_FAILED; + } + + return (void *)map_address; }