diff options
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r-- | lib9p/srv.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c index ecdf169..03d7b93 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -1185,6 +1185,11 @@ static void handle_Tread(struct srv_req *ctx, /* TODO: serialize simultaneous reads to the same FID */ + /* req->count <= CONFIG_9P_SRV_MAX_MSG_SIZE <= CONFIG_9P_SRV_MAX_HOSTMSG_SIZE <= SIZE_MAX */ + assert(req->count <= SIZE_MAX); + /* req->offset is u64, uoff is u64 */ + static_assert(req->offset <= UOFF_MAX); + if (req->count > ctx->basectx.max_msg_size - lib9p_version_min_Rread_size(ctx->basectx.version)) req->count = ctx->basectx.max_msg_size - lib9p_version_min_Rread_size(ctx->basectx.version); @@ -1219,20 +1224,44 @@ static void handle_Tread(struct srv_req *ctx, ctx->user = srv_userid_decref(ctx->user); } -static void handle_read_file(struct srv_req *ctx, struct srv_fidinfo *fidinfo, uint64_t offset, uint32_t count) { - iovec_or_error r = LO_CALL(fidinfo->file.io, pread, ctx, count, offset); - if (r.is_err) { - srv_respond(ctx, read, NULL, r.err); - return; - } +struct rread_writer { + struct srv_req *ctx; + size_t count; + bool written; + +}; +LO_IMPLEMENTATION_STATIC(io_writer, struct rread_writer, rread); + +static size_t_and_error rread_writev(struct rread_writer *self, const struct iovec *iov, int iovcnt) { + assert(self); + assert(!self->written); + assert(iovcnt == 1); + assert(iov); + assert(iov->iov_len <= self->count); + struct lib9p_msg_Rread resp = { - .tag = ctx->tag, - .count = r.iovec.iov_len, - .data = r.iovec.iov_base, + .tag = self->ctx->tag, + .count = iov->iov_len, + .data = iov->iov_base, }; - if (resp.count > count) - resp.count = count; - srv_respond(ctx, read, &resp, ERROR_NULL); + + srv_respond(self->ctx, read, &resp, ERROR_NULL); + + self->written = true; + return ERROR_AND(size_t, iov->iov_len, ERROR_NULL); +} + +static void handle_read_file(struct srv_req *ctx, struct srv_fidinfo *fidinfo, uint64_t offset, uint32_t count) { + struct rread_writer _writer = { + .ctx = ctx, + .count = (size_t) count, + .written = false, + }; + lo_interface io_writer writer = LO_BOX(io_writer, &_writer); + error err = LO_CALL(fidinfo->file.io, pread, ctx, writer, offset, count); + assert(ERROR_IS_NULL(err) == _writer.written); + if (!ERROR_IS_NULL(err)) + srv_respond(ctx, read, NULL, err); } #if _LIB9P_ENABLE_stat |