Fennix/Kernel/include/fs/ramfs.hpp
EnderIce2 557c7e6235
fix(kernel/vfs): 🎉 a complete rewrite of the vfs
This is the fourth time re-writing the VFS, hope this will be the last. Tried to make it as modular as possible so this won't be necessary in the future. 🙏

This change required the entire kernel code to be modified.
2025-05-13 15:59:12 +00:00

151 lines
3.3 KiB
C++

/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <fs/vfs.hpp>
#include <memory.hpp>
namespace vfs
{
class RAMFS
{
public:
class InodeBuffer
{
public:
void *Data = nullptr;
size_t DataSize = 0;
void Allocate(size_t size, bool extend = false, bool atEnd = true)
{
if (extend == false)
{
if (Data)
Free();
Data = kmalloc(size);
if (!Data)
throw std::bad_alloc();
DataSize = size;
}
else
{
if (Data == nullptr)
{
Data = kmalloc(size);
if (!Data)
throw std::bad_alloc();
DataSize = size;
}
else
{
size_t newSize = DataSize + size;
void *newData = kmalloc(newSize);
if (!newData)
throw std::bad_alloc();
if (atEnd)
memcpy(newData, Data, DataSize);
else
memcpy(static_cast<char *>(newData) + size, Data, DataSize);
kfree(Data);
Data = newData;
DataSize = newSize;
}
}
}
void Free()
{
if (Data)
{
kfree(Data);
Data = nullptr;
DataSize = 0;
}
}
bool IsAllocated() const
{
return Data != nullptr;
}
InodeBuffer() = default;
~InodeBuffer() { Free(); }
};
class RAMFSInode
{
public:
struct Inode Node;
RAMFSInode *Parent = nullptr;
std::string Name;
kstat Stat{};
mode_t Mode = 0;
InodeBuffer Buffer;
std::string SymLink;
std::vector<RAMFSInode *> Children;
void AddChild(RAMFSInode *child)
{
Children.push_back(child);
child->Parent = this;
}
void RemoveChild(RAMFSInode *child)
{
auto it = std::find(Children.begin(), Children.end(), child);
if (it != Children.end())
{
Children.erase(it);
child->Parent = nullptr;
}
}
RAMFSInode() = default;
~RAMFSInode()
{
for (auto child : Children)
delete child;
}
};
private:
std::unordered_map<ino_t, RAMFSInode *> Files;
public:
dev_t DeviceID = -1;
ino_t NextInode = 0;
std::string RootName;
int Lookup(struct Inode *Parent, const char *Name, struct Inode **Result);
int Create(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
ssize_t ReadDir(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int SymLink(struct Inode *Node, const char *Name, const char *Target, struct Inode **Result);
ssize_t ReadLink(struct Inode *Node, char *Buffer, size_t Size);
int Stat(struct Inode *Node, struct kstat *Stat);
RAMFS() = default;
~RAMFS() = default;
};
}
bool MountAndRootRAMFS(Node Parent, const char *Name, size_t Index);