diff --git a/options/internal/include/mlibc/sysdeps.hpp b/options/internal/include/mlibc/sysdeps.hpp index 1850f1d5..c3c7cd02 100644 --- a/options/internal/include/mlibc/sysdeps.hpp +++ b/options/internal/include/mlibc/sysdeps.hpp @@ -28,6 +28,7 @@ int sys_isatty(int fd, int *ptr); int sys_stat(const char *pathname, struct stat *statbuf); int sys_fstat(int fd, struct stat *statbuf); int sys_readlink(const char *path, void *buffer, size_t max_size, ssize_t *length); +int sys_ftruncate(int fd, size_t size); int sys_fallocate(int fd, off_t offset, size_t size); int sys_unlink(const char *path); int sys_socket(int family, int type, int protocol, int *fd); diff --git a/options/posix/generic/unistd-stubs.cpp b/options/posix/generic/unistd-stubs.cpp index bebc708d..c75a23c5 100644 --- a/options/posix/generic/unistd-stubs.cpp +++ b/options/posix/generic/unistd-stubs.cpp @@ -98,9 +98,10 @@ int fsync(int) { __ensure(!"Not implemented"); __builtin_unreachable(); } -int ftruncate(int, off_t) { - __ensure(!"Not implemented"); - __builtin_unreachable(); +int ftruncate(int fd, off_t size) { + if(mlibc::sys_ftruncate(fd, size)) + return -1; + return 0; } char *getcwd(char *, size_t) { __ensure(!"Not implemented"); diff --git a/sysdeps/managarm/generic/file.cpp b/sysdeps/managarm/generic/file.cpp index eed28aac..d7bab2d2 100644 --- a/sysdeps/managarm/generic/file.cpp +++ b/sysdeps/managarm/generic/file.cpp @@ -298,7 +298,7 @@ int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offse } int sys_vm_unmap(void *pointer, size_t size) { - HEL_CHECK(helUnmapMemory(kHelNullHandle, pointer, size)); + HEL_CHECK(helUnmapMemory(kHelNullHandle, pointer, (size + 0xFFF) & ~size_t(0xFFF))); return 0; } @@ -1938,6 +1938,45 @@ int sys_readlink(const char *path, void *data, size_t max_size, ssize_t *length) } } +int sys_ftruncate(int fd, size_t size) { + HelAction actions[3]; + globalQueue.trim(); + + auto handle = cacheFileTable()[fd]; + __ensure(handle); + + managarm::fs::CntRequest req(getAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_TRUNCATE); + req.set_size(size); + + frigg::String ser(getAllocator()); + req.SerializeToString(&ser); + actions[0].type = kHelActionOffer; + actions[0].flags = kHelItemAncillary; + actions[1].type = kHelActionSendFromBuffer; + actions[1].flags = kHelItemChain; + actions[1].buffer = ser.data(); + actions[1].length = ser.size(); + actions[2].type = kHelActionRecvInline; + actions[2].flags = 0; + HEL_CHECK(helSubmitAsync(handle, actions, 3, + globalQueue.getQueue(), 0, 0)); + + auto element = globalQueue.dequeueSingle(); + auto offer = parseSimple(element); + auto send_req = parseSimple(element); + auto recv_resp = parseInline(element); + + HEL_CHECK(offer->error); + HEL_CHECK(send_req->error); + HEL_CHECK(recv_resp->error); + + managarm::fs::SvrResponse resp(getAllocator()); + resp.ParseFromArray(recv_resp->data, recv_resp->length); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; +} + int sys_fallocate(int fd, off_t offset, size_t size) { HelAction actions[3]; globalQueue.trim();