2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
25 * Sun Microsystems, Inc.
27 * Mountain View, California 94043
30 #if defined(LIBC_SCCS) && !defined(lint)
31 /*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
32 /*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/
33 static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr.c,v 1.9.2.1 2000/05/06 21:16:04 dec Exp $";
37 * xdr.c, Generic XDR routines implementation.
39 * Copyright (C) 1986, Sun Microsystems, Inc.
41 * These are the "generic" xdr routines used to serialize and de-serialize
42 * most common data items. See xdr.h for more info on the interface to
50 #include <rpc/types.h>
54 * constants specific to the xdr "protocol"
56 #define XDR_FALSE ((long) 0)
57 #define XDR_TRUE ((long) 1)
58 #define LASTUNSIGNED ((u_int) 0-1)
63 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
66 * Free a data structure using XDR
67 * Not a filter, but a convenient utility nonetheless
84 xdr_void(/* xdrs, addr */)
103 switch (xdrs->x_op) {
107 return (XDR_PUTLONG(xdrs, &l));
110 if (!XDR_GETLONG(xdrs, &l)) {
123 * XDR unsigned integers
132 switch (xdrs->x_op) {
136 return (XDR_PUTLONG(xdrs, (long *)&l));
139 if (!XDR_GETLONG(xdrs, (long *)&l)) {
154 * same as xdr_u_long - open coded to save a proc call!
161 switch (xdrs->x_op) {
163 return (XDR_PUTLONG(xdrs, lp));
165 return (XDR_GETLONG(xdrs, lp));
174 * XDR unsigned long integers
175 * same as xdr_long - open coded to save a proc call!
178 xdr_u_long(xdrs, ulp)
182 switch (xdrs->x_op) {
184 return (XDR_PUTLONG(xdrs, (long *)ulp));
186 return (XDR_GETLONG(xdrs, (long *)ulp));
195 * XDR 32-bit integers
196 * same as xdr_u_int32_t - open coded to save a proc call!
199 xdr_int32_t(xdrs, int32_p)
205 switch (xdrs->x_op) {
209 return (XDR_PUTLONG(xdrs, &l));
212 if (!XDR_GETLONG(xdrs, &l)) {
215 *int32_p = (int32_t) l;
225 * XDR unsigned 32-bit integers
226 * same as xdr_int32_t - open coded to save a proc call!
229 xdr_u_int32_t(xdrs, u_int32_p)
231 u_int32_t *u_int32_p;
235 switch (xdrs->x_op) {
238 l = (u_long) *u_int32_p;
239 return (XDR_PUTLONG(xdrs, (long *)&l));
242 if (!XDR_GETLONG(xdrs, (long *)&l)) {
245 *u_int32_p = (u_int32_t) l;
255 * XDR 64-bit integers
258 xdr_int64_t(xdrs, int64_p)
264 switch (xdrs->x_op) {
267 ul[0] = (u_long)((u_int64_t)*int64_p >> 32) & 0xffffffff;
268 ul[1] = (u_long)((u_int64_t)*int64_p) & 0xffffffff;
269 if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
271 return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
273 if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
275 if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
278 (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
287 * XDR unsigned 64-bit integers
290 xdr_u_int64_t(xdrs, uint64_p)
296 switch (xdrs->x_op) {
299 ul[0] = (u_long)(*uint64_p >> 32) & 0xffffffff;
300 ul[1] = (u_long)(*uint64_p) & 0xffffffff;
301 if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
303 return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
306 if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
308 if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
310 *uint64_p = (u_int64_t)
311 (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
330 switch (xdrs->x_op) {
334 return (XDR_PUTLONG(xdrs, &l));
337 if (!XDR_GETLONG(xdrs, &l)) {
350 * XDR unsigned short integers
353 xdr_u_short(xdrs, usp)
359 switch (xdrs->x_op) {
363 return (XDR_PUTLONG(xdrs, (long *)&l));
366 if (!XDR_GETLONG(xdrs, (long *)&l)) {
380 * XDR 16-bit integers
383 xdr_int16_t(xdrs, int16_p)
389 switch (xdrs->x_op) {
393 return (XDR_PUTLONG(xdrs, &l));
396 if (!XDR_GETLONG(xdrs, &l)) {
399 *int16_p = (int16_t) l;
409 * XDR unsigned 16-bit integers
412 xdr_u_int16_t(xdrs, u_int16_p)
414 u_int16_t *u_int16_p;
418 switch (xdrs->x_op) {
421 l = (u_long) *u_int16_p;
422 return (XDR_PUTLONG(xdrs, (long *)&l));
425 if (!XDR_GETLONG(xdrs, (long *)&l)) {
428 *u_int16_p = (u_int16_t) l;
449 if (!xdr_int(xdrs, &i)) {
457 * XDR an unsigned char
467 if (!xdr_u_int(xdrs, &u)) {
484 switch (xdrs->x_op) {
487 lb = *bp ? XDR_TRUE : XDR_FALSE;
488 return (XDR_PUTLONG(xdrs, &lb));
491 if (!XDR_GETLONG(xdrs, &lb)) {
494 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
512 enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
515 * enums are treated as ints
517 if (sizeof (enum sizecheck) == sizeof (long)) {
518 return (xdr_long(xdrs, (long *)ep));
519 } else if (sizeof (enum sizecheck) == sizeof (int)) {
520 return (xdr_int(xdrs, (int *)ep));
521 } else if (sizeof (enum sizecheck) == sizeof (short)) {
522 return (xdr_short(xdrs, (short *)ep));
527 (void) (xdr_short(xdrs, (short *)ep));
528 (void) (xdr_int(xdrs, (int *)ep));
529 return (xdr_long(xdrs, (long *)ep));
535 * Allows the specification of a fixed size sequence of opaque bytes.
536 * cp points to the opaque object and cnt gives the byte length.
539 xdr_opaque(xdrs, cp, cnt)
544 register u_int rndup;
545 static crud[BYTES_PER_XDR_UNIT];
548 * if no data we are done
554 * round byte count to full xdr units
556 rndup = cnt % BYTES_PER_XDR_UNIT;
558 rndup = BYTES_PER_XDR_UNIT - rndup;
560 if (xdrs->x_op == XDR_DECODE) {
561 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
566 return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
569 if (xdrs->x_op == XDR_ENCODE) {
570 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
575 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
578 if (xdrs->x_op == XDR_FREE) {
587 * *cpp is a pointer to the bytes, *sizep is the count.
588 * If *cpp is NULL maxsize bytes are allocated
591 xdr_bytes(xdrs, cpp, sizep, maxsize)
594 register u_int *sizep;
597 register char *sp = *cpp; /* sp is the actual string pointer */
598 register u_int nodesize;
601 * first deal with the length since xdr bytes are counted
603 if (! xdr_u_int(xdrs, sizep)) {
607 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
612 * now deal with the actual bytes
614 switch (xdrs->x_op) {
621 *cpp = sp = (char *)mem_alloc(nodesize);
624 (void) fprintf(stderr, "xdr_bytes: out of memory\n");
630 return (xdr_opaque(xdrs, sp, nodesize));
634 mem_free(sp, nodesize);
643 * Implemented here due to commonality of the object.
651 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
655 * XDR a descriminated union
656 * Support routine for discriminated unions.
657 * You create an array of xdrdiscrim structures, terminated with
658 * an entry with a null procedure pointer. The routine gets
659 * the discriminant value and then searches the array of xdrdiscrims
660 * looking for that value. It calls the procedure given in the xdrdiscrim
661 * to handle the discriminant. If there is no specific routine a default
662 * routine may be called.
663 * If there is no specific or default routine an error is returned.
666 xdr_union(xdrs, dscmp, unp, choices, dfault)
668 enum_t *dscmp; /* enum to decide which arm to work on */
669 char *unp; /* the union itself */
670 struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
671 xdrproc_t dfault; /* default xdr routine */
673 register enum_t dscm;
676 * we deal with the discriminator; it's an enum
678 if (! xdr_enum(xdrs, dscmp)) {
684 * search choices for a value that matches the discriminator.
685 * if we find one, execute the xdr routine for that value.
687 for (; choices->proc != NULL_xdrproc_t; choices++) {
688 if (choices->value == dscm)
689 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
693 * no match - execute the default xdr routine if there is one
695 return ((dfault == NULL_xdrproc_t) ? FALSE :
696 (*dfault)(xdrs, unp, LASTUNSIGNED));
701 * Non-portable xdr primitives.
702 * Care should be taken when moving these routines to new architectures.
707 * XDR null terminated ASCII strings
708 * xdr_string deals with "C strings" - arrays of bytes that are
709 * terminated by a NULL character. The parameter cpp references a
710 * pointer to storage; If the pointer is null, then the necessary
711 * storage is allocated. The last parameter is the max allowed length
712 * of the string as specified by a protocol.
715 xdr_string(xdrs, cpp, maxsize)
720 register char *sp = *cpp; /* sp is the actual string pointer */
725 * first deal with the length since xdr strings are counted-strings
727 switch (xdrs->x_op) {
730 return(TRUE); /* already free */
732 /* fall through... */
737 if (! xdr_u_int(xdrs, &size)) {
740 if (size > maxsize) {
746 * now deal with the actual bytes
748 switch (xdrs->x_op) {
755 *cpp = sp = (char *)mem_alloc(nodesize);
757 (void) fprintf(stderr, "xdr_string: out of memory\n");
764 return (xdr_opaque(xdrs, sp, size));
767 mem_free(sp, nodesize);
775 * Wrapper for xdr_string that can be called directly from
776 * routines like clnt_call
779 xdr_wrapstring(xdrs, cpp)
783 return xdr_string(xdrs, cpp, LASTUNSIGNED);