mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-06 12:59:18 +00:00
Update kernel
This commit is contained in:
@ -19,203 +19,389 @@
|
||||
#define __FENNIX_KERNEL_FILESYSTEM_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <smart_ptr.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
#include <smart_ptr.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
#define FILENAME_LENGTH 256
|
||||
#define PATH_MAX 256
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
struct Node;
|
||||
#define S_IXOTH 0001
|
||||
#define S_IWOTH 0002
|
||||
#define S_IROTH 0004
|
||||
#define S_IRWXO 0007
|
||||
#define S_IXGRP 0010
|
||||
#define S_IWGRP 0020
|
||||
#define S_IRGRP 0040
|
||||
#define S_IRWXG 0070
|
||||
#define S_IXUSR 0100
|
||||
#define S_IWUSR 0200
|
||||
#define S_IRUSR 0400
|
||||
#define S_IRWXU 0700
|
||||
|
||||
typedef size_t (*OperationMount)(const char *, unsigned long, const void *);
|
||||
typedef size_t (*OperationUmount)(int);
|
||||
typedef size_t (*OperationRead)(Node *node, size_t Size, uint8_t *Buffer);
|
||||
typedef size_t (*OperationWrite)(Node *node, size_t Size, uint8_t *Buffer);
|
||||
typedef void (*OperationOpen)(Node *node, uint8_t Mode, uint8_t Flags);
|
||||
typedef void (*OperationClose)(Node *node);
|
||||
typedef size_t (*OperationSync)(void);
|
||||
typedef void (*OperationCreate)(Node *node, char *Name, uint16_t NameLength);
|
||||
typedef void (*OperationMkdir)(Node *node, char *Name, uint16_t NameLength);
|
||||
typedef size_t (*OperationSeek)(Node *node, size_t Offset, uint8_t Whence);
|
||||
#define O_RDONLY 00
|
||||
#define O_WRONLY 01
|
||||
#define O_RDWR 02
|
||||
#define O_CREAT 0100
|
||||
#define O_EXCL 0200
|
||||
#define O_TRUNC 01000
|
||||
#define O_APPEND 02000
|
||||
#define O_CLOEXEC 02000000
|
||||
|
||||
#define MountFSFunction(name) size_t name(const char *unknown0, unsigned long unknown1, const uint8_t *unknown2)
|
||||
#define UMountFSFunction(name) size_t name(int unknown0)
|
||||
#define S_IFIFO 0010000
|
||||
#define S_IFCHR 0020000
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFBLK 0060000
|
||||
#define S_IFREG 0100000
|
||||
#define S_IFLNK 0120000
|
||||
#define S_IFSOCK 0140000
|
||||
|
||||
#define ReadFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer)
|
||||
#define WriteFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer)
|
||||
#define OpenFSFunction(name) void name(VirtualFileSystem::Node *node, uint8_t Mode, uint8_t Flags)
|
||||
#define CloseFSFunction(name) void name(VirtualFileSystem::Node *node)
|
||||
#define SyncFSFunction(name) size_t name(void)
|
||||
#define CreateFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength)
|
||||
#define MkdirFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength)
|
||||
#define SeekFSFunction(name) off_t name(VirtualFileSystem::Node *node, off_t Offset, uint8_t Whence)
|
||||
#define S_IFMT 0170000
|
||||
|
||||
enum FileStatus
|
||||
{
|
||||
OK,
|
||||
NotFound,
|
||||
NotEmpty,
|
||||
NotSupported,
|
||||
AccessDenied,
|
||||
Timeout,
|
||||
SectorNotFound,
|
||||
PartiallyCompleted,
|
||||
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
|
||||
#define S_ISCHR(mode) (((mode)&S_IFMT) == S_IFCHR)
|
||||
#define S_ISBLK(mode) (((mode)&S_IFMT) == S_IFBLK)
|
||||
#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
|
||||
#define S_ISFIFO(mode) (((mode)&S_IFMT) == S_IFIFO)
|
||||
#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK)
|
||||
|
||||
InvalidName,
|
||||
InvalidParameter,
|
||||
InvalidHandle,
|
||||
InvalidPath,
|
||||
InvalidDevice,
|
||||
InvalidOperator,
|
||||
InvalidNode,
|
||||
struct stat
|
||||
{
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
mode_t st_mode;
|
||||
nlink_t st_nlink;
|
||||
|
||||
FileExists,
|
||||
FileIsADirectory,
|
||||
FileIsInvalid,
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
dev_t st_rdev;
|
||||
off_t st_size;
|
||||
time_t st_atime;
|
||||
time_t st_mtime;
|
||||
time_t st_ctime;
|
||||
blksize_t st_blksize;
|
||||
blkcnt_t st_blocks;
|
||||
mode_t st_attr;
|
||||
};
|
||||
|
||||
DirectoryNotEmpty,
|
||||
NotADirectory,
|
||||
struct stat64
|
||||
{
|
||||
dev_t st_dev;
|
||||
ino64_t st_ino;
|
||||
mode_t st_mode;
|
||||
nlink_t st_nlink;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
dev_t st_rdev;
|
||||
off64_t st_size;
|
||||
time_t st_atime;
|
||||
time_t st_mtime;
|
||||
time_t st_ctime;
|
||||
blksize_t st_blksize;
|
||||
blkcnt64_t st_blocks;
|
||||
mode_t st_attr;
|
||||
};
|
||||
|
||||
UnknownFileStatusError
|
||||
};
|
||||
static inline int ConvertFileFlags(const char *Mode)
|
||||
{
|
||||
int Flags = 0;
|
||||
|
||||
enum NodeFlags
|
||||
{
|
||||
NODE_FLAG_ERROR = 0x0,
|
||||
FILE = 0x01,
|
||||
DIRECTORY = 0x02,
|
||||
CHARDEVICE = 0x03,
|
||||
BLOCKDEVICE = 0x04,
|
||||
PIPE = 0x05,
|
||||
SYMLINK = 0x06,
|
||||
MOUNTPOINT = 0x08
|
||||
};
|
||||
if (strchr(Mode, '+'))
|
||||
Flags |= O_RDWR;
|
||||
else if (*Mode == 'r')
|
||||
Flags |= O_RDONLY;
|
||||
else
|
||||
Flags |= O_WRONLY;
|
||||
|
||||
struct FileSystemOperations
|
||||
{
|
||||
char Name[FILENAME_LENGTH];
|
||||
OperationMount Mount = nullptr;
|
||||
OperationUmount Umount = nullptr;
|
||||
OperationRead Read = nullptr;
|
||||
OperationWrite Write = nullptr;
|
||||
OperationOpen Open = nullptr;
|
||||
OperationClose Close = nullptr;
|
||||
OperationCreate Create = nullptr;
|
||||
OperationMkdir MakeDirectory = nullptr;
|
||||
OperationSeek Seek = nullptr;
|
||||
};
|
||||
if (strchr(Mode, 'x'))
|
||||
Flags |= O_EXCL;
|
||||
|
||||
struct Node
|
||||
{
|
||||
char Name[FILENAME_LENGTH];
|
||||
uint64_t IndexNode = 0;
|
||||
uint64_t Mask = 0;
|
||||
uint64_t Mode = 0;
|
||||
NodeFlags Flags = NodeFlags::NODE_FLAG_ERROR;
|
||||
uint64_t UserIdentifier = 0, GroupIdentifier = 0;
|
||||
uintptr_t Address = 0;
|
||||
size_t Length = 0;
|
||||
off_t Offset = 0;
|
||||
Node *Parent = nullptr;
|
||||
FileSystemOperations *Operator = nullptr;
|
||||
/* For root node:
|
||||
0 - root "/"
|
||||
1 - etc
|
||||
...
|
||||
*/
|
||||
std::vector<Node *> Children;
|
||||
};
|
||||
if (strchr(Mode, 'e'))
|
||||
Flags |= O_CLOEXEC;
|
||||
|
||||
struct File
|
||||
{
|
||||
char Name[FILENAME_LENGTH];
|
||||
FileStatus Status;
|
||||
bool IsOK()
|
||||
{
|
||||
return Status == FileStatus::OK;
|
||||
}
|
||||
if (*Mode != 'r')
|
||||
Flags |= O_CREAT;
|
||||
|
||||
size_t GetLength()
|
||||
{
|
||||
return node->Length;
|
||||
}
|
||||
if (*Mode == 'w')
|
||||
Flags |= O_TRUNC;
|
||||
|
||||
std::vector<Node *> GetChildren()
|
||||
{
|
||||
return node->Children;
|
||||
}
|
||||
if (*Mode == 'a')
|
||||
Flags |= O_APPEND;
|
||||
|
||||
NodeFlags GetFlags()
|
||||
{
|
||||
return node->Flags;
|
||||
}
|
||||
|
||||
/** @brief Special cases only. */
|
||||
Node *GetNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
private:
|
||||
Node *node;
|
||||
off_t ContextOffset;
|
||||
|
||||
friend class Virtual;
|
||||
};
|
||||
|
||||
/* Manage / etc.. */
|
||||
class Virtual
|
||||
{
|
||||
private:
|
||||
Node *FileSystemRoot = nullptr;
|
||||
|
||||
public:
|
||||
std::shared_ptr<char> GetPathFromNode(Node *node);
|
||||
Node *GetNodeFromPath(const char *Path, Node *Parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Convert a Node to a File
|
||||
*
|
||||
* @param node Node to convert
|
||||
* @return Converted node
|
||||
*/
|
||||
File ConvertNodeToFILE(Node *node);
|
||||
|
||||
bool PathIsRelative(const char *Path);
|
||||
|
||||
Node *GetParent(const char *Path, Node *Parent);
|
||||
Node *GetRootNode() { return FileSystemRoot; }
|
||||
|
||||
Node *AddNewChild(const char *Name, Node *Parent);
|
||||
Node *GetChild(const char *Name, Node *Parent);
|
||||
FileStatus RemoveChild(const char *Name, Node *Parent);
|
||||
|
||||
std::shared_ptr<char> NormalizePath(const char *Path, Node *Parent = nullptr);
|
||||
bool PathExists(const char *Path, Node *Parent = nullptr);
|
||||
Node *CreateRoot(const char *RootName, FileSystemOperations *Operator);
|
||||
Node *Create(const char *Path, NodeFlags Flag, Node *Parent = nullptr);
|
||||
|
||||
FileStatus Delete(const char *Path, bool Recursive = false, Node *Parent = nullptr);
|
||||
FileStatus Delete(Node *Path, bool Recursive = false, Node *Parent = nullptr);
|
||||
|
||||
File Mount(const char *Path, FileSystemOperations *Operator);
|
||||
FileStatus Unmount(File &File);
|
||||
|
||||
size_t Read(File &File, uint8_t *Buffer, size_t Size);
|
||||
size_t Write(File &File, uint8_t *Buffer, size_t Size);
|
||||
off_t Seek(File &File, off_t Offset, uint8_t Whence);
|
||||
|
||||
File Open(const char *Path, Node *Parent = nullptr);
|
||||
FileStatus Close(File &File);
|
||||
|
||||
Virtual();
|
||||
~Virtual();
|
||||
};
|
||||
return Flags;
|
||||
}
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
struct Node;
|
||||
|
||||
typedef std::size_t (*OperationRead)(Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset);
|
||||
typedef std::size_t (*OperationWrite)(Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset);
|
||||
typedef void (*OperationCreate)(Node *node, char *Name, uint16_t NameLength, off_t &RefOffset);
|
||||
typedef void (*OperationMkdir)(Node *node, char *Name, uint16_t NameLength, off_t &RefOffset);
|
||||
typedef std::size_t (*OperationSeek)(Node *node, std::size_t Offset, int Whence, off_t &RefOffset);
|
||||
|
||||
#define ReadFSFunction(name) \
|
||||
std::size_t name(VirtualFileSystem::Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset)
|
||||
#define WriteFSFunction(name) \
|
||||
std::size_t name(VirtualFileSystem::Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset)
|
||||
#define CreateFSFunction(name) \
|
||||
void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength, off_t &RefOffset)
|
||||
#define MkdirFSFunction(name) \
|
||||
void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength, off_t &RefOffset)
|
||||
#define SeekFSFunction(name) \
|
||||
off_t name(VirtualFileSystem::Node *node, off_t Offset, uint8_t Whence, off_t &RefOffset)
|
||||
|
||||
enum NodeFlags
|
||||
{
|
||||
NODE_FLAG_ERROR = 0x0,
|
||||
FILE = S_IFREG,
|
||||
DIRECTORY = S_IFDIR,
|
||||
CHARDEVICE = S_IFCHR,
|
||||
BLOCKDEVICE = S_IFBLK,
|
||||
PIPE = S_IFIFO,
|
||||
SYMLINK = S_IFLNK,
|
||||
MOUNTPOINT = S_IFDIR
|
||||
};
|
||||
|
||||
struct FileSystemOperations
|
||||
{
|
||||
/**
|
||||
* Name of the filesystem operations
|
||||
*
|
||||
* @note Mandatory
|
||||
*/
|
||||
char Name[FILENAME_LENGTH];
|
||||
|
||||
/**
|
||||
* Pointer to the read function
|
||||
*
|
||||
* @note Mandatory
|
||||
*/
|
||||
OperationRead Read = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to the write function
|
||||
*
|
||||
* @note Mandatory
|
||||
*/
|
||||
OperationWrite Write = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to the create function
|
||||
*
|
||||
* @note Optional
|
||||
*/
|
||||
OperationCreate Create = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to the mkdir function
|
||||
*
|
||||
* @note Optional
|
||||
*/
|
||||
OperationMkdir MakeDirectory = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to the seek function
|
||||
*
|
||||
* @note Optional
|
||||
*/
|
||||
OperationSeek Seek = nullptr;
|
||||
};
|
||||
|
||||
#define RefNode VirtualFileSystem::ReferenceNode
|
||||
|
||||
class ReferenceNode
|
||||
{
|
||||
private:
|
||||
std::atomic_int64_t Offset = 0;
|
||||
off_t FileSize = 0;
|
||||
NewLock(RefNodeLock);
|
||||
Node *node;
|
||||
RefNode *SymlinkTo;
|
||||
|
||||
public:
|
||||
decltype(FileSize) &Length = FileSize;
|
||||
Node *GetNode() const { return node; }
|
||||
std::string AbsolutePath;
|
||||
|
||||
size_t Read(uint8_t *Buffer, size_t Size);
|
||||
size_t Write(uint8_t *Buffer, size_t Size);
|
||||
off_t Seek(off_t Offset, int Whence);
|
||||
|
||||
ReferenceNode(Node *node);
|
||||
~ReferenceNode();
|
||||
|
||||
friend class Virtual;
|
||||
friend class FileDescriptorTable;
|
||||
};
|
||||
|
||||
class Node
|
||||
{
|
||||
private:
|
||||
NewLock(NodeLock);
|
||||
|
||||
public:
|
||||
class Virtual *FileSystem = nullptr;
|
||||
ino_t IndexNode = 0;
|
||||
const char *Name;
|
||||
const char *Symlink;
|
||||
Node *SymlinkTarget = nullptr;
|
||||
mode_t Mode = 0;
|
||||
NodeFlags Flags = NodeFlags::NODE_FLAG_ERROR;
|
||||
uid_t UserIdentifier = 0;
|
||||
gid_t GroupIdentifier = 0;
|
||||
uintptr_t Address = 0;
|
||||
off_t Length = 0;
|
||||
Node *Parent = nullptr;
|
||||
FileSystemOperations *Operator = nullptr;
|
||||
/* For root node:
|
||||
0 - root "/"
|
||||
1 - etc
|
||||
...
|
||||
*/
|
||||
std::vector<Node *> Children;
|
||||
|
||||
/**
|
||||
* References to this node (open files, etc..)
|
||||
*/
|
||||
std::vector<ReferenceNode *> References;
|
||||
|
||||
/**
|
||||
* Create a new reference to this node
|
||||
* @return Pointer to the new reference
|
||||
*/
|
||||
ReferenceNode *CreateReference();
|
||||
|
||||
/**
|
||||
* Remove a reference to this node
|
||||
* @param Reference Pointer to the reference to remove
|
||||
*/
|
||||
void RemoveReference(ReferenceNode *Reference);
|
||||
|
||||
Node() {}
|
||||
~Node() {}
|
||||
};
|
||||
|
||||
class Virtual
|
||||
{
|
||||
private:
|
||||
Node *FileSystemRoot = nullptr;
|
||||
NewLock(VirtualLock);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
Node *AddNewChild(const char *Name, Node *Parent);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
Node *GetChild(const char *Name, Node *Parent);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
int RemoveChild(const char *Name, Node *Parent);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
Node *GetParent(const char *Path, Node *Parent);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
Node *GetNodeFromPath_Unsafe(const char *Path, Node *Parent = nullptr);
|
||||
|
||||
public:
|
||||
std::string GetPathFromNode(Node *node);
|
||||
Node *GetNodeFromPath(const char *Path, Node *Parent = nullptr);
|
||||
|
||||
bool PathIsRelative(const char *Path);
|
||||
|
||||
Node *GetRootNode() { return FileSystemRoot; }
|
||||
|
||||
std::string NormalizePath(const char *Path, Node *Parent = nullptr);
|
||||
bool PathExists(const char *Path, Node *Parent = nullptr);
|
||||
Node *CreateRoot(const char *RootName, FileSystemOperations *Operator);
|
||||
Node *Create(const char *Path, NodeFlags Flag, Node *Parent = nullptr);
|
||||
|
||||
int Delete(const char *Path, bool Recursive = false, Node *Parent = nullptr);
|
||||
int Delete(Node *Path, bool Recursive = false, Node *Parent = nullptr);
|
||||
|
||||
Node *Mount(const char *Path, FileSystemOperations *Operator);
|
||||
int Unmount(Node *File);
|
||||
|
||||
/**
|
||||
* Open a file
|
||||
* @param Path The path to the file, relative or absolute. The buffer shouldn't be modified while the function is running.
|
||||
* @param Parent Pointer to the parent node, if nullptr, the root node will be used.
|
||||
* @return A pointer to the VirtualFileSystem::ReferenceNode, or nullptr if the file doesn't exist.
|
||||
*/
|
||||
RefNode *Open(const char *Path, Node *Parent = nullptr);
|
||||
|
||||
Virtual();
|
||||
~Virtual();
|
||||
};
|
||||
|
||||
class FileDescriptorTable
|
||||
{
|
||||
public:
|
||||
struct FileDescriptor
|
||||
{
|
||||
RefNode *Handle{};
|
||||
mode_t Mode = 0;
|
||||
int Flags = 0;
|
||||
int Descriptor = -1;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<FileDescriptor> FileDescriptors;
|
||||
VirtualFileSystem::Node *fdDir = nullptr;
|
||||
|
||||
FileDescriptor GetFileDescriptor(int FileDescriptor);
|
||||
int ProbeMode(mode_t Mode, int Flags);
|
||||
int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags);
|
||||
int RemoveFileDescriptor(int FileDescriptor);
|
||||
int GetFreeFileDescriptor();
|
||||
|
||||
public:
|
||||
std::string GetAbsolutePath(int FileDescriptor);
|
||||
std::vector<FileDescriptor> &GetFileDescriptors() { return FileDescriptors; }
|
||||
|
||||
int _open(const char *pathname, int flags, mode_t mode);
|
||||
int _creat(const char *pathname, mode_t mode);
|
||||
ssize_t _read(int fd, void *buf, size_t count);
|
||||
ssize_t _write(int fd, const void *buf, size_t count);
|
||||
int _close(int fd);
|
||||
off_t _lseek(int fd, off_t offset, int whence);
|
||||
int _stat(const char *pathname, struct stat *statbuf);
|
||||
int _fstat(int fd, struct stat *statbuf);
|
||||
int _lstat(const char *pathname, struct stat *statbuf);
|
||||
|
||||
FileDescriptorTable(void *Owner);
|
||||
~FileDescriptorTable();
|
||||
};
|
||||
}
|
||||
|
||||
int fopen(const char *pathname, const char *mode);
|
||||
int creat(const char *pathname, mode_t mode);
|
||||
ssize_t fread(int fd, void *buf, size_t count);
|
||||
ssize_t fwrite(int fd, const void *buf, size_t count);
|
||||
int fclose(int fd);
|
||||
off_t lseek(int fd, off_t offset, int whence);
|
||||
int stat(const char *pathname, struct stat *statbuf);
|
||||
int fstat(int fd, struct stat *statbuf);
|
||||
int lstat(const char *pathname, struct stat *statbuf);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_FILESYSTEM_H__
|
||||
|
Reference in New Issue
Block a user