lib: fs: implement mounting filesystems; reading, writing from files
This commit is contained in:
@@ -4,6 +4,12 @@
|
||||
|
||||
#include <fs/allocator.h>
|
||||
#include <fs/context.h>
|
||||
#include <fs/dentry.h>
|
||||
#include <fs/inode.h>
|
||||
#include <fs/status.h>
|
||||
#include <fs/superblock.h>
|
||||
#include <mango/log.h>
|
||||
#include <stdio.h>
|
||||
|
||||
BTREE_DEFINE_SIMPLE_GET(struct fs_file, unsigned long, f_node, f_id, get_file);
|
||||
BTREE_DEFINE_SIMPLE_INSERT(struct fs_file, f_node, f_id, put_file);
|
||||
@@ -16,9 +22,7 @@ struct fs_context {
|
||||
struct fs_vtable ctx_vtable;
|
||||
};
|
||||
|
||||
struct fs_context *fs_context_create(
|
||||
struct fs_allocator *alloc,
|
||||
struct fs_superblock *sb)
|
||||
struct fs_context *fs_context_create(struct fs_allocator *alloc)
|
||||
{
|
||||
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
||||
if (!ctx) {
|
||||
@@ -27,10 +31,10 @@ struct fs_context *fs_context_create(
|
||||
|
||||
memset(ctx, 0x0, sizeof *ctx);
|
||||
|
||||
ctx->ctx_sb = sb;
|
||||
ctx->ctx_alloc = alloc;
|
||||
|
||||
ctx->ctx_vtable.open = fs_msg_open;
|
||||
ctx->ctx_vtable.read = fs_msg_read;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
@@ -40,6 +44,35 @@ void fs_context_destroy(struct fs_context *ctx)
|
||||
fs_free(ctx->ctx_alloc, ctx);
|
||||
}
|
||||
|
||||
enum fs_status fs_context_mount_filesystem(
|
||||
struct fs_context *ctx,
|
||||
fs_mount_function_t func,
|
||||
void *arg,
|
||||
enum fs_mount_flags flags)
|
||||
{
|
||||
if (!func) {
|
||||
return FS_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
struct fs_superblock *sb = NULL;
|
||||
enum fs_status status = func(ctx, arg, flags, &sb);
|
||||
if (status != FS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!sb) {
|
||||
return FS_ERR_INTERNAL_FAILURE;
|
||||
}
|
||||
|
||||
ctx->ctx_sb = sb;
|
||||
return FS_SUCCESS;
|
||||
}
|
||||
|
||||
enum fs_status fs_context_unmount_filesystem(struct fs_context *ctx)
|
||||
{
|
||||
return FS_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
||||
{
|
||||
struct fs_file *f = get_file(&ctx->ctx_filelist, id);
|
||||
@@ -58,29 +91,104 @@ struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
||||
return f;
|
||||
}
|
||||
|
||||
struct fs_file *fs_context_get_file(struct fs_context *ctx, unsigned long id)
|
||||
{
|
||||
return get_file(&ctx->ctx_filelist, id);
|
||||
}
|
||||
|
||||
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
||||
{
|
||||
}
|
||||
|
||||
struct fs_dentry *fs_context_resolve_path(
|
||||
struct fs_context *ctx,
|
||||
const char *path)
|
||||
static size_t get_first_path_component(const char *in, char *out, size_t max)
|
||||
{
|
||||
return NULL;
|
||||
size_t i = 0;
|
||||
while (i < max - 1) {
|
||||
if (in[i] == '\0' || in[i] == '/') {
|
||||
break;
|
||||
}
|
||||
|
||||
out[i] = in[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
out[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
kern_status_t fs_context_dispatch_msg(
|
||||
extern enum fs_status fs_context_resolve_path(
|
||||
struct fs_context *ctx,
|
||||
kern_handle_t channel,
|
||||
struct msg_endpoint *sender,
|
||||
struct msg_header *hdr)
|
||||
const char *path,
|
||||
struct fs_dentry **out)
|
||||
{
|
||||
return fs_dispatch(
|
||||
channel,
|
||||
&ctx->ctx_vtable,
|
||||
sender,
|
||||
hdr,
|
||||
NULL,
|
||||
0,
|
||||
ctx);
|
||||
if (!ctx->ctx_sb || !ctx->ctx_sb->s_root) {
|
||||
return FS_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
struct fs_dentry *cur = ctx->ctx_sb->s_root;
|
||||
|
||||
char tok[256];
|
||||
|
||||
while (*path != '\0') {
|
||||
while (*path == '/') {
|
||||
path++;
|
||||
}
|
||||
|
||||
size_t tok_len
|
||||
= get_first_path_component(path, tok, sizeof tok);
|
||||
|
||||
if (!tok_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool is_dir = *(path + tok_len) != '\0';
|
||||
|
||||
if (cur->d_inode->i_mode != FS_INODE_DIR) {
|
||||
return FS_ERR_NOT_DIRECTORY;
|
||||
}
|
||||
|
||||
struct fs_dentry *next = NULL;
|
||||
enum fs_status status
|
||||
= fs_inode_lookup(cur->d_inode, tok, &next);
|
||||
|
||||
if (status != FS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!next) {
|
||||
return FS_ERR_INTERNAL_FAILURE;
|
||||
}
|
||||
|
||||
cur = next;
|
||||
|
||||
path += tok_len;
|
||||
}
|
||||
|
||||
*out = cur;
|
||||
return FS_SUCCESS;
|
||||
}
|
||||
|
||||
kern_status_t fs_context_dispatch_msg(struct fs_context *ctx, xpc_msg_t *msg)
|
||||
{
|
||||
return fs_dispatch(NULL, msg, &ctx->ctx_vtable, ctx);
|
||||
}
|
||||
|
||||
void *fs_context_alloc(struct fs_context *ctx, size_t count)
|
||||
{
|
||||
return fs_alloc(ctx->ctx_alloc, count);
|
||||
}
|
||||
|
||||
void *fs_context_calloc(struct fs_context *ctx, size_t count, size_t sz)
|
||||
{
|
||||
return fs_calloc(ctx->ctx_alloc, count, sz);
|
||||
}
|
||||
|
||||
void *fs_context_realloc(struct fs_context *ctx, void *p, size_t count)
|
||||
{
|
||||
return fs_realloc(ctx->ctx_alloc, p, count);
|
||||
}
|
||||
|
||||
void fs_context_free(struct fs_context *ctx, void *p)
|
||||
{
|
||||
fs_free(ctx->ctx_alloc, p);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user