cleanup spec
[platform/upstream/glibc.git] / sunrpc / xdr.c
1 /*
2  * xdr.c, Generic XDR routines implementation.
3  *
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * These are the "generic" xdr routines used to serialize and de-serialize
34  * most common data items.  See xdr.h for more info on the interface to
35  * xdr.
36  */
37
38 #include <stdio.h>
39 #include <limits.h>
40 #include <string.h>
41 #include <libintl.h>
42 #include <wchar.h>
43 #include <stdint.h>
44
45 #include <rpc/types.h>
46 #include <rpc/xdr.h>
47
48
49 /*
50  * constants specific to the xdr "protocol"
51  */
52 #define XDR_FALSE       ((long) 0)
53 #define XDR_TRUE        ((long) 1)
54 #define LASTUNSIGNED    ((u_int) 0-1)
55
56 /*
57  * for unit alignment
58  */
59 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
60
61 /*
62  * Free a data structure using XDR
63  * Not a filter, but a convenient utility nonetheless
64  */
65 void
66 xdr_free (xdrproc_t proc, char *objp)
67 {
68   XDR x;
69
70   x.x_op = XDR_FREE;
71   (*proc) (&x, objp);
72 }
73 #ifdef EXPORT_RPC_SYMBOLS
74 libc_hidden_def (xdr_free)
75 #else
76 libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0)
77 #endif
78
79 /*
80  * XDR nothing
81  */
82 bool_t
83 xdr_void (void)
84 {
85   return TRUE;
86 }
87 #ifdef EXPORT_RPC_SYMBOLS
88 libc_hidden_def (xdr_void)
89 #else
90 libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0)
91 #endif
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 #ifdef EXPORT_RPC_SYMBOLS
128 libc_hidden_def (xdr_int)
129 #else
130 libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0)
131 #endif
132
133 /*
134  * XDR unsigned integers
135  */
136 bool_t
137 xdr_u_int (XDR *xdrs, u_int *up)
138 {
139 #if UINT_MAX < ULONG_MAX
140   long l;
141
142   switch (xdrs->x_op)
143     {
144     case XDR_ENCODE:
145       l = (u_long) * up;
146       return XDR_PUTLONG (xdrs, &l);
147
148     case XDR_DECODE:
149       if (!XDR_GETLONG (xdrs, &l))
150         {
151           return FALSE;
152         }
153       *up = (u_int) (u_long) l;
154     case XDR_FREE:
155       return TRUE;
156     }
157   return FALSE;
158 #elif UINT_MAX == ULONG_MAX
159   return xdr_u_long (xdrs, (u_long *) up);
160 #elif UINT_MAX == USHRT_MAX
161   return xdr_short (xdrs, (short *) up);
162 #else
163 #error unexpected integer sizes in_xdr_u_int()
164 #endif
165 }
166 #ifdef EXPORT_RPC_SYMBOLS
167 libc_hidden_def (xdr_u_int)
168 #else
169 libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0)
170 #endif
171
172 /*
173  * XDR long integers
174  * The definition of xdr_long() is kept for backward
175  * compatibility. Instead xdr_int() should be used.
176  */
177 bool_t
178 xdr_long (XDR *xdrs, long *lp)
179 {
180
181   if (xdrs->x_op == XDR_ENCODE
182       && (sizeof (int32_t) == sizeof (long)
183           || (int32_t) *lp == *lp))
184     return XDR_PUTLONG (xdrs, lp);
185
186   if (xdrs->x_op == XDR_DECODE)
187     return XDR_GETLONG (xdrs, lp);
188
189   if (xdrs->x_op == XDR_FREE)
190     return TRUE;
191
192   return FALSE;
193 }
194 #ifdef EXPORT_RPC_SYMBOLS
195 libc_hidden_def (xdr_long)
196 #else
197 libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0)
198 #endif
199
200 /*
201  * XDR unsigned long integers
202  * The definition of xdr_u_long() is kept for backward
203  * compatibility. Instead xdr_u_int() should be used.
204  */
205 bool_t
206 xdr_u_long (XDR *xdrs, u_long *ulp)
207 {
208   switch (xdrs->x_op)
209     {
210     case XDR_DECODE:
211       {
212         long int tmp;
213
214         if (XDR_GETLONG (xdrs, &tmp) == FALSE)
215           return FALSE;
216
217         *ulp = (uint32_t) tmp;
218         return TRUE;
219       }
220
221     case XDR_ENCODE:
222       if (sizeof (uint32_t) != sizeof (u_long)
223           && (uint32_t) *ulp != *ulp)
224         return FALSE;
225
226       return XDR_PUTLONG (xdrs, (long *) ulp);
227
228     case XDR_FREE:
229       return TRUE;
230     }
231   return FALSE;
232 }
233 #ifdef EXPORT_RPC_SYMBOLS
234 libc_hidden_def (xdr_u_long)
235 #else
236 libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0)
237 #endif
238
239 /*
240  * XDR hyper integers
241  * same as xdr_u_hyper - open coded to save a proc call!
242  */
243 bool_t
244 xdr_hyper (XDR *xdrs, quad_t *llp)
245 {
246   long int t1, t2;
247
248   if (xdrs->x_op == XDR_ENCODE)
249     {
250       t1 = (long) ((*llp) >> 32);
251       t2 = (long) (*llp);
252       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
253     }
254
255   if (xdrs->x_op == XDR_DECODE)
256     {
257       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
258         return FALSE;
259       *llp = ((quad_t) t1) << 32;
260       *llp |= (uint32_t) t2;
261       return TRUE;
262     }
263
264   if (xdrs->x_op == XDR_FREE)
265     return TRUE;
266
267   return FALSE;
268 }
269 #ifdef EXPORT_RPC_SYMBOLS
270 libc_hidden_def (xdr_hyper)
271 #else
272 libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1)
273 #endif
274
275 /*
276  * XDR hyper integers
277  * same as xdr_hyper - open coded to save a proc call!
278  */
279 bool_t
280 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
281 {
282   long int t1, t2;
283
284   if (xdrs->x_op == XDR_ENCODE)
285     {
286       t1 = (unsigned long) ((*ullp) >> 32);
287       t2 = (unsigned long) (*ullp);
288       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
289     }
290
291   if (xdrs->x_op == XDR_DECODE)
292     {
293       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
294         return FALSE;
295       *ullp = ((u_quad_t) t1) << 32;
296       *ullp |= (uint32_t) t2;
297       return TRUE;
298     }
299
300   if (xdrs->x_op == XDR_FREE)
301     return TRUE;
302
303   return FALSE;
304 }
305 #ifdef EXPORT_RPC_SYMBOLS
306 libc_hidden_def (xdr_u_hyper)
307 #else
308 libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1)
309 #endif
310
311 bool_t
312 xdr_longlong_t (XDR *xdrs, quad_t *llp)
313 {
314   return xdr_hyper (xdrs, llp);
315 }
316 #ifdef EXPORT_RPC_SYMBOLS
317 libc_hidden_def (xdr_longlong_t)
318 #else
319 libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1)
320 #endif
321
322 bool_t
323 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
324 {
325   return xdr_u_hyper (xdrs, ullp);
326 }
327 #ifdef EXPORT_RPC_SYMBOLS
328 libc_hidden_def (xdr_u_longlong_t)
329 #else
330 libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1)
331 #endif
332
333 /*
334  * XDR short integers
335  */
336 bool_t
337 xdr_short (XDR *xdrs, short *sp)
338 {
339   long l;
340
341   switch (xdrs->x_op)
342     {
343     case XDR_ENCODE:
344       l = (long) *sp;
345       return XDR_PUTLONG (xdrs, &l);
346
347     case XDR_DECODE:
348       if (!XDR_GETLONG (xdrs, &l))
349         {
350           return FALSE;
351         }
352       *sp = (short) l;
353       return TRUE;
354
355     case XDR_FREE:
356       return TRUE;
357     }
358   return FALSE;
359 }
360 #ifdef EXPORT_RPC_SYMBOLS
361 libc_hidden_def (xdr_short)
362 #else
363 libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0)
364 #endif
365
366 /*
367  * XDR unsigned short integers
368  */
369 bool_t
370 xdr_u_short (XDR *xdrs, u_short *usp)
371 {
372   long l;
373
374   switch (xdrs->x_op)
375     {
376     case XDR_ENCODE:
377       l = (u_long) * usp;
378       return XDR_PUTLONG (xdrs, &l);
379
380     case XDR_DECODE:
381       if (!XDR_GETLONG (xdrs, &l))
382         {
383           return FALSE;
384         }
385       *usp = (u_short) (u_long) l;
386       return TRUE;
387
388     case XDR_FREE:
389       return TRUE;
390     }
391   return FALSE;
392 }
393 #ifdef EXPORT_RPC_SYMBOLS
394 libc_hidden_def (xdr_u_short)
395 #else
396 libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0)
397 #endif
398
399
400 /*
401  * XDR a char
402  */
403 bool_t
404 xdr_char (XDR *xdrs, char *cp)
405 {
406   int i;
407
408   i = (*cp);
409   if (!xdr_int (xdrs, &i))
410     {
411       return FALSE;
412     }
413   *cp = i;
414   return TRUE;
415 }
416 #ifdef EXPORT_RPC_SYMBOLS
417 libc_hidden_def (xdr_char)
418 #else
419 libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0)
420 #endif
421
422 /*
423  * XDR an unsigned char
424  */
425 bool_t
426 xdr_u_char (XDR *xdrs, u_char *cp)
427 {
428   u_int u;
429
430   u = (*cp);
431   if (!xdr_u_int (xdrs, &u))
432     {
433       return FALSE;
434     }
435   *cp = u;
436   return TRUE;
437 }
438 #ifdef EXPORT_RPC_SYMBOLS
439 libc_hidden_def (xdr_u_char)
440 #else
441 libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0)
442 #endif
443
444 /*
445  * XDR booleans
446  */
447 bool_t
448 xdr_bool (XDR *xdrs, bool_t *bp)
449 {
450   long lb;
451
452   switch (xdrs->x_op)
453     {
454     case XDR_ENCODE:
455       lb = *bp ? XDR_TRUE : XDR_FALSE;
456       return XDR_PUTLONG (xdrs, &lb);
457
458     case XDR_DECODE:
459       if (!XDR_GETLONG (xdrs, &lb))
460         {
461           return FALSE;
462         }
463       *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
464       return TRUE;
465
466     case XDR_FREE:
467       return TRUE;
468     }
469   return FALSE;
470 }
471 #ifdef EXPORT_RPC_SYMBOLS
472 libc_hidden_def (xdr_bool)
473 #else
474 libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0)
475 #endif
476
477 /*
478  * XDR enumerations
479  */
480 bool_t
481 xdr_enum (XDR *xdrs, enum_t *ep)
482 {
483   enum sizecheck
484     {
485       SIZEVAL
486     };                          /* used to find the size of an enum */
487
488   /*
489    * enums are treated as ints
490    */
491   if (sizeof (enum sizecheck) == 4)
492     {
493 #if INT_MAX < LONG_MAX
494       long l;
495
496       switch (xdrs->x_op)
497         {
498         case XDR_ENCODE:
499           l = *ep;
500           return XDR_PUTLONG (xdrs, &l);
501
502         case XDR_DECODE:
503           if (!XDR_GETLONG (xdrs, &l))
504             {
505               return FALSE;
506             }
507           *ep = l;
508         case XDR_FREE:
509           return TRUE;
510
511         }
512       return FALSE;
513 #else
514       return xdr_long (xdrs, (long *) ep);
515 #endif
516     }
517   else if (sizeof (enum sizecheck) == sizeof (short))
518     {
519       return xdr_short (xdrs, (short *) ep);
520     }
521   else
522     {
523       return FALSE;
524     }
525 }
526 #ifdef EXPORT_RPC_SYMBOLS
527 libc_hidden_def (xdr_enum)
528 #else
529 libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0)
530 #endif
531
532 /*
533  * XDR opaque data
534  * Allows the specification of a fixed size sequence of opaque bytes.
535  * cp points to the opaque object and cnt gives the byte length.
536  */
537 bool_t
538 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
539 {
540   u_int rndup;
541   static char crud[BYTES_PER_XDR_UNIT];
542
543   /*
544    * if no data we are done
545    */
546   if (cnt == 0)
547     return TRUE;
548
549   /*
550    * round byte count to full xdr units
551    */
552   rndup = cnt % BYTES_PER_XDR_UNIT;
553   if (rndup > 0)
554     rndup = BYTES_PER_XDR_UNIT - rndup;
555
556   switch (xdrs->x_op)
557     {
558     case XDR_DECODE:
559       if (!XDR_GETBYTES (xdrs, cp, cnt))
560         {
561           return FALSE;
562         }
563       if (rndup == 0)
564         return TRUE;
565       return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
566
567     case XDR_ENCODE:
568       if (!XDR_PUTBYTES (xdrs, cp, cnt))
569         {
570           return FALSE;
571         }
572       if (rndup == 0)
573         return TRUE;
574       return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
575
576     case XDR_FREE:
577       return TRUE;
578     }
579   return FALSE;
580 }
581 #ifdef EXPORT_RPC_SYMBOLS
582 libc_hidden_def (xdr_opaque)
583 #else
584 libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0)
585 #endif
586
587 /*
588  * XDR counted bytes
589  * *cpp is a pointer to the bytes, *sizep is the count.
590  * If *cpp is NULL maxsize bytes are allocated
591  */
592 bool_t
593 xdr_bytes (xdrs, cpp, sizep, maxsize)
594      XDR *xdrs;
595      char **cpp;
596      u_int *sizep;
597      u_int maxsize;
598 {
599   char *sp = *cpp;      /* sp is the actual string pointer */
600   u_int nodesize;
601
602   /*
603    * first deal with the length since xdr bytes are counted
604    */
605   if (!xdr_u_int (xdrs, sizep))
606     {
607       return FALSE;
608     }
609   nodesize = *sizep;
610   if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
611     {
612       return FALSE;
613     }
614
615   /*
616    * now deal with the actual bytes
617    */
618   switch (xdrs->x_op)
619     {
620     case XDR_DECODE:
621       if (nodesize == 0)
622         {
623           return TRUE;
624         }
625       if (sp == NULL)
626         {
627           *cpp = sp = (char *) mem_alloc (nodesize);
628         }
629       if (sp == NULL)
630         {
631           (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
632           return FALSE;
633         }
634       /* fall into ... */
635
636     case XDR_ENCODE:
637       return xdr_opaque (xdrs, sp, nodesize);
638
639     case XDR_FREE:
640       if (sp != NULL)
641         {
642           mem_free (sp, nodesize);
643           *cpp = NULL;
644         }
645       return TRUE;
646     }
647   return FALSE;
648 }
649 #ifdef EXPORT_RPC_SYMBOLS
650 libc_hidden_def (xdr_bytes)
651 #else
652 libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0)
653 #endif
654
655 /*
656  * Implemented here due to commonality of the object.
657  */
658 bool_t
659 xdr_netobj (xdrs, np)
660      XDR *xdrs;
661      struct netobj *np;
662 {
663
664   return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
665 }
666 #ifdef EXPORT_RPC_SYMBOLS
667 libc_hidden_def (xdr_netobj)
668 #else
669 libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0)
670 #endif
671
672 /*
673  * XDR a discriminated union
674  * Support routine for discriminated unions.
675  * You create an array of xdrdiscrim structures, terminated with
676  * an entry with a null procedure pointer.  The routine gets
677  * the discriminant value and then searches the array of xdrdiscrims
678  * looking for that value.  It calls the procedure given in the xdrdiscrim
679  * to handle the discriminant.  If there is no specific routine a default
680  * routine may be called.
681  * If there is no specific or default routine an error is returned.
682  */
683 bool_t
684 xdr_union (xdrs, dscmp, unp, choices, dfault)
685      XDR *xdrs;
686      enum_t *dscmp;             /* enum to decide which arm to work on */
687      char *unp;                 /* the union itself */
688      const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
689      xdrproc_t dfault;          /* default xdr routine */
690 {
691   enum_t dscm;
692
693   /*
694    * we deal with the discriminator;  it's an enum
695    */
696   if (!xdr_enum (xdrs, dscmp))
697     {
698       return FALSE;
699     }
700   dscm = *dscmp;
701
702   /*
703    * search choices for a value that matches the discriminator.
704    * if we find one, execute the xdr routine for that value.
705    */
706   for (; choices->proc != NULL_xdrproc_t; choices++)
707     {
708       if (choices->value == dscm)
709         return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
710     }
711
712   /*
713    * no match - execute the default xdr routine if there is one
714    */
715   return ((dfault == NULL_xdrproc_t) ? FALSE :
716           (*dfault) (xdrs, unp, LASTUNSIGNED));
717 }
718 libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0)
719
720
721 /*
722  * Non-portable xdr primitives.
723  * Care should be taken when moving these routines to new architectures.
724  */
725
726
727 /*
728  * XDR null terminated ASCII strings
729  * xdr_string deals with "C strings" - arrays of bytes that are
730  * terminated by a NULL character.  The parameter cpp references a
731  * pointer to storage; If the pointer is null, then the necessary
732  * storage is allocated.  The last parameter is the max allowed length
733  * of the string as specified by a protocol.
734  */
735 bool_t
736 xdr_string (xdrs, cpp, maxsize)
737      XDR *xdrs;
738      char **cpp;
739      u_int maxsize;
740 {
741   char *sp = *cpp;      /* sp is the actual string pointer */
742   /* Initialize to silence the compiler.  It is not really needed because SIZE
743      never actually gets used without being initialized.  */
744   u_int size = 0;
745   u_int nodesize;
746
747   /*
748    * first deal with the length since xdr strings are counted-strings
749    */
750   switch (xdrs->x_op)
751     {
752     case XDR_FREE:
753       if (sp == NULL)
754         {
755           return TRUE;          /* already free */
756         }
757       /* fall through... */
758     case XDR_ENCODE:
759       if (sp == NULL)
760         return FALSE;
761       size = strlen (sp);
762       break;
763     case XDR_DECODE:
764       break;
765     }
766   if (!xdr_u_int (xdrs, &size))
767     {
768       return FALSE;
769     }
770   if (size > maxsize)
771     {
772       return FALSE;
773     }
774   nodesize = size + 1;
775   if (nodesize == 0)
776     {
777       /* This means an overflow.  It a bug in the caller which
778          provided a too large maxsize but nevertheless catch it
779          here.  */
780       return FALSE;
781     }
782
783   /*
784    * now deal with the actual bytes
785    */
786   switch (xdrs->x_op)
787     {
788     case XDR_DECODE:
789       if (sp == NULL)
790         *cpp = sp = (char *) mem_alloc (nodesize);
791       if (sp == NULL)
792         {
793           (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
794           return FALSE;
795         }
796       sp[size] = 0;
797       /* fall into ... */
798
799     case XDR_ENCODE:
800       return xdr_opaque (xdrs, sp, size);
801
802     case XDR_FREE:
803       mem_free (sp, nodesize);
804       *cpp = NULL;
805       return TRUE;
806     }
807   return FALSE;
808 }
809 #ifdef EXPORT_RPC_SYMBOLS
810 libc_hidden_def (xdr_string)
811 #else
812 libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0)
813 #endif
814
815 /*
816  * Wrapper for xdr_string that can be called directly from
817  * routines like clnt_call
818  */
819 bool_t
820 xdr_wrapstring (xdrs, cpp)
821      XDR *xdrs;
822      char **cpp;
823 {
824   if (xdr_string (xdrs, cpp, LASTUNSIGNED))
825     {
826       return TRUE;
827     }
828   return FALSE;
829 }
830 #ifdef EXPORT_RPC_SYMBOLS
831 libc_hidden_def (xdr_wrapstring)
832 #else
833 libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0)
834 #endif