lib: fs: implement mounting filesystems; reading, writing from files
This commit is contained in:
@@ -23,7 +23,7 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(libfs libmango interface::fs libc)
|
target_link_libraries(libfs libmango interface::fs libc libxpc)
|
||||||
target_link_libraries(libfs-static libmango interface::fs libc-core)
|
target_link_libraries(libfs-static libmango interface::fs libc-core libxpc-static)
|
||||||
|
|
||||||
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
#include <fs/allocator.h>
|
#include <fs/allocator.h>
|
||||||
#include <fs/context.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_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);
|
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_vtable ctx_vtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_context *fs_context_create(
|
struct fs_context *fs_context_create(struct fs_allocator *alloc)
|
||||||
struct fs_allocator *alloc,
|
|
||||||
struct fs_superblock *sb)
|
|
||||||
{
|
{
|
||||||
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@@ -27,10 +31,10 @@ struct fs_context *fs_context_create(
|
|||||||
|
|
||||||
memset(ctx, 0x0, sizeof *ctx);
|
memset(ctx, 0x0, sizeof *ctx);
|
||||||
|
|
||||||
ctx->ctx_sb = sb;
|
|
||||||
ctx->ctx_alloc = alloc;
|
ctx->ctx_alloc = alloc;
|
||||||
|
|
||||||
ctx->ctx_vtable.open = fs_msg_open;
|
ctx->ctx_vtable.open = fs_msg_open;
|
||||||
|
ctx->ctx_vtable.read = fs_msg_read;
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
@@ -40,6 +44,35 @@ void fs_context_destroy(struct fs_context *ctx)
|
|||||||
fs_free(ctx->ctx_alloc, 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 *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
||||||
{
|
{
|
||||||
struct fs_file *f = get_file(&ctx->ctx_filelist, 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;
|
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)
|
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_dentry *fs_context_resolve_path(
|
static size_t get_first_path_component(const char *in, char *out, size_t max)
|
||||||
struct fs_context *ctx,
|
|
||||||
const char *path)
|
|
||||||
{
|
{
|
||||||
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,
|
struct fs_context *ctx,
|
||||||
kern_handle_t channel,
|
const char *path,
|
||||||
struct msg_endpoint *sender,
|
struct fs_dentry **out)
|
||||||
struct msg_header *hdr)
|
|
||||||
{
|
{
|
||||||
return fs_dispatch(
|
if (!ctx->ctx_sb || !ctx->ctx_sb->s_root) {
|
||||||
channel,
|
return FS_ERR_NO_ENTRY;
|
||||||
&ctx->ctx_vtable,
|
}
|
||||||
sender,
|
|
||||||
hdr,
|
struct fs_dentry *cur = ctx->ctx_sb->s_root;
|
||||||
NULL,
|
|
||||||
0,
|
char tok[256];
|
||||||
ctx);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
41
lib/libfs/file.c
Normal file
41
lib/libfs/file.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
struct fs_inode *fs_file_get_inode(const struct fs_file *f)
|
||||||
|
{
|
||||||
|
return f->f_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fs_file_get_cursor(const struct fs_file *f)
|
||||||
|
{
|
||||||
|
return f->f_seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_read) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t seek = f->f_seek;
|
||||||
|
enum fs_status status = f->f_ops->f_read(f, buf, count, &seek);
|
||||||
|
f->f_seek = seek;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_write(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_write) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t seek = f->f_seek;
|
||||||
|
enum fs_status status = f->f_ops->f_write(f, buf, count, &seek);
|
||||||
|
f->f_seek = seek;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
|
|
||||||
|
#include <fs/dentry.h>
|
||||||
#include <fs/file.h>
|
#include <fs/file.h>
|
||||||
|
#include <fs/inode.h>
|
||||||
|
|
||||||
struct fs_file {
|
struct fs_file {
|
||||||
/* id of the open file, equal to the koid of the port being used to
|
/* id of the open file, equal to the koid of the port being used to
|
||||||
@@ -12,6 +14,10 @@ struct fs_file {
|
|||||||
struct btree_node f_node;
|
struct btree_node f_node;
|
||||||
|
|
||||||
const struct fs_file_ops *f_ops;
|
const struct fs_file_ops *f_ops;
|
||||||
|
|
||||||
|
off_t f_seek;
|
||||||
|
struct fs_inode *f_inode;
|
||||||
|
struct fs_dentry *f_dent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,30 +2,54 @@
|
|||||||
#define FS_CONTEXT_H_
|
#define FS_CONTEXT_H_
|
||||||
|
|
||||||
#include <rosetta/fs.h>
|
#include <rosetta/fs.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
struct fs_dentry;
|
||||||
struct fs_context;
|
struct fs_context;
|
||||||
struct fs_allocator;
|
struct fs_allocator;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
|
|
||||||
extern struct fs_context *fs_context_create(
|
enum fs_mount_flags {
|
||||||
struct fs_allocator *alloc,
|
FS_MOUNT_READONLY = 0x01u,
|
||||||
struct fs_superblock *sb);
|
};
|
||||||
|
|
||||||
|
typedef enum fs_status (*fs_mount_function_t)(
|
||||||
|
struct fs_context *,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags,
|
||||||
|
struct fs_superblock **);
|
||||||
|
|
||||||
|
extern struct fs_context *fs_context_create(struct fs_allocator *alloc);
|
||||||
extern void fs_context_destroy(struct fs_context *ctx);
|
extern void fs_context_destroy(struct fs_context *ctx);
|
||||||
|
|
||||||
|
extern enum fs_status fs_context_mount_filesystem(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
fs_mount_function_t func,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags);
|
||||||
|
extern enum fs_status fs_context_unmount_filesystem(struct fs_context *ctx);
|
||||||
|
|
||||||
extern struct fs_file *fs_context_open_file(
|
extern struct fs_file *fs_context_open_file(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
unsigned long id);
|
unsigned long id);
|
||||||
|
extern struct fs_file *fs_context_get_file(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
unsigned long id);
|
||||||
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
||||||
|
|
||||||
extern struct fs_dentry *fs_context_resolve_path(
|
extern enum fs_status fs_context_resolve_path(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
const char *path);
|
const char *path,
|
||||||
|
struct fs_dentry **out);
|
||||||
|
|
||||||
extern kern_status_t fs_context_dispatch_msg(
|
extern kern_status_t fs_context_dispatch_msg(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
kern_handle_t channel,
|
xpc_msg_t *msg);
|
||||||
struct msg_endpoint *sender,
|
|
||||||
struct msg_header *hdr);
|
extern void *fs_context_alloc(struct fs_context *ctx, size_t count);
|
||||||
|
extern void *fs_context_calloc(struct fs_context *ctx, size_t count, size_t sz);
|
||||||
|
extern void *fs_context_realloc(struct fs_context *ctx, void *p, size_t count);
|
||||||
|
extern void fs_context_free(struct fs_context *ctx, void *p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ struct fs_dentry {
|
|||||||
struct fs_superblock *d_sb;
|
struct fs_superblock *d_sb;
|
||||||
const struct fs_dentry_ops *d_ops;
|
const struct fs_dentry_ops *d_ops;
|
||||||
void *d_fsdata;
|
void *d_fsdata;
|
||||||
|
char *d_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,11 +5,31 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
struct xpc_buffer;
|
||||||
|
|
||||||
struct fs_file_ops {
|
struct fs_file_ops {
|
||||||
ssize_t (*f_read)(struct fs_file *, void *, size_t);
|
enum fs_status (*f_read)(
|
||||||
ssize_t (*f_write)(struct fs_file *, const void *, size_t);
|
struct fs_file *,
|
||||||
off_t (*f_seek)(struct fs_file *, off_t, int);
|
struct xpc_buffer *,
|
||||||
|
size_t,
|
||||||
|
off_t *);
|
||||||
|
enum fs_status (*f_write)(
|
||||||
|
struct fs_file *,
|
||||||
|
const struct xpc_buffer *,
|
||||||
|
size_t,
|
||||||
|
off_t *);
|
||||||
|
enum fs_status (*f_seek)(struct fs_file *, off_t, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct fs_inode *fs_file_get_inode(const struct fs_file *f);
|
||||||
|
extern size_t fs_file_get_cursor(const struct fs_file *f);
|
||||||
|
extern enum fs_status fs_file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count);
|
||||||
|
extern enum fs_status fs_file_write(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,17 +1,37 @@
|
|||||||
#ifndef FS_INODE_H_
|
#ifndef FS_INODE_H_
|
||||||
#define FS_INODE_H_
|
#define FS_INODE_H_
|
||||||
|
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_inode;
|
struct fs_inode;
|
||||||
struct fs_dentry;
|
struct fs_dentry;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
|
struct fs_file_ops;
|
||||||
|
|
||||||
|
enum fs_inode_mode {
|
||||||
|
FS_INODE_REG = 0x01u,
|
||||||
|
FS_INODE_DIR = 0x02u,
|
||||||
|
};
|
||||||
|
|
||||||
struct fs_inode_ops {
|
struct fs_inode_ops {
|
||||||
int (*i_lookup)(struct fs_inode *, struct fs_dentry *);
|
enum fs_status (*i_lookup)(
|
||||||
|
struct fs_inode *,
|
||||||
|
const char *,
|
||||||
|
struct fs_dentry **);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_inode {
|
struct fs_inode {
|
||||||
|
enum fs_inode_mode i_mode;
|
||||||
struct fs_superblock *i_sb;
|
struct fs_superblock *i_sb;
|
||||||
const struct fs_inode_ops *i_ops;
|
const struct fs_inode_ops *i_ops;
|
||||||
|
const struct fs_file_ops *i_fops;
|
||||||
|
size_t i_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern enum fs_status fs_inode_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
18
lib/libfs/include/fs/status.h
Normal file
18
lib/libfs/include/fs/status.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef FS_STATUS_H_
|
||||||
|
#define FS_STATUS_H_
|
||||||
|
|
||||||
|
enum fs_status {
|
||||||
|
FS_SUCCESS = 0,
|
||||||
|
FS_ERR_NO_ENTRY,
|
||||||
|
FS_ERR_NO_MEMORY,
|
||||||
|
FS_ERR_INVALID_ARGUMENT,
|
||||||
|
FS_ERR_NOT_IMPLEMENTED,
|
||||||
|
FS_ERR_IS_DIRECTORY,
|
||||||
|
FS_ERR_NOT_DIRECTORY,
|
||||||
|
FS_ERR_BAD_STATE,
|
||||||
|
FS_ERR_INTERNAL_FAILURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int fs_status_to_errno(enum fs_status status);
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/libfs/inode.c
Normal file
13
lib/libfs/inode.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <fs/inode.h>
|
||||||
|
|
||||||
|
enum fs_status fs_inode_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out)
|
||||||
|
{
|
||||||
|
if (!inode->i_ops || !inode->i_ops->i_lookup) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inode->i_ops->i_lookup(inode, name, out);
|
||||||
|
}
|
||||||
@@ -2,12 +2,17 @@
|
|||||||
#define _FS_INTERFACE_H_
|
#define _FS_INTERFACE_H_
|
||||||
|
|
||||||
#include <mango/types.h>
|
#include <mango/types.h>
|
||||||
|
#include <xpc/buffer.h>
|
||||||
|
#include <xpc/context.h>
|
||||||
|
#include <xpc/endpoint.h>
|
||||||
|
#include <xpc/string.h>
|
||||||
|
|
||||||
struct msg_endpoint;
|
struct msg_endpoint;
|
||||||
|
|
||||||
extern kern_status_t fs_msg_open(
|
extern kern_status_t fs_msg_open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *ctx,
|
||||||
const char *path,
|
const xpc_endpoint_t *sender,
|
||||||
|
const xpc_string_t *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg);
|
void *arg);
|
||||||
@@ -18,4 +23,13 @@ extern kern_status_t fs_msg_close(
|
|||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_read(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
size_t count,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_read,
|
||||||
|
xpc_buffer_t *out_data,
|
||||||
|
void *arg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,21 +1,53 @@
|
|||||||
|
#include "../file.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fs/context.h>
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
extern kern_status_t fs_msg_open(
|
extern kern_status_t fs_msg_open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *xpc,
|
||||||
const char *path,
|
xpc_endpoint_t *sender,
|
||||||
|
const xpc_string_t *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
char path_buf[4096];
|
||||||
|
size_t path_len = 0;
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_string_read(path, path_buf, sizeof path_buf, &path_len);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
struct fs_context *ctx = arg;
|
struct fs_context *ctx = arg;
|
||||||
|
|
||||||
struct fs_dentry *dent = fs_context_resolve_path(ctx, path);
|
struct fs_file *f = fs_context_open_file(ctx, sender->e_port);
|
||||||
if (!dent) {
|
if (!f) {
|
||||||
*out_err = ENOENT;
|
*out_err = ENOMEM;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->f_inode) {
|
||||||
|
*out_err = EBUSY;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_dentry *dent = NULL;
|
||||||
|
enum fs_status fs_status
|
||||||
|
= fs_context_resolve_path(ctx, path_buf, &dent);
|
||||||
|
if (fs_status != FS_SUCCESS) {
|
||||||
|
fs_context_close_file(ctx, f);
|
||||||
|
*out_err = fs_status_to_errno(status);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->f_seek = 0;
|
||||||
|
f->f_dent = dent;
|
||||||
|
f->f_inode = dent->d_inode;
|
||||||
|
f->f_ops = dent->d_inode->i_fops;
|
||||||
|
|
||||||
*out_err = SUCCESS;
|
*out_err = SUCCESS;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
30
lib/libfs/interface/read.c
Normal file
30
lib/libfs/interface/read.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_read(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
xpc_endpoint_t *sender,
|
||||||
|
size_t count,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_read,
|
||||||
|
xpc_buffer_t *out_data,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start = fs_file_get_cursor(f);
|
||||||
|
enum fs_status status = fs_file_read(f, out_data, count);
|
||||||
|
size_t end = fs_file_get_cursor(f);
|
||||||
|
|
||||||
|
*out_err = fs_status_to_errno(status);
|
||||||
|
*out_nr_read = end - start;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
25
lib/libfs/status.c
Normal file
25
lib/libfs/status.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
int fs_status_to_errno(enum fs_status status)
|
||||||
|
{
|
||||||
|
switch (status) {
|
||||||
|
case FS_SUCCESS:
|
||||||
|
return SUCCESS;
|
||||||
|
case FS_ERR_NO_ENTRY:
|
||||||
|
return ENOENT;
|
||||||
|
case FS_ERR_NO_MEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case FS_ERR_INVALID_ARGUMENT:
|
||||||
|
return EINVAL;
|
||||||
|
case FS_ERR_NOT_IMPLEMENTED:
|
||||||
|
return ENOSYS;
|
||||||
|
case FS_ERR_IS_DIRECTORY:
|
||||||
|
return EISDIR;
|
||||||
|
case FS_ERR_NOT_DIRECTORY:
|
||||||
|
return ENOTDIR;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user