Import TBBT (NFS trace replay).
[bluesky.git] / TBBT / trace_play / rpc / xdr.c
1 #ifndef lint
2 static char sfs_xdr_c_id[] = "@(#)xdr.c     2.1     97/10/23";
3 #endif
4 /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
5 /*
6  *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
7  *      All rights reserved.
8  *              Standard Performance Evaluation Corporation (SPEC)
9  *              6585 Merchant Place, Suite 100
10  *              Warrenton, VA 20187
11  *
12  *      This product contains benchmarks acquired from several sources who
13  *      understand and agree with SPEC's goal of creating fair and objective
14  *      benchmarks to measure computer performance.
15  *
16  *      This copyright notice is placed here only to protect SPEC in the
17  *      event the source is misused in any manner that is contrary to the
18  *      spirit, the goals and the intent of SPEC.
19  *
20  *      The source code is provided to the user or company under the license
21  *      agreement for the SPEC Benchmark Suite for this product.
22  */
23 /*
24  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
25  * unrestricted use provided that this legend is included on all tape
26  * media and as a part of the software program in whole or part.  Users
27  * may copy or modify Sun RPC without charge, but are not authorized
28  * to license or distribute it to anyone else except as part of a product or
29  * program developed by the user.
30  * 
31  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
32  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
33  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
34  * 
35  * Sun RPC is provided with no support and without any obligation on the
36  * part of Sun Microsystems, Inc. to assist in its use, correction,
37  * modification or enhancement.
38  * 
39  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
40  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
41  * OR ANY PART THEREOF.
42  * 
43  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
44  * or profits or other special, indirect and consequential damages, even if
45  * Sun has been advised of the possibility of such damages.
46  * 
47  * Sun Microsystems, Inc.
48  * 2550 Garcia Avenue
49  * Mountain View, California  94043
50  */
51 #if !defined(lint) && defined(SCCSIDS)
52 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
53 #endif
54
55 /*
56  * xdr.c, Generic XDR routines implementation.
57  *
58  * Copyright (C) 1986, Sun Microsystems, Inc.
59  *
60  * These are the "generic" xdr routines used to serialize and de-serialize
61  * most common data items.  See xdr.h for more info on the interface to
62  * xdr.
63  */
64 #ifndef lint
65 static char sfs_clnt_id[] = "@(#)xdr.c     2.1     97/10/23";
66 #endif
67
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71
72 #include "rpc/types.h"
73 #include "rpc/xdr.h"
74
75 /*
76  * constants specific to the xdr "protocol"
77  */
78 #define XDR_FALSE       ((int32_t) 0)
79 #define XDR_TRUE        ((int32_t) 1)
80 #define LASTUNSIGNED    ((uint_t) 0-1)
81
82 /*
83  * for unit alignment
84  */
85 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
86
87 /*
88  * Free a data structure using XDR
89  * Not a filter, but a convenient utility nonetheless
90  */
91 void
92 xdr_free(
93         xdrproc_t proc,
94         char *objp)
95 {
96         XDR x;
97         
98         x.x_op = XDR_FREE;
99         (*proc)(&x, objp);
100 }
101
102 /*
103  * XDR nothing
104  */
105 bool_t
106 xdr_void(void)
107 {
108
109         return (TRUE);
110 }
111
112 /*
113  * XDR integers
114  */
115 bool_t
116 xdr_int(
117         XDR *xdrs,
118         int *ip)
119 {
120
121 #ifdef lint
122         (void) (xdr_int16_t(xdrs, (int16_t *)ip));
123         return (xdr_int32_t(xdrs, (int32_t *)ip));
124 #else
125         if (sizeof (int) == sizeof (int32_t)) {
126                 return (xdr_int32_t(xdrs, (int32_t *)ip));
127         } else {
128                 return (xdr_int16_t(xdrs, (int16_t *)ip));
129         }
130 #endif
131 }
132
133 /*
134  * XDR unsigned integers
135  */
136 bool_t
137 xdr_u_int(
138         XDR *xdrs,
139         uint_t *up)
140 {
141
142 #ifdef lint
143         (void) (xdr_int16_t(xdrs, (int16_t *)up));
144         return (xdr_uint32_t(xdrs, (uint32_t *)up));
145 #else
146         if (sizeof (uint_t) == sizeof (uint32_t)) {
147                 return (xdr_uint32_t(xdrs, (uint32_t *)up));
148         } else {
149                 return (xdr_int16_t(xdrs, (int16_t *)up));
150         }
151 #endif
152 }
153
154 /*
155  * XDR long integers
156  * same as xdr_u_long - open coded to save a proc call!
157  */
158 bool_t
159 xdr_long(
160         XDR *xdrs,
161         int32_t *lp)
162 {
163
164         if (xdrs->x_op == XDR_ENCODE)
165                 return (XDR_PUTLONG(xdrs, lp));
166
167         if (xdrs->x_op == XDR_DECODE)
168                 return (XDR_GETLONG(xdrs, lp));
169
170         if (xdrs->x_op == XDR_FREE)
171                 return (TRUE);
172
173         return (FALSE);
174 }
175
176 bool_t
177 xdr_int32_t(
178         XDR *xdrs,
179         int32_t *lp)
180 {
181
182         if (xdrs->x_op == XDR_ENCODE)
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
194 /*
195  * XDR unsigned long integers
196  * same as xdr_long - open coded to save a proc call!
197  */
198 bool_t
199 xdr_u_long(
200         XDR *xdrs,
201         uint32_t *ulp)
202 {
203
204         if (xdrs->x_op == XDR_DECODE)
205                 return (XDR_GETLONG(xdrs, (int32_t *)ulp));
206         if (xdrs->x_op == XDR_ENCODE)
207                 return (XDR_PUTLONG(xdrs, (int32_t *)ulp));
208         if (xdrs->x_op == XDR_FREE)
209                 return (TRUE);
210         return (FALSE);
211 }
212
213 bool_t
214 xdr_uint32_t(
215         XDR *xdrs,
216         uint32_t *ulp)
217 {
218
219         if (xdrs->x_op == XDR_DECODE)
220                 return (XDR_GETLONG(xdrs, (int32_t *)ulp));
221         if (xdrs->x_op == XDR_ENCODE)
222                 return (XDR_PUTLONG(xdrs, (int32_t *)ulp));
223         if (xdrs->x_op == XDR_FREE)
224                 return (TRUE);
225         return (FALSE);
226 }
227
228 /*
229  * XDR short integers
230  */
231 bool_t
232 xdr_short(
233         XDR *xdrs,
234         int16_t *sp)
235 {
236         int32_t l;
237
238         switch (xdrs->x_op) {
239
240         case XDR_ENCODE:
241                 l = (int32_t) *sp;
242                 return (XDR_PUTLONG(xdrs, &l));
243
244         case XDR_DECODE:
245                 if (!XDR_GETLONG(xdrs, &l)) {
246                         return (FALSE);
247                 }
248                 *sp = (int16_t) l;
249                 return (TRUE);
250
251         case XDR_FREE:
252                 return (TRUE);
253         }
254         return (FALSE);
255 }
256
257 bool_t
258 xdr_int16_t(
259         XDR *xdrs,
260         int16_t *sp)
261 {
262         int32_t l;
263
264         switch (xdrs->x_op) {
265
266         case XDR_ENCODE:
267                 l = (int32_t) *sp;
268                 return (XDR_PUTLONG(xdrs, &l));
269
270         case XDR_DECODE:
271                 if (!XDR_GETLONG(xdrs, &l)) {
272                         return (FALSE);
273                 }
274                 *sp = (int16_t) l;
275                 return (TRUE);
276
277         case XDR_FREE:
278                 return (TRUE);
279         }
280         return (FALSE);
281 }
282
283 /*
284  * XDR unsigned short integers
285  */
286 bool_t
287 xdr_u_short(
288         XDR *xdrs,
289         uint16_t *usp)
290 {
291         uint32_t l;
292
293         switch (xdrs->x_op) {
294
295         case XDR_ENCODE:
296                 l = (uint32_t) *usp;
297                 return (XDR_PUTLONG(xdrs, (int32_t *)&l));
298
299         case XDR_DECODE:
300                 if (!XDR_GETLONG(xdrs, (int32_t *)&l)) {
301                         return (FALSE);
302                 }
303                 *usp = (uint16_t) l;
304                 return (TRUE);
305
306         case XDR_FREE:
307                 return (TRUE);
308         }
309         return (FALSE);
310 }
311
312 bool_t
313 xdr_uint16_t(
314         XDR *xdrs,
315         uint16_t *usp)
316 {
317         uint32_t l;
318
319         switch (xdrs->x_op) {
320
321         case XDR_ENCODE:
322                 l = (uint32_t) *usp;
323                 return (XDR_PUTLONG(xdrs, (int32_t *)&l));
324
325         case XDR_DECODE:
326                 if (!XDR_GETLONG(xdrs, (int32_t *)&l)) {
327                         return (FALSE);
328                 }
329                 *usp = (uint16_t) l;
330                 return (TRUE);
331
332         case XDR_FREE:
333                 return (TRUE);
334         }
335         return (FALSE);
336 }
337
338
339 /*
340  * XDR a char
341  */
342 bool_t
343 xdr_char(
344         XDR *xdrs,
345         char *cp)
346 {
347         int i;
348
349         i = (*cp);
350         if (!xdr_int(xdrs, &i)) {
351                 return (FALSE);
352         }
353         *cp = i;
354         return (TRUE);
355 }
356
357 /*
358  * XDR an unsigned char
359  */
360 bool_t
361 xdr_u_char(
362         XDR *xdrs,
363         uchar_t *cp)
364 {
365         uint_t u;
366
367         u = (*cp);
368         if (!xdr_u_int(xdrs, &u)) {
369                 return (FALSE);
370         }
371         *cp = u;
372         return (TRUE);
373 }
374
375 /*
376  * XDR booleans
377  */
378 bool_t
379 xdr_bool(
380         XDR *xdrs,
381         bool_t *bp)
382 {
383         int32_t lb;
384
385         switch (xdrs->x_op) {
386
387         case XDR_ENCODE:
388                 lb = *bp ? XDR_TRUE : XDR_FALSE;
389                 return (XDR_PUTLONG(xdrs, &lb));
390
391         case XDR_DECODE:
392                 if (!XDR_GETLONG(xdrs, &lb)) {
393                         return (FALSE);
394                 }
395                 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
396                 return (TRUE);
397
398         case XDR_FREE:
399                 return (TRUE);
400         }
401         return (FALSE);
402 }
403
404 /*
405  * XDR enumerations
406  */
407 bool_t
408 xdr_enum(
409         XDR *xdrs,
410         enum_t *ep)
411 {
412 #ifndef lint
413         enum sizecheck { SIZEVAL };     /* used to find the size of an enum */
414
415         /*
416          * enums are treated as ints
417          */
418         if (sizeof (enum sizecheck) == sizeof (int32_t)) {
419                 return (xdr_int32_t(xdrs, (int32_t *)ep));
420         } else if (sizeof (enum sizecheck) == sizeof (int16_t)) {
421                 return (xdr_int16_t(xdrs, (int16_t *)ep));
422         } else {
423                 return (FALSE);
424         }
425 #else
426         (void) (xdr_int16_t(xdrs, (int16_t *)ep));
427         return (xdr_int32_t(xdrs, (int32_t *)ep));
428 #endif
429 }
430
431 /*
432  * XDR opaque data
433  * Allows the specification of a fixed size sequence of opaque bytes.
434  * cp points to the opaque object and cnt gives the byte length.
435  */
436 bool_t
437 xdr_opaque(
438         XDR *xdrs,
439         void *cp,
440         uint_t cnt)
441 {
442         uint_t rndup;
443         static crud[BYTES_PER_XDR_UNIT];
444
445         /*
446          * if no data we are done
447          */
448         if (cnt == 0)
449                 return (TRUE);
450
451         /*
452          * round byte count to full xdr units
453          */
454         rndup = cnt % BYTES_PER_XDR_UNIT;
455         if (rndup > 0)
456                 rndup = BYTES_PER_XDR_UNIT - rndup;
457
458         if (xdrs->x_op == XDR_DECODE) {
459                 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
460                         return (FALSE);
461                 }
462                 if (rndup == 0)
463                         return (TRUE);
464                 return (XDR_GETBYTES(xdrs, crud, rndup));
465         }
466
467         if (xdrs->x_op == XDR_ENCODE) {
468                 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
469                         return (FALSE);
470                 }
471                 if (rndup == 0)
472                         return (TRUE);
473                 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
474         }
475
476         if (xdrs->x_op == XDR_FREE) {
477                 return (TRUE);
478         }
479
480         return (FALSE);
481 }
482
483 /*
484  * XDR counted bytes
485  * *cpp is a pointer to the bytes, *sizep is the count.
486  * If *cpp is NULL maxsize bytes are allocated
487  */
488 bool_t
489 xdr_bytes(
490         XDR *xdrs,
491         char **cpp,
492         uint_t *sizep,
493         uint_t maxsize)
494 {
495         char *sp = *cpp;  /* sp is the actual string pointer */
496         uint_t nodesize;
497
498         /*
499          * first deal with the length since xdr bytes are counted
500          */
501         if (! xdr_u_int(xdrs, sizep)) {
502                 return (FALSE);
503         }
504         nodesize = *sizep;
505         if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
506                 return (FALSE);
507         }
508
509         /*
510          * now deal with the actual bytes
511          */
512         switch (xdrs->x_op) {
513
514         case XDR_DECODE:
515                 if (nodesize == 0) {
516                         return (TRUE);
517                 }
518                 if (sp == NULL) {
519                         *cpp = sp = (char *)mem_alloc(nodesize);
520                 }
521                 if (sp == NULL) {
522                         (void) fprintf(stderr, "xdr_bytes: out of memory\n");
523                         return (FALSE);
524                 }
525                 /* fall into ... */
526
527         case XDR_ENCODE:
528                 return (xdr_opaque(xdrs, sp, nodesize));
529
530         case XDR_FREE:
531                 if (sp != NULL) {
532                         mem_free(sp, nodesize);
533                         *cpp = NULL;
534                 }
535                 return (TRUE);
536         }
537         return (FALSE);
538 }
539
540 /*
541  * Implemented here due to commonality of the object.
542  */
543 bool_t
544 xdr_netobj(
545         XDR *xdrs,
546         struct netobj *np)
547 {
548
549         return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
550 }
551
552 /*
553  * XDR a descriminated union
554  * Support routine for discriminated unions.
555  * You create an array of xdrdiscrim structures, terminated with
556  * an entry with a null procedure pointer.  The routine gets
557  * the discriminant value and then searches the array of xdrdiscrims
558  * looking for that value.  It calls the procedure given in the xdrdiscrim
559  * to handle the discriminant.  If there is no specific routine a default
560  * routine may be called.
561  * If there is no specific or default routine an error is returned.
562  */
563 bool_t
564 xdr_union(
565         XDR *xdrs,
566         enum_t *dscmp,          /* enum to decide which arm to work on */
567         char *unp,              /* the union itself */
568         struct xdr_discrim *choices,    /* [value, xdr proc] for each arm */
569         xdrproc_t dfault)       /* default xdr routine */
570 {
571         enum_t dscm;
572
573         /*
574          * we deal with the discriminator;  it's an enum
575          */
576         if (! xdr_enum(xdrs, dscmp)) {
577                 return (FALSE);
578         }
579         dscm = *dscmp;
580
581         /*
582          * search choices for a value that matches the discriminator.
583          * if we find one, execute the xdr routine for that value.
584          */
585         for (; choices->proc != NULL_xdrproc_t; choices++) {
586                 if (choices->value == dscm)
587                         return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
588         }
589
590         /*
591          * no match - execute the default xdr routine if there is one
592          */
593         return ((dfault == NULL_xdrproc_t) ? FALSE :
594             (*dfault)(xdrs, unp, LASTUNSIGNED));
595 }
596
597
598 /*
599  * Non-portable xdr primitives.
600  * Care should be taken when moving these routines to new architectures.
601  */
602
603
604 /*
605  * XDR null terminated ASCII strings
606  * xdr_string deals with "C strings" - arrays of bytes that are
607  * terminated by a NULL character.  The parameter cpp references a
608  * pointer to storage; If the pointer is null, then the necessary
609  * storage is allocated.  The last parameter is the max allowed length
610  * of the string as specified by a protocol.
611  */
612 bool_t
613 xdr_string(
614         XDR *xdrs,
615         char **cpp,
616         uint_t maxsize)
617 {
618         char *sp = *cpp;  /* sp is the actual string pointer */
619         uint_t size;
620         uint_t nodesize;
621
622         /*
623          * first deal with the length since xdr strings are counted-strings
624          */
625         switch (xdrs->x_op) {
626         case XDR_FREE:
627                 if (sp == NULL) {
628                         return(TRUE);   /* already free */
629                 }
630                 /* fall through... */
631         case XDR_ENCODE:
632                 size = strlen(sp);
633                 break;
634         }
635         if (! xdr_u_int(xdrs, &size)) {
636                 return (FALSE);
637         }
638         if (size > maxsize) {
639                 return (FALSE);
640         }
641         nodesize = size + 1;
642
643         /*
644          * now deal with the actual bytes
645          */
646         switch (xdrs->x_op) {
647
648         case XDR_DECODE:
649                 if (nodesize == 0) {
650                         return (TRUE);
651                 }
652                 if (sp == NULL)
653                         *cpp = sp = (char *)mem_alloc(nodesize);
654                 if (sp == NULL) {
655                         (void) fprintf(stderr, "xdr_string: out of memory\n");
656                         return (FALSE);
657                 }
658                 sp[size] = 0;
659                 /* fall into ... */
660
661         case XDR_ENCODE:
662                 return (xdr_opaque(xdrs, sp, size));
663
664         case XDR_FREE:
665                 mem_free(sp, nodesize);
666                 *cpp = NULL;
667                 return (TRUE);
668         }
669         return (FALSE);
670 }
671
672 /* 
673  * Wrapper for xdr_string that can be called directly from 
674  * routines like clnt_call
675  */
676 bool_t
677 xdr_wrapstring(
678         XDR *xdrs,
679         char **cpp)
680 {
681         if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
682                 return (TRUE);
683         }
684         return (FALSE);
685 }