diff --git a/kernel/src/fs/VFS.h b/kernel/src/fs/VFS.h index cc8e0f8c..d3179af1 100644 --- a/kernel/src/fs/VFS.h +++ b/kernel/src/fs/VFS.h @@ -21,6 +21,11 @@ namespace VFS virtual Result> create_subdirectory(const char* name) = 0; + // File-specific methods + virtual Result read(u8* buf, usize offset, usize length) const = 0; + + virtual Result write(const u8* buf, usize offset, usize length) = 0; + // Generic methods virtual FileSystem& fs() const = 0; diff --git a/kernel/src/fs/tmpfs/FileSystem.cpp b/kernel/src/fs/tmpfs/FileSystem.cpp index 64dae8a0..c5a77386 100644 --- a/kernel/src/fs/tmpfs/FileSystem.cpp +++ b/kernel/src/fs/tmpfs/FileSystem.cpp @@ -81,4 +81,37 @@ namespace TmpFS return inode; } + + Result FileInode::read(u8* buf, usize offset, usize length) const + { + if (length == 0) return 0; + + if (offset > m_data_buffer.size()) return 0; + if (offset + length > m_data_buffer.size()) length = m_data_buffer.size() - offset; + + memcpy(buf, m_data_buffer.data() + offset, length); + + return length; + } + + Result FileInode::write(const u8* buf, usize offset, usize length) + { + if (length == 0) return 0; + + if (offset > m_data_buffer.size()) + { + // Fill the in-between space with zeroes. + usize old_size = m_data_buffer.size(); + usize zeroes = offset - old_size; + + TRY(m_data_buffer.try_resize(offset)); + + memset(m_data_buffer.data() + old_size, 0, zeroes); + } + + u8* slice = TRY(m_data_buffer.slice(offset, length)); + memcpy(slice, buf, length); + + return length; + } } diff --git a/kernel/src/fs/tmpfs/FileSystem.h b/kernel/src/fs/tmpfs/FileSystem.h index 2959790a..8e029eb4 100644 --- a/kernel/src/fs/tmpfs/FileSystem.h +++ b/kernel/src/fs/tmpfs/FileSystem.h @@ -2,6 +2,7 @@ #include "fs/VFS.h" #include #include +#include #include #include @@ -58,10 +59,15 @@ namespace TmpFS return m_inode_number; } + Result read(u8*, usize, usize) const override; + + Result write(const u8*, usize, usize) override; + virtual ~FileInode() = default; private: VFS::FileSystem* m_fs; + Buffer m_data_buffer; usize m_inode_number; }; @@ -87,6 +93,16 @@ namespace TmpFS Result> find(const char* name) const override; + Result read(u8*, usize, usize) const override + { + return err(EISDIR); + } + + Result write(const u8*, usize, usize) override + { + return err(EISDIR); + } + VFS::FileSystem& fs() const override { return *m_fs; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 739cfb72..b403cdeb 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -75,6 +75,14 @@ static Result try_init_vfs() kinfoln("/etc/passwd's inode number: %zu", passwd.inode_number()); + const char* data = "hello, world!"; + TRY(passwd.write((const u8*)data, 0, 14)); + + char output[14]; + TRY(passwd.read((u8*)output, 0, 14)); + + kinfoln("/etc/passwd contents: '%s'", output); + return {}; } diff --git a/libluna/include/luna/Buffer.h b/libluna/include/luna/Buffer.h index db42ce89..bb2796b3 100644 --- a/libluna/include/luna/Buffer.h +++ b/libluna/include/luna/Buffer.h @@ -15,7 +15,9 @@ class Buffer Result try_resize(usize new_size); - Result create_slice_at_end(usize size); + Result slice_at_end(usize size); + + Result slice(usize offset, usize size); u8* data() { @@ -27,6 +29,16 @@ class Buffer return m_data; } + u8* end() + { + return m_data + m_size; + } + + const u8* end() const + { + return m_data + m_size; + } + usize size() const { return m_size; diff --git a/libluna/src/Buffer.cpp b/libluna/src/Buffer.cpp index a54e1c2d..1b331e2e 100644 --- a/libluna/src/Buffer.cpp +++ b/libluna/src/Buffer.cpp @@ -32,9 +32,15 @@ Result Buffer::try_resize(usize new_size) return {}; } -Result Buffer::create_slice_at_end(usize size) +Result Buffer::slice_at_end(usize size) { usize old_size = m_size; TRY(try_resize(m_size + size)); return m_data + old_size; } + +Result Buffer::slice(usize offset, usize size) +{ + if (offset + size > m_size) { TRY(try_resize(offset + size)); } + return m_data + offset; +}