OSDN Git Service

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