Kernel: Implement read/write/truncate for TmpFileInode

This commit is contained in:
Bananymous 2023-11-05 02:28:43 +02:00
parent f9bf47ab30
commit 8164c15b6c
3 changed files with 81 additions and 0 deletions

View File

@ -28,6 +28,9 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<TmpInode>> open_inode(ino_t ino); BAN::ErrorOr<BAN::RefPtr<TmpInode>> open_inode(ino_t ino);
// FIXME: read_block and write_block should not require external buffer
// probably some wrapper like PageTable::with_fast_page could work?
void read_inode(ino_t ino, TmpInodeInfo& out); void read_inode(ino_t ino, TmpInodeInfo& out);
void write_inode(ino_t ino, const TmpInodeInfo&); void write_inode(ino_t ino, const TmpInodeInfo&);
void delete_inode(ino_t ino); void delete_inode(ino_t ino);

View File

@ -53,6 +53,11 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpFileInode>> create(TmpFileSystem&, mode_t, uid_t, gid_t); static BAN::ErrorOr<BAN::RefPtr<TmpFileInode>> create(TmpFileSystem&, mode_t, uid_t, gid_t);
~TmpFileInode(); ~TmpFileInode();
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
private: private:
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&); TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);

View File

@ -130,6 +130,79 @@ namespace Kernel
m_fs.delete_inode(ino()); m_fs.delete_inode(ino());
} }
BAN::ErrorOr<size_t> TmpFileInode::read_impl(off_t offset, BAN::ByteSpan buffer)
{
if (offset >= size() || buffer.size() == 0)
return 0;
BAN::Vector<uint8_t> block_buffer;
TRY(block_buffer.resize(blksize()));
const size_t bytes_to_read = BAN::Math::min<size_t>(size() - offset, buffer.size());
size_t read_done = 0;
while (read_done < bytes_to_read)
{
const size_t data_block_index = (read_done + offset) / blksize();
const size_t block_offset = (read_done + offset) % blksize();
const size_t block_index = this->block_index(data_block_index);
const size_t bytes = BAN::Math::min<size_t>(bytes_to_read - read_done, blksize() - block_offset);
m_fs.read_block(block_index, block_buffer.span());
memcpy(buffer.data() + read_done, block_buffer.data() + block_offset, bytes);
read_done += bytes;
}
return read_done;
}
BAN::ErrorOr<size_t> TmpFileInode::write_impl(off_t offset, BAN::ConstByteSpan buffer)
{
// FIXME: handle overflow
if (offset + buffer.size() > (size_t)size())
TRY(truncate_impl(offset + buffer.size()));
BAN::Vector<uint8_t> block_buffer;
TRY(block_buffer.resize(blksize()));
const size_t bytes_to_write = buffer.size();
size_t write_done = 0;
while (write_done < bytes_to_write)
{
const size_t data_block_index = (write_done + offset) / blksize();
const size_t block_offset = (write_done + offset) % blksize();
const size_t block_index = this->block_index(data_block_index);
const size_t bytes = BAN::Math::min<size_t>(bytes_to_write - write_done, blksize() - block_offset);
if (bytes < (size_t)blksize())
m_fs.read_block(block_index, block_buffer.span());
memcpy(block_buffer.data() + block_offset, buffer.data() + write_done, bytes);
m_fs.write_block(block_index, block_buffer.span());
write_done += bytes;
}
return write_done;
}
BAN::ErrorOr<void> TmpFileInode::truncate_impl(size_t new_size)
{
size_t start_block = size() / blksize() * blksize();
for (size_t off = start_block; off < new_size; off += blksize())
TRY(block_index_with_allocation(off / blksize()));
m_inode_info.size = new_size;
return {};
}
/* DIRECTORY INODE */ /* DIRECTORY INODE */
BAN::ErrorOr<BAN::RefPtr<TmpDirectoryInode>> TmpDirectoryInode::create_root(TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) BAN::ErrorOr<BAN::RefPtr<TmpDirectoryInode>> TmpDirectoryInode::create_root(TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)