Compare commits
No commits in common. "bb38807ed1fdeb0b38555ede879c1fb63b3c7770" and "29ccd43c7ac12005f22c14c744afc500fcdeb903" have entirely different histories.
bb38807ed1
...
29ccd43c7a
121
src/fs.cpp
121
src/fs.cpp
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
namespace vc5::filesys {
|
namespace vc5::filesys {
|
||||||
|
|
||||||
|
using BlockData = std::array<u8, block_size>;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
auto inode_mode(INodeType type) -> u16
|
auto inode_mode(INodeType type) -> u16
|
||||||
@ -113,7 +115,7 @@ auto Fs::append_to_directory(INode& dir_inode, const DirEntry& entry)
|
|||||||
for (u16 i = 0; i < inode_ndir_blocks; ++i) {
|
for (u16 i = 0; i < inode_ndir_blocks; ++i) {
|
||||||
auto dir_entry_block = dir_inode.blocks[i];
|
auto dir_entry_block = dir_inode.blocks[i];
|
||||||
|
|
||||||
auto block = read_block<IntBlock<u16>>(dir_entry_block);
|
auto block = read_block<BlockData>(dir_entry_block);
|
||||||
if (not block)
|
if (not block)
|
||||||
return std::unexpected(block.error());
|
return std::unexpected(block.error());
|
||||||
}
|
}
|
||||||
@ -153,11 +155,11 @@ auto Fs::inode_last_block_id(const INode& inode) -> Result<u16>
|
|||||||
auto block_id = inode.blocks[inode_ind_block];
|
auto block_id = inode.blocks[inode_ind_block];
|
||||||
assert(block_id != 0);
|
assert(block_id != 0);
|
||||||
|
|
||||||
auto ind_block = read_block<IntBlock<u16>>(block_id);
|
auto ind_block = read_block<BlockData>(block_id);
|
||||||
if (not ind_block)
|
if (not ind_block)
|
||||||
return std::unexpected(ind_block.error());
|
return std::unexpected(ind_block.error());
|
||||||
|
|
||||||
return ind_block->data[inode.blocks_count - inode_ind_block];
|
return ind_block.value()[inode.blocks_count - inode_ind_block];
|
||||||
|
|
||||||
} else if (inode.blocks_count == inode_dind_block) {
|
} else if (inode.blocks_count == inode_dind_block) {
|
||||||
|
|
||||||
@ -167,18 +169,18 @@ auto Fs::inode_last_block_id(const INode& inode) -> Result<u16>
|
|||||||
auto first_block_id = inode.blocks[inode_dind_block];
|
auto first_block_id = inode.blocks[inode_dind_block];
|
||||||
assert(first_block_id != 0);
|
assert(first_block_id != 0);
|
||||||
|
|
||||||
auto first_ind_block = read_block<IntBlock<u16>>(first_block_id);
|
auto first_ind_block = read_block<BlockData>(first_block_id);
|
||||||
if (not first_ind_block)
|
if (not first_ind_block)
|
||||||
return std::unexpected(first_ind_block.error());
|
return std::unexpected(first_ind_block.error());
|
||||||
|
|
||||||
auto second_block_id
|
auto second_block_id
|
||||||
= first_ind_block->data[inode.blocks_count - inode_dind_block];
|
= first_ind_block.value()[inode.blocks_count - inode_dind_block];
|
||||||
|
|
||||||
auto second_ind_block = read_block<IntBlock<u16>>(second_block_id);
|
auto second_ind_block = read_block<BlockData>(second_block_id);
|
||||||
if (not second_ind_block)
|
if (not second_ind_block)
|
||||||
return std::unexpected(second_ind_block.error());
|
return std::unexpected(second_ind_block.error());
|
||||||
|
|
||||||
return second_ind_block->data[inode.blocks_count - inode_dind_block];
|
return second_ind_block.value()[inode.blocks_count - inode_dind_block];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return std::unexpected("inode at capacity");
|
return std::unexpected("inode at capacity");
|
||||||
@ -297,95 +299,6 @@ auto Fs::sync_to_disk() -> Result<void>
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
class BeWriter {
|
|
||||||
public:
|
|
||||||
template <typename Data>
|
|
||||||
BeWriter(Data* data)
|
|
||||||
: m_data(reinterpret_cast<u8*>(data)) {};
|
|
||||||
|
|
||||||
template <typename Int>
|
|
||||||
requires std::is_integral_v<Int>
|
|
||||||
auto operator<<(Int v) -> BeWriter&
|
|
||||||
{
|
|
||||||
for (std::size_t i = 0; i < sizeof(Int); ++i) {
|
|
||||||
*m_data = v >> (sizeof(Int) - i - 1) * 8 & 0xff;
|
|
||||||
m_data++;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t size>
|
|
||||||
requires(size % 8 == 0)
|
|
||||||
auto operator<<(const std::bitset<size>& bitmap) -> BeWriter&
|
|
||||||
{
|
|
||||||
for (std::size_t bit = 0; bit < bitmap.size(); bit += 8) {
|
|
||||||
u8 v = 0;
|
|
||||||
for (std::size_t i = 0; i < 8; ++i)
|
|
||||||
v |= bitmap[bit + i] << i;
|
|
||||||
*this << v;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Elem, std::size_t size>
|
|
||||||
requires std::is_integral_v<Elem>
|
|
||||||
auto operator<<(const std::array<Elem, size>& array) -> BeWriter&
|
|
||||||
{
|
|
||||||
for (auto elem : array)
|
|
||||||
*this << elem;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
u8* m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BeReader {
|
|
||||||
public:
|
|
||||||
template <typename Data>
|
|
||||||
BeReader(const Data* data)
|
|
||||||
: m_data(reinterpret_cast<const u8*>(data)) {};
|
|
||||||
|
|
||||||
template <typename Int>
|
|
||||||
requires std::is_integral_v<Int>
|
|
||||||
auto operator>>(Int& v) -> BeReader&
|
|
||||||
{
|
|
||||||
v = 0;
|
|
||||||
for (std::size_t i = 0; i < sizeof(Int); ++i) {
|
|
||||||
v |= *m_data << (sizeof(Int) - i - 1) * 8;
|
|
||||||
m_data++;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t size>
|
|
||||||
requires(size % 8 == 0)
|
|
||||||
auto operator>>(std::bitset<size>& bitmap) -> BeReader&
|
|
||||||
{
|
|
||||||
for (std::size_t bit = 0; bit < bitmap.size(); bit += 8) {
|
|
||||||
u8 v;
|
|
||||||
*this >> v;
|
|
||||||
for (std::size_t i = 0; i < 8; ++i)
|
|
||||||
bitmap[bit + i] = v >> i & 1;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Elem, std::size_t size>
|
|
||||||
requires std::is_integral_v<Elem>
|
|
||||||
auto operator>>(std::array<Elem, size>& array) -> BeReader&
|
|
||||||
{
|
|
||||||
for (auto& elem : array)
|
|
||||||
*this >> elem;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const u8* m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
using BlockData = std::array<u8, block_size>;
|
|
||||||
|
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
requires(sizeof(Data) <= block_size)
|
requires(sizeof(Data) <= block_size)
|
||||||
auto Fs::read_block_part(u16 block_id, u16 offset) -> Result<Data>
|
auto Fs::read_block_part(u16 block_id, u16 offset) -> Result<Data>
|
||||||
@ -412,9 +325,9 @@ auto Fs::write_block_part(u16 block_id, const Data& data, u16 offset)
|
|||||||
BlockData block = {};
|
BlockData block = {};
|
||||||
m_disk->read(block.data(), block_id);
|
m_disk->read(block.data(), block_id);
|
||||||
|
|
||||||
auto writer = BeWriter(block.data() + offset);
|
std::memcpy(block.data(),
|
||||||
data.write(writer);
|
reinterpret_cast<const uint8_t*>(&data) + offset,
|
||||||
|
sizeof(Data));
|
||||||
m_disk->write(block.data(), block_id);
|
m_disk->write(block.data(), block_id);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@ -427,10 +340,8 @@ auto Fs::read_block(u16 block_id) -> Result<Data>
|
|||||||
BlockData block = {};
|
BlockData block = {};
|
||||||
m_disk->read(block.data(), block_id);
|
m_disk->read(block.data(), block_id);
|
||||||
|
|
||||||
auto reader = BeReader(block.data());
|
|
||||||
|
|
||||||
Data data;
|
Data data;
|
||||||
data.read(reader);
|
std::memcpy(reinterpret_cast<uint8_t*>(&data), block.data(), sizeof(Data));
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -440,10 +351,8 @@ template <typename Data>
|
|||||||
auto Fs::write_block(const Data& data, u16 block_id) -> Result<void>
|
auto Fs::write_block(const Data& data, u16 block_id) -> Result<void>
|
||||||
{
|
{
|
||||||
BlockData block = {};
|
BlockData block = {};
|
||||||
|
std::memcpy(
|
||||||
auto writer = BeWriter(block.data());
|
block.data(), reinterpret_cast<const uint8_t*>(&data), sizeof(Data));
|
||||||
data.write(writer);
|
|
||||||
|
|
||||||
m_disk->write(block.data(), block_id);
|
m_disk->write(block.data(), block_id);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
105
src/fs.hpp
105
src/fs.hpp
@ -3,7 +3,6 @@
|
|||||||
#include "block_device.hpp"
|
#include "block_device.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <concepts>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@ -21,16 +20,6 @@ struct DirEntry {
|
|||||||
u16 next;
|
u16 next;
|
||||||
u16 name_len;
|
u16 name_len;
|
||||||
std::array<char, name_max_len> name;
|
std::array<char, name_max_len> name;
|
||||||
|
|
||||||
template <typename Writer> void write(Writer& w) const
|
|
||||||
{
|
|
||||||
w << inode << next << name_len << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Reader> auto read(Reader& r)
|
|
||||||
{
|
|
||||||
r >> inode >> next >> name_len >> name;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr u16 inode_size = 32;
|
constexpr u16 inode_size = 32;
|
||||||
@ -57,18 +46,6 @@ struct INode {
|
|||||||
u16 last_block_size;
|
u16 last_block_size;
|
||||||
u32 size;
|
u32 size;
|
||||||
std::array<u16, inode_blocks_count> blocks;
|
std::array<u16, inode_blocks_count> blocks;
|
||||||
|
|
||||||
template <typename Writer> void write(Writer& w) const
|
|
||||||
{
|
|
||||||
w << mode << blocks_count << links_count << last_block_size << size
|
|
||||||
<< blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Reader> auto read(Reader& r)
|
|
||||||
{
|
|
||||||
r >> mode >> blocks_count >> links_count >> last_block_size >> size
|
|
||||||
>> blocks;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(INode) <= inode_size);
|
static_assert(sizeof(INode) <= inode_size);
|
||||||
@ -88,50 +65,12 @@ struct Superblock {
|
|||||||
u16 inode_blocks_count;
|
u16 inode_blocks_count;
|
||||||
std::array<u16, iblocks_max_count> iblocks;
|
std::array<u16, iblocks_max_count> iblocks;
|
||||||
std::bitset<inodes_max_count> inode_bitmap;
|
std::bitset<inodes_max_count> inode_bitmap;
|
||||||
|
|
||||||
template <typename Writer> void write(Writer& w) const
|
|
||||||
{
|
|
||||||
w << volume_id << fs_version << blocks_count << blocks_free
|
|
||||||
<< root_inode << inode_blocks_count << iblocks << inode_bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Reader> auto read(Reader& r)
|
|
||||||
{
|
|
||||||
r >> volume_id >> fs_version >> blocks_count >> blocks_free
|
|
||||||
>> root_inode >> inode_blocks_count >> iblocks >> inode_bitmap;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Superblock) <= block_size);
|
static_assert(sizeof(Superblock) <= block_size);
|
||||||
|
|
||||||
struct BlocksBitmap {
|
struct BlocksBitmap {
|
||||||
std::bitset<blocks_max_count> bitmap;
|
std::bitset<blocks_max_count> bitmap;
|
||||||
|
|
||||||
template <typename Writer> void write(Writer& w) const
|
|
||||||
{
|
|
||||||
w << bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Reader> auto read(Reader& r)
|
|
||||||
{
|
|
||||||
r >> bitmap;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Int>
|
|
||||||
requires std::is_integral_v<Int>
|
|
||||||
struct IntBlock {
|
|
||||||
std::array<u16, block_size / sizeof(Int)> data;
|
|
||||||
|
|
||||||
template <typename Writer> void write(Writer& w) const
|
|
||||||
{
|
|
||||||
w << data;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Reader> auto read(Reader& r)
|
|
||||||
{
|
|
||||||
r >> data;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(BlocksBitmap) <= block_size);
|
static_assert(sizeof(BlocksBitmap) <= block_size);
|
||||||
@ -210,4 +149,48 @@ private:
|
|||||||
BlocksBitmap m_blocks_bitmap = {};
|
BlocksBitmap m_blocks_bitmap = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ByteReader {
|
||||||
|
public:
|
||||||
|
template <typename Data>
|
||||||
|
ByteReader(const Data* data)
|
||||||
|
: m_data(reinterpret_cast<const u8*>(data)) {};
|
||||||
|
|
||||||
|
template <typename Data>
|
||||||
|
requires std::is_integral_v<Data>
|
||||||
|
auto operator>>(Data& v) -> ByteReader&
|
||||||
|
{
|
||||||
|
v = 0;
|
||||||
|
for (std::size_t i = 0; i < sizeof(Data); ++i) {
|
||||||
|
v |= *m_data << (sizeof(Data) - i - 1) * 8;
|
||||||
|
m_data++;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const u8* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ByteWriter {
|
||||||
|
public:
|
||||||
|
template <typename Data>
|
||||||
|
ByteWriter(Data* data)
|
||||||
|
: m_data(reinterpret_cast<u8*>(data)) {};
|
||||||
|
|
||||||
|
template <typename Data>
|
||||||
|
requires std::is_integral_v<Data>
|
||||||
|
auto operator>>(Data& v) -> ByteWriter&
|
||||||
|
{
|
||||||
|
v = 0;
|
||||||
|
for (std::size_t i = 0; i < sizeof(Data); ++i) {
|
||||||
|
*m_data = v >> (sizeof(Data) - i - 1) * 8 & 0xff;
|
||||||
|
m_data++;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u8* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user