ONC+ Developer's Guide

Memory Requirements for XDR Routines

When using XDR routines, there is sometimes a need to pre-allocate memory (or to determine memory requirements). In these instances where the developer needs to control the allocation and de-allocation of memory for XDR conversion routines to use there is a routine, xdr_sizeof(), that is used to return the number of bytes needed to encode and decode data using one of the XDR filter functions (func()). xdr_sizeof()'s output does not include RPC headers or record markers and they must be added in to get a complete accounting of the memory required. xdr_sizeof() returns a zero on error.

xdr_sizeof(xdrproc_t func, void *data)

xdr_sizeof() is specifically useful the allocation of memory in applications that use XDR outside of the RPC environment; to select between transport protocols; and at the lower levels of RPC to perform client and server creation functions.

Example A-5 and Example A-6 illustrate two uses of xdr_sizeof().


Example A-5 xdr_sizeof Example #1

#include <rpc/rpc.h>

/*
 *	This function takes as input a CLIENT handle, an XDR function
and
 *	a pointer to data to be XDR'd. It returns TRUE if the amount of
 *	data to be XDR'd may be sent using the transport associated
with
 *	the CLIENT handle, and false otherwise.
 */
bool_t
cansend(cl, xdrfunc, xdrdata)
	CLIENT *cl;
	xdrproc_t xdrfunc;
	void   *xdrdata;
{
	int fd;
	struct t_info tinfo;

	if (clnt_control(cl, CLGET_FD, &fd) == -1) {
		/* handle clnt_control() error */
		return (FALSE);
	}

	if (t_getinfo(fd, &tinfo) == -1) {
		/* handle t_getinfo() error */
		return (FALSE);
	} else {
		if (tinfo.servtype == T_CLTS) {
			/*
			 * This is a connectionless transport. Use xdr_sizeof()
			 * to compute the size of this request to see whether it
			 * is too large for this transport.
			 */
			switch(tinfo.tsdu) {
				case 0:                      /* no concept of TSDUs */
				case -2:                       /* can't send normal data */
					return (FALSE);
					break;
				case -1:                        /* no limit on TSDU size */
					return (TRUE);
					break;
				default:
					if (tinfo.tsdu < xdr_sizeof(xdrfunc, xdrdata))
						return (FALSE);
					else
						return (TRUE);
			}
		} else
			return (TRUE);
	}
}

Example A-6 is the second xdr_sizeof() example.


Example A-6 xdr_sizeof Example #2

#include <sys/statvfs.h>
#include <sys/sysmacros.h>

/*
 *	This function takes as input a file name, an XDR function, and
a
 *	pointer to data to be XDR'd. It returns TRUE if the filesystem
 *	on which the file resides has room for the additional amount
of
 *	data to be XDR'd. Note that since the information statvfs(2)
 *	returns about the filesystem is in blocks you must convert the
 *	value returned by xdr_sizeof() from bytes to disk blocks.
 */
bool_t
canwrite(file, xdrfunc, xdrdata)
	char	     *file;
	xdrproc_t xdrfunc;
	void     *xdrdata;
{
	struct statvfs s;

	if (statvfs(file, &s) == -1) {
		/* handle statvfs() error */
		return (FALSE);
	}

	if (s.f_bavail >= btod(xdr_sizeof(xdrfunc, xdrdata)))
		return (TRUE);
	else
		return (FALSE);
}