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