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