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