diff --git a/kernel/include/fs/FileDescriptor.h b/kernel/include/fs/FileDescriptor.h index 20b1199e..43a715aa 100644 --- a/kernel/include/fs/FileDescriptor.h +++ b/kernel/include/fs/FileDescriptor.h @@ -14,14 +14,20 @@ struct Descriptor return m_can_read && m_is_open; } + bool can_write() + { + return m_can_write && m_is_open; + } + void close() { m_is_open = false; } 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); + void open(VFS::Node* node, bool can_read, bool can_write); Descriptor(const Descriptor& other); Descriptor(); @@ -29,6 +35,7 @@ struct Descriptor private: bool m_is_open; bool m_can_read; + bool m_can_write; VFS::Node* m_node; uint64_t m_offset; }; \ No newline at end of file diff --git a/kernel/include/fs/VFS.h b/kernel/include/fs/VFS.h index 9b6b2fcf..9bab5f83 100644 --- a/kernel/include/fs/VFS.h +++ b/kernel/include/fs/VFS.h @@ -14,6 +14,7 @@ namespace VFS struct Node; typedef ssize_t (*node_read)(Node*, size_t, size_t, char*); + typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*); typedef Node* (*node_finddir)(Node*, const char*); typedef int (*node_mkdir)(Node*, const char*); @@ -27,10 +28,12 @@ namespace VFS node_read read_func; node_finddir find_func; node_mkdir mkdir_func; + node_write write_func; Node* link; }; ssize_t read(Node* node, size_t offset, size_t length, char* buffer); + ssize_t write(Node* node, size_t offset, size_t length, const char* buffer); int mkdir(const char* path, const char* name); // FIXME: Support deducing this via a single path. void mount_root(Node* root); diff --git a/kernel/src/fs/FileDescriptor.cpp b/kernel/src/fs/FileDescriptor.cpp index 4af4d25d..7a491403 100644 --- a/kernel/src/fs/FileDescriptor.cpp +++ b/kernel/src/fs/FileDescriptor.cpp @@ -5,13 +5,15 @@ 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_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_node(other.m_node), + m_offset(other.m_offset) { } -void Descriptor::open(VFS::Node* node, bool can_read) +void Descriptor::open(VFS::Node* node, bool can_read, bool can_write) { m_can_read = can_read; + m_can_write = can_write; m_node = node; m_offset = 0; m_is_open = true; @@ -22,4 +24,11 @@ ssize_t Descriptor::read(size_t size, char* buffer) ssize_t result = VFS::read(m_node, m_offset, size, buffer); m_offset += result; return result; +} + +ssize_t Descriptor::write(size_t size, const char* buffer) +{ + ssize_t result = VFS::write(m_node, m_offset, size, buffer); + m_offset += result; + return result; } \ No newline at end of file diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index e9d775f9..9eff4a24 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -26,12 +26,30 @@ ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer) return -1; } - kdbgln("read(): node %s (inode %ld), offset %zd, %zd bytes, into %p", node->name, node->inode, offset, length, - (void*)buffer); - return node->read_func(node, offset, length, buffer); } +ssize_t VFS::write(Node* node, size_t offset, size_t length, const char* buffer) +{ + if (!node) + { + kwarnln("write() failed: trying to write to nullptr"); + return -1; + } + if (node->type == VFS_DIRECTORY) + { + kwarnln("write() failed: is a directory"); + return -EISDIR; + } + if (!node->write_func) + { + kwarnln("write() failed: the chosen node doesn't support writing"); + return -1; + } + + return node->write_func(node, offset, length, buffer); +} + void VFS::mount_root(Node* root) { if (!root) @@ -92,15 +110,12 @@ VFS::Node* VFS::resolve_path(const char* filename, Node* root) } if (child->flags & VFS_MOUNTPOINT) { - kdbgln("Current node (%s, inode=%ld) is a mountpoint, resolving actual node", child->name, - child->inode); if (!child->link) { kwarnln("Current node's link is null"); return 0; } child = child->link; - kdbgln("Resolved to %s (inode %ld)", child->name, child->inode); } current_node = child; kfree(buffer);