summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Tobar <rtobarc@gmail.com>2021-10-12 20:59:49 +0800
committerAndreas Kling <kling@serenityos.org>2021-10-13 16:10:50 +0200
commit8936b111a73016402f59771f75d5773a2dcd3f0e (patch)
tree91661fabea9717a3c949fde56e761ada9f68eded
parent52976bfac675f9166fd1a9bf0bf6082e4615a086 (diff)
downloadserenity-8936b111a73016402f59771f75d5773a2dcd3f0e.zip
Kernel: Factor out common code from read/readv syscalls
Having these bits of code factored out not only prevents duplication now, but will also allow us to implement pread without repeating ourselves (too much).
-rw-r--r--Kernel/Syscalls/read.cpp59
1 files changed, 29 insertions, 30 deletions
diff --git a/Kernel/Syscalls/read.cpp b/Kernel/Syscalls/read.cpp
index 888aca9b1d..80dbb114f3 100644
--- a/Kernel/Syscalls/read.cpp
+++ b/Kernel/Syscalls/read.cpp
@@ -12,6 +12,31 @@ namespace Kernel {
using BlockFlags = Thread::FileBlocker::BlockFlags;
+static KResultOr<OpenFileDescription*> open_readable_file_description(Process::OpenFileDescriptions const& fds, int fd)
+{
+ auto description = TRY(fds.open_file_description(fd));
+ if (!description->is_readable())
+ return EBADF;
+ if (description->is_directory())
+ return EISDIR;
+ return description;
+}
+
+static KResult check_blocked_read(OpenFileDescription* description)
+{
+ if (description->is_blocking()) {
+ if (!description->can_read()) {
+ auto unblock_flags = BlockFlags::None;
+ if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted())
+ return EINTR;
+ if (!has_flag(unblock_flags, BlockFlags::Read))
+ return EAGAIN;
+ // TODO: handle exceptions in unblock_flags
+ }
+ }
+ return KSuccess;
+}
+
KResultOr<FlatPtr> Process::sys$readv(int fd, Userspace<const struct iovec*> iov, int iov_count)
{
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
@@ -34,24 +59,11 @@ KResultOr<FlatPtr> Process::sys$readv(int fd, Userspace<const struct iovec*> iov
return EINVAL;
}
- auto description = TRY(fds().open_file_description(fd));
- if (!description->is_readable())
- return EBADF;
- if (description->is_directory())
- return EISDIR;
+ auto description = TRY(open_readable_file_description(fds(), fd));
int nread = 0;
for (auto& vec : vecs) {
- if (description->is_blocking()) {
- if (!description->can_read()) {
- auto unblock_flags = BlockFlags::None;
- if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted())
- return EINTR;
- if (!has_flag(unblock_flags, BlockFlags::Read))
- return EAGAIN;
- // TODO: handle exceptions in unblock_flags
- }
- }
+ TRY(check_blocked_read(description));
auto buffer = UserOrKernelBuffer::for_user_buffer((u8*)vec.iov_base, vec.iov_len);
if (!buffer.has_value())
return EFAULT;
@@ -71,21 +83,8 @@ KResultOr<FlatPtr> Process::sys$read(int fd, Userspace<u8*> buffer, size_t size)
if (size > NumericLimits<ssize_t>::max())
return EINVAL;
dbgln_if(IO_DEBUG, "sys$read({}, {}, {})", fd, buffer.ptr(), size);
- auto description = TRY(fds().open_file_description(fd));
- if (!description->is_readable())
- return EBADF;
- if (description->is_directory())
- return EISDIR;
- if (description->is_blocking()) {
- if (!description->can_read()) {
- auto unblock_flags = BlockFlags::None;
- if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted())
- return EINTR;
- if (!has_flag(unblock_flags, BlockFlags::Read))
- return EAGAIN;
- // TODO: handle exceptions in unblock_flags
- }
- }
+ auto description = TRY(open_readable_file_description(fds(), fd));
+ TRY(check_blocked_read(description));
auto user_buffer = UserOrKernelBuffer::for_user_buffer(buffer, size);
if (!user_buffer.has_value())
return EFAULT;