Kernel, libc: Implement O_NONBLOCK
This commit is contained in:
parent
da61e3648f
commit
b2f5a0502f
@ -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_DIR := $(LUNA_ROOT)/apps
|
||||||
APPS_SRC := $(APPS_DIR)/src
|
APPS_SRC := $(APPS_DIR)/src
|
||||||
|
34
apps/src/block.c
Normal file
34
apps/src/block.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -32,7 +32,7 @@ struct Descriptor
|
|||||||
ssize_t read(size_t size, char* buffer);
|
ssize_t read(size_t size, char* buffer);
|
||||||
ssize_t write(size_t size, const 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);
|
int seek(long offset);
|
||||||
long offset()
|
long offset()
|
||||||
@ -45,6 +45,11 @@ struct Descriptor
|
|||||||
return m_node->length;
|
return m_node->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool able_to_block()
|
||||||
|
{
|
||||||
|
return m_able_to_block;
|
||||||
|
}
|
||||||
|
|
||||||
Descriptor(const Descriptor& other);
|
Descriptor(const Descriptor& other);
|
||||||
Descriptor();
|
Descriptor();
|
||||||
|
|
||||||
@ -54,6 +59,7 @@ struct Descriptor
|
|||||||
bool m_is_open;
|
bool m_is_open;
|
||||||
bool m_can_read;
|
bool m_can_read;
|
||||||
bool m_can_write;
|
bool m_can_write;
|
||||||
|
bool m_able_to_block;
|
||||||
VFS::Node* m_node;
|
VFS::Node* m_node;
|
||||||
uint64_t m_offset;
|
uint64_t m_offset;
|
||||||
};
|
};
|
@ -6,6 +6,7 @@
|
|||||||
#define EINTR 4
|
#define EINTR 4
|
||||||
#define ENOEXEC 8
|
#define ENOEXEC 8
|
||||||
#define EBADF 9
|
#define EBADF 9
|
||||||
|
#define EAGAIN 11
|
||||||
#define ENOMEM 12
|
#define ENOMEM 12
|
||||||
#define EFAULT 14
|
#define EFAULT 14
|
||||||
#define EEXIST 17
|
#define EEXIST 17
|
||||||
|
@ -6,15 +6,16 @@ Descriptor::Descriptor() : m_is_open(false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Descriptor::Descriptor(const Descriptor& other)
|
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_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write),
|
||||||
m_offset(other.m_offset)
|
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_read = can_read;
|
||||||
m_can_write = can_write;
|
m_can_write = can_write;
|
||||||
|
m_able_to_block = able_to_block;
|
||||||
m_node = node;
|
m_node = node;
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
m_is_open = true;
|
m_is_open = true;
|
||||||
@ -49,5 +50,6 @@ const Descriptor& Descriptor::operator=(const Descriptor& other)
|
|||||||
m_can_write = other.m_can_write;
|
m_can_write = other.m_can_write;
|
||||||
m_offset = other.m_offset;
|
m_offset = other.m_offset;
|
||||||
m_node = other.m_node;
|
m_node = other.m_node;
|
||||||
|
m_able_to_block = other.m_able_to_block;
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#define OPEN_READ 1
|
#define OPEN_READ 1
|
||||||
#define OPEN_WRITE 2
|
#define OPEN_WRITE 2
|
||||||
|
#define OPEN_NONBLOCK 4
|
||||||
|
|
||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
#define SEEK_CUR 1
|
#define SEEK_CUR 1
|
||||||
@ -155,17 +156,17 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* kernel_filename = strdup_from_user(filename);
|
char* kfilename = strdup_from_user(filename);
|
||||||
if (!kernel_filename)
|
if (!kfilename)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS::Node* node = VFS::resolve_path(kernel_filename);
|
VFS::Node* node = VFS::resolve_path(kfilename);
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
kfree(kernel_filename);
|
kfree(kfilename);
|
||||||
context->rax = -ENOENT;
|
context->rax = -ENOENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -174,19 +175,21 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
bool can_write = (flags & OPEN_WRITE) > 0;
|
bool can_write = (flags & OPEN_WRITE) > 0;
|
||||||
if (!can_read && !can_write)
|
if (!can_read && !can_write)
|
||||||
{
|
{
|
||||||
kfree(kernel_filename);
|
kfree(kfilename);
|
||||||
context->rax = -EINVAL;
|
context->rax = -EINVAL;
|
||||||
return;
|
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 && can_write) ? "rw"
|
||||||
: can_read ? "r-"
|
: can_read ? "r-"
|
||||||
: "-w",
|
: "-w",
|
||||||
fd);
|
fd);
|
||||||
|
|
||||||
kfree(kernel_filename);
|
kfree(kfilename);
|
||||||
current_task->files[fd].open(node, can_read, can_write);
|
current_task->files[fd].open(node, can_read, can_write, able_to_block);
|
||||||
context->rax = fd;
|
context->rax = fd;
|
||||||
return;
|
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 (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->state = current_task->Blocking;
|
||||||
current_task->blocking_read_info.fd = fd;
|
current_task->blocking_read_info.fd = fd;
|
||||||
current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.
|
current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.
|
||||||
|
@ -10,6 +10,7 @@ extern int errno;
|
|||||||
#define EINTR 4 // Interrupted system call. Not implemented.
|
#define EINTR 4 // Interrupted system call. Not implemented.
|
||||||
#define ENOEXEC 8 // Exec format error
|
#define ENOEXEC 8 // Exec format error
|
||||||
#define EBADF 9 // Bad file descriptor
|
#define EBADF 9 // Bad file descriptor
|
||||||
|
#define EAGAIN 11 // Resource temporarily unavailable
|
||||||
#define ENOMEM 12 // Cannot allocate memory
|
#define ENOMEM 12 // Cannot allocate memory
|
||||||
#define EFAULT 14 // Bad address
|
#define EFAULT 14 // Bad address
|
||||||
#define EEXIST 17 // File exists
|
#define EEXIST 17 // File exists
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#define O_WRONLY 2
|
#define O_WRONLY 2
|
||||||
/* Open for reading and writing. */
|
/* Open for reading and writing. */
|
||||||
#define O_RDWR 3
|
#define O_RDWR 3
|
||||||
|
/* Open without blocking. */
|
||||||
|
#define O_NONBLOCK 4
|
||||||
|
|
||||||
/* Duplicate a file descriptor. */
|
/* Duplicate a file descriptor. */
|
||||||
#define F_DUPFD 0
|
#define F_DUPFD 0
|
||||||
|
@ -207,6 +207,7 @@ extern "C"
|
|||||||
case ENOSPC: return "No space left on device";
|
case ENOSPC: return "No space left on device";
|
||||||
case ENOTSUP: return "Operation not supported";
|
case ENOTSUP: return "Operation not supported";
|
||||||
case EPIPE: return "Broken pipe";
|
case EPIPE: return "Broken pipe";
|
||||||
|
case EAGAIN: return "Resource temporarily unavailable";
|
||||||
case 0: return "Success";
|
case 0: return "Success";
|
||||||
default: return "Unknown error";
|
default: return "Unknown error";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user