From b2f5a0502f386d9bec4e75295e72cd52c86df207 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 21 Oct 2022 21:51:03 +0200 Subject: [PATCH] Kernel, libc: Implement O_NONBLOCK --- apps/Makefile | 2 +- apps/src/block.c | 34 ++++++++++++++++++++++++++++++ kernel/include/fs/FileDescriptor.h | 8 ++++++- kernel/include/std/errno.h | 1 + kernel/src/fs/FileDescriptor.cpp | 8 ++++--- kernel/src/sys/stdio.cpp | 24 ++++++++++++++------- libs/libc/include/errno.h | 1 + libs/libc/include/fcntl.h | 2 ++ libs/libc/src/string.cpp | 1 + 9 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 apps/src/block.c diff --git a/apps/Makefile b/apps/Makefile index 75ce6d09..ce699bd4 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,4 +1,4 @@ -APPS := init sym sh crash uname uptime hello +APPS := init sym sh crash uname uptime hello block APPS_DIR := $(LUNA_ROOT)/apps APPS_SRC := $(APPS_DIR)/src diff --git a/apps/src/block.c b/apps/src/block.c new file mode 100644 index 00000000..1af9e98e --- /dev/null +++ b/apps/src/block.c @@ -0,0 +1,34 @@ +#include +#include +#include + +int main() +{ + int fd = open("/dev/kbd", O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + perror("open"); + return 1; + } + + FILE* fp = fdopen(fd, "r"); + if (!fp) + { + perror("fdopen"); + close(fd); + return 1; + } + + char buf[32]; + fread(buf, sizeof(buf) - 1, 1, fp); + if (ferror(fp)) + { + perror("fread"); + fclose(fp); + return 1; + } + + fclose(fp); + + return 0; +} \ No newline at end of file diff --git a/kernel/include/fs/FileDescriptor.h b/kernel/include/fs/FileDescriptor.h index c7f0b62c..bc0a6986 100644 --- a/kernel/include/fs/FileDescriptor.h +++ b/kernel/include/fs/FileDescriptor.h @@ -32,7 +32,7 @@ struct Descriptor ssize_t read(size_t size, char* buffer); ssize_t write(size_t size, const char* buffer); - void open(VFS::Node* node, bool can_read, bool can_write); + void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block); int seek(long offset); long offset() @@ -45,6 +45,11 @@ struct Descriptor return m_node->length; } + bool able_to_block() + { + return m_able_to_block; + } + Descriptor(const Descriptor& other); Descriptor(); @@ -54,6 +59,7 @@ struct Descriptor bool m_is_open; bool m_can_read; bool m_can_write; + bool m_able_to_block; VFS::Node* m_node; uint64_t m_offset; }; \ No newline at end of file diff --git a/kernel/include/std/errno.h b/kernel/include/std/errno.h index c2c59830..a3e79b13 100644 --- a/kernel/include/std/errno.h +++ b/kernel/include/std/errno.h @@ -6,6 +6,7 @@ #define EINTR 4 #define ENOEXEC 8 #define EBADF 9 +#define EAGAIN 11 #define ENOMEM 12 #define EFAULT 14 #define EEXIST 17 diff --git a/kernel/src/fs/FileDescriptor.cpp b/kernel/src/fs/FileDescriptor.cpp index c98e4f8e..67d83816 100644 --- a/kernel/src/fs/FileDescriptor.cpp +++ b/kernel/src/fs/FileDescriptor.cpp @@ -6,15 +6,16 @@ Descriptor::Descriptor() : m_is_open(false) } Descriptor::Descriptor(const Descriptor& other) - : m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), m_node(other.m_node), - m_offset(other.m_offset) + : m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), + m_able_to_block(other.m_able_to_block), m_node(other.m_node), m_offset(other.m_offset) { } -void Descriptor::open(VFS::Node* node, bool can_read, bool can_write) +void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block) { m_can_read = can_read; m_can_write = can_write; + m_able_to_block = able_to_block; m_node = node; m_offset = 0; m_is_open = true; @@ -49,5 +50,6 @@ const Descriptor& Descriptor::operator=(const Descriptor& other) m_can_write = other.m_can_write; m_offset = other.m_offset; m_node = other.m_node; + m_able_to_block = other.m_able_to_block; return other; } \ No newline at end of file diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index 8be87515..8dbd35c3 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -14,6 +14,7 @@ #define OPEN_READ 1 #define OPEN_WRITE 2 +#define OPEN_NONBLOCK 4 #define SEEK_SET 0 #define SEEK_CUR 1 @@ -155,17 +156,17 @@ void sys_open(Context* context, const char* filename, int flags) return; } - char* kernel_filename = strdup_from_user(filename); - if (!kernel_filename) + char* kfilename = strdup_from_user(filename); + if (!kfilename) { context->rax = -EFAULT; return; } - VFS::Node* node = VFS::resolve_path(kernel_filename); + VFS::Node* node = VFS::resolve_path(kfilename); if (!node) { - kfree(kernel_filename); + kfree(kfilename); context->rax = -ENOENT; return; } @@ -174,19 +175,21 @@ void sys_open(Context* context, const char* filename, int flags) bool can_write = (flags & OPEN_WRITE) > 0; if (!can_read && !can_write) { - kfree(kernel_filename); + kfree(kfilename); context->rax = -EINVAL; return; } - kdbgln("open(): opening %s %s, allocated file descriptor %d", kernel_filename, + bool able_to_block = (flags & OPEN_NONBLOCK) == 0; + + kdbgln("open(): opening %s %s, allocated file descriptor %d", kfilename, (can_read && can_write) ? "rw" : can_read ? "r-" : "-w", fd); - kfree(kernel_filename); - current_task->files[fd].open(node, can_read, can_write); + kfree(kfilename); + current_task->files[fd].open(node, can_read, can_write, able_to_block); context->rax = fd; return; } @@ -211,6 +214,11 @@ void sys_read(Context* context, int fd, size_t size, char* buffer) } if (VFS::would_block(current_task->files[fd].node())) { + if (!current_task->files[fd].able_to_block()) + { + context->rax = -EAGAIN; + return; + } current_task->state = current_task->Blocking; current_task->blocking_read_info.fd = fd; current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors. diff --git a/libs/libc/include/errno.h b/libs/libc/include/errno.h index 78868490..afa20aef 100644 --- a/libs/libc/include/errno.h +++ b/libs/libc/include/errno.h @@ -10,6 +10,7 @@ extern int errno; #define EINTR 4 // Interrupted system call. Not implemented. #define ENOEXEC 8 // Exec format error #define EBADF 9 // Bad file descriptor +#define EAGAIN 11 // Resource temporarily unavailable #define ENOMEM 12 // Cannot allocate memory #define EFAULT 14 // Bad address #define EEXIST 17 // File exists diff --git a/libs/libc/include/fcntl.h b/libs/libc/include/fcntl.h index fb358446..a8e61756 100644 --- a/libs/libc/include/fcntl.h +++ b/libs/libc/include/fcntl.h @@ -7,6 +7,8 @@ #define O_WRONLY 2 /* Open for reading and writing. */ #define O_RDWR 3 +/* Open without blocking. */ +#define O_NONBLOCK 4 /* Duplicate a file descriptor. */ #define F_DUPFD 0 diff --git a/libs/libc/src/string.cpp b/libs/libc/src/string.cpp index c2406681..341e4bc2 100644 --- a/libs/libc/src/string.cpp +++ b/libs/libc/src/string.cpp @@ -207,6 +207,7 @@ extern "C" case ENOSPC: return "No space left on device"; case ENOTSUP: return "Operation not supported"; case EPIPE: return "Broken pipe"; + case EAGAIN: return "Resource temporarily unavailable"; case 0: return "Success"; default: return "Unknown error"; }