diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 134a69fb7c..e4f855ddda 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -249,6 +249,41 @@ Inode::Open(int mode, OpenFileCookie* cookie) } +status_t +Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length) +{ + bool eof = false; + uint32 size = 0; + uint32 len = 0; + + while (size < *_length && !eof) { + RequestBuilder req(ProcCompound); + req.PutFH(fHandle); + req.Read(cookie->fStateId, cookie->fStateSeq, pos + size, + *_length - size); + + RPC::Reply *rpl; + fFilesystem->Server()->SendCall(req.Request(), &rpl); + ReplyInterpreter reply(rpl); + + status_t result; + result = reply.PutFH(); + if (result != B_OK) + return result; + + result = reply.Read(reinterpret_cast(buffer) + size, &len, &eof); + if (result != B_OK) + return result; + + size += len; + } + + *_length = size; + + return B_OK; +} + + status_t Inode::OpenDir(uint64* cookie) { diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 769a71a6a3..c75e197620 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -37,6 +37,8 @@ public: status_t Stat(struct stat* st); status_t Open(int mode, OpenFileCookie* cookie); + status_t Read(OpenFileCookie* cookie, off_t pos, + void* buffer, size_t* length); status_t OpenDir(uint64* cookie); status_t ReadDir(void* buffer, uint32 size, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index f53e0fd8cb..d9648a1cc5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -30,6 +30,7 @@ enum Opcode { OpOpenConfirm = 20, OpPutFH = 22, OpPutRootFH = 24, + OpRead = 25, OpReadDir = 26, OpSetClientID = 35, OpSetClientIDConfirm = 36 diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index dac46ce247..1c158ee38c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -164,6 +164,21 @@ ReplyInterpreter::OpenConfirm(uint32* stateSeq) } +status_t +ReplyInterpreter::Read(void* buffer, uint32* size, bool* eof) +{ + status_t res = _OperationError(OpRead); + if (res != B_OK) + return res; + + *eof = fReply->Stream().GetBoolean(); + const void* ptr = fReply->Stream().GetOpaque(size); + memcpy(buffer, ptr, *size); + + return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; +} + + status_t ReplyInterpreter::ReadDir(uint64* cookie, DirEntry** dirents, uint32* _count, bool* eof) diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 9a6f4188d4..c3d5395349 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -47,6 +47,7 @@ public: status_t OpenConfirm(uint32* stateSeq); inline status_t PutFH(); inline status_t PutRootFH(); + status_t Read(void* buffer, uint32* size, bool* eof); status_t ReadDir(uint64* cookie, DirEntry** dirents, uint32* count, bool* eof); status_t SetClientID(uint64* clientid, uint64* verifier); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 3ce7f2c98b..641a4fc80e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -205,6 +205,28 @@ RequestBuilder::PutRootFH() } +status_t +RequestBuilder::Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpRead); + fRequest->Stream().AddUInt(stateSeq); + fRequest->Stream().AddUInt(id[0]); + fRequest->Stream().AddUInt(id[1]); + fRequest->Stream().AddUInt(id[2]); + fRequest->Stream().AddUHyper(pos); + fRequest->Stream().AddUInt(len); + + fOpCount++; + + return B_OK; +} + + status_t RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs, uint32 attr_count) diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index e3b5d301eb..e2c89b4ec5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -33,6 +33,8 @@ public: uint32 stateSeq); status_t PutFH(const Filehandle& fh); status_t PutRootFH(); + status_t Read(const uint32* id, uint32 stateSeq, + uint64 pos, uint32 len); status_t ReadDir(uint32 count, uint64* cookie, Attribute* attrs, uint32 attr_count); status_t SetClientID(const RPC::Server* serv); diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index d9d3e355a1..ffdc7885da 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -156,6 +156,17 @@ nfs4_open(fs_volume* volume, fs_vnode* vnode, int openMode, void** _cookie) } +status_t +nfs4_read(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos, + void* buffer, size_t* length) +{ + Inode* inode = reinterpret_cast(vnode->private_node); + OpenFileCookie* cookie = reinterpret_cast(_cookie); + + return inode->Read(cookie, pos, buffer, length); +} + + static status_t nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie) { @@ -299,7 +310,7 @@ fs_vnode_ops gNFSv4VnodeOps = { nfs4_open, NULL, // close() NULL, // free_cookie() - NULL, // read() + nfs4_read, NULL, // write, /* directory operations */