#include "btree.h" #include "file.h" #include "interface.h" #include #include #include #include #include #include #include #include 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); struct fs_context { struct fs_superblock *ctx_sb; struct fs_allocator *ctx_alloc; struct btree ctx_filelist; struct fs_vtable ctx_vtable; }; struct fs_context *fs_context_create(struct fs_allocator *alloc) { struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx); if (!ctx) { return NULL; } memset(ctx, 0x0, sizeof *ctx); ctx->ctx_alloc = alloc; ctx->ctx_vtable.open = fs_msg_open; ctx->ctx_vtable.read = fs_msg_read; return ctx; } 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); if (!f) { f = fs_alloc(ctx->ctx_alloc, sizeof *f); if (!f) { return NULL; } memset(f, 0x0, sizeof *f); f->f_id = id; put_file(&ctx->ctx_filelist, f); } 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) { } static size_t get_first_path_component(const char *in, char *out, size_t max) { 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; } extern enum fs_status fs_context_resolve_path( struct fs_context *ctx, const char *path, struct fs_dentry **out) { 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); }