]> git.ipfire.org Git - thirdparty/glibc.git/blame - sunrpc/xdr.c
Update.
[thirdparty/glibc.git] / sunrpc / xdr.c
CommitLineData
28f540f4
RM
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.
be64fe6d 9 *
28f540f4
RM
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.
be64fe6d 13 *
28f540f4
RM
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.
be64fe6d 17 *
28f540f4
RM
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.
be64fe6d 21 *
28f540f4
RM
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.
be64fe6d 25 *
28f540f4
RM
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California 94043
29 */
30#if !defined(lint) && defined(SCCSIDS)
31static 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>
3776d592 45#include <limits.h>
f671aeab 46#include <string.h>
28f540f4
RM
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 */
a1129917 61static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
28f540f4
RM
62
63/*
64 * Free a data structure using XDR
65 * Not a filter, but a convenient utility nonetheless
66 */
67void
a1129917 68xdr_free (xdrproc_t proc, char *objp)
28f540f4 69{
e7fd8a39 70 XDR x;
be64fe6d 71
e7fd8a39
UD
72 x.x_op = XDR_FREE;
73 (*proc) (&x, objp);
28f540f4
RM
74}
75
76/*
77 * XDR nothing
78 */
79bool_t
e7fd8a39 80xdr_void (void)
28f540f4 81{
e7fd8a39 82 return TRUE;
28f540f4
RM
83}
84
85/*
86 * XDR integers
87 */
88bool_t
a1129917 89xdr_int (XDR *xdrs, int *ip)
28f540f4
RM
90{
91
e7fd8a39
UD
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;
28f540f4 105 }
e7fd8a39
UD
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
28f540f4
RM
118}
119
120/*
121 * XDR unsigned integers
122 */
123bool_t
a1129917 124xdr_u_int (XDR *xdrs, u_int *up)
28f540f4 125{
e7fd8a39
UD
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;
28f540f4 139 }
e7fd8a39
UD
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
28f540f4
RM
152}
153
154/*
155 * XDR long integers
156 * same as xdr_u_long - open coded to save a proc call!
157 */
158bool_t
a1129917 159xdr_long (XDR *xdrs, long *lp)
28f540f4
RM
160{
161
e7fd8a39
UD
162 if (xdrs->x_op == XDR_ENCODE)
163 return XDR_PUTLONG (xdrs, lp);
28f540f4 164
e7fd8a39
UD
165 if (xdrs->x_op == XDR_DECODE)
166 return XDR_GETLONG (xdrs, lp);
28f540f4 167
e7fd8a39
UD
168 if (xdrs->x_op == XDR_FREE)
169 return TRUE;
28f540f4 170
e7fd8a39 171 return FALSE;
28f540f4
RM
172}
173
174/*
175 * XDR unsigned long integers
176 * same as xdr_long - open coded to save a proc call!
177 */
178bool_t
a1129917 179xdr_u_long (XDR *xdrs, u_long *ulp)
28f540f4 180{
e7fd8a39
UD
181 switch (xdrs->x_op)
182 {
183 case XDR_DECODE:
f218b5f5
UD
184 {
185 long int tmp;
186
187 if (XDR_GETLONG (xdrs, &tmp) == FALSE)
188 return FALSE;
189
190 *ulp = (uint32_t) tmp;
191 return TRUE;
192 }
e7fd8a39
UD
193
194 case XDR_ENCODE:
195 return XDR_PUTLONG (xdrs, (long *) ulp);
196
197 case XDR_FREE:
198 return TRUE;
199 }
200 return FALSE;
28f540f4
RM
201}
202
50f301a8
AS
203/*
204 * XDR hyper integers
205 * same as xdr_u_hyper - open coded to save a proc call!
206 */
207bool_t
208xdr_hyper (XDR *xdrs, quad_t *llp)
209{
210 long t1;
bdd5fccd 211 unsigned long int t2;
50f301a8
AS
212
213 if (xdrs->x_op == XDR_ENCODE)
214 {
215 t1 = (long) ((*llp) >> 32);
216 t2 = (long) (*llp);
217 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
218 }
219
220 if (xdrs->x_op == XDR_DECODE)
221 {
222 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
223 return FALSE;
224 *llp = ((quad_t) t1) << 32;
225 *llp |= t2;
226 return TRUE;
227 }
228
229 if (xdrs->x_op == XDR_FREE)
230 return TRUE;
231
232 return FALSE;
233}
234
235
236/*
237 * XDR hyper integers
238 * same as xdr_hyper - open coded to save a proc call!
239 */
240bool_t
241xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
242{
243 unsigned long t1;
244 unsigned long t2;
245
246 if (xdrs->x_op == XDR_ENCODE)
247 {
248 t1 = (unsigned long) ((*ullp) >> 32);
249 t2 = (unsigned long) (*ullp);
250 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
251 }
252
253 if (xdrs->x_op == XDR_DECODE)
254 {
255 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
256 return FALSE;
257 *ullp = ((u_quad_t) t1) << 32;
258 *ullp |= t2;
259 return TRUE;
260 }
261
262 if (xdrs->x_op == XDR_FREE)
263 return TRUE;
264
265 return FALSE;
266}
267
268bool_t
269xdr_longlong_t (XDR *xdrs, quad_t *llp)
270{
271 return xdr_hyper (xdrs, llp);
272}
273
274bool_t
275xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
276{
277 return xdr_u_hyper (xdrs, ullp);
278}
279
28f540f4
RM
280/*
281 * XDR short integers
282 */
283bool_t
50f301a8 284xdr_short (XDR *xdrs, short *sp)
28f540f4 285{
e7fd8a39
UD
286 long l;
287
288 switch (xdrs->x_op)
289 {
290 case XDR_ENCODE:
291 l = (long) *sp;
292 return XDR_PUTLONG (xdrs, &l);
293
294 case XDR_DECODE:
295 if (!XDR_GETLONG (xdrs, &l))
296 {
297 return FALSE;
28f540f4 298 }
e7fd8a39
UD
299 *sp = (short) l;
300 return TRUE;
301
302 case XDR_FREE:
303 return TRUE;
304 }
305 return FALSE;
28f540f4
RM
306}
307
308/*
309 * XDR unsigned short integers
310 */
311bool_t
50f301a8 312xdr_u_short (XDR *xdrs, u_short *usp)
28f540f4 313{
e7fd8a39
UD
314 u_long l;
315
316 switch (xdrs->x_op)
317 {
318 case XDR_ENCODE:
319 l = (u_long) * usp;
320 return XDR_PUTLONG (xdrs, &l);
321
322 case XDR_DECODE:
323 if (!XDR_GETLONG (xdrs, &l))
324 {
325 return FALSE;
28f540f4 326 }
e7fd8a39
UD
327 *usp = (u_short) l;
328 return TRUE;
329
330 case XDR_FREE:
331 return TRUE;
332 }
333 return FALSE;
28f540f4
RM
334}
335
336
337/*
338 * XDR a char
339 */
340bool_t
50f301a8 341xdr_char (XDR *xdrs, char *cp)
28f540f4 342{
e7fd8a39
UD
343 int i;
344
345 i = (*cp);
346 if (!xdr_int (xdrs, &i))
347 {
348 return FALSE;
349 }
350 *cp = i;
351 return TRUE;
28f540f4
RM
352}
353
354/*
355 * XDR an unsigned char
356 */
357bool_t
50f301a8 358xdr_u_char (XDR *xdrs, u_char *cp)
28f540f4 359{
e7fd8a39
UD
360 u_int u;
361
362 u = (*cp);
363 if (!xdr_u_int (xdrs, &u))
364 {
365 return FALSE;
366 }
367 *cp = u;
368 return TRUE;
28f540f4
RM
369}
370
371/*
372 * XDR booleans
373 */
374bool_t
50f301a8 375xdr_bool (XDR *xdrs, bool_t *bp)
28f540f4 376{
e7fd8a39
UD
377 long lb;
378
379 switch (xdrs->x_op)
380 {
381 case XDR_ENCODE:
382 lb = *bp ? XDR_TRUE : XDR_FALSE;
383 return XDR_PUTLONG (xdrs, &lb);
384
385 case XDR_DECODE:
386 if (!XDR_GETLONG (xdrs, &lb))
387 {
388 return FALSE;
28f540f4 389 }
e7fd8a39
UD
390 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
391 return TRUE;
392
393 case XDR_FREE:
394 return TRUE;
395 }
396 return FALSE;
28f540f4
RM
397}
398
399/*
400 * XDR enumerations
401 */
402bool_t
50f301a8 403xdr_enum (XDR *xdrs, enum_t *ep)
28f540f4 404{
e7fd8a39
UD
405 enum sizecheck
406 {
407 SIZEVAL
408 }; /* used to find the size of an enum */
409
410 /*
411 * enums are treated as ints
412 */
413 if (sizeof (enum sizecheck) == 4)
414 {
415#if INT_MAX < LONG_MAX
416 long l;
417
418 switch (xdrs->x_op)
419 {
420 case XDR_ENCODE:
421 l = *ep;
422 return XDR_PUTLONG (xdrs, &l);
423
424 case XDR_DECODE:
425 if (!XDR_GETLONG (xdrs, &l))
426 {
427 return FALSE;
428 }
429 *ep = l;
430 case XDR_FREE:
431 return TRUE;
432
28f540f4 433 }
e7fd8a39
UD
434 return FALSE;
435#else
436 return xdr_long (xdrs, (long *) ep);
437#endif
438 }
439 else if (sizeof (enum sizecheck) == sizeof (short))
440 {
441 return xdr_short (xdrs, (short *) ep);
442 }
443 else
444 {
445 return FALSE;
446 }
28f540f4
RM
447}
448
449/*
450 * XDR opaque data
451 * Allows the specification of a fixed size sequence of opaque bytes.
452 * cp points to the opaque object and cnt gives the byte length.
453 */
454bool_t
50f301a8 455xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
28f540f4 456{
e7fd8a39
UD
457 u_int rndup;
458 static char crud[BYTES_PER_XDR_UNIT];
459
460 /*
461 * if no data we are done
462 */
463 if (cnt == 0)
464 return TRUE;
465
466 /*
467 * round byte count to full xdr units
468 */
469 rndup = cnt % BYTES_PER_XDR_UNIT;
470 if (rndup > 0)
471 rndup = BYTES_PER_XDR_UNIT - rndup;
472
473 switch (xdrs->x_op)
474 {
475 case XDR_DECODE:
476 if (!XDR_GETBYTES (xdrs, cp, cnt))
477 {
478 return FALSE;
28f540f4 479 }
e7fd8a39
UD
480 if (rndup == 0)
481 return TRUE;
482 return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
483
484 case XDR_ENCODE:
485 if (!XDR_PUTBYTES (xdrs, cp, cnt))
486 {
487 return FALSE;
488 }
489 if (rndup == 0)
490 return TRUE;
491 return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
492
493 case XDR_FREE:
494 return TRUE;
495 }
496 return FALSE;
28f540f4
RM
497}
498
499/*
500 * XDR counted bytes
501 * *cpp is a pointer to the bytes, *sizep is the count.
502 * If *cpp is NULL maxsize bytes are allocated
503 */
504bool_t
e7fd8a39
UD
505xdr_bytes (xdrs, cpp, sizep, maxsize)
506 XDR *xdrs;
507 char **cpp;
508 u_int *sizep;
509 u_int maxsize;
28f540f4 510{
e7fd8a39
UD
511 char *sp = *cpp; /* sp is the actual string pointer */
512 u_int nodesize;
513
514 /*
515 * first deal with the length since xdr bytes are counted
516 */
517 if (!xdr_u_int (xdrs, sizep))
518 {
519 return FALSE;
520 }
521 nodesize = *sizep;
522 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
523 {
524 return FALSE;
525 }
526
527 /*
528 * now deal with the actual bytes
529 */
530 switch (xdrs->x_op)
531 {
532 case XDR_DECODE:
533 if (nodesize == 0)
534 {
535 return TRUE;
536 }
537 if (sp == NULL)
538 {
539 *cpp = sp = (char *) mem_alloc (nodesize);
28f540f4 540 }
e7fd8a39
UD
541 if (sp == NULL)
542 {
543 (void) fprintf (stderr, "xdr_bytes: out of memory\n");
544 return FALSE;
28f540f4 545 }
e7fd8a39 546 /* fall into ... */
28f540f4 547
e7fd8a39
UD
548 case XDR_ENCODE:
549 return xdr_opaque (xdrs, sp, nodesize);
550
551 case XDR_FREE:
552 if (sp != NULL)
553 {
554 mem_free (sp, nodesize);
555 *cpp = NULL;
28f540f4 556 }
e7fd8a39
UD
557 return TRUE;
558 }
559 return FALSE;
28f540f4
RM
560}
561
562/*
563 * Implemented here due to commonality of the object.
564 */
565bool_t
e7fd8a39
UD
566xdr_netobj (xdrs, np)
567 XDR *xdrs;
568 struct netobj *np;
28f540f4
RM
569{
570
e7fd8a39 571 return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
28f540f4
RM
572}
573
574/*
6d52618b 575 * XDR a discriminated union
28f540f4
RM
576 * Support routine for discriminated unions.
577 * You create an array of xdrdiscrim structures, terminated with
578 * an entry with a null procedure pointer. The routine gets
579 * the discriminant value and then searches the array of xdrdiscrims
580 * looking for that value. It calls the procedure given in the xdrdiscrim
581 * to handle the discriminant. If there is no specific routine a default
582 * routine may be called.
583 * If there is no specific or default routine an error is returned.
584 */
585bool_t
e7fd8a39
UD
586xdr_union (xdrs, dscmp, unp, choices, dfault)
587 XDR *xdrs;
588 enum_t *dscmp; /* enum to decide which arm to work on */
589 char *unp; /* the union itself */
590 const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
591 xdrproc_t dfault; /* default xdr routine */
28f540f4 592{
e7fd8a39
UD
593 enum_t dscm;
594
595 /*
596 * we deal with the discriminator; it's an enum
597 */
598 if (!xdr_enum (xdrs, dscmp))
599 {
600 return FALSE;
601 }
602 dscm = *dscmp;
603
604 /*
605 * search choices for a value that matches the discriminator.
606 * if we find one, execute the xdr routine for that value.
607 */
608 for (; choices->proc != NULL_xdrproc_t; choices++)
609 {
610 if (choices->value == dscm)
611 return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
612 }
613
614 /*
615 * no match - execute the default xdr routine if there is one
616 */
617 return ((dfault == NULL_xdrproc_t) ? FALSE :
618 (*dfault) (xdrs, unp, LASTUNSIGNED));
28f540f4
RM
619}
620
621
622/*
623 * Non-portable xdr primitives.
624 * Care should be taken when moving these routines to new architectures.
625 */
626
627
628/*
629 * XDR null terminated ASCII strings
630 * xdr_string deals with "C strings" - arrays of bytes that are
631 * terminated by a NULL character. The parameter cpp references a
632 * pointer to storage; If the pointer is null, then the necessary
633 * storage is allocated. The last parameter is the max allowed length
634 * of the string as specified by a protocol.
635 */
636bool_t
e7fd8a39
UD
637xdr_string (xdrs, cpp, maxsize)
638 XDR *xdrs;
639 char **cpp;
640 u_int maxsize;
28f540f4 641{
e7fd8a39
UD
642 char *sp = *cpp; /* sp is the actual string pointer */
643 u_int size;
644 u_int nodesize;
645
646 /*
647 * first deal with the length since xdr strings are counted-strings
648 */
649 switch (xdrs->x_op)
650 {
651 case XDR_FREE:
652 if (sp == NULL)
653 {
654 return TRUE; /* already free */
28f540f4 655 }
e7fd8a39
UD
656 /* fall through... */
657 case XDR_ENCODE:
658 if (sp == NULL)
659 return FALSE;
660 size = strlen (sp);
661 break;
662 case XDR_DECODE:
663 break;
664 }
665 if (!xdr_u_int (xdrs, &size))
666 {
667 return FALSE;
668 }
669 if (size > maxsize)
670 {
671 return FALSE;
672 }
673 nodesize = size + 1;
674
675 /*
676 * now deal with the actual bytes
677 */
678 switch (xdrs->x_op)
679 {
680 case XDR_DECODE:
681 if (nodesize == 0)
682 {
683 return TRUE;
28f540f4 684 }
e7fd8a39
UD
685 if (sp == NULL)
686 *cpp = sp = (char *) mem_alloc (nodesize);
687 if (sp == NULL)
688 {
689 (void) fprintf (stderr, "xdr_string: out of memory\n");
690 return FALSE;
28f540f4 691 }
e7fd8a39
UD
692 sp[size] = 0;
693 /* fall into ... */
694
695 case XDR_ENCODE:
696 return xdr_opaque (xdrs, sp, size);
697
698 case XDR_FREE:
699 mem_free (sp, nodesize);
700 *cpp = NULL;
701 return TRUE;
702 }
703 return FALSE;
28f540f4
RM
704}
705
be64fe6d
RM
706/*
707 * Wrapper for xdr_string that can be called directly from
28f540f4
RM
708 * routines like clnt_call
709 */
710bool_t
e7fd8a39
UD
711xdr_wrapstring (xdrs, cpp)
712 XDR *xdrs;
713 char **cpp;
28f540f4 714{
e7fd8a39
UD
715 if (xdr_string (xdrs, cpp, LASTUNSIGNED))
716 {
717 return TRUE;
718 }
719 return FALSE;
28f540f4 720}