diff --git a/lib/libxpc/buffer.c b/lib/libxpc/buffer.c index 9a6da88..5871705 100644 --- a/lib/libxpc/buffer.c +++ b/lib/libxpc/buffer.c @@ -5,6 +5,7 @@ kern_status_t xpc_buffer_read( const xpc_buffer_t *buf, + size_t offset, void *out, size_t max, size_t *nr_read) @@ -14,25 +15,35 @@ kern_status_t xpc_buffer_read( return KERN_BAD_STATE; } - size_t to_read = max; - if (to_read > buf->buf_len) { - to_read = buf->buf_len; + if (offset >= buf->buf_len) { + if (nr_read) { + *nr_read = 0; + } + + return KERN_OK; } - kern_status_t status - = xpc_msg_read(buf->buf_origin, buf->buf_offset, out, to_read); + size_t to_read = max; + if (offset + to_read > buf->buf_len) { + to_read = buf->buf_len - offset; + } + + kern_status_t status = xpc_msg_read( + buf->buf_origin, + buf->buf_offset + offset, + out, + to_read, + nr_read); if (status != KERN_OK) { return status; } - /* TODO */ - *nr_read = to_read; - return KERN_OK; } kern_status_t xpc_buffer_write( xpc_buffer_t *buf, + size_t offset, const void *in, size_t len, size_t *nr_written) @@ -41,9 +52,17 @@ kern_status_t xpc_buffer_write( return KERN_BAD_STATE; } + if (offset >= buf->buf_max) { + if (nr_written) { + *nr_written = 0; + } + + return KERN_OK; + } + size_t to_write = len; - if (to_write > buf->buf_max) { - to_write = buf->buf_max; + if (offset + to_write > buf->buf_max) { + to_write = buf->buf_max - offset; } if (!(buf->buf_flags & XPC_BUFFER_F_REMOTE)) { @@ -54,8 +73,70 @@ kern_status_t xpc_buffer_write( return xpc_msg_write( buf->buf_origin, - buf->buf_offset, + buf->buf_offset + offset, in, to_write, nr_written); } + +xpc_status_t xpc_buffer_readv( + const xpc_buffer_t *buf, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_read) +{ + if (!(buf->buf_flags & XPC_BUFFER_F_IN)) { + return KERN_BAD_STATE; + } + + /* TODO limit to buffer bounds */ + + if (!(buf->buf_flags & XPC_BUFFER_F_REMOTE)) { + /* TODO */ + return KERN_UNIMPLEMENTED; + } + + return xpc_msg_readv( + buf->buf_origin, + buf->buf_offset + offset, + iov, + nr_iov, + nr_read); +} + +xpc_status_t xpc_buffer_writev( + xpc_buffer_t *buf, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_written) +{ + if (!(buf->buf_flags & XPC_BUFFER_F_OUT)) { + return KERN_BAD_STATE; + } + + /* TODO limit to buffer bounds */ + + if (!(buf->buf_flags & XPC_BUFFER_F_REMOTE)) { + /* TODO */ + return KERN_UNIMPLEMENTED; + } + + return xpc_msg_writev( + buf->buf_origin, + buf->buf_offset + offset, + iov, + nr_iov, + nr_written); +} + +xpc_status_t xpc_buffer_length(const xpc_buffer_t *s) +{ + return s->buf_len; +} + +xpc_status_t xpc_buffer_capacity(const xpc_buffer_t *s) +{ + return s->buf_max; +} diff --git a/lib/libxpc/include/xpc/buffer.h b/lib/libxpc/include/xpc/buffer.h index 47051b0..d234516 100644 --- a/lib/libxpc/include/xpc/buffer.h +++ b/lib/libxpc/include/xpc/buffer.h @@ -1,6 +1,7 @@ #ifndef XPC_BUFFER_H_ #define XPC_BUFFER_H_ +#include #include #include @@ -71,13 +72,31 @@ typedef struct xpc_buffer { extern xpc_status_t xpc_buffer_read( const xpc_buffer_t *s, + size_t offset, void *out, size_t max, size_t *nr_read); extern xpc_status_t xpc_buffer_write( xpc_buffer_t *s, + size_t offset, const void *in, size_t len, size_t *nr_written); +extern xpc_status_t xpc_buffer_readv( + const xpc_buffer_t *s, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_read); +extern xpc_status_t xpc_buffer_writev( + xpc_buffer_t *s, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_written); + +extern xpc_status_t xpc_buffer_length(const xpc_buffer_t *s); +extern xpc_status_t xpc_buffer_capacity(const xpc_buffer_t *s); + #endif diff --git a/lib/libxpc/include/xpc/msg.h b/lib/libxpc/include/xpc/msg.h index debd15c..4ab0e15 100644 --- a/lib/libxpc/include/xpc/msg.h +++ b/lib/libxpc/include/xpc/msg.h @@ -34,7 +34,8 @@ extern kern_status_t xpc_msg_read( const xpc_msg_t *msg, size_t offset, void *p, - size_t count); + size_t count, + size_t *nr_read); extern kern_status_t xpc_msg_write( const xpc_msg_t *msg, size_t offset, @@ -42,6 +43,19 @@ extern kern_status_t xpc_msg_write( size_t count, size_t *nr_written); +extern kern_status_t xpc_msg_readv( + const xpc_msg_t *msg, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_read); +extern kern_status_t xpc_msg_writev( + const xpc_msg_t *msg, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_written); + extern kern_status_t xpc_msg_reply( const xpc_msg_t *msg, kern_iovec_t *iov, diff --git a/lib/libxpc/msg.c b/lib/libxpc/msg.c index 81d13c3..fab2434 100644 --- a/lib/libxpc/msg.c +++ b/lib/libxpc/msg.c @@ -89,17 +89,17 @@ kern_status_t xpc_msg_read( const xpc_msg_t *msg, size_t offset, void *p, - size_t count) + size_t count, + size_t *nr_read) { kern_iovec_t iov = IOVEC(p, count); - size_t r = 0; return msg_read( msg->msg_sender.e_channel, msg->msg_sender.e_msg, offset, &iov, 1, - &r); + nr_read); } kern_status_t xpc_msg_write( @@ -119,6 +119,38 @@ kern_status_t xpc_msg_write( nr_written); } +kern_status_t xpc_msg_readv( + const xpc_msg_t *msg, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_read) +{ + return msg_read( + msg->msg_sender.e_channel, + msg->msg_sender.e_msg, + offset, + iov, + nr_iov, + nr_read); +} + +kern_status_t xpc_msg_writev( + const xpc_msg_t *msg, + size_t offset, + kern_iovec_t *iov, + size_t nr_iov, + size_t *nr_written) +{ + return msg_write( + msg->msg_sender.e_channel, + msg->msg_sender.e_msg, + offset, + iov, + nr_iov, + nr_written); +} + kern_status_t xpc_msg_reply( const xpc_msg_t *msg, kern_iovec_t *iov, diff --git a/lib/libxpc/string.c b/lib/libxpc/string.c index 4f06817..53adc4f 100644 --- a/lib/libxpc/string.c +++ b/lib/libxpc/string.c @@ -19,14 +19,12 @@ xpc_status_t xpc_string_read( } kern_status_t status - = xpc_msg_read(s->s_origin, s->s_offset, out, to_read); + = xpc_msg_read(s->s_origin, s->s_offset, out, to_read, nr_read); if (status != KERN_OK) { return status; } out[to_read] = '\0'; - /* TODO */ - *nr_read = to_read; return KERN_OK; }