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