ONC+ Developer's Guide

64–Bit Considerations for rpcgen

In Example 3–27 proc is declared as type rpcproc_t. Formerly, RPC programs, versions, procedures, and ports were declared to be of type u_long. On a 32–bit machine, a u_long is a 4–byte quantity (as is an int); on a 64–bit system, a u_long is an 8-byte quantity. The data types rpcprog_t, rpcvers_t, rpc_proc_t, and rpcport_t, introduced in the Solaris 7 environment, should be used whenever possible in declaring RPC programs, versions, procedures, and ports in place of both u_long and long. These newer types provide backwards compatibility with 32–bit systems. They are guaranteed to be 4–byte quantities no matter which system rpcgen is run on. While rpcgen programs using u_long versions of programs, versions, and procedures can still run, they have different consequences on 32– and 64–bit machines. For that reason, replace them with the appropriate newer data types. In fact, avoid using long and u_long whenever possible.

Beginning with the Solaris 7 environment, source files created with rpcgen containing XDR routines use different inline macros depending on whether the code is to run on a 32–bit or 64–bit machine. Specifically, the source files will use the IXDR_GET_INT32() and IXDR_PUT_INT32() macros instead of IXDR_GETLONG() and IXDR_PUTLONG(). For example, if the rpcgen source file foo.x contains the following code, the resulting foo_xdr.c file ensures that the correct inline macro is used.

struct foo {
        char      c;
        int       i1;
        int       i2;
        int       i3;
        long      l;
        short     s;

#if defined(_LP64) || defined(_KERNEL)
	register int *buf; 

	register long *buf; 

  . . . 
 #if defined(_LP64) || defined(_KERNEL)

 	IXDR_PUT_INT32(buf, objp->i1);                         

	IXDR_PUT_INT32(buf, objp->i2);                         
	IXDR_PUT_INT32(buf, objp->i3);                         

	IXDR_PUT_INT32(buf, objp->l);                         

	IXDR_PUT_SHORT(buf, objp->s); 

	IXDR_PUT_LONG(buf, objp->i1);                         

	IXDR_PUT_LONG(buf, objp->i2);                         

	IXDR_PUT_LONG(buf, objp->i3);                         
	IXDR_PUT_LONG(buf, objp->l);                         

	IXDR_PUT_SHORT(buf, objp->s); 

The code declares buf to be either int or long, depending on whether the machine is 64–bit or 32–bit.

Currently, data types transported by using RPC are limited in size to 4-byte quantities (32 bits). The 8-byte long is provided to enable applications to make maximum use of 64–bit architecture. However, programmers should avoid using longs, and functions that use longs, such as x_putlong(), in favor of ints whenever possible. As noted previously, RPC programs, versions, procedures, and ports have their own dedicated types. xdr_long() fails if the data value is not between INT32_MIN and INT32_MAX. Also, the data could be truncated if inline macros such as IXDR_GET_LONG() and IXDR_PUT_LONG() are used. The same concerns apply to u_long variables. See also the xdr_long(3NSL) man page.