Browse Source

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.
Rodrigo Tobar 3 năm trước cách đây
mục cha
commit
e1093c3403
3 tập tin đã thay đổi với 23 bổ sung0 xóa
  1. 1 0
      Kernel/API/Syscall.h
  2. 1 0
      Kernel/Process.h
  3. 21 0
      Kernel/Syscalls/read.cpp

+ 1 - 0
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)                   \

+ 1 - 0
Kernel/Process.h

@@ -294,6 +294,7 @@ public:
     KResultOr<FlatPtr> sys$open(Userspace<const Syscall::SC_open_params*>);
     KResultOr<FlatPtr> sys$close(int fd);
     KResultOr<FlatPtr> sys$read(int fd, Userspace<u8*>, size_t);
+    KResultOr<FlatPtr> sys$pread(int fd, Userspace<u8*>, size_t, off_t);
     KResultOr<FlatPtr> sys$readv(int fd, Userspace<const struct iovec*> iov, int iov_count);
     KResultOr<FlatPtr> sys$write(int fd, Userspace<const u8*>, size_t);
     KResultOr<FlatPtr> sys$writev(int fd, Userspace<const struct iovec*> iov, int iov_count);

+ 21 - 0
Kernel/Syscalls/read.cpp

@@ -91,4 +91,25 @@ KResultOr<FlatPtr> Process::sys$read(int fd, Userspace<u8*> buffer, size_t size)
     return TRY(description->read(user_buffer.value(), size));
 }
 
+KResultOr<FlatPtr> Process::sys$pread(int fd, Userspace<u8*> buffer, size_t size, off_t offset)
+{
+    VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
+    REQUIRE_PROMISE(stdio);
+    if (size == 0)
+        return 0;
+    if (size > NumericLimits<ssize_t>::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));
+}
+
 }