diff --git a/lib/libfs/context.c b/lib/libfs/context.c index 3bb7b59..247bbfe 100644 --- a/lib/libfs/context.c +++ b/lib/libfs/context.c @@ -92,6 +92,7 @@ struct fs_context *fs_context_create(struct fs_allocator *alloc) ctx->ctx_vtable.write = fs_msg_write; ctx->ctx_vtable.seek = fs_msg_seek; ctx->ctx_vtable.map = fs_msg_map; + ctx->ctx_vtable.getdents = fs_msg_getdents; return ctx; } diff --git a/lib/libfs/file.c b/lib/libfs/file.c index 5857974..9c927c5 100644 --- a/lib/libfs/file.c +++ b/lib/libfs/file.c @@ -52,3 +52,15 @@ enum fs_status fs_file_write( f->f_seek = seek; return status; } + +enum fs_status fs_file_readdir(struct fs_file *f, struct xpc_buffer *buf) +{ + if (!f->f_ops || !f->f_ops->f_readdir) { + return FS_ERR_NOT_IMPLEMENTED; + } + + off_t seek = f->f_seek; + enum fs_status status = f->f_ops->f_readdir(f, buf, &seek); + f->f_seek = seek; + return status; +} diff --git a/lib/libfs/include/fs/file.h b/lib/libfs/include/fs/file.h index 4d9d335..b28ed8c 100644 --- a/lib/libfs/include/fs/file.h +++ b/lib/libfs/include/fs/file.h @@ -19,6 +19,8 @@ struct fs_file_ops { size_t, off_t *); enum fs_status (*f_seek)(struct fs_file *, off_t, int); + enum fs_status ( + *f_readdir)(struct fs_file *, struct xpc_buffer *, off_t *); }; extern struct fs_inode *fs_file_get_inode(const struct fs_file *f); @@ -37,4 +39,8 @@ extern enum fs_status fs_file_write( const struct xpc_buffer *buf, size_t count); +extern enum fs_status fs_file_readdir( + struct fs_file *f, + struct xpc_buffer *buf); + #endif diff --git a/lib/libfs/interface.h b/lib/libfs/interface.h index 26f29e0..e14e554 100644 --- a/lib/libfs/interface.h +++ b/lib/libfs/interface.h @@ -27,7 +27,6 @@ extern kern_status_t fs_msg_read( const xpc_endpoint_t *sender, size_t count, int *out_err, - size_t *out_nr_read, xpc_buffer_t *out_data, void *arg); extern kern_status_t fs_msg_write( @@ -55,4 +54,11 @@ extern kern_status_t fs_msg_map( kern_handle_t *out_vmo, void *arg); +extern kern_status_t fs_msg_getdents( + xpc_context_t *ctx, + const xpc_endpoint_t *sender, + int *out_err, + xpc_buffer_t *out_dents, + void *arg); + #endif diff --git a/lib/libfs/interface/getdents.c b/lib/libfs/interface/getdents.c new file mode 100644 index 0000000..20bccc7 --- /dev/null +++ b/lib/libfs/interface/getdents.c @@ -0,0 +1,34 @@ +#include "../file.h" + +#include +#include +#include +#include + +kern_status_t fs_msg_getdents( + xpc_context_t *xpc, + const xpc_endpoint_t *sender, + int *out_err, + xpc_buffer_t *out_dents, + 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; + } + + if (!(f->f_inode->i_mode & FS_INODE_DIR)) { + *out_err = ENOTDIR; + return KERN_OK; + } + + size_t start = fs_file_get_cursor(f); + enum fs_status status = fs_file_readdir(f, out_dents); + size_t end = fs_file_get_cursor(f); + + *out_err = fs_status_to_errno(status); + + return KERN_OK; +} diff --git a/lib/libfs/interface/read.c b/lib/libfs/interface/read.c index 4e6aa7f..7e732f0 100644 --- a/lib/libfs/interface/read.c +++ b/lib/libfs/interface/read.c @@ -8,7 +8,6 @@ extern kern_status_t fs_msg_read( xpc_endpoint_t *sender, size_t count, int *out_err, - size_t *out_nr_read, xpc_buffer_t *out_data, void *arg) { @@ -24,7 +23,7 @@ extern kern_status_t fs_msg_read( size_t end = fs_file_get_cursor(f); *out_err = fs_status_to_errno(status); - *out_nr_read = end - start; + out_data->buf_len = end - start; return KERN_OK; }