summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 8940afe..04cd119 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -729,12 +729,10 @@ static void handle_Topen(struct _lib9p_srv_req *ctx,
if (lib9p_ctx_has_error(&ctx->ctx.basectx))
return;
- filep->_io_flags = flags;
- filep->_io_unit = iounit;
- filep->_io_qid = stat.file_qid;
-
- resp->qid = filep->_io_qid;
- resp->iounit = filep->_io_unit;
+ filep->_io_flags = filep->_io_flags | flags;
+ filep->_io_isdir = stat.file_mode & LIB9P_DM_DIR;
+ resp->qid = stat.file_qid;
+ resp->iounit = iounit;
}
static void handle_Tcreate(struct _lib9p_srv_req *ctx,
@@ -751,8 +749,50 @@ static void handle_Tread(struct _lib9p_srv_req *ctx,
struct lib9p_msg_Rread *resp) {
handler_common(ctx, req, resp);
- lib9p_error(&ctx->ctx.basectx,
- LINUX_EOPNOTSUPP, "read not yet implemented");
+ struct lib9p_srv_file **filepp = fidmap_load(&ctx->parent_sess->fids, req->fid);
+ if (!filepp) {
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EBADF, "bad file number %"PRIu32, req->fid);
+ return;
+ }
+ struct lib9p_srv_file *filep = *filepp;
+
+ switch (filep->_io_flags & LIB9P_O_MODE_MASK) {
+ case LIB9P_O_READ:
+ case LIB9P_O_RDWR:
+ /* ok */
+ break;
+ default:
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EINVAL, "FID not open for reading");
+ return;
+ }
+
+ resp->data.dat = (char *)(&resp[1]);
+ if (filep->_io_isdir) {
+ size_t idx;
+ if (req->offset == 0)
+ idx = 0;
+ else if (req->offset == filep->_io_dir_off)
+ idx = filep->_io_dir_idx;
+ else {
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EINVAL, "invalid offset (must be 0 or %"PRIu32"): %"PRIu32,
+ filep->_io_dir_off, req->offset);
+ return;
+ }
+ size_t num = filep->vtable->dread(&ctx->ctx, filep, (uint8_t *)resp->data.dat, req->count, idx);
+ filep->_io_dir_idx = idx+num;
+ uint32_t len = 0;
+ for (size_t i = 0; i < num; i++) {
+ uint32_t i_len;
+ lib9p_validate_stat(&ctx->ctx.basectx, req->count, (uint8_t *)resp->data.dat, &i_len, NULL);
+ len += i_len;
+ }
+ filep->_io_dir_off = req->offset + len;
+ resp->data.len = len;
+ } else
+ resp->data.len = filep->vtable->pread(&ctx->ctx, filep, resp->data.dat, req->count, req->offset);
}
static void handle_Twrite(struct _lib9p_srv_req *ctx,