8a70d2e557be5fb823fb7af2c077f528b6a6e3e3
[platform/upstream/glibc.git] / sunrpc / xdr.c
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.
9  *
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.
13  *
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.
17  *
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.
21  *
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.
25  *
26  * Sun Microsystems, Inc.
27  * 2550 Garcia Avenue
28  * Mountain View, California  94043
29  */
30 #if !defined(lint) && defined(SCCSIDS)
31 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
32 #endif
33
34 /*
35  * xdr.c, Generic XDR routines implementation.
36  *
37  * Copyright (C) 1986, Sun Microsystems, Inc.
38  *
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.
42  */
43
44 #include <stdio.h>
45 #include <limits.h>
46 #include <string.h>
47 #include <libintl.h>
48
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51
52 #ifdef USE_IN_LIBIO
53 # include <wchar.h>
54 #endif
55
56 /*
57  * constants specific to the xdr "protocol"
58  */
59 #define XDR_FALSE       ((long) 0)
60 #define XDR_TRUE        ((long) 1)
61 #define LASTUNSIGNED    ((u_int) 0-1)
62
63 /*
64  * for unit alignment
65  */
66 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
67
68 /*
69  * Free a data structure using XDR
70  * Not a filter, but a convenient utility nonetheless
71  */
72 void
73 xdr_free (xdrproc_t proc, char *objp)
74 {
75   XDR x;
76
77   x.x_op = XDR_FREE;
78   (*proc) (&x, objp);
79 }
80
81 /*
82  * XDR nothing
83  */
84 bool_t
85 xdr_void (void)
86 {
87   return TRUE;
88 }
89 INTDEF(xdr_void)
90
91 /*
92  * XDR integers
93  */
94 bool_t
95 xdr_int (XDR *xdrs, int *ip)
96 {
97
98 #if INT_MAX < LONG_MAX
99   long l;
100
101   switch (xdrs->x_op)
102     {
103     case XDR_ENCODE:
104       l = (long) *ip;
105       return XDR_PUTLONG (xdrs, &l);
106
107     case XDR_DECODE:
108       if (!XDR_GETLONG (xdrs, &l))
109         {
110           return FALSE;
111         }
112       *ip = (int) l;
113     case XDR_FREE:
114       return TRUE;
115     }
116   return FALSE;
117 #elif INT_MAX == LONG_MAX
118   return INTUSE(xdr_long) (xdrs, (long *) ip);
119 #elif INT_MAX == SHRT_MAX
120   return INTUSE(xdr_short) (xdrs, (short *) ip);
121 #else
122 #error unexpected integer sizes in_xdr_int()
123 #endif
124 }
125 INTDEF(xdr_int)
126
127 /*
128  * XDR unsigned integers
129  */
130 bool_t
131 xdr_u_int (XDR *xdrs, u_int *up)
132 {
133 #if UINT_MAX < ULONG_MAX
134   long l;
135
136   switch (xdrs->x_op)
137     {
138     case XDR_ENCODE:
139       l = (u_long) * up;
140       return XDR_PUTLONG (xdrs, &l);
141
142     case XDR_DECODE:
143       if (!XDR_GETLONG (xdrs, &l))
144         {
145           return FALSE;
146         }
147       *up = (u_int) (u_long) l;
148     case XDR_FREE:
149       return TRUE;
150     }
151   return FALSE;
152 #elif UINT_MAX == ULONG_MAX
153   return INTUSE(xdr_u_long) (xdrs, (u_long *) up);
154 #elif UINT_MAX == USHRT_MAX
155   return INTUSE(xdr_short) (xdrs, (short *) up);
156 #else
157 #error unexpected integer sizes in_xdr_u_int()
158 #endif
159 }
160 INTDEF(xdr_u_int)
161
162 /*
163  * XDR long integers
164  * The definition of xdr_long() is kept for backward
165  * compatibility. Instead xdr_int() should be used.
166  */
167 bool_t
168 xdr_long (XDR *xdrs, long *lp)
169 {
170
171   if (xdrs->x_op == XDR_ENCODE
172       && (sizeof (int32_t) == sizeof (long)
173           || (int32_t) *lp == *lp))
174     return XDR_PUTLONG (xdrs, lp);
175
176   if (xdrs->x_op == XDR_DECODE)
177     return XDR_GETLONG (xdrs, lp);
178
179   if (xdrs->x_op == XDR_FREE)
180     return TRUE;
181
182   return FALSE;
183 }
184 INTDEF(xdr_long)
185
186 /*
187  * XDR unsigned long integers
188  * The definition of xdr_u_long() is kept for backward
189  * compatibility. Instead xdr_u_int() should be used.
190  */
191 bool_t
192 xdr_u_long (XDR *xdrs, u_long *ulp)
193 {
194   switch (xdrs->x_op)
195     {
196     case XDR_DECODE:
197       {
198         long int tmp;
199
200         if (XDR_GETLONG (xdrs, &tmp) == FALSE)
201           return FALSE;
202
203         *ulp = (uint32_t) tmp;
204         return TRUE;
205       }
206
207     case XDR_ENCODE:
208       if (sizeof (uint32_t) != sizeof (u_long)
209           && (uint32_t) *ulp != *ulp)
210         return FALSE;
211
212       return XDR_PUTLONG (xdrs, (long *) ulp);
213
214     case XDR_FREE:
215       return TRUE;
216     }
217   return FALSE;
218 }
219 INTDEF(xdr_u_long)
220
221 /*
222  * XDR hyper integers
223  * same as xdr_u_hyper - open coded to save a proc call!
224  */
225 bool_t
226 xdr_hyper (XDR *xdrs, quad_t *llp)
227 {
228   long int t1, t2;
229
230   if (xdrs->x_op == XDR_ENCODE)
231     {
232       t1 = (long) ((*llp) >> 32);
233       t2 = (long) (*llp);
234       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
235     }
236
237   if (xdrs->x_op == XDR_DECODE)
238     {
239       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
240         return FALSE;
241       *llp = ((quad_t) t1) << 32;
242       *llp |= (uint32_t) t2;
243       return TRUE;
244     }
245
246   if (xdrs->x_op == XDR_FREE)
247     return TRUE;
248
249   return FALSE;
250 }
251 INTDEF(xdr_hyper)
252
253
254 /*
255  * XDR hyper integers
256  * same as xdr_hyper - open coded to save a proc call!
257  */
258 bool_t
259 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
260 {
261   long int t1, t2;
262
263   if (xdrs->x_op == XDR_ENCODE)
264     {
265       t1 = (unsigned long) ((*ullp) >> 32);
266       t2 = (unsigned long) (*ullp);
267       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
268     }
269
270   if (xdrs->x_op == XDR_DECODE)
271     {
272       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
273         return FALSE;
274       *ullp = ((u_quad_t) t1) << 32;
275       *ullp |= (uint32_t) t2;
276       return TRUE;
277     }
278
279   if (xdrs->x_op == XDR_FREE)
280     return TRUE;
281
282   return FALSE;
283 }
284 INTDEF(xdr_u_hyper)
285
286 bool_t
287 xdr_longlong_t (XDR *xdrs, quad_t *llp)
288 {
289   return INTUSE(xdr_hyper) (xdrs, llp);
290 }
291
292 bool_t
293 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
294 {
295   return INTUSE(xdr_u_hyper) (xdrs, ullp);
296 }
297
298 /*
299  * XDR short integers
300  */
301 bool_t
302 xdr_short (XDR *xdrs, short *sp)
303 {
304   long l;
305
306   switch (xdrs->x_op)
307     {
308     case XDR_ENCODE:
309       l = (long) *sp;
310       return XDR_PUTLONG (xdrs, &l);
311
312     case XDR_DECODE:
313       if (!XDR_GETLONG (xdrs, &l))
314         {
315           return FALSE;
316         }
317       *sp = (short) l;
318       return TRUE;
319
320     case XDR_FREE:
321       return TRUE;
322     }
323   return FALSE;
324 }
325 INTDEF(xdr_short)
326
327 /*
328  * XDR unsigned short integers
329  */
330 bool_t
331 xdr_u_short (XDR *xdrs, u_short *usp)
332 {
333   long l;
334
335   switch (xdrs->x_op)
336     {
337     case XDR_ENCODE:
338       l = (u_long) * usp;
339       return XDR_PUTLONG (xdrs, &l);
340
341     case XDR_DECODE:
342       if (!XDR_GETLONG (xdrs, &l))
343         {
344           return FALSE;
345         }
346       *usp = (u_short) (u_long) l;
347       return TRUE;
348
349     case XDR_FREE:
350       return TRUE;
351     }
352   return FALSE;
353 }
354 INTDEF(xdr_u_short)
355
356
357 /*
358  * XDR a char
359  */
360 bool_t
361 xdr_char (XDR *xdrs, char *cp)
362 {
363   int i;
364
365   i = (*cp);
366   if (!INTUSE(xdr_int) (xdrs, &i))
367     {
368       return FALSE;
369     }
370   *cp = i;
371   return TRUE;
372 }
373
374 /*
375  * XDR an unsigned char
376  */
377 bool_t
378 xdr_u_char (XDR *xdrs, u_char *cp)
379 {
380   u_int u;
381
382   u = (*cp);
383   if (!INTUSE(xdr_u_int) (xdrs, &u))
384     {
385       return FALSE;
386     }
387   *cp = u;
388   return TRUE;
389 }
390
391 /*
392  * XDR booleans
393  */
394 bool_t
395 xdr_bool (XDR *xdrs, bool_t *bp)
396 {
397   long lb;
398
399   switch (xdrs->x_op)
400     {
401     case XDR_ENCODE:
402       lb = *bp ? XDR_TRUE : XDR_FALSE;
403       return XDR_PUTLONG (xdrs, &lb);
404
405     case XDR_DECODE:
406       if (!XDR_GETLONG (xdrs, &lb))
407         {
408           return FALSE;
409         }
410       *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
411       return TRUE;
412
413     case XDR_FREE:
414       return TRUE;
415     }
416   return FALSE;
417 }
418 INTDEF(xdr_bool)
419
420 /*
421  * XDR enumerations
422  */
423 bool_t
424 xdr_enum (XDR *xdrs, enum_t *ep)
425 {
426   enum sizecheck
427     {
428       SIZEVAL
429     };                          /* used to find the size of an enum */
430
431   /*
432    * enums are treated as ints
433    */
434   if (sizeof (enum sizecheck) == 4)
435     {
436 #if INT_MAX < LONG_MAX
437       long l;
438
439       switch (xdrs->x_op)
440         {
441         case XDR_ENCODE:
442           l = *ep;
443           return XDR_PUTLONG (xdrs, &l);
444
445         case XDR_DECODE:
446           if (!XDR_GETLONG (xdrs, &l))
447             {
448               return FALSE;
449             }
450           *ep = l;
451         case XDR_FREE:
452           return TRUE;
453
454         }
455       return FALSE;
456 #else
457       return INTUSE(xdr_long) (xdrs, (long *) ep);
458 #endif
459     }
460   else if (sizeof (enum sizecheck) == sizeof (short))
461     {
462       return INTUSE(xdr_short) (xdrs, (short *) ep);
463     }
464   else
465     {
466       return FALSE;
467     }
468 }
469 INTDEF(xdr_enum)
470
471 /*
472  * XDR opaque data
473  * Allows the specification of a fixed size sequence of opaque bytes.
474  * cp points to the opaque object and cnt gives the byte length.
475  */
476 bool_t
477 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
478 {
479   u_int rndup;
480   static char crud[BYTES_PER_XDR_UNIT];
481
482   /*
483    * if no data we are done
484    */
485   if (cnt == 0)
486     return TRUE;
487
488   /*
489    * round byte count to full xdr units
490    */
491   rndup = cnt % BYTES_PER_XDR_UNIT;
492   if (rndup > 0)
493     rndup = BYTES_PER_XDR_UNIT - rndup;
494
495   switch (xdrs->x_op)
496     {
497     case XDR_DECODE:
498       if (!XDR_GETBYTES (xdrs, cp, cnt))
499         {
500           return FALSE;
501         }
502       if (rndup == 0)
503         return TRUE;
504       return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
505
506     case XDR_ENCODE:
507       if (!XDR_PUTBYTES (xdrs, cp, cnt))
508         {
509           return FALSE;
510         }
511       if (rndup == 0)
512         return TRUE;
513       return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
514
515     case XDR_FREE:
516       return TRUE;
517     }
518   return FALSE;
519 }
520 INTDEF(xdr_opaque)
521
522 /*
523  * XDR counted bytes
524  * *cpp is a pointer to the bytes, *sizep is the count.
525  * If *cpp is NULL maxsize bytes are allocated
526  */
527 bool_t
528 xdr_bytes (xdrs, cpp, sizep, maxsize)
529      XDR *xdrs;
530      char **cpp;
531      u_int *sizep;
532      u_int maxsize;
533 {
534   char *sp = *cpp;      /* sp is the actual string pointer */
535   u_int nodesize;
536
537   /*
538    * first deal with the length since xdr bytes are counted
539    */
540   if (!INTUSE(xdr_u_int) (xdrs, sizep))
541     {
542       return FALSE;
543     }
544   nodesize = *sizep;
545   if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
546     {
547       return FALSE;
548     }
549
550   /*
551    * now deal with the actual bytes
552    */
553   switch (xdrs->x_op)
554     {
555     case XDR_DECODE:
556       if (nodesize == 0)
557         {
558           return TRUE;
559         }
560       if (sp == NULL)
561         {
562           *cpp = sp = (char *) mem_alloc (nodesize);
563         }
564       if (sp == NULL)
565         {
566           (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
567           return FALSE;
568         }
569       /* fall into ... */
570
571     case XDR_ENCODE:
572       return INTUSE(xdr_opaque) (xdrs, sp, nodesize);
573
574     case XDR_FREE:
575       if (sp != NULL)
576         {
577           mem_free (sp, nodesize);
578           *cpp = NULL;
579         }
580       return TRUE;
581     }
582   return FALSE;
583 }
584 INTDEF(xdr_bytes)
585
586 /*
587  * Implemented here due to commonality of the object.
588  */
589 bool_t
590 xdr_netobj (xdrs, np)
591      XDR *xdrs;
592      struct netobj *np;
593 {
594
595   return INTUSE(xdr_bytes) (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
596 }
597 INTDEF(xdr_netobj)
598
599 /*
600  * XDR a discriminated union
601  * Support routine for discriminated unions.
602  * You create an array of xdrdiscrim structures, terminated with
603  * an entry with a null procedure pointer.  The routine gets
604  * the discriminant value and then searches the array of xdrdiscrims
605  * looking for that value.  It calls the procedure given in the xdrdiscrim
606  * to handle the discriminant.  If there is no specific routine a default
607  * routine may be called.
608  * If there is no specific or default routine an error is returned.
609  */
610 bool_t
611 xdr_union (xdrs, dscmp, unp, choices, dfault)
612      XDR *xdrs;
613      enum_t *dscmp;             /* enum to decide which arm to work on */
614      char *unp;                 /* the union itself */
615      const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
616      xdrproc_t dfault;          /* default xdr routine */
617 {
618   enum_t dscm;
619
620   /*
621    * we deal with the discriminator;  it's an enum
622    */
623   if (!INTUSE(xdr_enum) (xdrs, dscmp))
624     {
625       return FALSE;
626     }
627   dscm = *dscmp;
628
629   /*
630    * search choices for a value that matches the discriminator.
631    * if we find one, execute the xdr routine for that value.
632    */
633   for (; choices->proc != NULL_xdrproc_t; choices++)
634     {
635       if (choices->value == dscm)
636         return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
637     }
638
639   /*
640    * no match - execute the default xdr routine if there is one
641    */
642   return ((dfault == NULL_xdrproc_t) ? FALSE :
643           (*dfault) (xdrs, unp, LASTUNSIGNED));
644 }
645 INTDEF(xdr_union)
646
647
648 /*
649  * Non-portable xdr primitives.
650  * Care should be taken when moving these routines to new architectures.
651  */
652
653
654 /*
655  * XDR null terminated ASCII strings
656  * xdr_string deals with "C strings" - arrays of bytes that are
657  * terminated by a NULL character.  The parameter cpp references a
658  * pointer to storage; If the pointer is null, then the necessary
659  * storage is allocated.  The last parameter is the max allowed length
660  * of the string as specified by a protocol.
661  */
662 bool_t
663 xdr_string (xdrs, cpp, maxsize)
664      XDR *xdrs;
665      char **cpp;
666      u_int maxsize;
667 {
668   char *sp = *cpp;      /* sp is the actual string pointer */
669   u_int size;
670   u_int nodesize;
671
672   /*
673    * first deal with the length since xdr strings are counted-strings
674    */
675   switch (xdrs->x_op)
676     {
677     case XDR_FREE:
678       if (sp == NULL)
679         {
680           return TRUE;          /* already free */
681         }
682       /* fall through... */
683     case XDR_ENCODE:
684       if (sp == NULL)
685         return FALSE;
686       size = strlen (sp);
687       break;
688     case XDR_DECODE:
689       break;
690     }
691   if (!INTUSE(xdr_u_int) (xdrs, &size))
692     {
693       return FALSE;
694     }
695   if (size > maxsize)
696     {
697       return FALSE;
698     }
699   nodesize = size + 1;
700   if (nodesize == 0)
701     {
702       /* This means an overflow.  It a bug in the caller which
703          provided a too large maxsize but nevertheless catch it
704          here.  */
705       return FALSE;
706     }
707
708   /*
709    * now deal with the actual bytes
710    */
711   switch (xdrs->x_op)
712     {
713     case XDR_DECODE:
714       if (sp == NULL)
715         *cpp = sp = (char *) mem_alloc (nodesize);
716       if (sp == NULL)
717         {
718           (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
719           return FALSE;
720         }
721       sp[size] = 0;
722       /* fall into ... */
723
724     case XDR_ENCODE:
725       return INTUSE(xdr_opaque) (xdrs, sp, size);
726
727     case XDR_FREE:
728       mem_free (sp, nodesize);
729       *cpp = NULL;
730       return TRUE;
731     }
732   return FALSE;
733 }
734 INTDEF(xdr_string)
735
736 /*
737  * Wrapper for xdr_string that can be called directly from
738  * routines like clnt_call
739  */
740 bool_t
741 xdr_wrapstring (xdrs, cpp)
742      XDR *xdrs;
743      char **cpp;
744 {
745   if (INTUSE(xdr_string) (xdrs, cpp, LASTUNSIGNED))
746     {
747       return TRUE;
748     }
749   return FALSE;
750 }