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