From e1093c3403dd86475dbe73c1f1ecd028de563898 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Tue, 12 Oct 2021 21:13:28 +0800 Subject: [PATCH] Kernel: Implement pread syscall The OpenFileDescription class already offers the necessary functionlity, so implementing this was only a matter of following the structure for `read` while handling the additional `offset` argument. --- Kernel/API/Syscall.h | 1 + Kernel/Process.h | 1 + Kernel/Syscalls/read.cpp | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index b2d463def2..c321b4b7f9 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -140,6 +140,7 @@ enum class NeedsBigProcessLock { S(ptsname, NeedsBigProcessLock::Yes) \ S(purge, NeedsBigProcessLock::Yes) \ S(read, NeedsBigProcessLock::Yes) \ + S(pread, NeedsBigProcessLock::Yes) \ S(readlink, NeedsBigProcessLock::Yes) \ S(readv, NeedsBigProcessLock::Yes) \ S(realpath, NeedsBigProcessLock::Yes) \ diff --git a/Kernel/Process.h b/Kernel/Process.h index 95376f3b12..2f8cceb1fa 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -294,6 +294,7 @@ public: KResultOr sys$open(Userspace); KResultOr sys$close(int fd); KResultOr sys$read(int fd, Userspace, size_t); + KResultOr sys$pread(int fd, Userspace, size_t, off_t); KResultOr sys$readv(int fd, Userspace iov, int iov_count); KResultOr sys$write(int fd, Userspace, size_t); KResultOr sys$writev(int fd, Userspace iov, int iov_count); diff --git a/Kernel/Syscalls/read.cpp b/Kernel/Syscalls/read.cpp index 80dbb114f3..444c3daa02 100644 --- a/Kernel/Syscalls/read.cpp +++ b/Kernel/Syscalls/read.cpp @@ -91,4 +91,25 @@ KResultOr Process::sys$read(int fd, Userspace buffer, size_t size) return TRY(description->read(user_buffer.value(), size)); } +KResultOr Process::sys$pread(int fd, Userspace buffer, size_t size, off_t offset) +{ + VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) + REQUIRE_PROMISE(stdio); + if (size == 0) + return 0; + if (size > NumericLimits::max()) + return EINVAL; + if (offset < 0) + return EINVAL; + dbgln_if(IO_DEBUG, "sys$pread({}, {}, {}, {})", fd, buffer.ptr(), size, offset); + auto description = TRY(open_readable_file_description(fds(), fd)); + if (!description->file().is_seekable()) + return EINVAL; + TRY(check_blocked_read(description)); + auto user_buffer = UserOrKernelBuffer::for_user_buffer(buffer, size); + if (!user_buffer.has_value()) + return EFAULT; + return TRY(description->read(user_buffer.value(), offset, size)); +} + }