186 lines
4.6 KiB
C
186 lines
4.6 KiB
C
// vfs.c
|
|
// Author: Josh Holtrop
|
|
// Date: 08/22/04
|
|
// Modified: 12/21/04
|
|
|
|
#include "hos_defines.h"
|
|
#include "kout.h"
|
|
#include "fs/vfs.h"
|
|
#include "fs/ext2.h"
|
|
#include "kernel.h"
|
|
#include "mm/vmm.h"
|
|
#include "lang/lang.h"
|
|
|
|
vfs_fs_t *fses[VFS_MAX_FS]; // a vfs_fs structure for every filesystem we support
|
|
vfs_mount_node_t *mounts;
|
|
|
|
// basic initialization routine, init all filesystem drivers
|
|
int vfs_init()
|
|
{
|
|
k_check(ext2_init(FS_EXT2), "ext2_init() failed!");
|
|
return 0;
|
|
}
|
|
|
|
// called by a filesystem driver to let us know that it is ready to handle fs requests
|
|
int vfs_register_fs(int fsn, vfs_fs_t *fs)
|
|
{
|
|
if (fsn < 0 || fsn >= VFS_MAX_FS || fses[fsn])
|
|
{
|
|
kprintf("Invalid filesystem register: %d\n", fsn);
|
|
return -1;
|
|
}
|
|
fses[fsn] = fs;
|
|
return 0;
|
|
}
|
|
|
|
// called to mount a block device with a certain filesystem to a part of our VFS Mount Tree
|
|
int vfs_mount(major_t maj, minor_t min, int fsType, char *mountPoint)
|
|
{
|
|
if (fsType < 0 || fsType >= VFS_MAX_FS || !fses[fsType])
|
|
return -1; // invalid filesystem type
|
|
if (!strcmp("/", mountPoint))
|
|
{
|
|
if (mounts)
|
|
return -2; // root already mounted
|
|
void *super = fses[fsType]->mount_super(maj, min);
|
|
vfs_mount_t *mnt = New(vfs_mount_t);
|
|
mnt->refs = 0;
|
|
mnt->fs = fsType;
|
|
mnt->major = maj;
|
|
mnt->minor = min;
|
|
mnt->super = super;
|
|
vfs_mount_node_t *node = New(vfs_mount_node_t);
|
|
mount = node;
|
|
node->next = NULL;
|
|
node->mount = mnt;
|
|
node->vfs_inode = 0;
|
|
return 0;
|
|
}
|
|
if (mountPoint[0] != '/')
|
|
return -3; // mount point must be absolute
|
|
int l = strlen(mountPoint);
|
|
if (l < 2)
|
|
return -4; // mount point must be non-null string
|
|
return -5;
|
|
}
|
|
|
|
vfs_inode_t vfs_get_inode_number(char *path)
|
|
{
|
|
if (path[0] != '/')
|
|
return 0;
|
|
vfs_file_addr_t file_addr;
|
|
file_addr.mount = mounts->mount;
|
|
file_addr.inode = fses[file_addr.mount->fsType]->get_root_inode(file_addr.mount);
|
|
|
|
}
|
|
|
|
|
|
// stat a file, fills a vfs_stat_t structure with stat information and returns standard status
|
|
int vfs_stat(char *file, vfs_stat_t *stat)
|
|
{
|
|
vfs_mount_match_t match = vfs_get_rel_path(file);
|
|
if (match.mount == NULL)
|
|
return -256;
|
|
if (fses[match.mount->fs]->stat)
|
|
return fses[match.mount->fs]->stat(match.mount, file + match.length - 1, stat);
|
|
return -257;
|
|
}
|
|
|
|
|
|
vfs_open_file_t *vfs_open_dir(vfs_inode_t inode)
|
|
{
|
|
vfs_open_file_t *open_dir = New(vfs_open_file_t);
|
|
if (fses[match.mount->fs]->open_dir && !(fses[match.mount->fs]->open_dir(match.mount, file + match.length - 1, open_dir)))
|
|
{
|
|
open_dir->mount = match.mount;
|
|
return open_dir;
|
|
}
|
|
kfree(open_dir);
|
|
return NULL;
|
|
}
|
|
|
|
int vfs_read_dir(vfs_open_file_t *open_dir, vfs_dir_entry_t *dentry)
|
|
{
|
|
return !(fses[open_dir->mount->fs]->read_dir &&
|
|
!(fses[open_dir->mount->fs]->read_dir(open_dir->mount, open_dir, dentry)));
|
|
}
|
|
|
|
int vfs_close_dir(vfs_open_file_t *open_dir)
|
|
{
|
|
int status = 0;
|
|
if (fses[open_dir->mount->fs]->close_dir)
|
|
status = fses[open_dir->mount->fs]->close_dir(open_dir->mount, open_dir);
|
|
kfree(open_dir);
|
|
return status;
|
|
}
|
|
|
|
|
|
vfs_open_file_t *vfs_open_block_file(char *file)
|
|
{
|
|
vfs_mount_match_t match = vfs_get_rel_path(file);
|
|
if (match.mount == NULL)
|
|
return NULL;
|
|
vfs_open_file_t *open_file = New(vfs_open_file_t);
|
|
if (fses[match.mount->fs]->open_block_file && !(fses[match.mount->fs]->open_block_file(match.mount, file + match.length - 1, open_file)))
|
|
{
|
|
open_file->mount = match.mount;
|
|
return open_file;
|
|
}
|
|
kfree(open_file);
|
|
return NULL;
|
|
}
|
|
|
|
int vfs_read_block_file(vfs_open_file_t *open_file, void *buffer)
|
|
{
|
|
if (fses[open_file->mount->fs]->read_block_file)
|
|
return fses[open_file->mount->fs]->read_block_file(open_file->mount, open_file, buffer);
|
|
return 0;
|
|
}
|
|
|
|
int vfs_block_file_seek(vfs_open_file_t *open_file, u32_t block_number)
|
|
{
|
|
if (fses[open_file->mount->fs]->block_file_seek)
|
|
return fses[open_file->mount->fs]->block_file_seek(open_file->mount, open_file, block_number);
|
|
return -1;
|
|
}
|
|
|
|
int vfs_close_block_file(vfs_open_file_t *open_file)
|
|
{
|
|
int status = 0;
|
|
if (fses[open_file->mount->fs]->close_block_file)
|
|
status = fses[open_file->mount->fs]->close_block_file(open_file->mount, open_file);
|
|
kfree(open_file);
|
|
return status;
|
|
}
|
|
|
|
|
|
// DEBUG routines to draw the VFS Mount Tree
|
|
/******************************************/
|
|
void vfs_dump_tree()
|
|
{
|
|
if (!vfsMountTree)
|
|
kprintf("vfsMountTree == NULL!\n");
|
|
else
|
|
vfs_dump_node(vfsMountTree, 0);
|
|
}
|
|
|
|
void vfs_dump_node(vfs_node_t *node, int level)
|
|
{
|
|
int i;
|
|
for (i = 0; i < level; i++)
|
|
{
|
|
putc(' ');
|
|
}
|
|
kprintf("%c (0x%x) mount: 0x%x, up: 0x%x, next:0x%x, down:0x%x\n", node->chr, node, node->mount, node->up, node->next, node->down);
|
|
node = node->down;
|
|
if (!node)
|
|
return;
|
|
while (node)
|
|
{
|
|
vfs_dump_node(node, level + 1);
|
|
node = node->next;
|
|
}
|
|
}
|
|
/******************************************/
|
|
|