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