ONC+ Developer's Guide

64-bit Considerations for rpcgen

Note that 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 four-byte quantity (as is an int); on a 64-bit system, a u_long is an eight-byte quantity. The data types rpcprog_t, rpcvers_t, rpc_proc_t, and rpcport_t - introduced in Solaris 7 - should be used whenever possible in declaring RPC programs, versions, procedures, and ports in place of both u_long and long. The reason is that these newer types provide backwards compatibility with 32-bit systems; they're guaranteed to be four-byte quantities no matter which system rpcgen is run on. While rpcgenprograms using u_longversions of programs, versions, and procedures will still run, they may have different consequences on 32- and 64-bit machines. For that reason it is a good idea to replace them with the appropriate newer data types. In fact, it is a good idea to avoid using long and u_long whenever possible (see the note below).

Beginning with Solaris 7, source files created byrpcgen, containing XDR routines, use different inline macros depending on whether the code is to run on a 32- or 64-bit machine - specifically, it uses 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

struct foo {
        char      c;
        int       i1;
        int       i2;
        int       i3;
        long      l;
        short     s;
};
the resulting foo_xdr.c file will ensure that the correct inline macro is used:
#if defined(_LP64) || defined(_KERNEL)
        register int *buf;
#else
        register long *buf;
#endif

. . .

#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);
#else
                        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);
#endif
Note that the code declares buf to be either int or long, depending on whether the machine is 64- or 32-bit.


Note -

Currently, data types transported via RPC are limited in size to four-byte quantities (32 bits). The eight-byte long is provided to allow 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 above, RPC programs, versions, procedures, and ports have their own dedicated types.) The reason is that xdr_long() will fail if the data value is not between INT32_MIN and INT32_MAX - or the data could be truncated if inline macros such as IXDR_GET_LONG() and IXDR_PUT_LONG() are used. (The same applies for u_longs.) See also the xdr_long(3NSL) man page.