144 lines
2.3 KiB
C
144 lines
2.3 KiB
C
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/kassert.h>
|
|
#include <sys/kdebug.h>
|
|
#include <sys/spinlock.h>
|
|
#include <sys/disk.h>
|
|
#include <sys/vfs.h>
|
|
#include <sys/handle.h>
|
|
|
|
extern VFS *O2FS_Mount(Disk *root);
|
|
|
|
static Spinlock vfsLock;
|
|
static VFS *rootFS;
|
|
static VNode *rootNode;
|
|
|
|
static Slab vfsSlab;
|
|
static Slab vnodeSlab;
|
|
|
|
DEFINE_SLAB(VFS, &vfsSlab);
|
|
DEFINE_SLAB(VNode, &vnodeSlab);
|
|
|
|
int
|
|
VFS_MountRoot(Disk *rootDisk)
|
|
{
|
|
int status;
|
|
|
|
Spinlock_Init(&vfsLock, "VFS Lock", SPINLOCK_TYPE_NORMAL);
|
|
|
|
Slab_Init(&vfsSlab, "VFS Slab", sizeof(VFS), 16);
|
|
Slab_Init(&vnodeSlab, "VNode Slab", sizeof(VNode), 16);
|
|
|
|
rootFS = O2FS_Mount(rootDisk);
|
|
if (!rootFS)
|
|
return -1;
|
|
|
|
status = rootFS->op->getroot(rootFS, &rootNode);
|
|
if (status < 0)
|
|
Panic("Failed to get root VNode\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
VNode *
|
|
VFS_Lookup(const char *path)
|
|
{
|
|
int status;
|
|
const char *start = path + 1;
|
|
const char *end = path + 1;
|
|
uint64_t len;
|
|
VNode *curNode;
|
|
VNode *oldNode;
|
|
char curName[256];
|
|
|
|
if (path[0] != '/')
|
|
return NULL;
|
|
|
|
status = rootFS->op->getroot(rootFS, &curNode);
|
|
if (status < 0)
|
|
Panic("Failed to get root VNode\n");
|
|
|
|
while (1) {
|
|
while (*end != '\0' && *end != '/')
|
|
end++;
|
|
|
|
len = (size_t)(end - start);
|
|
if (len == 0) {
|
|
// Handle root and trailing slash
|
|
return curNode;
|
|
}
|
|
if (len > 256) {
|
|
// Release
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(curName, start, len);
|
|
curName[len] = '\0';
|
|
|
|
oldNode = curNode;
|
|
curNode = NULL;
|
|
status = oldNode->op->lookup(oldNode, &curNode, curName);
|
|
if (status < 0) {
|
|
// Release
|
|
return NULL;
|
|
}
|
|
|
|
// Release oldNode
|
|
|
|
if (*end == '\0')
|
|
return curNode;
|
|
|
|
start = end + 1;
|
|
end = end + 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
VFS_Stat(const char *path, struct stat *sb)
|
|
{
|
|
VNode *vn = VFS_Lookup(path);
|
|
if (vn == NULL)
|
|
return -ENOENT;
|
|
|
|
vn->op->stat(vn, sb);
|
|
|
|
// Release
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
VFS_Open(VNode *fn)
|
|
{
|
|
return fn->op->open(fn);
|
|
}
|
|
|
|
int
|
|
VFS_Close(VNode *fn)
|
|
{
|
|
return fn->op->close(fn);
|
|
}
|
|
|
|
int
|
|
VFS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
|
{
|
|
return fn->op->read(fn, buf, off, len);
|
|
}
|
|
|
|
int
|
|
VFS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
|
{
|
|
return fn->op->write(fn, buf, off, len);
|
|
}
|
|
|
|
int
|
|
VFS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
|
|
{
|
|
return fn->op->readdir(fn, buf, len, off);
|
|
}
|
|
|