diff options
author | Rodrigo Tobar <rtobarc@gmail.com> | 2021-10-12 20:59:49 +0800 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-13 16:10:50 +0200 |
commit | 8936b111a73016402f59771f75d5773a2dcd3f0e (patch) | |
tree | 91661fabea9717a3c949fde56e761ada9f68eded | |
parent | 52976bfac675f9166fd1a9bf0bf6082e4615a086 (diff) | |
download | serenity-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.cpp | 59 |
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; |