Fix driver implementation

This commit is contained in:
EnderIce2
2024-07-07 03:14:54 +03:00
parent 3e5177d375
commit 51ea074b60
29 changed files with 3069 additions and 1510 deletions

View File

@ -26,30 +26,140 @@
namespace vfs
{
FileNode *Virtual::__CacheRecursiveSearch(FileNode *Root, const char *NameOrPath, bool IsName)
FileNode *Virtual::CacheSearchReturnLast(FileNode *Parent, const char **Path)
{
assert(Parent != nullptr);
struct cwk_segment segment;
if (!cwk_path_get_first_segment(*Path, &segment))
ReturnLogError(nullptr, "Failed to get first segment of path");
size_t segments = 0;
while (cwk_path_get_next_segment(&segment))
segments++;
if (segments == 0)
return Parent;
const char *path = *Path;
if (strncmp(path, "\002root-", 6) == 0) /* FIXME: deduce the index */
{
path += 6;
while (*path != '\0' && *path != '\003')
path++;
if (*path == '\003')
path++;
}
else
path = *Path;
FileNode *__Parent = Parent;
if (this->PathIsAbsolute(path))
{
while (__Parent->Parent)
__Parent = __Parent->Parent;
}
cwk_path_get_first_segment(path, &segment);
do
{
std::string segmentName(segment.begin, segment.size);
bool found = false;
for (FileNode *fn : __Parent->Children)
{
if (fn->Name != segmentName)
continue;
cwk_segment __seg = segment;
assert(cwk_path_get_next_segment(&__seg)); /* There's something wrong */
__Parent = fn;
found = true;
break;
}
if (!found)
{
*Path = segment.begin;
break;
}
} while (cwk_path_get_next_segment(&segment));
return __Parent;
}
FileNode *Virtual::CacheRecursiveSearch(FileNode *Root, const char *NameOrPath, bool IsName)
{
if (Root == nullptr)
return nullptr;
if (IsName)
debug("%s cache search for \"%s\" in \"%s\"", IsName ? "Relative" : "Absolute", NameOrPath, Root->Path.c_str());
struct cwk_segment segment;
if (!cwk_path_get_first_segment(NameOrPath, &segment))
ReturnLogError(nullptr, "Failed to get first segment of path");
size_t segments = 0;
while (cwk_path_get_next_segment(&segment))
segments++;
if (IsName && segments == 0)
{
if (strcmp(Root->Name.c_str(), NameOrPath) == 0)
return Root;
for (FileNode *fn : Root->Children)
{
if (fn->Name == NameOrPath)
return fn;
}
ReturnLogError(nullptr, "Failed to find \"%s\" in \"%s\"", NameOrPath, Root->Path.c_str());
}
const char *path = NameOrPath;
if (strncmp(path, "\002root-", 6) == 0) /* FIXME: deduce the index */
{
path += 6;
while (*path != '\0' && *path != '\003')
path++;
if (*path == '\003')
path++;
}
else
path = NameOrPath;
FileNode *__Parent = Root;
if (this->PathIsAbsolute(path))
{
if (strcmp(Root->Path.c_str(), NameOrPath) == 0)
return Root;
/* Get the root if Root is not the root 【・_・?】 */
while (__Parent->Parent)
__Parent = __Parent->Parent;
}
for (const auto &Child : Root->Children)
cwk_path_get_first_segment(path, &segment);
do
{
FileNode *ret = __CacheRecursiveSearch(Child, NameOrPath, IsName);
if (ret)
return ret;
}
std::string segmentName(segment.begin, segment.size);
debug("Failed to find %s in %s", NameOrPath, Root->Path.c_str());
bool found = false;
for (FileNode *fn : __Parent->Children)
{
if (fn->Name != segmentName)
continue;
cwk_segment __seg = segment;
if (!cwk_path_get_next_segment(&__seg))
return fn;
__Parent = fn;
found = true;
break;
}
if (!found)
break;
} while (cwk_path_get_next_segment(&segment));
debug("Failed to find \"%s\" in \"%s\"", NameOrPath, Root->Path.c_str());
return nullptr;
}
@ -57,35 +167,17 @@ namespace vfs
{
FileNode *rootNode = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0);
FileNode *ret = __CacheRecursiveSearch(rootNode, Path, false);
FileNode *ret = CacheRecursiveSearch(rootNode, Path, false);
if (ret)
return ret;
debug("Path \"%s\" not found", Path);
return nullptr;
__unreachable;
debug("Path \"%s\" not found; attempting to search by segments", Path);
/* FIXME: This may not be the greatest idea */
struct cwk_segment segment;
if (!cwk_path_get_first_segment(Path, &segment))
return __CacheRecursiveSearch(rootNode, Path, true);
do
{
std::string segmentStr(segment.begin, segment.size);
ret = __CacheRecursiveSearch(rootNode, segmentStr.c_str(), true);
if (ret)
return ret;
} while (cwk_path_get_next_segment(&segment));
return nullptr;
}
FileNode *Virtual::CreateCacheNode(FileNode *Parent, Inode *Node, const char *Name, mode_t Mode)
{
FileNode *fn = new FileNode();
FileNode *fn = new FileNode;
fn->Name = Name;
if (Parent)
{
@ -107,7 +199,7 @@ namespace vfs
int Virtual::RemoveCacheNode(FileNode *Node)
{
if (Node == nullptr)
return -1;
return -EINVAL;
if (Node->Parent)
{

View File

@ -31,49 +31,6 @@ namespace vfs
return cwk_path_is_relative(Path);
}
dev_t Virtual::EarlyReserveDevice()
{
RegisterLock.store(true);
size_t len = DeviceMap.size();
return len;
}
int Virtual::LateRegisterFileSystem(dev_t Device, FileSystemInfo *fsi, Inode *Root)
{
auto it = DeviceMap.find(Device);
if (it != DeviceMap.end())
ReturnLogError(-EEXIST, "Device %d already registered", Device);
FSMountInfo fsmi{.fsi = fsi, .Root = Root};
DeviceMap.insert({Device, fsmi});
RegisterLock.store(false);
return 0;
}
dev_t Virtual::RegisterFileSystem(FileSystemInfo *fsi, Inode *Root)
{
RegisterLock.store(true);
size_t len = DeviceMap.size();
FSMountInfo fsmi{.fsi = fsi, .Root = Root};
DeviceMap.insert({len, fsmi});
RegisterLock.store(false);
return len;
}
int Virtual::UnregisterFileSystem(dev_t Device)
{
auto it = DeviceMap.find(Device);
if (it == DeviceMap.end())
ReturnLogError(-ENOENT, "Device %d not found", Device);
if (it->second.fsi->SuperOps.Synchronize)
it->second.fsi->SuperOps.Synchronize(it->second.fsi, NULL);
if (it->second.fsi->SuperOps.Destroy)
it->second.fsi->SuperOps.Destroy(it->second.fsi);
DeviceMap.erase(it);
return 0;
}
void Virtual::AddRoot(Inode *Root)
{
SmartLock(VirtualLock);
@ -88,9 +45,15 @@ namespace vfs
Inode *RootNode = FileSystemRoots->Children[Index];
char rootName[128]{};
snprintf(rootName, sizeof(rootName), "root-%ld", Index);
snprintf(rootName, sizeof(rootName), "\002root-%ld\003", Index);
return this->CreateCacheNode(nullptr, RootNode, rootName, 0);
auto it = FileRoots.find(Index);
if (it != FileRoots.end())
return it->second;
FileNode *ret = this->CreateCacheNode(nullptr, RootNode, rootName, 0);
FileRoots.insert({Index, ret});
return ret;
}
FileNode *Virtual::Create(FileNode *Parent, const char *Name, mode_t Mode)
@ -126,34 +89,93 @@ namespace vfs
return this->Create(Parent, Name, Mode);
}
FileNode *Virtual::Mount(FileNode *Parent, Inode *Node, const char *Path)
{
char *path = strdup(Path);
char *lastSlash = strrchr(path, '/');
if (lastSlash == path)
lastSlash++;
*lastSlash = '\0';
FileNode *parentNode = this->GetByPath(path, Parent);
free(path);
lastSlash = strrchr(Path, '/');
lastSlash++;
return this->CreateCacheNode(parentNode, Node, lastSlash, Node->Mode);
}
int Virtual::Unmount(const char *Path)
{
FileNode *node = this->GetByPath(Path, nullptr);
if (node == nullptr)
ReturnLogError(-ENOENT, "Path %s not found", Path);
return this->RemoveCacheNode(node);
}
FileNode *Virtual::GetByPath(const char *Path, FileNode *Parent)
{
FileNode *fn = this->CacheLookup(Path);
if (fn)
return fn;
if (Parent == nullptr)
Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0);
auto it = DeviceMap.find(Parent->Node->Device);
if (it == DeviceMap.end())
ReturnLogError(nullptr, "Device %d not found", Parent->Node->Device);
if (strcmp(Path, ".") == 0)
return Parent;
if (strcmp(Path, "..") == 0)
return Parent->Parent ? Parent->Parent : Parent;
FileNode *fn = this->CacheRecursiveSearch(Parent, Path, this->PathIsRelative(Path));
if (fn)
return fn;
if (strncmp(Path, "\002root-", 6) == 0) /* FIXME: deduce the index */
{
Path += 7;
while (*Path != '\0' && *Path != '\003')
Path++;
if (*Path == '\003')
Path++;
}
FileNode *__Parent = CacheSearchReturnLast(Parent, &Path);
struct cwk_segment segment;
if (!cwk_path_get_first_segment(Path, &segment))
{
auto it = DeviceMap.find(Parent->Node->Device);
if (unlikely(it == DeviceMap.end()))
ReturnLogError(nullptr, "Device %d not found", Parent->Node->Device);
if (it->second.fsi->Ops.Lookup == NULL)
ReturnLogError(nullptr, "Lookup not supported for %d", it->first);
Inode *Node = NULL;
int ret = it->second.fsi->Ops.Lookup(Parent->Node, Path, &Node);
if (ret < 0)
ReturnLogError(nullptr, "Lookup for \"%s\"(%d) failed with %d", Path, it->first, ret);
if (Parent->Node == Node) /* root / */
{
debug("Returning root (%#lx)", Node);
return Parent;
}
ReturnLogError(nullptr, "Path has no segments");
}
Inode *Node = NULL;
FileNode *__Parent = Parent;
do
{
auto it = DeviceMap.find(__Parent->Node->Device);
if (unlikely(it == DeviceMap.end()))
ReturnLogError(nullptr, "Device %d not found", __Parent->Node->Device);
if (it->second.fsi->Ops.Lookup == NULL)
ReturnLogError(nullptr, "Lookup not supported for %d", it->first);
std::string segmentName(segment.begin, segment.size);
int ret = it->second.fsi->Ops.Lookup(__Parent->Node, segmentName.c_str(), &Node);
if (ret < 0)
ReturnLogError(nullptr, "Lookup for %d failed with %d", it->first, ret);
ReturnLogError(nullptr, "Lookup for \"%s\"(%d) failed with %d", segmentName.c_str(), it->first, ret);
__Parent = this->CreateCacheNode(__Parent, Node, segmentName.c_str(), 0);
} while (cwk_path_get_next_segment(&segment));
@ -161,6 +183,10 @@ namespace vfs
if (!ret->IsDirectory())
return ret;
auto it = DeviceMap.find(__Parent->Node->Device);
if (unlikely(it == DeviceMap.end()))
ReturnLogError(nullptr, "Device %d not found", __Parent->Node->Device);
size_t dirAllocLen = sizeof(struct kdirent) + strlen(Path);
struct kdirent *dirent = (struct kdirent *)malloc(dirAllocLen);
size_t offset = 2; /* Skip . and .. */
@ -180,6 +206,34 @@ namespace vfs
return ret;
}
std::string Virtual::GetByNode(FileNode *Node)
{
if (Node->Parent == nullptr)
{
if (Node->Node->Flags & I_FLAG_ROOT)
return Node->fsi->RootName;
assert(Node->Parent != nullptr);
}
std::string path;
auto appendPath = [&path](const char *name)
{
if (path.size() > 0)
path += "/";
path += name;
};
FileNode *current = Node;
while (current->Parent != nullptr)
{
appendPath(current->Name.c_str());
current = current->Parent;
}
return path;
}
FileNode *Virtual::CreateLink(const char *Path, FileNode *Parent, const char *Target)
{
auto it = DeviceMap.find(Parent->Node->Device);

View File

@ -143,7 +143,7 @@ namespace vfs
};
FileHeader *hdr = new FileHeader{};
SetMode(Mode, hdr);
SetMode(inode.Mode, hdr);
strncpy(hdr->name, basename, sizeof(hdr->name));
strncpy(hdr->signature, TMAGIC, TMAGLEN);
strncpy(hdr->version, TVERSION, TVERSLEN);
@ -205,12 +205,14 @@ namespace vfs
}
memcpy(Buffer, (uint8_t *)((uintptr_t)node->Header + sizeof(FileHeader) + Offset), Size);
debug("Read %d bytes from %d[%d]", Size, Node->Index, Offset);
// debug("Read %d bytes from %d[%d]", Size, Node->Index, Offset);
return Size;
}
ssize_t USTAR::ReadDir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
__no_sanitize("alignment")
ssize_t USTAR::ReadDir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
{
/* FIXME: FIX ALIGNMENT FOR DIRENT! */
auto Node = (USTARInode *)_Node;
off_t realOffset = Offset;
@ -321,6 +323,15 @@ namespace vfs
entries++;
}
if (totalSize + sizeof(struct kdirent) >= Size)
return totalSize;
ent = (struct kdirent *)((uintptr_t)Buffer + totalSize);
ent->d_ino = 0;
ent->d_off = 0;
ent->d_reclen = 0;
ent->d_type = DT_UNKNOWN;
ent->d_name[0] = '\0';
return totalSize;
}
@ -809,7 +820,8 @@ bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size)
FileSystemInfo *fsi = new FileSystemInfo;
fsi->Name = "ustar";
fsi->Flags = I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
fsi->RootName = "/";
fsi->Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
fsi->SuperOps.DeleteInode = __ustar_DestroyInode;
fsi->SuperOps.Destroy = __ustar_Destroy;
fsi->Ops.Lookup = __ustar_Lookup;

View File

@ -19,7 +19,6 @@
#include <convert.h>
#include <printf.h>
#include <rand.hpp>
#include <cwalk.h>
#include "../kernel.h"
@ -52,7 +51,7 @@ namespace vfs
foreach (const auto &Root in Parent->Children)
{
char rootName[128]{};
snprintf(rootName, sizeof(rootName), "root-%ld", offset);
snprintf(rootName, sizeof(rootName), "\x02root-%ld\x03", offset);
if (strcmp(rootName, Name) == 0)
{
@ -71,78 +70,9 @@ namespace vfs
assert(!"Not implemented");
}
ssize_t __vfs_Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
{
switch (Node->GetMinor())
{
case 2: /* /dev/null */
{
return 0;
}
case 3: /* /dev/zero */
{
if (Size <= 0)
return 0;
memset(Buffer, 0, Size);
return Size;
}
case 4: /* /dev/random */
{
if (Size <= 0)
return 0;
if (Size < sizeof(uint64_t))
{
uint8_t *buf = (uint8_t *)Buffer;
for (size_t i = 0; i < Size; i++)
buf[i] = (uint8_t)(Random::rand16() & 0xFF);
return Size;
}
uint64_t *buf = (uint64_t *)Buffer;
for (size_t i = 0; i < Size / sizeof(uint64_t); i++)
buf[i] = Random::rand64();
return Size;
}
case 5: /* /dev/mem */
{
stub;
return 0;
}
default:
return -ENOENT;
};
}
ssize_t __vfs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
switch (Node->GetMinor())
{
case 2: /* /dev/null */
{
return Size;
}
case 3: /* /dev/zero */
{
return Size;
}
case 4: /* /dev/random */
{
return Size;
}
case 5: /* /dev/mem */
{
stub;
return 0;
}
default:
return -ENOENT;
};
}
/* This implementation is used internally by the kernel, so no "." & ".." */
ssize_t __vfs_Readdir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
__no_sanitize("alignment")
ssize_t __vfs_Readdir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
{
if (_Node->GetMinor() != 0)
{
@ -189,6 +119,15 @@ namespace vfs
if (ent)
ent->d_off = INT32_MAX;
if (totalSize + sizeof(struct kdirent) >= Size)
return totalSize;
ent = (struct kdirent *)((uintptr_t)Buffer + totalSize);
ent->d_ino = 0;
ent->d_off = 0;
ent->d_reclen = 0;
ent->d_type = DT_UNKNOWN;
ent->d_name[0] = '\0';
return totalSize;
}
@ -222,13 +161,9 @@ namespace vfs
S_IRWXG |
S_IRWXO |
S_IFDIR;
FileNode *dev = this->ForceCreate(this->GetRoot(0), "dev", mode);
FileNode *mnt = this->ForceCreate(this->GetRoot(0), "mnt", mode);
FileNode *proc = this->ForceCreate(this->GetRoot(0), "proc", mode);
FileNode *log = this->ForceCreate(this->GetRoot(0), "var", mode);
log = this->ForceCreate(log, "log", mode);
dev->Node->Flags = iFlags;
mnt->Node->Flags = iFlags;
proc->Node->Flags = iFlags;
log->Node->Flags = iFlags;
@ -242,49 +177,54 @@ namespace vfs
self->Node->SetDevice(0, 1);
self->Node->Flags = iFlags;
/* c rw- rw- rw- */
mode = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH |
S_IFCHR;
FileNode *null = this->ForceCreate(dev, "null", mode);
null->Node->Device = FileSystemRoots->Node.Device;
null->Node->SetDevice(0, 2);
null->Node->Flags = iFlags;
/* c rw- rw- rw- */
mode = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH |
S_IFCHR;
FileNode *zero = this->ForceCreate(dev, "zero", mode);
zero->Node->Device = FileSystemRoots->Node.Device;
zero->Node->SetDevice(0, 3);
zero->Node->Flags = iFlags;
/* c rw- rw- rw- */
mode = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH |
S_IFCHR;
FileNode *random = this->ForceCreate(dev, "random", mode);
random->Node->Device = FileSystemRoots->Node.Device;
random->Node->SetDevice(0, 4);
random->Node->Flags = iFlags;
/* c rw- r-- --- */
mode = S_IRUSR | S_IWUSR |
S_IRGRP |
S_IFCHR;
FileNode *mem = this->ForceCreate(dev, "mem", mode);
mem->Node->Device = FileSystemRoots->Node.Device;
mem->Node->SetDevice(0, 5);
mem->Node->Flags = iFlags;
new vfs::PTMXDevice();
}
dev_t Virtual::EarlyReserveDevice()
{
RegisterLock.store(true);
size_t len = DeviceMap.size();
return len;
}
int Virtual::LateRegisterFileSystem(dev_t Device, FileSystemInfo *fsi, Inode *Root)
{
auto it = DeviceMap.find(Device);
if (it != DeviceMap.end())
ReturnLogError(-EEXIST, "Device %d already registered", Device);
Root->Flags |= I_FLAG_ROOT;
FSMountInfo fsmi{.fsi = fsi, .Root = Root};
DeviceMap.insert({Device, fsmi});
RegisterLock.store(false);
return 0;
}
dev_t Virtual::RegisterFileSystem(FileSystemInfo *fsi, Inode *Root)
{
RegisterLock.store(true);
size_t len = DeviceMap.size();
Root->Flags |= I_FLAG_ROOT;
FSMountInfo fsmi{.fsi = fsi, .Root = Root};
DeviceMap.insert({len, fsmi});
RegisterLock.store(false);
return len;
}
int Virtual::UnregisterFileSystem(dev_t Device)
{
auto it = DeviceMap.find(Device);
if (it == DeviceMap.end())
ReturnLogError(-ENOENT, "Device %d not found", Device);
if (it->second.fsi->SuperOps.Synchronize)
it->second.fsi->SuperOps.Synchronize(it->second.fsi, NULL);
if (it->second.fsi->SuperOps.Destroy)
it->second.fsi->SuperOps.Destroy(it->second.fsi);
DeviceMap.erase(it);
return 0;
}
Virtual::Virtual()
{
SmartLock(VirtualLock);
@ -297,19 +237,18 @@ namespace vfs
S_IROTH | S_IXOTH |
S_IFDIR;
FileSystemRoots->Node.Flags = I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
FileSystemRoots->Node.Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
FileSystemRoots->Node.Offset = INT32_MAX;
FileSystemRoots->Name = "<ROOT>";
FileSystemInfo *fsi = new FileSystemInfo;
fsi->Name = "Virtual Roots";
fsi->Flags = I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
fsi->RootName = "ROOT";
fsi->Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
fsi->SuperOps = {};
fsi->Ops.Lookup = __vfs_Lookup;
fsi->Ops.Create = __vfs_Create;
fsi->Ops.Read = __vfs_Read;
fsi->Ops.Write = __vfs_Write;
fsi->Ops.ReadDir = __vfs_Readdir;
fsi->Ops.ReadLink = __vfs_ReadLink;