#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
static struct xdr_ops *xdrmem_ops(void);
void
xdrmem_create(XDR *xdrs, caddr_t addr, uint_t size, enum xdr_op op)
{
xdrs->x_op = op;
xdrs->x_ops = xdrmem_ops();
xdrs->x_private = xdrs->x_base = addr;
xdrs->x_handy = size;
xdrs->x_public = NULL;
}
static void
xdrmem_destroy(XDR *xdrs)
{
}
static bool_t
xdrmem_getint32(XDR *xdrs, int32_t *int32p)
{
if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0)
return (FALSE);
*int32p = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private))));
xdrs->x_private += sizeof (int32_t);
return (TRUE);
}
static bool_t
xdrmem_putint32(XDR *xdrs, int32_t *int32p)
{
if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0)
return (FALSE);
*(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*int32p));
xdrs->x_private += sizeof (int32_t);
return (TRUE);
}
static bool_t
xdrmem_getbytes(XDR *xdrs, caddr_t addr, int len)
{
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
bcopy(xdrs->x_private, addr, len);
xdrs->x_private += len;
return (TRUE);
}
static bool_t
xdrmem_putbytes(XDR *xdrs, caddr_t addr, int len)
{
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
bcopy(addr, xdrs->x_private, len);
xdrs->x_private += len;
return (TRUE);
}
static uint_t
xdrmem_getpos(XDR *xdrs)
{
return ((uint_t)((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_base));
}
static bool_t
xdrmem_setpos(XDR *xdrs, uint_t pos)
{
caddr_t newaddr = xdrs->x_base + pos;
caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
ptrdiff_t diff;
if (newaddr > lastaddr)
return (FALSE);
xdrs->x_private = newaddr;
diff = lastaddr - newaddr;
xdrs->x_handy = (int)diff;
return (TRUE);
}
static rpc_inline_t *
xdrmem_inline(XDR *xdrs, int len)
{
rpc_inline_t *buf = NULL;
if (xdrs->x_handy >= len) {
xdrs->x_handy -= len;
buf = (rpc_inline_t *)xdrs->x_private;
xdrs->x_private += len;
}
return (buf);
}
static bool_t
xdrmem_control(XDR *xdrs, int request, void *info)
{
xdr_bytesrec *xptr;
int32_t *int32p;
int len;
switch (request) {
case XDR_GET_BYTES_AVAIL:
xptr = (xdr_bytesrec *)info;
xptr->xc_is_last_record = TRUE;
xptr->xc_num_avail = xdrs->x_handy;
return (TRUE);
case XDR_PEEK:
if (xdrs->x_handy < sizeof (int32_t))
return (FALSE);
int32p = (int32_t *)info;
*int32p = (int32_t)ntohl((uint32_t)
(*((int32_t *)(xdrs->x_private))));
return (TRUE);
case XDR_SKIPBYTES:
int32p = (int32_t *)info;
len = RNDUP((int)(*int32p));
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
xdrs->x_private += len;
return (TRUE);
}
return (FALSE);
}
static struct xdr_ops *
xdrmem_ops(void)
{
static struct xdr_ops ops;
if (ops.x_getint32 == NULL) {
ops.x_getbytes = xdrmem_getbytes;
ops.x_putbytes = xdrmem_putbytes;
ops.x_getpostn = xdrmem_getpos;
ops.x_setpostn = xdrmem_setpos;
ops.x_inline = xdrmem_inline;
ops.x_destroy = xdrmem_destroy;
ops.x_control = xdrmem_control;
ops.x_getint32 = xdrmem_getint32;
ops.x_putint32 = xdrmem_putint32;
}
return (&ops);
}