Update.
[glibc.git] / sunrpc / xdr.c
blob46dfe3b6b4bde53a902c51243b155939a8a8831d
1 /* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
2 /*
3 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4 * unrestricted use provided that this legend is included on all tape
5 * media and as a part of the software program in whole or part. Users
6 * may copy or modify Sun RPC without charge, but are not authorized
7 * to license or distribute it to anyone else except as part of a product or
8 * program developed by the user.
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California 94043
30 #if !defined(lint) && defined(SCCSIDS)
31 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
32 #endif
35 * xdr.c, Generic XDR routines implementation.
37 * Copyright (C) 1986, Sun Microsystems, Inc.
39 * These are the "generic" xdr routines used to serialize and de-serialize
40 * most common data items. See xdr.h for more info on the interface to
41 * xdr.
44 #include <stdio.h>
45 #include <limits.h>
46 #include <string.h>
48 #include <rpc/types.h>
49 #include <rpc/xdr.h>
52 * constants specific to the xdr "protocol"
54 #define XDR_FALSE ((long) 0)
55 #define XDR_TRUE ((long) 1)
56 #define LASTUNSIGNED ((u_int) 0-1)
59 * for unit alignment
61 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
64 * Free a data structure using XDR
65 * Not a filter, but a convenient utility nonetheless
67 void
68 xdr_free (xdrproc_t proc, char *objp)
70 XDR x;
72 x.x_op = XDR_FREE;
73 (*proc) (&x, objp);
77 * XDR nothing
79 bool_t
80 xdr_void (void)
82 return TRUE;
86 * XDR integers
88 bool_t
89 xdr_int (XDR *xdrs, int *ip)
92 #if INT_MAX < LONG_MAX
93 long l;
95 switch (xdrs->x_op)
97 case XDR_ENCODE:
98 l = (long) *ip;
99 return XDR_PUTLONG (xdrs, &l);
101 case XDR_DECODE:
102 if (!XDR_GETLONG (xdrs, &l))
104 return FALSE;
106 *ip = (int) l;
107 case XDR_FREE:
108 return TRUE;
110 return FALSE;
111 #elif INT_MAX == LONG_MAX
112 return xdr_long (xdrs, (long *) ip);
113 #elif INT_MAX == SHRT_MAX
114 return xdr_short (xdrs, (short *) ip);
115 #else
116 #error unexpected integer sizes in_xdr_int()
117 #endif
121 * XDR unsigned integers
123 bool_t
124 xdr_u_int (XDR *xdrs, u_int *up)
126 #if UINT_MAX < ULONG_MAX
127 u_long l;
129 switch (xdrs->x_op)
131 case XDR_ENCODE:
132 l = (u_long) * up;
133 return XDR_PUTLONG (xdrs, &l);
135 case XDR_DECODE:
136 if (!XDR_GETLONG (xdrs, &l))
138 return FALSE;
140 *up = (u_int) l;
141 case XDR_FREE:
142 return TRUE;
144 return FALSE;
145 #elif UINT_MAX == ULONG_MAX
146 return xdr_u_long (xdrs, (u_long *) up);
147 #elif UINT_MAX == USHRT_MAX
148 return xdr_short (xdrs, (short *) up);
149 #else
150 #error unexpected integer sizes in_xdr_u_int()
151 #endif
155 * XDR long integers
156 * The definition of xdr_long() is kept for backward
157 * compatibility. Instead xdr_int() should be used.
159 bool_t
160 xdr_long (XDR *xdrs, long *lp)
163 if (xdrs->x_op == XDR_ENCODE
164 && (sizeof (int32_t) == sizeof (long)
165 || (int32_t) *lp == *lp))
166 return XDR_PUTLONG (xdrs, lp);
168 if (xdrs->x_op == XDR_DECODE)
169 return XDR_GETLONG (xdrs, lp);
171 if (xdrs->x_op == XDR_FREE)
172 return TRUE;
174 return FALSE;
178 * XDR unsigned long integers
179 * The definition of xdr_u_long() is kept for backward
180 * compatibility. Instead xdr_u_int() should be used.
182 bool_t
183 xdr_u_long (XDR *xdrs, u_long *ulp)
185 switch (xdrs->x_op)
187 case XDR_DECODE:
189 long int tmp;
191 if (XDR_GETLONG (xdrs, &tmp) == FALSE)
192 return FALSE;
194 *ulp = (uint32_t) tmp;
195 return TRUE;
198 case XDR_ENCODE:
199 if (sizeof (uint32_t) != sizeof (u_long)
200 && (uint32_t) *ulp != *ulp)
201 return FALSE;
203 return XDR_PUTLONG (xdrs, (long *) ulp);
205 case XDR_FREE:
206 return TRUE;
208 return FALSE;
212 * XDR hyper integers
213 * same as xdr_u_hyper - open coded to save a proc call!
215 bool_t
216 xdr_hyper (XDR *xdrs, quad_t *llp)
218 long t1;
219 unsigned long int t2;
221 if (xdrs->x_op == XDR_ENCODE)
223 t1 = (long) ((*llp) >> 32);
224 t2 = (long) (*llp);
225 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
228 if (xdrs->x_op == XDR_DECODE)
230 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
231 return FALSE;
232 *llp = ((quad_t) t1) << 32;
233 *llp |= t2;
234 return TRUE;
237 if (xdrs->x_op == XDR_FREE)
238 return TRUE;
240 return FALSE;
245 * XDR hyper integers
246 * same as xdr_hyper - open coded to save a proc call!
248 bool_t
249 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
251 unsigned long t1;
252 unsigned long t2;
254 if (xdrs->x_op == XDR_ENCODE)
256 t1 = (unsigned long) ((*ullp) >> 32);
257 t2 = (unsigned long) (*ullp);
258 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
261 if (xdrs->x_op == XDR_DECODE)
263 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
264 return FALSE;
265 *ullp = ((u_quad_t) t1) << 32;
266 *ullp |= t2;
267 return TRUE;
270 if (xdrs->x_op == XDR_FREE)
271 return TRUE;
273 return FALSE;
276 bool_t
277 xdr_longlong_t (XDR *xdrs, quad_t *llp)
279 return xdr_hyper (xdrs, llp);
282 bool_t
283 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
285 return xdr_u_hyper (xdrs, ullp);
289 * XDR short integers
291 bool_t
292 xdr_short (XDR *xdrs, short *sp)
294 long l;
296 switch (xdrs->x_op)
298 case XDR_ENCODE:
299 l = (long) *sp;
300 return XDR_PUTLONG (xdrs, &l);
302 case XDR_DECODE:
303 if (!XDR_GETLONG (xdrs, &l))
305 return FALSE;
307 *sp = (short) l;
308 return TRUE;
310 case XDR_FREE:
311 return TRUE;
313 return FALSE;
317 * XDR unsigned short integers
319 bool_t
320 xdr_u_short (XDR *xdrs, u_short *usp)
322 u_long l;
324 switch (xdrs->x_op)
326 case XDR_ENCODE:
327 l = (u_long) * usp;
328 return XDR_PUTLONG (xdrs, &l);
330 case XDR_DECODE:
331 if (!XDR_GETLONG (xdrs, &l))
333 return FALSE;
335 *usp = (u_short) l;
336 return TRUE;
338 case XDR_FREE:
339 return TRUE;
341 return FALSE;
346 * XDR a char
348 bool_t
349 xdr_char (XDR *xdrs, char *cp)
351 int i;
353 i = (*cp);
354 if (!xdr_int (xdrs, &i))
356 return FALSE;
358 *cp = i;
359 return TRUE;
363 * XDR an unsigned char
365 bool_t
366 xdr_u_char (XDR *xdrs, u_char *cp)
368 u_int u;
370 u = (*cp);
371 if (!xdr_u_int (xdrs, &u))
373 return FALSE;
375 *cp = u;
376 return TRUE;
380 * XDR booleans
382 bool_t
383 xdr_bool (XDR *xdrs, bool_t *bp)
385 long lb;
387 switch (xdrs->x_op)
389 case XDR_ENCODE:
390 lb = *bp ? XDR_TRUE : XDR_FALSE;
391 return XDR_PUTLONG (xdrs, &lb);
393 case XDR_DECODE:
394 if (!XDR_GETLONG (xdrs, &lb))
396 return FALSE;
398 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
399 return TRUE;
401 case XDR_FREE:
402 return TRUE;
404 return FALSE;
408 * XDR enumerations
410 bool_t
411 xdr_enum (XDR *xdrs, enum_t *ep)
413 enum sizecheck
415 SIZEVAL
416 }; /* used to find the size of an enum */
419 * enums are treated as ints
421 if (sizeof (enum sizecheck) == 4)
423 #if INT_MAX < LONG_MAX
424 long l;
426 switch (xdrs->x_op)
428 case XDR_ENCODE:
429 l = *ep;
430 return XDR_PUTLONG (xdrs, &l);
432 case XDR_DECODE:
433 if (!XDR_GETLONG (xdrs, &l))
435 return FALSE;
437 *ep = l;
438 case XDR_FREE:
439 return TRUE;
442 return FALSE;
443 #else
444 return xdr_long (xdrs, (long *) ep);
445 #endif
447 else if (sizeof (enum sizecheck) == sizeof (short))
449 return xdr_short (xdrs, (short *) ep);
451 else
453 return FALSE;
458 * XDR opaque data
459 * Allows the specification of a fixed size sequence of opaque bytes.
460 * cp points to the opaque object and cnt gives the byte length.
462 bool_t
463 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
465 u_int rndup;
466 static char crud[BYTES_PER_XDR_UNIT];
469 * if no data we are done
471 if (cnt == 0)
472 return TRUE;
475 * round byte count to full xdr units
477 rndup = cnt % BYTES_PER_XDR_UNIT;
478 if (rndup > 0)
479 rndup = BYTES_PER_XDR_UNIT - rndup;
481 switch (xdrs->x_op)
483 case XDR_DECODE:
484 if (!XDR_GETBYTES (xdrs, cp, cnt))
486 return FALSE;
488 if (rndup == 0)
489 return TRUE;
490 return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
492 case XDR_ENCODE:
493 if (!XDR_PUTBYTES (xdrs, cp, cnt))
495 return FALSE;
497 if (rndup == 0)
498 return TRUE;
499 return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
501 case XDR_FREE:
502 return TRUE;
504 return FALSE;
508 * XDR counted bytes
509 * *cpp is a pointer to the bytes, *sizep is the count.
510 * If *cpp is NULL maxsize bytes are allocated
512 bool_t
513 xdr_bytes (xdrs, cpp, sizep, maxsize)
514 XDR *xdrs;
515 char **cpp;
516 u_int *sizep;
517 u_int maxsize;
519 char *sp = *cpp; /* sp is the actual string pointer */
520 u_int nodesize;
523 * first deal with the length since xdr bytes are counted
525 if (!xdr_u_int (xdrs, sizep))
527 return FALSE;
529 nodesize = *sizep;
530 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
532 return FALSE;
536 * now deal with the actual bytes
538 switch (xdrs->x_op)
540 case XDR_DECODE:
541 if (nodesize == 0)
543 return TRUE;
545 if (sp == NULL)
547 *cpp = sp = (char *) mem_alloc (nodesize);
549 if (sp == NULL)
551 (void) fprintf (stderr, "xdr_bytes: out of memory\n");
552 return FALSE;
554 /* fall into ... */
556 case XDR_ENCODE:
557 return xdr_opaque (xdrs, sp, nodesize);
559 case XDR_FREE:
560 if (sp != NULL)
562 mem_free (sp, nodesize);
563 *cpp = NULL;
565 return TRUE;
567 return FALSE;
571 * Implemented here due to commonality of the object.
573 bool_t
574 xdr_netobj (xdrs, np)
575 XDR *xdrs;
576 struct netobj *np;
579 return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
583 * XDR a discriminated union
584 * Support routine for discriminated unions.
585 * You create an array of xdrdiscrim structures, terminated with
586 * an entry with a null procedure pointer. The routine gets
587 * the discriminant value and then searches the array of xdrdiscrims
588 * looking for that value. It calls the procedure given in the xdrdiscrim
589 * to handle the discriminant. If there is no specific routine a default
590 * routine may be called.
591 * If there is no specific or default routine an error is returned.
593 bool_t
594 xdr_union (xdrs, dscmp, unp, choices, dfault)
595 XDR *xdrs;
596 enum_t *dscmp; /* enum to decide which arm to work on */
597 char *unp; /* the union itself */
598 const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
599 xdrproc_t dfault; /* default xdr routine */
601 enum_t dscm;
604 * we deal with the discriminator; it's an enum
606 if (!xdr_enum (xdrs, dscmp))
608 return FALSE;
610 dscm = *dscmp;
613 * search choices for a value that matches the discriminator.
614 * if we find one, execute the xdr routine for that value.
616 for (; choices->proc != NULL_xdrproc_t; choices++)
618 if (choices->value == dscm)
619 return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
623 * no match - execute the default xdr routine if there is one
625 return ((dfault == NULL_xdrproc_t) ? FALSE :
626 (*dfault) (xdrs, unp, LASTUNSIGNED));
631 * Non-portable xdr primitives.
632 * Care should be taken when moving these routines to new architectures.
637 * XDR null terminated ASCII strings
638 * xdr_string deals with "C strings" - arrays of bytes that are
639 * terminated by a NULL character. The parameter cpp references a
640 * pointer to storage; If the pointer is null, then the necessary
641 * storage is allocated. The last parameter is the max allowed length
642 * of the string as specified by a protocol.
644 bool_t
645 xdr_string (xdrs, cpp, maxsize)
646 XDR *xdrs;
647 char **cpp;
648 u_int maxsize;
650 char *sp = *cpp; /* sp is the actual string pointer */
651 u_int size;
652 u_int nodesize;
655 * first deal with the length since xdr strings are counted-strings
657 switch (xdrs->x_op)
659 case XDR_FREE:
660 if (sp == NULL)
662 return TRUE; /* already free */
664 /* fall through... */
665 case XDR_ENCODE:
666 if (sp == NULL)
667 return FALSE;
668 size = strlen (sp);
669 break;
670 case XDR_DECODE:
671 break;
673 if (!xdr_u_int (xdrs, &size))
675 return FALSE;
677 if (size > maxsize)
679 return FALSE;
681 nodesize = size + 1;
684 * now deal with the actual bytes
686 switch (xdrs->x_op)
688 case XDR_DECODE:
689 if (nodesize == 0)
691 return TRUE;
693 if (sp == NULL)
694 *cpp = sp = (char *) mem_alloc (nodesize);
695 if (sp == NULL)
697 (void) fprintf (stderr, "xdr_string: out of memory\n");
698 return FALSE;
700 sp[size] = 0;
701 /* fall into ... */
703 case XDR_ENCODE:
704 return xdr_opaque (xdrs, sp, size);
706 case XDR_FREE:
707 mem_free (sp, nodesize);
708 *cpp = NULL;
709 return TRUE;
711 return FALSE;
715 * Wrapper for xdr_string that can be called directly from
716 * routines like clnt_call
718 bool_t
719 xdr_wrapstring (xdrs, cpp)
720 XDR *xdrs;
721 char **cpp;
723 if (xdr_string (xdrs, cpp, LASTUNSIGNED))
725 return TRUE;
727 return FALSE;