SUNRPC: Add helpers for decoding opaque and string types

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
Trond Myklebust 2018-03-20 17:03:05 -04:00 committed by Anna Schumaker
parent d943f2dd8d
commit 0e779aa703
2 changed files with 88 additions and 0 deletions

View File

@ -253,6 +253,12 @@ xdr_stream_remaining(const struct xdr_stream *xdr)
return xdr->nwords << 2;
}
ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr,
size_t size);
ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr,
size_t maxlen, gfp_t gfp_flags);
ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str,
size_t size);
ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str,
size_t maxlen, gfp_t gfp_flags);
/**

View File

@ -1518,6 +1518,88 @@ out:
}
EXPORT_SYMBOL_GPL(xdr_process_buf);
/**
* xdr_stream_decode_opaque - Decode variable length opaque
* @xdr: pointer to xdr_stream
* @ptr: location to store opaque data
* @size: size of storage buffer @ptr
*
* Return values:
* On success, returns size of object stored in *@ptr
* %-EBADMSG on XDR buffer overflow
* %-EMSGSIZE on overflow of storage buffer @ptr
*/
ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr, size_t size)
{
ssize_t ret;
void *p;
ret = xdr_stream_decode_opaque_inline(xdr, &p, size);
if (ret <= 0)
return ret;
memcpy(ptr, p, ret);
return ret;
}
EXPORT_SYMBOL_GPL(xdr_stream_decode_opaque);
/**
* xdr_stream_decode_opaque_dup - Decode and duplicate variable length opaque
* @xdr: pointer to xdr_stream
* @ptr: location to store pointer to opaque data
* @maxlen: maximum acceptable object size
* @gfp_flags: GFP mask to use
*
* Return values:
* On success, returns size of object stored in *@ptr
* %-EBADMSG on XDR buffer overflow
* %-EMSGSIZE if the size of the object would exceed @maxlen
* %-ENOMEM on memory allocation failure
*/
ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr,
size_t maxlen, gfp_t gfp_flags)
{
ssize_t ret;
void *p;
ret = xdr_stream_decode_opaque_inline(xdr, &p, maxlen);
if (ret > 0) {
*ptr = kmemdup(p, ret, gfp_flags);
if (*ptr != NULL)
return ret;
ret = -ENOMEM;
}
*ptr = NULL;
return ret;
}
EXPORT_SYMBOL_GPL(xdr_stream_decode_opaque_dup);
/**
* xdr_stream_decode_string - Decode variable length string
* @xdr: pointer to xdr_stream
* @str: location to store string
* @size: size of storage buffer @str
*
* Return values:
* On success, returns length of NUL-terminated string stored in *@str
* %-EBADMSG on XDR buffer overflow
* %-EMSGSIZE on overflow of storage buffer @str
*/
ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str, size_t size)
{
ssize_t ret;
void *p;
ret = xdr_stream_decode_opaque_inline(xdr, &p, size);
if (ret > 0) {
memcpy(str, p, ret);
str[ret] = '\0';
return strlen(str);
}
*str = '\0';
return ret;
}
EXPORT_SYMBOL_GPL(xdr_stream_decode_string);
/**
* xdr_stream_decode_string_dup - Decode and duplicate variable length string
* @xdr: pointer to xdr_stream