diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile b/src/add-ons/kernel/file_systems/nfs4/Jamfile index 7c16aa0e5c..bf19a10fc1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Jamfile +++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile @@ -5,4 +5,5 @@ UsePrivateHeaders kernel ; KernelAddon nfs4 : Connection.cpp kernel_interface.cpp + XDR.cpp ; diff --git a/src/add-ons/kernel/file_systems/nfs4/XDR.cpp b/src/add-ons/kernel/file_systems/nfs4/XDR.cpp new file mode 100644 index 0000000000..b5af847367 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/XDR.cpp @@ -0,0 +1,326 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include "XDR.h" + +#include +#include + +#include + + +using namespace XDR; + +Stream::Stream(void* buffer, uint32 size) + : + fBuffer(reinterpret_cast(buffer)), + fSize(size), + fPosition(0) +{ +} + + +Stream::~Stream() +{ +} + + +uint32 +Stream::_PositionToSize() const +{ + return fPosition * sizeof(uint32); +} + + +uint32 +Stream::_RealSize(uint32 size) const +{ + uint32 real_size = size; + if (real_size % 4 != 0) + real_size = ((real_size >> 2) + 1) << 2; + return real_size; +} + + +ReadStream::ReadStream(void* buffer, uint32 size) + : + Stream(buffer, size), + fEOF(false) +{ +} + + +ReadStream::~ReadStream() +{ +} + + +int32 +ReadStream::GetInt() +{ + if (_PositionToSize() >= fSize) { + fEOF = true; + return 0; + } + + return B_BENDIAN_TO_HOST_INT32(fBuffer[fPosition++]); +} + + +uint32 +ReadStream::GetUInt() +{ + if (_PositionToSize() >= fSize) { + fEOF = true; + return 0; + } + + return B_BENDIAN_TO_HOST_INT32(fBuffer[fPosition++]); +} + + +int64 +ReadStream::GetHyper() +{ + if (_PositionToSize() + sizeof(int64) > fSize) { + fEOF = true; + return 0; + } + + int64* ptr = reinterpret_cast(fBuffer + fPosition); + fPosition += 2; + + return B_BENDIAN_TO_HOST_INT64(*ptr); +} + + +uint64 +ReadStream::GetUHyper() +{ + if (_PositionToSize() + sizeof(uint64) > fSize) { + fEOF = true; + return 0; + } + + uint64* ptr = reinterpret_cast(fBuffer + fPosition); + fPosition += 2; + + return B_BENDIAN_TO_HOST_INT64(*ptr); +} + + +const char* +ReadStream::GetString() +{ + if (_PositionToSize() >= fSize) { + fEOF = true; + return NULL; + } + + uint32 size; + const void* ptr = GetOpaque(&size); + if (ptr == NULL) + return NULL; + + char* str = reinterpret_cast(malloc(size + 1)); + if (str == NULL) + return NULL; + + memcpy(str, ptr, size); + str[size] = 0; + + return str; +} + + +const void* +ReadStream::GetOpaque(uint32* size) +{ + if (_PositionToSize() >= fSize) { + fEOF = true; + return NULL; + } + + void* ptr = NULL; + uint32 s = GetUInt(); + if (s != 0) { + ptr = fBuffer + fPosition; + if (_PositionToSize() + s <= fSize) + fPosition += _RealSize(s) / sizeof(uint32); + else { + s = fSize - _PositionToSize(); + fPosition = fSize; + } + } + + if (size != NULL) + *size = s; + + return ptr; +} + + +WriteStream::WriteStream() + : + Stream(malloc(kInitialSize), kInitialSize), + fError(B_OK) +{ +} + + +WriteStream::WriteStream(const WriteStream& x) + : + Stream(malloc(x.fSize), x.fSize), + fError(x.fError) +{ + fPosition = x.fPosition; + memcpy(fBuffer, x.fBuffer, fSize); +} + + +WriteStream::~WriteStream() +{ + free(fBuffer); +} + + +status_t +WriteStream::InsertUInt(Stream::Position pos, uint32 x) +{ + if (pos * sizeof(uint32) >= fSize) { + fError = B_BAD_VALUE; + return B_BAD_VALUE; + } + + fBuffer[pos] = B_HOST_TO_BENDIAN_INT32(x); + return B_OK; +} + + +status_t +WriteStream::AddInt(int32 x) +{ + status_t err = _CheckResize(sizeof(int32)); + if (err != B_OK) + return err; + + fBuffer[fPosition++] = B_HOST_TO_BENDIAN_INT32(x); + return B_OK; +} + + +status_t +WriteStream::AddUInt(uint32 x) +{ + status_t err = _CheckResize(sizeof(uint32)); + if (err != B_OK) + return err; + + fBuffer[fPosition++] = B_HOST_TO_BENDIAN_INT32(x); + return B_OK; +} + + +status_t +WriteStream::AddHyper(int64 x) +{ + status_t err = _CheckResize(sizeof(int64)); + if (err != B_OK) + return err; + + int64* ptr = reinterpret_cast(fBuffer + fPosition); + *ptr = B_HOST_TO_BENDIAN_INT64(x); + fPosition += 2; + return B_OK; +} + + +status_t +WriteStream::AddUHyper(uint64 x) +{ + status_t err = _CheckResize(sizeof(uint64)); + if (err != B_OK) + return err; + + uint64* ptr = reinterpret_cast(fBuffer + fPosition); + *ptr = B_HOST_TO_BENDIAN_INT64(x); + fPosition += 2; + return B_OK; +} + + +status_t +WriteStream::AddString(const char* str, uint32 maxlen) +{ + uint32 len = strlen(str); + uint32 size = min_c(maxlen, len); + + return AddOpaque(str, size); +} + + +status_t +WriteStream::AddOpaque(const void *ptr, uint32 size) +{ + uint32 real_size = _RealSize(size); + status_t err = _CheckResize(real_size + sizeof(uint32)); + if (err != B_OK) + return err; + + AddUInt(size); + memset(fBuffer + fPosition, 0, real_size); + memcpy(fBuffer + fPosition, ptr, size); + fPosition += real_size / sizeof(int32); + + return B_OK; +} + + +status_t +WriteStream::AddOpaque(const WriteStream& stream) +{ + return AddOpaque(stream.GetBuffer(), stream.GetSize()); +} + + +status_t +WriteStream::Append(const WriteStream& stream) +{ + uint32 size = stream.GetSize(); + status_t err = _CheckResize(size); + if (err != B_OK) + return err; + + memcpy(fBuffer + fPosition, stream.GetBuffer(), size); + fPosition += size / sizeof(int32); + + return B_OK; +} + + +status_t +WriteStream::_CheckResize(uint32 size) +{ + if (_PositionToSize() + size <= fSize) + return B_OK; + + uint32 new_size = max_c(fSize * 2, fPosition * sizeof(uint32) + size); + + void* ptr = realloc(fBuffer, new_size); + if (ptr == NULL) { + fError = B_NO_MEMORY; + return B_NO_MEMORY; + } + + fBuffer = reinterpret_cast(ptr); + fSize = new_size; + + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/XDR.h b/src/add-ons/kernel/file_systems/nfs4/XDR.h new file mode 100644 index 0000000000..05bdaf2842 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/XDR.h @@ -0,0 +1,156 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef XDR_H +#define XDR_H + + +#include + + +namespace XDR { + +class Stream { +public: + typedef uint32 Position; + + virtual ~Stream(); + + inline const void* GetBuffer() const; + inline Position GetCurrent() const; + +protected: + Stream(void* buffer, uint32 size); + + inline uint32 _PositionToSize() const; + inline uint32 _RealSize(uint32 size) const; + + uint32* fBuffer; + uint32 fSize; + Position fPosition; +}; + +class ReadStream : public Stream { +public: + ReadStream(void* buffer, uint32 size); + virtual ~ReadStream(); + + inline int GetSize() const; + + int32 GetInt(); + uint32 GetUInt(); + int64 GetHyper(); + uint64 GetUHyper(); + + inline bool GetBoolean(); + + const char* GetString(); + + const void* GetOpaque(uint32* size); + + inline bool IsEOF() const; + +private: + bool fEOF; +}; + +class WriteStream : public Stream { +public: + WriteStream(); + WriteStream(const WriteStream& x); + virtual ~WriteStream(); + + inline int GetSize() const; + + status_t InsertUInt(Stream::Position pos, uint32 x); + + status_t AddInt(int32 x); + status_t AddUInt(uint32 x); + status_t AddHyper(int64 x); + status_t AddUHyper(uint64 x); + + inline status_t AddBoolean(bool x); + + status_t AddString(const char* str, uint32 maxlen); + + status_t AddOpaque(const void* ptr, uint32 size); + status_t AddOpaque(const WriteStream& stream); + + status_t Append(const WriteStream& stream); + + inline status_t GetError() const; + +private: + status_t _CheckResize(uint32 size); + + status_t fError; + + static const uint32 kInitialSize = 64; +}; + + +inline const void* +Stream::GetBuffer() const +{ + return fBuffer; +} + + +inline Stream::Position +Stream::GetCurrent() const +{ + return fPosition; +} + + +inline int +ReadStream::GetSize() const +{ + return fSize; +} + + +inline bool +ReadStream::IsEOF() const +{ + return fEOF; +} + + +inline bool +ReadStream::GetBoolean() +{ + return GetInt() != 0; +} + + +inline int +WriteStream::GetSize() const +{ + return fPosition * sizeof(uint32); +} + + +inline status_t +WriteStream::AddBoolean(bool x) +{ + return AddInt(static_cast(x)); +} + + +inline status_t +WriteStream::GetError() const +{ + return fError; +} + + +} // namespace XDR + + +#endif // XDR_H +