diff --git a/lib/libfs/context.c b/lib/libfs/context.c index 1f825ca..3bb7b59 100644 --- a/lib/libfs/context.c +++ b/lib/libfs/context.c @@ -90,6 +90,7 @@ struct fs_context *fs_context_create(struct fs_allocator *alloc) ctx->ctx_vtable.close = fs_msg_close; ctx->ctx_vtable.read = fs_msg_read; ctx->ctx_vtable.write = fs_msg_write; + ctx->ctx_vtable.seek = fs_msg_seek; ctx->ctx_vtable.map = fs_msg_map; return ctx; diff --git a/lib/libfs/interface.h b/lib/libfs/interface.h index 924550d..26f29e0 100644 --- a/lib/libfs/interface.h +++ b/lib/libfs/interface.h @@ -38,6 +38,14 @@ extern kern_status_t fs_msg_write( size_t *out_nr_written, void *arg); +extern kern_status_t fs_msg_seek( + xpc_context_t *ctx, + const xpc_endpoint_t *sender, + off_t offset, + int origin, + int *out_err, + off_t *out_new_pos, + void *arg); extern kern_status_t fs_msg_map( xpc_context_t *ctx, const xpc_endpoint_t *sender, diff --git a/lib/libfs/interface/seek.c b/lib/libfs/interface/seek.c new file mode 100644 index 0000000..bc494f6 --- /dev/null +++ b/lib/libfs/interface/seek.c @@ -0,0 +1,52 @@ +#include "../file.h" + +#include +#include +#include +#include +#include + +extern kern_status_t fs_msg_seek( + xpc_context_t *xpc, + const xpc_endpoint_t *sender, + off_t rel_offset, + int origin, + int *out_err, + off_t *out_new_pos, + 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; + } + + off_t new_offset = 0; + + switch (origin) { + case SEEK_SET: + new_offset = rel_offset; + break; + case SEEK_CUR: + new_offset = f->f_seek + rel_offset; + break; + case SEEK_END: + new_offset = f->f_inode->i_size + rel_offset; + break; + default: + *out_err = EINVAL; + return KERN_OK; + } + + if (new_offset > f->f_inode->i_size) { + *out_err = EINVAL; + return KERN_OK; + } + + f->f_seek = new_offset; + *out_err = SUCCESS; + *out_new_pos = new_offset; + + return KERN_OK; +}