diff --git a/kernel/src/sys/file.cpp b/kernel/src/sys/file.cpp index bfb1f949..66c22c83 100644 --- a/kernel/src/sys/file.cpp +++ b/kernel/src/sys/file.cpp @@ -229,3 +229,32 @@ Result sys_umask(Registers*, SyscallArgs args) return old_umask; } + +Result sys_truncate(Registers*, SyscallArgs args) +{ + auto path = TRY(MemoryManager::strdup_from_user(args[0])); + size_t length = (size_t)args[1]; + + auto* current = Scheduler::current(); + auto inode = TRY(VFS::resolve_path(path.chars(), current->auth, current->current_directory)); + + if (!VFS::can_write(inode, current->auth)) return err(EACCES); + + TRY(inode->truncate(length)); + + return 0; +} + +Result sys_ftruncate(Registers*, SyscallArgs args) +{ + int fd = (int)args[0]; + size_t length = (size_t)args[1]; + + auto* current = Scheduler::current(); + auto description = TRY(current->resolve_fd(fd))->description; + if (!(description->flags & O_WRONLY)) return err(EBADF); + + TRY(description->inode->truncate(length)); + + return 0; +} diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 5293b839..d2966a07 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -184,6 +184,12 @@ extern "C" /* Set the process group associated with a terminal file descriptor. */ int tcsetpgrp(int fd, pid_t pgrp); + /* Truncate a file to a specific length. */ + int truncate(const char* path, size_t size); + + /* Truncate a file to a specific length. */ + int ftruncate(int fd, size_t size); + #ifdef __cplusplus } #endif diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index 32c56c88..c9d4741d 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -498,4 +498,16 @@ extern "C" { return ioctl(fd, TIOCSPGRP, &pgid); } + + int truncate(const char* path, size_t size) + { + long rc = syscall(SYS_truncate, path, size); + __errno_return(rc, int); + } + + int ftruncate(int fd, size_t size) + { + long rc = syscall(SYS_ftruncate, fd, size); + __errno_return(rc, int); + } } diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index 281e13d5..62bb044d 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -7,7 +7,8 @@ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \ _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \ - _e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) + _e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \ + _e(truncate) _e(ftruncate) enum Syscalls {