OSDN Git Service

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