Initial Commit
This commit is contained in:
+147
@@ -0,0 +1,147 @@
|
||||
#include "vfs.h"
|
||||
#include <video/render.h>
|
||||
#include <arch/x86_64/e9.h>
|
||||
#include "mp/spinlock.h"
|
||||
|
||||
static spinlock_t s_vfs_lock = SPINLOCK_INIT;
|
||||
static vfs_file_t vfs_fd_table[VFS_MAX_FDS];
|
||||
|
||||
fd_t VFS_Open_internal(const char* path)
|
||||
{
|
||||
uint32_t ino = ext2_resolve_path(path);
|
||||
if (ino == 0)
|
||||
return -1;
|
||||
|
||||
// find free fd
|
||||
for (int i = 4; i < VFS_MAX_FDS; i++)
|
||||
{
|
||||
if (!vfs_fd_table[i].used)
|
||||
{
|
||||
vfs_fd_table[i].used = true;
|
||||
vfs_fd_table[i].type = VFS_NODE_EXT2;
|
||||
vfs_fd_table[i].offset = 0;
|
||||
vfs_fd_table[i].ext2.inode_num = ino;
|
||||
|
||||
if (!ext2_read_inode(ino, &vfs_fd_table[i].ext2.inode))
|
||||
return -1;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd_t VFS_Open(const char* path) {
|
||||
uint64_t flags;
|
||||
spinlock_acquire_irqsave(&s_vfs_lock, &flags);
|
||||
fd_t fd = VFS_Open_internal(path);
|
||||
spinlock_release_irqrestore(&s_vfs_lock, flags);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int VFS_Close_internal(fd_t fd)
|
||||
{
|
||||
if (fd < 0 || fd >= VFS_MAX_FDS)
|
||||
return -1;
|
||||
|
||||
vfs_fd_table[fd].used = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VFS_Close(fd_t fd) {
|
||||
uint64_t flags;
|
||||
spinlock_acquire_irqsave(&s_vfs_lock, &flags);
|
||||
int resp = VFS_Close_internal(fd);
|
||||
spinlock_release_irqrestore(&s_vfs_lock, flags);
|
||||
return resp;
|
||||
}
|
||||
|
||||
int VFS_Read(fd_t fd, uint8_t* buf, size_t size)
|
||||
{
|
||||
if (fd < 0 || fd >= VFS_MAX_FDS)
|
||||
return -1;
|
||||
|
||||
vfs_file_t* file = &vfs_fd_table[fd];
|
||||
|
||||
if (!file->used)
|
||||
return -1;
|
||||
|
||||
switch (file->type)
|
||||
{
|
||||
case VFS_NODE_EXT2:
|
||||
{
|
||||
uint32_t file_size = file->ext2.inode.i_size;
|
||||
|
||||
if (file->offset >= file_size)
|
||||
return 0;
|
||||
|
||||
// clamp read
|
||||
if (file->offset + size > file_size)
|
||||
size = file_size - file->offset;
|
||||
|
||||
// naive: read whole file then slice
|
||||
uint8_t tmp[file_size];
|
||||
if (!ext2_read_file(&file->ext2.inode, tmp))
|
||||
return -1;
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buf[i] = tmp[file->offset + i];
|
||||
|
||||
file->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int VFS_Write(fd_t file, uint8_t* data, size_t size)
|
||||
{
|
||||
switch (file)
|
||||
{
|
||||
case VFS_FD_STDIN:
|
||||
return 0;
|
||||
|
||||
case VFS_FD_STDOUT:
|
||||
for (size_t i = 0; i < size; i++)
|
||||
putchar(data[i]);
|
||||
return size;
|
||||
case VFS_FD_STDERR:
|
||||
for (size_t i = 0; i < size; i++)
|
||||
putchar(data[i]);
|
||||
return size;
|
||||
|
||||
case VFS_FD_DEBUG:
|
||||
for (size_t i = 0; i < size; i++)
|
||||
e9_putc(data[i]);
|
||||
return size;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (file < 0 || file >= VFS_MAX_FDS)
|
||||
return -1;
|
||||
|
||||
vfs_file_t* f = &vfs_fd_table[file];
|
||||
|
||||
if (!f->used)
|
||||
return -1;
|
||||
|
||||
if (f->type == VFS_NODE_EXT2)
|
||||
{
|
||||
if (!ext2_write_file(
|
||||
&f->ext2.inode,
|
||||
f->ext2.inode_num,
|
||||
data,
|
||||
size,
|
||||
EXT2_WRITE_APPEND))
|
||||
return -1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user