mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-27 15:04:31 +00:00
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.
151 lines
3.3 KiB
C++
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);
|