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 /Kernel/Syscalls/read.cpp | |
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).
Diffstat (limited to 'Kernel/Syscalls/read.cpp')
-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; |