nfs4: Add NFS4 reply interpreter
Currently supported operations are: ACCESS, GETATTR (partially), GETFH, LOOKUP and PUTROOTFH.
This commit is contained in:
@@ -5,6 +5,7 @@ UsePrivateHeaders kernel ;
|
|||||||
KernelAddon nfs4 :
|
KernelAddon nfs4 :
|
||||||
Connection.cpp
|
Connection.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
|
ReplyInterpreter.cpp
|
||||||
RequestBuilder.cpp
|
RequestBuilder.cpp
|
||||||
RPCAuth.cpp
|
RPCAuth.cpp
|
||||||
RPCCall.cpp
|
RPCCall.cpp
|
||||||
|
|||||||
@@ -9,6 +9,13 @@
|
|||||||
#define NFS4DEFS_H
|
#define NFS4DEFS_H
|
||||||
|
|
||||||
|
|
||||||
|
#define NFS4_FHSIZE 128
|
||||||
|
|
||||||
|
struct Filehandle {
|
||||||
|
uint8 fSize;
|
||||||
|
uint8 fFH[NFS4_FHSIZE];
|
||||||
|
};
|
||||||
|
|
||||||
enum Procedure {
|
enum Procedure {
|
||||||
ProcNull = 0,
|
ProcNull = 0,
|
||||||
ProcCompound = 1
|
ProcCompound = 1
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ReplyInterpreter.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <util/kernel_cpp.h>
|
||||||
|
|
||||||
|
|
||||||
|
ReplyInterpreter::ReplyInterpreter(RPC::Reply* reply)
|
||||||
|
:
|
||||||
|
fReply(reply)
|
||||||
|
{
|
||||||
|
fReply->Stream().GetUInt();
|
||||||
|
fReply->Stream().GetOpaque(NULL);
|
||||||
|
fReply->Stream().GetUInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReplyInterpreter::~ReplyInterpreter()
|
||||||
|
{
|
||||||
|
delete fReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::Access(uint32* supported, uint32* allowed)
|
||||||
|
{
|
||||||
|
status_t res = _OperationError(OpAccess);
|
||||||
|
if (res != B_OK)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
uint32 support = fReply->Stream().GetUInt();
|
||||||
|
uint32 allow = fReply->Stream().GetUInt();
|
||||||
|
|
||||||
|
if (supported != NULL)
|
||||||
|
*supported = support;
|
||||||
|
if (allowed != NULL)
|
||||||
|
*allowed = allow;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Bit Twiddling Hacks
|
||||||
|
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||||
|
static inline uint32 sCountBits(uint32 v)
|
||||||
|
{
|
||||||
|
v = v - ((v >> 1) & 0x55555555);
|
||||||
|
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||||
|
return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool sIsAttrSet(Attribute attr, uint32* bitmap, uint32 count)
|
||||||
|
{
|
||||||
|
if ((uint32)attr / 32 >= count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (bitmap[attr / 32] & 1 << attr % 32) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::GetAttr(AttrValue** attrs, uint32* count)
|
||||||
|
{
|
||||||
|
status_t res = _OperationError(OpGetAttr);
|
||||||
|
if (res != B_OK)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
uint32 bcount = fReply->Stream().GetUInt();
|
||||||
|
uint32 *bitmap = new(std::nothrow) uint32[bcount];
|
||||||
|
if (bitmap == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
uint32 attr_count = 0;
|
||||||
|
for (uint32 i = 0; i < bcount; i++) {
|
||||||
|
bitmap[i] = fReply->Stream().GetUInt();
|
||||||
|
attr_count = sCountBits(bitmap[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 size;
|
||||||
|
const void* ptr = fReply->Stream().GetOpaque(&size);
|
||||||
|
XDR::ReadStream stream(const_cast<void*>(ptr), size);
|
||||||
|
|
||||||
|
AttrValue* values = new(std::nothrow) AttrValue[attr_count];
|
||||||
|
if (values == NULL) {
|
||||||
|
delete bitmap;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 current = 0;
|
||||||
|
|
||||||
|
if (sIsAttrSet(FATTR4_TYPE, bitmap, bcount)) {
|
||||||
|
values[current].fAttribute = FATTR4_TYPE;
|
||||||
|
values[current].fData.fValue32 = stream.GetInt();
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sIsAttrSet(FATTR4_FH_EXPIRE_TYPE, bitmap, bcount)) {
|
||||||
|
values[current].fAttribute = FATTR4_FH_EXPIRE_TYPE;
|
||||||
|
values[current].fData.fValue32 = stream.GetUInt();
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sIsAttrSet(FATTR4_FILEID, bitmap, bcount)) {
|
||||||
|
values[current].fAttribute = FATTR4_FILEID;
|
||||||
|
values[current].fData.fValue64 = stream.GetUHyper();
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete bitmap;
|
||||||
|
|
||||||
|
*count = attr_count;
|
||||||
|
*attrs = values;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::GetFH(Filehandle* fh)
|
||||||
|
{
|
||||||
|
status_t res = _OperationError(OpGetFH);
|
||||||
|
if (res != B_OK)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
uint32 size;
|
||||||
|
const void* ptr = fReply->Stream().GetOpaque(&size);
|
||||||
|
if (ptr == NULL || size > NFS4_FHSIZE)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (fh != NULL) {
|
||||||
|
fh->fSize = size;
|
||||||
|
memcpy(fh->fFH, ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::_OperationError(Opcode op)
|
||||||
|
{
|
||||||
|
if (fReply->Error() != B_OK || fReply->Stream().IsEOF())
|
||||||
|
return fReply->Error();
|
||||||
|
|
||||||
|
if (fReply->Stream().GetInt() != op)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return _NFS4ErrorToHaiku(fReply->Stream().GetUInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::_NFS4ErrorToHaiku(uint32 x)
|
||||||
|
{
|
||||||
|
switch (x) {
|
||||||
|
case NFS4_OK: return B_OK;
|
||||||
|
case NFS4ERR_PERM: return B_PERMISSION_DENIED;
|
||||||
|
case NFS4ERR_NOENT: return B_ENTRY_NOT_FOUND;
|
||||||
|
case NFS4ERR_IO: return B_IO_ERROR;
|
||||||
|
case NFS4ERR_NXIO: return B_DEVICE_NOT_FOUND;
|
||||||
|
case NFS4ERR_ACCESS: return B_PERMISSION_DENIED;
|
||||||
|
case NFS4ERR_EXIST: return B_FILE_EXISTS;
|
||||||
|
case NFS4ERR_XDEV: return B_CROSS_DEVICE_LINK;
|
||||||
|
case NFS4ERR_NOTDIR: return B_NOT_A_DIRECTORY;
|
||||||
|
case NFS4ERR_ISDIR: return B_IS_A_DIRECTORY;
|
||||||
|
case NFS4ERR_INVAL: return B_BAD_VALUE;
|
||||||
|
case NFS4ERR_FBIG: return B_FILE_TOO_LARGE;
|
||||||
|
// ...
|
||||||
|
default: return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef REPLYINTERPRETER_H
|
||||||
|
#define REPLYINTERPRETER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include "NFS4Defs.h"
|
||||||
|
#include "RPCReply.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct AttrValue {
|
||||||
|
uint8 fAttribute;
|
||||||
|
union {
|
||||||
|
uint32 fValue32;
|
||||||
|
uint64 fValue64;
|
||||||
|
void* fPointer;
|
||||||
|
} fData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReplyInterpreter {
|
||||||
|
public:
|
||||||
|
ReplyInterpreter(RPC::Reply* reply);
|
||||||
|
~ReplyInterpreter();
|
||||||
|
|
||||||
|
status_t Access(uint32* supported, uint32* allowed);
|
||||||
|
status_t GetAttr(AttrValue** attrs, uint32* count);
|
||||||
|
status_t GetFH(Filehandle* fh);
|
||||||
|
inline status_t LookUp();
|
||||||
|
inline status_t PutRootFH();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _OperationError(Opcode op);
|
||||||
|
|
||||||
|
static status_t _NFS4ErrorToHaiku(uint32 x);
|
||||||
|
|
||||||
|
RPC::Reply* fReply;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
ReplyInterpreter::LookUp()
|
||||||
|
{
|
||||||
|
return _OperationError(OpLookUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
ReplyInterpreter::PutRootFH()
|
||||||
|
{
|
||||||
|
return _OperationError(OpPutRootFH);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // REPLYINTERPRETER_H
|
||||||
|
|
||||||
Reference in New Issue
Block a user