12using namespace MaxOS::common;
13using namespace MaxOS::filesystem;
14using namespace MaxOS::filesystem::format::ext2;
15using namespace MaxOS::drivers;
16using namespace MaxOS::drivers::disk;
17using namespace MaxOS::drivers::clock;
29 partition_offset(partition_offset),
39 ASSERT(superblock.signature == 0xEF53,
"Ext2 Filesystem doesnt have a valid signature\n");
42 if(superblock.version_major < 1) {
43 superblock.first_inode = 11;
44 superblock.inode_size = 128;
48 block_size = 1024 << superblock.block_size;
49 total_block_groups = (superblock.total_blocks + superblock.blocks_per_group - 1) / superblock.blocks_per_group;
50 block_group_descriptor_table_block = superblock.starting_block + 1;
52 pointers_per_block = block_size /
sizeof(
uint32_t);
53 inodes_per_block = block_size / superblock.inode_size;
54 sectors_per_block = block_size / 512;
58 uint32_t bgdt_lba = partition_offset + block_group_descriptor_table_block * sectors_per_block;
59 uint32_t sectors_to_read = (block_group_descriptor_table_size + block_size - 1) / block_size * sectors_per_block;
65 for(
uint32_t i = 0; i < total_block_groups; ++i) {
72Ext2Volume::~Ext2Volume() =
default;
216 auto allocated = allocate_group_blocks(
bg_index, 1);
217 amount -= allocated.size();
218 for(
auto block : allocated)
252 if((
bitmap.raw()[i / 8] & (1u << (i % 8))) != 0)
273 write_back_block_groups();
274 write_back_superblock();
301 if((
bitmap.raw()[i / 8] & (1u << (i % 8))) == 0)
307 bitmap.raw()[i / 8] &= ~(1u << (i % 8));
312 write_back_block_groups();
313 write_back_superblock();
321void Ext2Volume::write_back_block_groups()
const {
342void Ext2Volume::write_back_superblock() {
347 buffer.set_offset(0);
410 write_back_block_groups();
411 write_back_superblock();
421 (
uint16_t) (
is_directory ? InodePermissionsDefaults::DIRECTORY : InodePermissionsDefaults::FILE) & 0x0FFF;
456 write_back_block_groups();
457 write_back_superblock();
512 inode(m_volume->read_inode(inode_number)) {
520 parse_indirect(1,
inode.l1_indirect, &buffer);
521 parse_indirect(2,
inode.l2_indirect, &buffer);
522 parse_indirect(3,
inode.l3_indirect, &buffer);
571 parse_indirect(
level - 1, pointer, buffer);
613 write_indirect(
level - 1, pointers[i], index);
650 for(
int i = 0; i < 3; ++i) {
654 write_indirect(i + 1,
temp, index);
683 ASSERT(
blocks[0] != 0,
"Failed to allocate new blocks for file");
716InodeHandler::~InodeHandler() =
default;
845Ext2File::~Ext2File() =
default;
856 m_inode(m_volume, inode) {
863void Ext2Directory::parse_block(
buffer_t* buffer) {
873 if(entry->inode == 0 || entry->name_length == 0)
884 case EntryType::FILE:
888 case EntryType::DIRECTORY:
898 offset += entry->size;
909void Ext2Directory::remove_entry(
string const& name,
bool is_directory,
bool clear) {
914 for(; index < m_entries.
size(); ++index)
915 if(m_entry_names[index] ==
name) {
916 entry = &m_entries[index];
931 m_entries.
erase(entry);
932 m_entry_names.
erase(m_entry_names.
begin() + index);
963 m_entry_names.
clear();
984 parse_block(&buffer);
993void Ext2Directory::write_entries() {
1011 buffer_t buffer(block_size,
false);
1026 char*
name = m_entry_names[i].c_str();
1029 entry.name_length = m_entry_names[i].length();
1031 entry.size += (entry.size % 4) ? 4 - (entry.size % 4) : 0;
1042 if(i == m_entries.
size() - 1)
1072 entry.name_length =
name.length();
1073 entry.size =
sizeof(entry) + entry.name_length;
1074 entry.size += entry.size % 4 ? 4 - entry.size % 4 : 0;
1094 if(file->name() ==
name)
1098 auto file =
new Ext2File(m_volume, create_entry(
name, 0,
false).inode,
name);
1109 remove_entry(
name,
false);
1140 directory->create_entry(
".", directory->m_inode.inode_number,
true);
1141 directory->create_entry(
"..", m_inode.
inode_number,
true);
1152 remove_entry(
name,
true);
1165Ext2Directory::~Ext2Directory() =
default;
1174 : m_volume(disk, partition_offset) {
static Logger DEBUG()
Gets active logger set to DEBUG level.
static Logger WARNING()
Gets active logger set to WARNING level.
Wrapper class for a region of bytes in memor in an attempt to add some memory safety....
void set_offset(size_t offset)
Set the offset for where operations should begin from.
uint8_t * raw() const
The raw pointer to the bytes stored in memory, use is not recommended.
bool update_offset
Should operations write/read/copy update the offset in the buffer?
void copy_to(Buffer *buffer)
Copies all the bytes from this buffer into another buffer.
void copy_from(const Buffer *buffer)
Copies all the bytes from another buffer into this buffer.
void clear()
Fulls the buffer with 0's and resets the offset.
Stores the left, top, width and height of a rectangle.
void lock()
Lock the spinlock once it is available.
void unlock()
Unlock the spinlock.
uint32_t size() const
Returns the number of elements in the Vector.
void clear()
Removes all elements from the Vector.
iterator push_back(Type)
Adds an element to the end of the vector and returns the iterator of the element.
iterator begin() const
Returns the first element of the Vector.
void erase(Type)
Removes all elements from the Vector that are equal to the element.
static Clock * active_clock()
Gets the currently active clock.
Generic Disk, handles the reading and writing of data to the hard drive.
void write(uint32_t sector, common::buffer_t *data)
write data to the disk from a buffer (max capacity 512 bytes)
void read(uint32_t sector, common::buffer_t *data_buffer)
read data from the disk into a buffer (max capacity 512 bytes)
Handles a group of files (directory)
common::Vector< Directory * > m_subdirectories
The subdirectories in this directory.
string m_name
The name of this directory.
size_t size()
Get the size of the directory.
common::Vector< File * > m_files
The files in this directory.
virtual void read_from_disk()
read the directory from the disk
string name()
Get the name of the directory.
Directory * m_root_directory
The fist directory in the file system (not be confused with the system root)
Handles file operations and information.
size_t m_size
The size of the file.
string m_name
The name of the file.
uint32_t m_offset
The current offset in the file.
string name()
Get the name of the file.
virtual void flush()
Flush the file to the disk.
Defines structures and enums for the Extended 2 (ext2) filesystem format and relevant Filesystem,...
struct PACKED MaxOS::filesystem::format::ext2::SuperBlock superblock_t
Alias for SuperBlock struct.
EntryType
The type of a directory entry.
struct PACKED MaxOS::filesystem::format::ext2::DirectoryEntry directory_entry_t
Alias for DirectoryEntry struct.
struct PACKED MaxOS::filesystem::format::ext2::BlockGroupDescriptor block_group_descriptor_t
Alias for BlockGroupDescriptor struct.
struct PACKED MaxOS::filesystem::format::ext2::Inode inode_t
Alias for Inode struct.
uint32_t lba_t
Logical Block Addressing type.
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
void * memcpy(void *destination, const void *source, uint64_t num)
Copies a block of memory from one location to another.