diff options
Diffstat (limited to 'lib/libc/xdr')
-rw-r--r-- | lib/libc/xdr/Makefile.inc | 50 | ||||
-rw-r--r-- | lib/libc/xdr/Symbol.map | 45 | ||||
-rw-r--r-- | lib/libc/xdr/xdr.3 | 829 | ||||
-rw-r--r-- | lib/libc/xdr/xdr.c | 875 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_array.c | 163 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_float.c | 309 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_mem.c | 260 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_rec.c | 788 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_reference.c | 143 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_sizeof.c | 168 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_stdio.c | 196 |
11 files changed, 3826 insertions, 0 deletions
diff --git a/lib/libc/xdr/Makefile.inc b/lib/libc/xdr/Makefile.inc new file mode 100644 index 0000000..2d360ac --- /dev/null +++ b/lib/libc/xdr/Makefile.inc @@ -0,0 +1,50 @@ +# @(#)Makefile 5.11 (Berkeley) 9/6/90 +# $FreeBSD$ + +.PATH: ${.CURDIR}/xdr ${.CURDIR}/. +SRCS+= xdr.c xdr_array.c xdr_float.c xdr_mem.c \ + xdr_rec.c xdr_reference.c xdr_stdio.c + +SYM_MAPS+= ${.CURDIR}/xdr/Symbol.map + +MAN+= xdr.3 + +MLINKS+= rpc_xdr.3 xdr_accepted_reply.3 \ + rpc_xdr.3 xdr_authsys_parms.3 \ + rpc_xdr.3 xdr_callhdr.3 \ + rpc_xdr.3 xdr_callmsg.3 \ + rpc_xdr.3 xdr_opaque_auth.3 \ + rpc_xdr.3 xdr_rejected_reply.3 \ + rpc_xdr.3 xdr_replymsg.3 \ + xdr.3 xdr_array.3 \ + xdr.3 xdr_bool.3 \ + xdr.3 xdr_bytes.3 \ + xdr.3 xdr_char.3 \ + xdr.3 xdr_destroy.3 \ + xdr.3 xdr_double.3 \ + xdr.3 xdr_enum.3 \ + xdr.3 xdr_float.3 \ + xdr.3 xdr_free.3 \ + xdr.3 xdr_getpos.3 \ + xdr.3 xdr_inline.3 \ + xdr.3 xdr_int.3 \ + xdr.3 xdr_long.3 \ + xdr.3 xdrmem_create.3 \ + xdr.3 xdr_opaque.3 \ + xdr.3 xdr_pointer.3 \ + xdr.3 xdrrec_create.3 \ + xdr.3 xdrrec_endofrecord.3 \ + xdr.3 xdrrec_eof.3 \ + xdr.3 xdrrec_skiprecord.3 \ + xdr.3 xdr_reference.3 \ + xdr.3 xdr_setpos.3 \ + xdr.3 xdr_short.3 \ + xdr.3 xdrstdio_create.3 \ + xdr.3 xdr_string.3 \ + xdr.3 xdr_u_char.3 \ + xdr.3 xdr_u_long.3 \ + xdr.3 xdr_u_short.3 \ + xdr.3 xdr_union.3 \ + xdr.3 xdr_vector.3 \ + xdr.3 xdr_void.3 \ + xdr.3 xdr_wrapstring.3 diff --git a/lib/libc/xdr/Symbol.map b/lib/libc/xdr/Symbol.map new file mode 100644 index 0000000..f279dc5 --- /dev/null +++ b/lib/libc/xdr/Symbol.map @@ -0,0 +1,45 @@ +# $FreeBSD$ + +FBSD_1.0 { + xdr_free; + xdr_void; + xdr_int; + xdr_u_int; + xdr_long; + xdr_u_long; + xdr_int32_t; + xdr_u_int32_t; + xdr_short; + xdr_u_short; + xdr_int16_t; + xdr_u_int16_t; + xdr_char; + xdr_u_char; + xdr_bool; + xdr_enum; + xdr_opaque; + xdr_bytes; + xdr_netobj; + xdr_union; + xdr_string; + xdr_wrapstring; + xdr_int64_t; + xdr_u_int64_t; + xdr_hyper; + xdr_u_hyper; + xdr_longlong_t; + xdr_u_longlong_t; + xdr_array; + xdr_vector; + xdr_float; + xdr_double; + xdrmem_create; + xdrrec_create; + xdrrec_skiprecord; + xdrrec_eof; + xdrrec_endofrecord; + xdr_reference; + xdr_pointer; + #xdr_sizeof; # Why is xdr_sizeof.c not included in Makefileinc? + xdrstdio_create; +}; diff --git a/lib/libc/xdr/xdr.3 b/lib/libc/xdr/xdr.3 new file mode 100644 index 0000000..19c7e57 --- /dev/null +++ b/lib/libc/xdr/xdr.3 @@ -0,0 +1,829 @@ +.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI +.\" $FreeBSD$ +.\" +.Dd February 16, 1988 +.Dt XDR 3 +.Os +.Sh NAME +.Nm xdr , +.Nm xdr_array , +.Nm xdr_bool , +.Nm xdr_bytes , +.Nm xdr_char , +.Nm xdr_destroy , +.Nm xdr_double , +.Nm xdr_enum , +.Nm xdr_float , +.Nm xdr_free , +.Nm xdr_getpos , +.Nm xdr_hyper , +.Nm xdr_inline , +.Nm xdr_int , +.Nm xdr_long , +.Nm xdr_longlong_t , +.Nm xdrmem_create , +.Nm xdr_opaque , +.Nm xdr_pointer , +.Nm xdrrec_create , +.Nm xdrrec_endofrecord , +.Nm xdrrec_eof , +.Nm xdrrec_skiprecord , +.Nm xdr_reference , +.Nm xdr_setpos , +.Nm xdr_short , +.Nm xdrstdio_create , +.Nm xdr_string , +.Nm xdr_u_char , +.Nm xdr_u_hyper , +.Nm xdr_u_int , +.Nm xdr_u_long , +.Nm xdr_u_longlong_t , +.Nm xdr_u_short , +.Nm xdr_union , +.Nm xdr_vector , +.Nm xdr_void , +.Nm xdr_wrapstring +.Nd "library routines for external data representation" +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/types.h +.In rpc/xdr.h +.Pp +See +.Sx DESCRIPTION +for function declarations. +.Sh DESCRIPTION +These routines allow C programmers to describe +arbitrary data structures in a machine-independent fashion. +Data for remote procedure calls are transmitted using these +routines. +.Pp +.Bl -tag -width indent -compact +.It Xo +.Ft int +.Xc +.It Xo +.Fo xdr_array +.Fa "XDR *xdrs" +.Fa "char **arrp" +.Fa "u_int *sizep" +.Fa "u_int maxsize" +.Fa "u_int elsize" +.Fa "xdrproc_t elproc" +.Fc +.Xc +.Pp +A filter primitive that translates between variable-length +arrays +and their corresponding external representations. +The +.Fa arrp +argument +is the address of the pointer to the array, while +.Fa sizep +is the address of the element count of the array; +this element count cannot exceed +.Fa maxsize . +The +.Fa elsize +argument +is the +.Ic sizeof +each of the array's elements, and +.Fa elproc +is an +.Tn XDR +filter that translates between +the array elements' C form, and their external +representation. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_bool "XDR *xdrs" "bool_t *bp" +.Xc +.Pp +A filter primitive that translates between booleans (C +integers) +and their external representations. +When encoding data, this +filter produces values of either one or zero. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_bytes "XDR *xdrs" "char **sp" "u_int *sizep" "u_int maxsize" +.Xc +.Pp +A filter primitive that translates between counted byte +strings and their external representations. +The +.Fa sp +argument +is the address of the string pointer. +The length of the +string is located at address +.Fa sizep ; +strings cannot be longer than +.Fa maxsize . +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_char "XDR *xdrs" "char *cp" +.Xc +.Pp +A filter primitive that translates between C characters +and their external representations. +This routine returns one if it succeeds, zero otherwise. +Note: encoded characters are not packed, and occupy 4 bytes +each. +For arrays of characters, it is worthwhile to +consider +.Fn xdr_bytes , +.Fn xdr_opaque +or +.Fn xdr_string . +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdr_destroy "XDR *xdrs" +.Xc +.Pp +A macro that invokes the destroy routine associated with the +.Tn XDR +stream, +.Fa xdrs . +Destruction usually involves freeing private data structures +associated with the stream. +Using +.Fa xdrs +after invoking +.Fn xdr_destroy +is undefined. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_double "XDR *xdrs" "double *dp" +.Xc +.Pp +A filter primitive that translates between C +.Vt double +precision numbers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_enum "XDR *xdrs" "enum_t *ep" +.Xc +.Pp +A filter primitive that translates between C +.Vt enum Ns s +(actually integers) and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_float "XDR *xdrs" "float *fp" +.Xc +.Pp +A filter primitive that translates between C +.Vt float Ns s +and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdr_free "xdrproc_t proc" "void *objp" +.Xc +.Pp +Generic freeing routine. +The first argument is the +.Tn XDR +routine for the object being freed. +The second argument +is a pointer to the object itself. +Note: the pointer passed +to this routine is +.Em not +freed, but what it points to +.Em is +freed (recursively). +.Pp +.It Xo +.Ft u_int +.Xc +.It Xo +.Fn xdr_getpos "XDR *xdrs" +.Xc +.Pp +A macro that invokes the get\-position routine +associated with the +.Tn XDR +stream, +.Fa xdrs . +The routine returns an unsigned integer, +which indicates the position of the +.Tn XDR +byte stream. +A desirable feature of +.Tn XDR +streams is that simple arithmetic works with this number, +although the +.Tn XDR +stream instances need not guarantee this. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_hyper "XDR *xdrs" "quad_t *llp" +.Xc +A filter primitive that translates between ANSI C +.Vt "long long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft "long *" +.Xc +.It Xo +.Fn xdr_inline "XDR *xdrs" "int len" +.Xc +.Pp +A macro that invokes the in-line routine associated with the +.Tn XDR +stream, +.Fa xdrs . +The routine returns a pointer +to a contiguous piece of the stream's buffer; +.Fa len +is the byte length of the desired buffer. +Note: pointer is cast to +.Vt "long *" . +.Pp +Warning: +.Fn xdr_inline +may return +.Dv NULL +(0) +if it cannot allocate a contiguous piece of a buffer. +Therefore the behavior may vary among stream instances; +it exists for the sake of efficiency. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_int "XDR *xdrs" "int *ip" +.Xc +.Pp +A filter primitive that translates between C integers +and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_long "XDR *xdrs" "long *lp" +.Xc +.Pp +A filter primitive that translates between C +.Vt long +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_longlong_t "XDR *xdrs" "quad_t *llp" +.Xc +A filter primitive that translates between ANSI C +.Vt "long long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdrmem_create "XDR *xdrs" "char *addr" "u_int size" "enum xdr_op op" +.Xc +.Pp +This routine initializes the +.Tn XDR +stream object pointed to by +.Fa xdrs . +The stream's data is written to, or read from, +a chunk of memory at location +.Fa addr +whose length is no more than +.Fa size +bytes long. +The +.Fa op +argument +determines the direction of the +.Tn XDR +stream +(either +.Dv XDR_ENCODE , +.Dv XDR_DECODE , +or +.Dv XDR_FREE ) . +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_opaque "XDR *xdrs" "char *cp" "u_int cnt" +.Xc +.Pp +A filter primitive that translates between fixed size opaque +data +and its external representation. +The +.Fa cp +argument +is the address of the opaque object, and +.Fa cnt +is its size in bytes. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_pointer "XDR *xdrs" "char **objpp" "u_int objsize" "xdrproc_t xdrobj" +.Xc +.Pp +Like +.Fn xdr_reference +except that it serializes +.Dv NULL +pointers, whereas +.Fn xdr_reference +does not. +Thus, +.Fn xdr_pointer +can represent +recursive data structures, such as binary trees or +linked lists. +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fo xdrrec_create +.Fa "XDR *xdrs" +.Fa "u_int sendsize" +.Fa "u_int recvsize" +.Fa "void *handle" +.Fa "int \*(lp*readit\*(rp\*(lp\*(rp" +.Fa "int \*(lp*writeit\*(rp\*(lp\*(rp" +.Fc +.Xc +.Pp +This routine initializes the +.Tn XDR +stream object pointed to by +.Fa xdrs . +The stream's data is written to a buffer of size +.Fa sendsize ; +a value of zero indicates the system should use a suitable +default. +The stream's data is read from a buffer of size +.Fa recvsize ; +it too can be set to a suitable default by passing a zero +value. +When a stream's output buffer is full, +.Fn writeit +is called. +Similarly, when a stream's input buffer is empty, +.Fn readit +is called. +The behavior of these two routines is similar to +the +system calls +.Xr read 2 +and +.Xr write 2 , +except that +.Fa handle +is passed to the former routines as the first argument. +Note: the +.Tn XDR +stream's +.Fa op +field must be set by the caller. +.Pp +Warning: this +.Tn XDR +stream implements an intermediate record stream. +Therefore there are additional bytes in the stream +to provide record boundary information. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdrrec_endofrecord "XDR *xdrs" "int sendnow" +.Xc +.Pp +This routine can be invoked only on +streams created by +.Fn xdrrec_create . +The data in the output buffer is marked as a completed +record, +and the output buffer is optionally written out if +.Fa sendnow +is non-zero. +This routine returns one if it succeeds, zero +otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdrrec_eof "XDR *xdrs" +.Xc +.Pp +This routine can be invoked only on +streams created by +.Fn xdrrec_create . +After consuming the rest of the current record in the stream, +this routine returns one if the stream has no more input, +zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdrrec_skiprecord "XDR *xdrs" +.Xc +.Pp +This routine can be invoked only on +streams created by +.Fn xdrrec_create . +It tells the +.Tn XDR +implementation that the rest of the current record +in the stream's input buffer should be discarded. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_reference "XDR *xdrs" "char **pp" "u_int size" "xdrproc_t proc" +.Xc +.Pp +A primitive that provides pointer chasing within structures. +The +.Fa pp +argument +is the address of the pointer; +.Fa size +is the +.Ic sizeof +the structure that +.Fa *pp +points to; and +.Fa proc +is an +.Tn XDR +procedure that filters the structure +between its C form and its external representation. +This routine returns one if it succeeds, zero otherwise. +.Pp +Warning: this routine does not understand +.Dv NULL +pointers. +Use +.Fn xdr_pointer +instead. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_setpos "XDR *xdrs" "u_int pos" +.Xc +.Pp +A macro that invokes the set position routine associated with +the +.Tn XDR +stream +.Fa xdrs . +The +.Fa pos +argument +is a position value obtained from +.Fn xdr_getpos . +This routine returns one if the +.Tn XDR +stream could be repositioned, +and zero otherwise. +.Pp +Warning: it is difficult to reposition some types of +.Tn XDR +streams, so this routine may fail with one +type of stream and succeed with another. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_short "XDR *xdrs" "short *sp" +.Xc +.Pp +A filter primitive that translates between C +.Vt short +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Li "#ifdef _STDIO_H_" +.It Li "/* XDR using stdio library */" +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdrstdio_create "XDR *xdrs" "FILE *file" "enum xdr_op op" +.Xc +.It Li "#endif" +.Pp +This routine initializes the +.Tn XDR +stream object pointed to by +.Fa xdrs . +The +.Tn XDR +stream data is written to, or read from, the Standard +.Tn I/O +stream +.Fa file . +The +.Fa op +argument +determines the direction of the +.Tn XDR +stream (either +.Dv XDR_ENCODE , +.Dv XDR_DECODE , +or +.Dv XDR_FREE ) . +.Pp +Warning: the destroy routine associated with such +.Tn XDR +streams calls +.Xr fflush 3 +on the +.Fa file +stream, but never +.Xr fclose 3 . +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_string "XDR *xdrs" "char **sp" "u_int maxsize" +.Xc +.Pp +A filter primitive that translates between C strings and +their +corresponding external representations. +Strings cannot be longer than +.Fa maxsize . +Note: +.Fa sp +is the address of the string's pointer. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_char "XDR *xdrs" "unsigned char *ucp" +.Xc +.Pp +A filter primitive that translates between +.Vt unsigned +C characters and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_hyper "XDR *xdrs" "u_quad_t *ullp" +.Xc +A filter primitive that translates between +.Vt unsigned +ANSI C +.Vt long long +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_int "XDR *xdrs" "unsigned *up" +.Xc +.Pp +A filter primitive that translates between C +.Vt unsigned +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_long "XDR *xdrs" "unsigned long *ulp" +.Xc +.Pp +A filter primitive that translates between C +.Vt "unsigned long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_longlong_t "XDR *xdrs" "u_quad_t *ullp" +.Xc +A filter primitive that translates between +.Vt unsigned +ANSI C +.Vt "long long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_short "XDR *xdrs" "unsigned short *usp" +.Xc +.Pp +A filter primitive that translates between C +.Vt "unsigned short" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fo xdr_union +.Fa "XDR *xdrs" +.Fa "enum_t *dscmp" +.Fa "char *unp" +.Fa "const struct xdr_discrim *choices" +.Fa "xdrproc_t defaultarm" +.Fc +.Xc +.Pp +A filter primitive that translates between a discriminated C +.Vt union +and its corresponding external representation. +It first +translates the discriminant of the union located at +.Fa dscmp . +This discriminant is always an +.Vt enum_t . +Next the union located at +.Fa unp +is translated. +The +.Fa choices +argument +is a pointer to an array of +.Vt xdr_discrim +structures. +Each structure contains an ordered pair of +.Bq Va value , proc . +If the union's discriminant is equal to the associated +.Va value , +then the +.Fn proc +is called to translate the union. +The end of the +.Vt xdr_discrim +structure array is denoted by a routine of value +.Dv NULL . +If the discriminant is not found in the +.Fa choices +array, then the +.Fn defaultarm +procedure is called (if it is not +.Dv NULL ) . +Returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fo xdr_vector +.Fa "XDR *xdrs" +.Fa "char *arrp" +.Fa "u_int size" +.Fa "u_int elsize" +.Fa "xdrproc_t elproc" +.Fc +.Xc +.Pp +A filter primitive that translates between fixed-length +arrays +and their corresponding external representations. +The +.Fa arrp +argument +is the address of the pointer to the array, while +.Fa size +is the element count of the array. +The +.Fa elsize +argument +is the +.Ic sizeof +each of the array's elements, and +.Fa elproc +is an +.Tn XDR +filter that translates between +the array elements' C form, and their external +representation. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_void void +.Xc +.Pp +This routine always returns one. +It may be passed to +.Tn RPC +routines that require a function argument, +where nothing is to be done. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_wrapstring "XDR *xdrs" "char **sp" +.Xc +.Pp +A primitive that calls +.Fn xdr_string xdrs sp MAXUN.UNSIGNED ; +where +.Dv MAXUN.UNSIGNED +is the maximum value of an unsigned integer. +The +.Fn xdr_wrapstring +function +is handy because the +.Tn RPC +package passes a maximum of two +.Tn XDR +routines as arguments, and +.Fn xdr_string , +one of the most frequently used primitives, requires three. +Returns one if it succeeds, zero otherwise. +.El +.Sh SEE ALSO +.Xr rpc 3 +.Rs +.%T "eXternal Data Representation Standard: Protocol Specification" +.Re +.Rs +.%T "eXternal Data Representation: Sun Technical Notes" +.Re +.Rs +.%T "XDR: External Data Representation Standard" +.%O RFC1014 +.%Q "Sun Microsystems, Inc., USC\-ISI" +.Re diff --git a/lib/libc/xdr/xdr.c b/lib/libc/xdr/xdr.c new file mode 100644 index 0000000..c1e5eec --- /dev/null +++ b/lib/libc/xdr/xdr.c @@ -0,0 +1,875 @@ +/* $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr.c 1.35 87/08/12"; +static char *sccsid = "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include "namespace.h" +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include "un-namespace.h" + +typedef quad_t longlong_t; /* ANSI long long type */ +typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free(proc, objp) + xdrproc_t proc; + void *objp; +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc)(&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void(void) +{ + + return (TRUE); +} + + +/* + * XDR integers + */ +bool_t +xdr_int(xdrs, ip) + XDR *xdrs; + int *ip; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *ip; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *ip = (int) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int(xdrs, up) + XDR *xdrs; + u_int *up; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *up; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *up = (u_int) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR long integers + * same as xdr_u_long - open coded to save a proc call! + */ +bool_t +xdr_long(xdrs, lp) + XDR *xdrs; + long *lp; +{ + switch (xdrs->x_op) { + case XDR_ENCODE: + return (XDR_PUTLONG(xdrs, lp)); + case XDR_DECODE: + return (XDR_GETLONG(xdrs, lp)); + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned long integers + * same as xdr_long - open coded to save a proc call! + */ +bool_t +xdr_u_long(xdrs, ulp) + XDR *xdrs; + u_long *ulp; +{ + switch (xdrs->x_op) { + case XDR_ENCODE: + return (XDR_PUTLONG(xdrs, (long *)ulp)); + case XDR_DECODE: + return (XDR_GETLONG(xdrs, (long *)ulp)); + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR 32-bit integers + * same as xdr_u_int32_t - open coded to save a proc call! + */ +bool_t +xdr_int32_t(xdrs, int32_p) + XDR *xdrs; + int32_t *int32_p; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *int32_p; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *int32_p = (int32_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned 32-bit integers + * same as xdr_int32_t - open coded to save a proc call! + */ +bool_t +xdr_u_int32_t(xdrs, u_int32_p) + XDR *xdrs; + u_int32_t *u_int32_p; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *u_int32_p; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *u_int32_p = (u_int32_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR short integers + */ +bool_t +xdr_short(xdrs, sp) + XDR *xdrs; + short *sp; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *sp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *sp = (short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short(xdrs, usp) + XDR *xdrs; + u_short *usp; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *usp; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *usp = (u_short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR 16-bit integers + */ +bool_t +xdr_int16_t(xdrs, int16_p) + XDR *xdrs; + int16_t *int16_p; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *int16_p; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *int16_p = (int16_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned 16-bit integers + */ +bool_t +xdr_u_int16_t(xdrs, u_int16_p) + XDR *xdrs; + u_int16_t *u_int16_p; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *u_int16_p; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *u_int16_p = (u_int16_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR a char + */ +bool_t +xdr_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + int i; + + i = (*cp); + if (!xdr_int(xdrs, &i)) { + return (FALSE); + } + *cp = i; + return (TRUE); +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char(xdrs, cp) + XDR *xdrs; + u_char *cp; +{ + u_int u; + + u = (*cp); + if (!xdr_u_int(xdrs, &u)) { + return (FALSE); + } + *cp = u; + return (TRUE); +} + +/* + * XDR booleans + */ +bool_t +xdr_bool(xdrs, bp) + XDR *xdrs; + bool_t *bp; +{ + long lb; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return (XDR_PUTLONG(xdrs, &lb)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &lb)) { + return (FALSE); + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR enumerations + */ +bool_t +xdr_enum(xdrs, ep) + XDR *xdrs; + enum_t *ep; +{ + enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) { + return (xdr_long(xdrs, (long *)(void *)ep)); + } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) { + return (xdr_int(xdrs, (int *)(void *)ep)); + } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) { + return (xdr_short(xdrs, (short *)(void *)ep)); + } else { + return (FALSE); + } +} + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +bool_t +xdr_opaque(xdrs, cp, cnt) + XDR *xdrs; + caddr_t cp; + u_int cnt; +{ + u_int rndup; + static int crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return (TRUE); + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + if (xdrs->x_op == XDR_DECODE) { + if (!XDR_GETBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup)); + } + + if (xdrs->x_op == XDR_ENCODE) { + if (!XDR_PUTBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); + } + + if (xdrs->x_op == XDR_FREE) { + return (TRUE); + } + + return (FALSE); +} + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +bool_t +xdr_bytes(xdrs, cpp, sizep, maxsize) + XDR *xdrs; + char **cpp; + u_int *sizep; + u_int maxsize; +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) { + *cpp = sp = mem_alloc(nodesize); + } + if (sp == NULL) { + warnx("xdr_bytes: out of memory"); + return (FALSE); + } + /* FALLTHROUGH */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, nodesize)); + + case XDR_FREE: + if (sp != NULL) { + mem_free(sp, nodesize); + *cpp = NULL; + } + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj(xdrs, np) + XDR *xdrs; + struct netobj *np; +{ + + return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); +} + +/* + * XDR a descriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +bool_t +xdr_union(xdrs, dscmp, unp, choices, dfault) + XDR *xdrs; + enum_t *dscmp; /* enum to decide which arm to work on */ + char *unp; /* the union itself */ + const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ + xdrproc_t dfault; /* default xdr routine */ +{ + enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (! xdr_enum(xdrs, dscmp)) { + return (FALSE); + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) { + if (choices->value == dscm) + return ((*(choices->proc))(xdrs, unp)); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault)(xdrs, unp)); +} + + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +bool_t +xdr_string(xdrs, cpp, maxsize) + XDR *xdrs; + char **cpp; + u_int maxsize; +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) { + case XDR_FREE: + if (sp == NULL) { + return(TRUE); /* already free */ + } + /* FALLTHROUGH */ + case XDR_ENCODE: + size = strlen(sp); + break; + case XDR_DECODE: + break; + } + if (! xdr_u_int(xdrs, &size)) { + return (FALSE); + } + if (size > maxsize) { + return (FALSE); + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) + *cpp = sp = mem_alloc(nodesize); + if (sp == NULL) { + warnx("xdr_string: out of memory"); + return (FALSE); + } + sp[size] = 0; + /* FALLTHROUGH */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, size)); + + case XDR_FREE: + mem_free(sp, nodesize); + *cpp = NULL; + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; +{ + return xdr_string(xdrs, cpp, LASTUNSIGNED); +} + +/* + * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t() + * are in the "non-portable" section because they require that a `long long' + * be a 64-bit type. + * + * --thorpej@netbsd.org, November 30, 1999 + */ + +/* + * XDR 64-bit integers + */ +bool_t +xdr_int64_t(xdrs, llp) + XDR *xdrs; + int64_t *llp; +{ + u_long ul[2]; + + switch (xdrs->x_op) { + case XDR_ENCODE: + ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff; + ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff; + if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) + return (FALSE); + return (XDR_PUTLONG(xdrs, (long *)&ul[1])); + case XDR_DECODE: + if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) + return (FALSE); + if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) + return (FALSE); + *llp = (int64_t) + (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1])); + return (TRUE); + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR unsigned 64-bit integers + */ +bool_t +xdr_u_int64_t(xdrs, ullp) + XDR *xdrs; + u_int64_t *ullp; +{ + u_long ul[2]; + + switch (xdrs->x_op) { + case XDR_ENCODE: + ul[0] = (u_long)(*ullp >> 32) & 0xffffffff; + ul[1] = (u_long)(*ullp) & 0xffffffff; + if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) + return (FALSE); + return (XDR_PUTLONG(xdrs, (long *)&ul[1])); + case XDR_DECODE: + if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) + return (FALSE); + if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) + return (FALSE); + *ullp = (u_int64_t) + (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1])); + return (TRUE); + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR hypers + */ +bool_t +xdr_hyper(xdrs, llp) + XDR *xdrs; + longlong_t *llp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_int64_t(). + */ + return (xdr_int64_t(xdrs, (int64_t *)llp)); +} + + +/* + * XDR unsigned hypers + */ +bool_t +xdr_u_hyper(xdrs, ullp) + XDR *xdrs; + u_longlong_t *ullp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_u_int64_t(). + */ + return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp)); +} + + +/* + * XDR longlong_t's + */ +bool_t +xdr_longlong_t(xdrs, llp) + XDR *xdrs; + longlong_t *llp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_int64_t(). + */ + return (xdr_int64_t(xdrs, (int64_t *)llp)); +} + + +/* + * XDR u_longlong_t's + */ +bool_t +xdr_u_longlong_t(xdrs, ullp) + XDR *xdrs; + u_longlong_t *ullp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_u_int64_t(). + */ + return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp)); +} diff --git a/lib/libc/xdr/xdr_array.c b/lib/libc/xdr/xdr_array.c new file mode 100644 index 0000000..6c35452 --- /dev/null +++ b/lib/libc/xdr/xdr_array.c @@ -0,0 +1,163 @@ +/* $NetBSD: xdr_array.c,v 1.12 2000/01/22 22:19:18 mycroft Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr_array.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + +#include "namespace.h" +#include <err.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include "un-namespace.h" + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) + XDR *xdrs; + caddr_t *addrp; /* array pointer */ + u_int *sizep; /* number of elements */ + u_int maxsize; /* max numberof elements */ + u_int elsize; /* size in bytes of each element */ + xdrproc_t elproc; /* xdr routine to handle each element */ +{ + u_int i; + caddr_t target = *addrp; + u_int c; /* the actual element count */ + bool_t stat = TRUE; + u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (!xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + c = *sizep; + if ((c > maxsize || UINT_MAX/elsize < c) && + (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) { + case XDR_DECODE: + if (c == 0) + return (TRUE); + *addrp = target = mem_alloc(nodesize); + if (target == NULL) { + warnx("xdr_array: out of memory"); + return (FALSE); + } + memset(target, 0, nodesize); + break; + + case XDR_FREE: + return (TRUE); + + case XDR_ENCODE: + break; + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) { + stat = (*elproc)(xdrs, target); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) { + mem_free(*addrp, nodesize); + *addrp = NULL; + } + return (stat); +} + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) + XDR *xdrs; + char *basep; + u_int nelem; + u_int elemsize; + xdrproc_t xdr_elem; +{ + u_int i; + char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) { + if (!(*xdr_elem)(xdrs, elptr)) { + return(FALSE); + } + elptr += elemsize; + } + return(TRUE); +} diff --git a/lib/libc/xdr/xdr_float.c b/lib/libc/xdr/xdr_float.c new file mode 100644 index 0000000..0a4f09f --- /dev/null +++ b/lib/libc/xdr/xdr_float.c @@ -0,0 +1,309 @@ +/* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr_float.c, Generic XDR routines implementation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "floating point" xdr routines used to (de)serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include "namespace.h" +#include <sys/types.h> +#include <sys/param.h> + +#include <stdio.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include "un-namespace.h" + +/* + * NB: Not portable. + * This routine works on machines with IEEE754 FP and Vaxen. + */ + +#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ + defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ + defined(__arm__) || defined(__ppc__) || defined(__ia64__) || \ + defined(__arm26__) || defined(__sparc64__) || defined(__amd64__) +#include <machine/endian.h> +#define IEEEFP +#endif + +#if defined(__vax__) + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int mantissa: 23; + unsigned int exp : 8; + unsigned int sign : 1; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} sgl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x0, 0xff, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; +#endif /* vax */ + +bool_t +xdr_float(xdrs, fp) + XDR *xdrs; + float *fp; +{ +#ifndef IEEEFP + struct ieee_single is; + struct vax_single vs, *vsp; + struct sgl_limits *lim; + int i; +#endif + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef IEEEFP + return (XDR_PUTINT32(xdrs, (int32_t *)fp)); +#else + vs = *((struct vax_single *)fp); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((vs.mantissa2 == lim->s.mantissa2) && + (vs.exp == lim->s.exp) && + (vs.mantissa1 == lim->s.mantissa1)) { + is = lim->ieee; + goto shipit; + } + } + is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; + shipit: + is.sign = vs.sign; + return (XDR_PUTINT32(xdrs, (int32_t *)&is)); +#endif + + case XDR_DECODE: +#ifdef IEEEFP + return (XDR_GETINT32(xdrs, (int32_t *)fp)); +#else + vsp = (struct vax_single *)fp; + if (!XDR_GETINT32(xdrs, (int32_t *)&is)) + return (FALSE); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((is.exp == lim->ieee.exp) && + (is.mantissa == lim->ieee.mantissa)) { + *vsp = lim->s; + goto doneit; + } + } + vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = is.mantissa; + vsp->mantissa1 = (is.mantissa >> 16); + doneit: + vsp->sign = is.sign; + return (TRUE); +#endif + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +#if defined(__vax__) +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int mantissa1 : 20; + unsigned int exp : 11; + unsigned int sign : 1; + unsigned int mantissa2 : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; + +#endif /* vax */ + + +bool_t +xdr_double(xdrs, dp) + XDR *xdrs; + double *dp; +{ +#ifdef IEEEFP + int32_t *i32p; + bool_t rv; +#else + int32_t *lp; + struct ieee_double id; + struct vax_double vd; + struct dbl_limits *lim; + int i; +#endif + + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef IEEEFP + i32p = (int32_t *)(void *)dp; +#if BYTE_ORDER == BIG_ENDIAN + rv = XDR_PUTINT32(xdrs, i32p); + if (!rv) + return (rv); + rv = XDR_PUTINT32(xdrs, i32p+1); +#else + rv = XDR_PUTINT32(xdrs, i32p+1); + if (!rv) + return (rv); + rv = XDR_PUTINT32(xdrs, i32p); +#endif + return (rv); +#else + vd = *((struct vax_double *)dp); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((vd.mantissa4 == lim->d.mantissa4) && + (vd.mantissa3 == lim->d.mantissa3) && + (vd.mantissa2 == lim->d.mantissa2) && + (vd.mantissa1 == lim->d.mantissa1) && + (vd.exp == lim->d.exp)) { + id = lim->ieee; + goto shipit; + } + } + id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); + id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | + (vd.mantissa3 << 13) | + ((vd.mantissa4 >> 3) & MASK(13)); + shipit: + id.sign = vd.sign; + lp = (int32_t *)&id; + return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); +#endif + + case XDR_DECODE: +#ifdef IEEEFP + i32p = (int32_t *)(void *)dp; +#if BYTE_ORDER == BIG_ENDIAN + rv = XDR_GETINT32(xdrs, i32p); + if (!rv) + return (rv); + rv = XDR_GETINT32(xdrs, i32p+1); +#else + rv = XDR_GETINT32(xdrs, i32p+1); + if (!rv) + return (rv); + rv = XDR_GETINT32(xdrs, i32p); +#endif + return (rv); +#else + lp = (int32_t *)&id; + if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) + return (FALSE); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((id.mantissa2 == lim->ieee.mantissa2) && + (id.mantissa1 == lim->ieee.mantissa1) && + (id.exp == lim->ieee.exp)) { + vd = lim->d; + goto doneit; + } + } + vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + vd.mantissa1 = (id.mantissa1 >> 13); + vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | + (id.mantissa2 >> 29); + vd.mantissa3 = (id.mantissa2 >> 13); + vd.mantissa4 = (id.mantissa2 << 3); + doneit: + vd.sign = id.sign; + *dp = *((double *)&vd); + return (TRUE); +#endif + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} diff --git a/lib/libc/xdr/xdr_mem.c b/lib/libc/xdr/xdr_mem.c new file mode 100644 index 0000000..138269c --- /dev/null +++ b/lib/libc/xdr/xdr_mem.c @@ -0,0 +1,260 @@ +/* $NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + +#include "namespace.h" +#include <sys/types.h> + +#include <netinet/in.h> + +#include <string.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include "un-namespace.h" + +static void xdrmem_destroy(XDR *); +static bool_t xdrmem_getlong_aligned(XDR *, long *); +static bool_t xdrmem_putlong_aligned(XDR *, const long *); +static bool_t xdrmem_getlong_unaligned(XDR *, long *); +static bool_t xdrmem_putlong_unaligned(XDR *, const long *); +static bool_t xdrmem_getbytes(XDR *, char *, u_int); +static bool_t xdrmem_putbytes(XDR *, const char *, u_int); +/* XXX: w/64-bit pointers, u_int not enough! */ +static u_int xdrmem_getpos(XDR *); +static bool_t xdrmem_setpos(XDR *, u_int); +static int32_t *xdrmem_inline_aligned(XDR *, u_int); +static int32_t *xdrmem_inline_unaligned(XDR *, u_int); + +static const struct xdr_ops xdrmem_ops_aligned = { + xdrmem_getlong_aligned, + xdrmem_putlong_aligned, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline_aligned, + xdrmem_destroy +}; + +static const struct xdr_ops xdrmem_ops_unaligned = { + xdrmem_getlong_unaligned, + xdrmem_putlong_unaligned, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline_unaligned, + xdrmem_destroy +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create(xdrs, addr, size, op) + XDR *xdrs; + char *addr; + u_int size; + enum xdr_op op; +{ + + xdrs->x_op = op; + xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1)) + ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} + +/*ARGSUSED*/ +static void +xdrmem_destroy(xdrs) + XDR *xdrs; +{ + +} + +static bool_t +xdrmem_getlong_aligned(xdrs, lp) + XDR *xdrs; + long *lp; +{ + + if (xdrs->x_handy < sizeof(int32_t)) + return (FALSE); + xdrs->x_handy -= sizeof(int32_t); + *lp = ntohl(*(u_int32_t *)xdrs->x_private); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_putlong_aligned(xdrs, lp) + XDR *xdrs; + const long *lp; +{ + + if (xdrs->x_handy < sizeof(int32_t)) + return (FALSE); + xdrs->x_handy -= sizeof(int32_t); + *(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_getlong_unaligned(xdrs, lp) + XDR *xdrs; + long *lp; +{ + u_int32_t l; + + if (xdrs->x_handy < sizeof(int32_t)) + return (FALSE); + xdrs->x_handy -= sizeof(int32_t); + memmove(&l, xdrs->x_private, sizeof(int32_t)); + *lp = ntohl(l); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_putlong_unaligned(xdrs, lp) + XDR *xdrs; + const long *lp; +{ + u_int32_t l; + + if (xdrs->x_handy < sizeof(int32_t)) + return (FALSE); + xdrs->x_handy -= sizeof(int32_t); + l = htonl((u_int32_t)*lp); + memmove(xdrs->x_private, &l, sizeof(int32_t)); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_getbytes(xdrs, addr, len) + XDR *xdrs; + char *addr; + u_int len; +{ + + if (xdrs->x_handy < len) + return (FALSE); + xdrs->x_handy -= len; + memmove(addr, xdrs->x_private, len); + xdrs->x_private = (char *)xdrs->x_private + len; + return (TRUE); +} + +static bool_t +xdrmem_putbytes(xdrs, addr, len) + XDR *xdrs; + const char *addr; + u_int len; +{ + + if (xdrs->x_handy < len) + return (FALSE); + xdrs->x_handy -= len; + memmove(xdrs->x_private, addr, len); + xdrs->x_private = (char *)xdrs->x_private + len; + return (TRUE); +} + +static u_int +xdrmem_getpos(xdrs) + XDR *xdrs; +{ + + /* XXX w/64-bit pointers, u_int not enough! */ + return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base); +} + +static bool_t +xdrmem_setpos(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + char *newaddr = xdrs->x_base + pos; + char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy; + + if (newaddr > lastaddr) + return (FALSE); + xdrs->x_private = newaddr; + xdrs->x_handy = (u_int)(lastaddr - newaddr); /* XXX sizeof(u_int) <? sizeof(ptrdiff_t) */ + return (TRUE); +} + +static int32_t * +xdrmem_inline_aligned(xdrs, len) + XDR *xdrs; + u_int len; +{ + int32_t *buf = 0; + + if (xdrs->x_handy >= len) { + xdrs->x_handy -= len; + buf = (int32_t *)xdrs->x_private; + xdrs->x_private = (char *)xdrs->x_private + len; + } + return (buf); +} + +/* ARGSUSED */ +static int32_t * +xdrmem_inline_unaligned(xdrs, len) + XDR *xdrs; + u_int len; +{ + + return (0); +} diff --git a/lib/libc/xdr/xdr_rec.c b/lib/libc/xdr/xdr_rec.c new file mode 100644 index 0000000..a50d141 --- /dev/null +++ b/lib/libc/xdr/xdr_rec.c @@ -0,0 +1,788 @@ +/* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" + * layer above tcp (for rpc's use). + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These routines interface XDRSTREAMS to a tcp/ip connection. + * There is a record marking layer between the xdr stream + * and the tcp transport level. A record is composed on one or more + * record fragments. A record fragment is a thirty-two bit header followed + * by n bytes of data, where n is contained in the header. The header + * is represented as a htonl(u_long). Thegh order bit encodes + * whether or not the fragment is the last fragment of the record + * (1 => fragment is last, 0 => more fragments to follow. + * The other 31 bits encode the byte length of the fragment. + */ + +#include "namespace.h" +#include <sys/types.h> + +#include <netinet/in.h> + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/svc.h> +#include <rpc/clnt.h> +#include <sys/stddef.h> +#include "un-namespace.h" +#include "rpc_com.h" + +static bool_t xdrrec_getlong(XDR *, long *); +static bool_t xdrrec_putlong(XDR *, const long *); +static bool_t xdrrec_getbytes(XDR *, char *, u_int); + +static bool_t xdrrec_putbytes(XDR *, const char *, u_int); +static u_int xdrrec_getpos(XDR *); +static bool_t xdrrec_setpos(XDR *, u_int); +static int32_t *xdrrec_inline(XDR *, u_int); +static void xdrrec_destroy(XDR *); + +static const struct xdr_ops xdrrec_ops = { + xdrrec_getlong, + xdrrec_putlong, + xdrrec_getbytes, + xdrrec_putbytes, + xdrrec_getpos, + xdrrec_setpos, + xdrrec_inline, + xdrrec_destroy +}; + +/* + * A record is composed of one or more record fragments. + * A record fragment is a four-byte header followed by zero to + * 2**32-1 bytes. The header is treated as a long unsigned and is + * encode/decoded to the network via htonl/ntohl. The low order 31 bits + * are a byte count of the fragment. The highest order bit is a boolean: + * 1 => this fragment is the last fragment of the record, + * 0 => this fragment is followed by more fragment(s). + * + * The fragment/record machinery is not general; it is constructed to + * meet the needs of xdr and rpc based on tcp. + */ + +#define LAST_FRAG ((u_int32_t)(1 << 31)) + +typedef struct rec_strm { + char *tcp_handle; + /* + * out-goung bits + */ + int (*writeit)(void *, void *, int); + char *out_base; /* output buffer (points to frag header) */ + char *out_finger; /* next output position */ + char *out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of curren fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit)(void *, void *, int); + u_long in_size; /* fixed size of the input buffer */ + char *in_base; + char *in_finger; /* location of next byte to be had */ + char *in_boundry; /* can read up to this location */ + long fbtbc; /* fragment bytes to be consumed */ + bool_t last_frag; + u_int sendsize; + u_int recvsize; + + bool_t nonblock; + bool_t in_haveheader; + u_int32_t in_header; + char *in_hdrp; + int in_hdrlen; + int in_reclen; + int in_received; + int in_maxrec; +} RECSTREAM; + +static u_int fix_buf_size(u_int); +static bool_t flush_out(RECSTREAM *, bool_t); +static bool_t fill_input_buf(RECSTREAM *); +static bool_t get_input_bytes(RECSTREAM *, char *, int); +static bool_t set_input_fragment(RECSTREAM *); +static bool_t skip_input_bytes(RECSTREAM *, long); +static bool_t realloc_stream(RECSTREAM *, int); + + +/* + * Create an xdr handle for xdrrec + * xdrrec_create fills in xdrs. Sendsize and recvsize are + * send and recv buffer sizes (0 => use default). + * tcp_handle is an opaque handle that is passed as the first parameter to + * the procedures readit and writeit. Readit and writeit are read and + * write respectively. They are like the system + * calls expect that they take an opaque handle rather than an fd. + */ +void +xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) + XDR *xdrs; + u_int sendsize; + u_int recvsize; + void *tcp_handle; + /* like read, but pass it a tcp_handle, not sock */ + int (*readit)(void *, void *, int); + /* like write, but pass it a tcp_handle, not sock */ + int (*writeit)(void *, void *, int); +{ + RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); + + if (rstrm == NULL) { + warnx("xdrrec_create: out of memory"); + /* + * This is bad. Should rework xdrrec_create to + * return a handle, and in this case return NULL + */ + return; + } + rstrm->sendsize = sendsize = fix_buf_size(sendsize); + rstrm->out_base = mem_alloc(rstrm->sendsize); + if (rstrm->out_base == NULL) { + warnx("xdrrec_create: out of memory"); + mem_free(rstrm, sizeof(RECSTREAM)); + return; + } + rstrm->recvsize = recvsize = fix_buf_size(recvsize); + rstrm->in_base = mem_alloc(recvsize); + if (rstrm->in_base == NULL) { + warnx("xdrrec_create: out of memory"); + mem_free(rstrm->out_base, sendsize); + mem_free(rstrm, sizeof(RECSTREAM)); + return; + } + /* + * now the rest ... + */ + xdrs->x_ops = &xdrrec_ops; + xdrs->x_private = rstrm; + rstrm->tcp_handle = tcp_handle; + rstrm->readit = readit; + rstrm->writeit = writeit; + rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; + rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; + rstrm->out_finger += sizeof(u_int32_t); + rstrm->out_boundry += sendsize; + rstrm->frag_sent = FALSE; + rstrm->in_size = recvsize; + rstrm->in_boundry = rstrm->in_base; + rstrm->in_finger = (rstrm->in_boundry += recvsize); + rstrm->fbtbc = 0; + rstrm->last_frag = TRUE; + rstrm->in_haveheader = FALSE; + rstrm->in_hdrlen = 0; + rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; + rstrm->nonblock = FALSE; + rstrm->in_reclen = 0; + rstrm->in_received = 0; +} + + +/* + * The reoutines defined below are the xdr ops which will go into the + * xdr handle filled in by xdrrec_create. + */ + +static bool_t +xdrrec_getlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger); + int32_t mylong; + + /* first try the inline, fast case */ + if ((rstrm->fbtbc >= sizeof(int32_t)) && + (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { + *lp = (long)ntohl((u_int32_t)(*buflp)); + rstrm->fbtbc -= sizeof(int32_t); + rstrm->in_finger += sizeof(int32_t); + } else { + if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong, + sizeof(int32_t))) + return (FALSE); + *lp = (long)ntohl((u_int32_t)mylong); + } + return (TRUE); +} + +static bool_t +xdrrec_putlong(xdrs, lp) + XDR *xdrs; + const long *lp; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); + + if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= sizeof(int32_t); + rstrm->frag_sent = TRUE; + if (! flush_out(rstrm, FALSE)) + return (FALSE); + dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); + rstrm->out_finger += sizeof(int32_t); + } + *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); + return (TRUE); +} + +static bool_t /* must manage buffers, fragments, and records */ +xdrrec_getbytes(xdrs, addr, len) + XDR *xdrs; + char *addr; + u_int len; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + int current; + + while (len > 0) { + current = (int)rstrm->fbtbc; + if (current == 0) { + if (rstrm->last_frag) + return (FALSE); + if (! set_input_fragment(rstrm)) + return (FALSE); + continue; + } + current = (len < current) ? len : current; + if (! get_input_bytes(rstrm, addr, current)) + return (FALSE); + addr += current; + rstrm->fbtbc -= current; + len -= current; + } + return (TRUE); +} + +static bool_t +xdrrec_putbytes(xdrs, addr, len) + XDR *xdrs; + const char *addr; + u_int len; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + size_t current; + + while (len > 0) { + current = (size_t)((u_long)rstrm->out_boundry - + (u_long)rstrm->out_finger); + current = (len < current) ? len : current; + memmove(rstrm->out_finger, addr, current); + rstrm->out_finger += current; + addr += current; + len -= current; + if (rstrm->out_finger == rstrm->out_boundry) { + rstrm->frag_sent = TRUE; + if (! flush_out(rstrm, FALSE)) + return (FALSE); + } + } + return (TRUE); +} + +static u_int +xdrrec_getpos(xdrs) + XDR *xdrs; +{ + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + off_t pos; + + pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1); + if (pos != -1) + switch (xdrs->x_op) { + + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; + + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; + + default: + pos = (off_t) -1; + break; + } + return ((u_int) pos); +} + +static bool_t +xdrrec_setpos(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + u_int currpos = xdrrec_getpos(xdrs); + int delta = currpos - pos; + char *newpos; + + if ((int)currpos != -1) + switch (xdrs->x_op) { + + case XDR_ENCODE: + newpos = rstrm->out_finger - delta; + if ((newpos > (char *)(void *)(rstrm->frag_header)) && + (newpos < rstrm->out_boundry)) { + rstrm->out_finger = newpos; + return (TRUE); + } + break; + + case XDR_DECODE: + newpos = rstrm->in_finger - delta; + if ((delta < (int)(rstrm->fbtbc)) && + (newpos <= rstrm->in_boundry) && + (newpos >= rstrm->in_base)) { + rstrm->in_finger = newpos; + rstrm->fbtbc -= delta; + return (TRUE); + } + break; + + case XDR_FREE: + break; + } + return (FALSE); +} + +static int32_t * +xdrrec_inline(xdrs, len) + XDR *xdrs; + u_int len; +{ + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + int32_t *buf = NULL; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + if ((rstrm->out_finger + len) <= rstrm->out_boundry) { + buf = (int32_t *)(void *)rstrm->out_finger; + rstrm->out_finger += len; + } + break; + + case XDR_DECODE: + if ((len <= rstrm->fbtbc) && + ((rstrm->in_finger + len) <= rstrm->in_boundry)) { + buf = (int32_t *)(void *)rstrm->in_finger; + rstrm->fbtbc -= len; + rstrm->in_finger += len; + } + break; + + case XDR_FREE: + break; + } + return (buf); +} + +static void +xdrrec_destroy(xdrs) + XDR *xdrs; +{ + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + + mem_free(rstrm->out_base, rstrm->sendsize); + mem_free(rstrm->in_base, rstrm->recvsize); + mem_free(rstrm, sizeof(RECSTREAM)); +} + + +/* + * Exported routines to manage xdr records + */ + +/* + * Before reading (deserializing from the stream, one should always call + * this procedure to guarantee proper record alignment. + */ +bool_t +xdrrec_skiprecord(xdrs) + XDR *xdrs; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + enum xprt_stat xstat; + + if (rstrm->nonblock) { + if (__xdrrec_getrec(xdrs, &xstat, FALSE)) { + rstrm->fbtbc = 0; + return TRUE; + } + if (rstrm->in_finger == rstrm->in_boundry && + xstat == XPRT_MOREREQS) { + rstrm->fbtbc = 0; + return TRUE; + } + return FALSE; + } + + while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { + if (! skip_input_bytes(rstrm, rstrm->fbtbc)) + return (FALSE); + rstrm->fbtbc = 0; + if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) + return (FALSE); + } + rstrm->last_frag = FALSE; + return (TRUE); +} + +/* + * Look ahead function. + * Returns TRUE iff there is no more input in the buffer + * after consuming the rest of the current record. + */ +bool_t +xdrrec_eof(xdrs) + XDR *xdrs; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { + if (! skip_input_bytes(rstrm, rstrm->fbtbc)) + return (TRUE); + rstrm->fbtbc = 0; + if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) + return (TRUE); + } + if (rstrm->in_finger == rstrm->in_boundry) + return (TRUE); + return (FALSE); +} + +/* + * The client must tell the package when an end-of-record has occurred. + * The second paraemters tells whether the record should be flushed to the + * (output) tcp stream. (This let's the package support batched or + * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. + */ +bool_t +xdrrec_endofrecord(xdrs, sendnow) + XDR *xdrs; + bool_t sendnow; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent || + ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= + (u_long)rstrm->out_boundry)) { + rstrm->frag_sent = FALSE; + return (flush_out(rstrm, TRUE)); + } + len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - + sizeof(u_int32_t); + *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG); + rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger; + rstrm->out_finger += sizeof(u_int32_t); + return (TRUE); +} + +/* + * Fill the stream buffer with a record for a non-blocking connection. + * Return true if a record is available in the buffer, false if not. + */ +bool_t +__xdrrec_getrec(xdrs, statp, expectdata) + XDR *xdrs; + enum xprt_stat *statp; + bool_t expectdata; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + ssize_t n; + int fraglen; + + if (!rstrm->in_haveheader) { + n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp, + (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen); + if (n == 0) { + *statp = expectdata ? XPRT_DIED : XPRT_IDLE; + return FALSE; + } + if (n < 0) { + *statp = XPRT_DIED; + return FALSE; + } + rstrm->in_hdrp += n; + rstrm->in_hdrlen += n; + if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) { + *statp = XPRT_MOREREQS; + return FALSE; + } + rstrm->in_header = ntohl(rstrm->in_header); + fraglen = (int)(rstrm->in_header & ~LAST_FRAG); + if (fraglen == 0 || fraglen > rstrm->in_maxrec || + (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) { + *statp = XPRT_DIED; + return FALSE; + } + rstrm->in_reclen += fraglen; + if (rstrm->in_reclen > rstrm->recvsize) + realloc_stream(rstrm, rstrm->in_reclen); + if (rstrm->in_header & LAST_FRAG) { + rstrm->in_header &= ~LAST_FRAG; + rstrm->last_frag = TRUE; + } + } + + n = rstrm->readit(rstrm->tcp_handle, + rstrm->in_base + rstrm->in_received, + (rstrm->in_reclen - rstrm->in_received)); + + if (n < 0) { + *statp = XPRT_DIED; + return FALSE; + } + + if (n == 0) { + *statp = expectdata ? XPRT_DIED : XPRT_IDLE; + return FALSE; + } + + rstrm->in_received += n; + + if (rstrm->in_received == rstrm->in_reclen) { + rstrm->in_haveheader = FALSE; + rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; + rstrm->in_hdrlen = 0; + if (rstrm->last_frag) { + rstrm->fbtbc = rstrm->in_reclen; + rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen; + rstrm->in_finger = rstrm->in_base; + rstrm->in_reclen = rstrm->in_received = 0; + *statp = XPRT_MOREREQS; + return TRUE; + } + } + + *statp = XPRT_MOREREQS; + return FALSE; +} + +bool_t +__xdrrec_setnonblock(xdrs, maxrec) + XDR *xdrs; + int maxrec; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + rstrm->nonblock = TRUE; + if (maxrec == 0) + maxrec = rstrm->recvsize; + rstrm->in_maxrec = maxrec; + return TRUE; +} + +/* + * Internal useful routines + */ +static bool_t +flush_out(rstrm, eor) + RECSTREAM *rstrm; + bool_t eor; +{ + u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0; + u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) - + (u_long)(rstrm->frag_header) - sizeof(u_int32_t)); + + *(rstrm->frag_header) = htonl(len | eormask); + len = (u_int32_t)((u_long)(rstrm->out_finger) - + (u_long)(rstrm->out_base)); + if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) + != (int)len) + return (FALSE); + rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; + rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t); + return (TRUE); +} + +static bool_t /* knows nothing about records! Only about input buffers */ +fill_input_buf(rstrm) + RECSTREAM *rstrm; +{ + char *where; + u_int32_t i; + int len; + + if (rstrm->nonblock) + return FALSE; + + where = rstrm->in_base; + i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT); + where += i; + len = (u_int32_t)(rstrm->in_size - i); + if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) + return (FALSE); + rstrm->in_finger = where; + where += len; + rstrm->in_boundry = where; + return (TRUE); +} + +static bool_t /* knows nothing about records! Only about input buffers */ +get_input_bytes(rstrm, addr, len) + RECSTREAM *rstrm; + char *addr; + int len; +{ + size_t current; + + if (rstrm->nonblock) { + if (len > (int)(rstrm->in_boundry - rstrm->in_finger)) + return FALSE; + memcpy(addr, rstrm->in_finger, (size_t)len); + rstrm->in_finger += len; + return TRUE; + } + + while (len > 0) { + current = (size_t)((long)rstrm->in_boundry - + (long)rstrm->in_finger); + if (current == 0) { + if (! fill_input_buf(rstrm)) + return (FALSE); + continue; + } + current = (len < current) ? len : current; + memmove(addr, rstrm->in_finger, current); + rstrm->in_finger += current; + addr += current; + len -= current; + } + return (TRUE); +} + +static bool_t /* next two bytes of the input stream are treated as a header */ +set_input_fragment(rstrm) + RECSTREAM *rstrm; +{ + u_int32_t header; + + if (rstrm->nonblock) + return FALSE; + if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header))) + return (FALSE); + header = ntohl(header); + rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + /* + * Sanity check. Try not to accept wildly incorrect + * record sizes. Unfortunately, the only record size + * we can positively identify as being 'wildly incorrect' + * is zero. Ridiculously large record sizes may look wrong, + * but we don't have any way to be certain that they aren't + * what the client actually intended to send us. + */ + if (header == 0) + return(FALSE); + rstrm->fbtbc = header & (~LAST_FRAG); + return (TRUE); +} + +static bool_t /* consumes input bytes; knows nothing about records! */ +skip_input_bytes(rstrm, cnt) + RECSTREAM *rstrm; + long cnt; +{ + u_int32_t current; + + while (cnt > 0) { + current = (size_t)((long)rstrm->in_boundry - + (long)rstrm->in_finger); + if (current == 0) { + if (! fill_input_buf(rstrm)) + return (FALSE); + continue; + } + current = (u_int32_t)((cnt < current) ? cnt : current); + rstrm->in_finger += current; + cnt -= current; + } + return (TRUE); +} + +static u_int +fix_buf_size(s) + u_int s; +{ + + if (s < 100) + s = 4000; + return (RNDUP(s)); +} + +/* + * Reallocate the input buffer for a non-block stream. + */ +static bool_t +realloc_stream(rstrm, size) + RECSTREAM *rstrm; + int size; +{ + ptrdiff_t diff; + char *buf; + + if (size > rstrm->recvsize) { + buf = realloc(rstrm->in_base, (size_t)size); + if (buf == NULL) + return FALSE; + diff = buf - rstrm->in_base; + rstrm->in_finger += diff; + rstrm->in_base = buf; + rstrm->in_boundry = buf + size; + rstrm->recvsize = size; + rstrm->in_size = size; + } + + return TRUE; +} diff --git a/lib/libc/xdr/xdr_reference.c b/lib/libc/xdr/xdr_reference.c new file mode 100644 index 0000000..5a497b6 --- /dev/null +++ b/lib/libc/xdr/xdr_reference.c @@ -0,0 +1,143 @@ +/* $NetBSD: xdr_reference.c,v 1.13 2000/01/22 22:19:18 mycroft Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr_reference.c 1.11 87/08/11 SMI"; +static char *sccsid = "@(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr_reference.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1987, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * "pointers". See xdr.h for more info on the interface to xdr. + */ + +#include "namespace.h" +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include "libc_private.h" + +/* + * XDR an indirect pointer + * xdr_reference is for recursively translating a structure that is + * referenced by a pointer inside the structure that is currently being + * translated. pp references a pointer to storage. If *pp is null + * the necessary storage is allocated. + * size is the sizeof the referneced structure. + * proc is the routine to handle the referenced structure. + */ +bool_t +xdr_reference(xdrs, pp, size, proc) + XDR *xdrs; + caddr_t *pp; /* the pointer to work on */ + u_int size; /* size of the object pointed to */ + xdrproc_t proc; /* xdr routine to handle the object */ +{ + caddr_t loc = *pp; + bool_t stat; + + if (loc == NULL) + switch (xdrs->x_op) { + case XDR_FREE: + return (TRUE); + + case XDR_DECODE: + *pp = loc = (caddr_t) mem_alloc(size); + if (loc == NULL) { + warnx("xdr_reference: out of memory"); + return (FALSE); + } + memset(loc, 0, size); + break; + + case XDR_ENCODE: + break; + } + + stat = (*proc)(xdrs, loc); + + if (xdrs->x_op == XDR_FREE) { + mem_free(loc, size); + *pp = NULL; + } + return (stat); +} + + +/* + * xdr_pointer(): + * + * XDR a pointer to a possibly recursive data structure. This + * differs with xdr_reference in that it can serialize/deserialiaze + * trees correctly. + * + * What's sent is actually a union: + * + * union object_pointer switch (boolean b) { + * case TRUE: object_data data; + * case FALSE: void nothing; + * } + * + * > objpp: Pointer to the pointer to the object. + * > obj_size: size of the object. + * > xdr_obj: routine to XDR an object. + * + */ +bool_t +xdr_pointer(xdrs,objpp,obj_size,xdr_obj) + XDR *xdrs; + char **objpp; + u_int obj_size; + xdrproc_t xdr_obj; +{ + + bool_t more_data; + + more_data = (*objpp != NULL); + if (! xdr_bool(xdrs,&more_data)) { + return (FALSE); + } + if (! more_data) { + *objpp = NULL; + return (TRUE); + } + return (xdr_reference(xdrs,objpp,obj_size,xdr_obj)); +} diff --git a/lib/libc/xdr/xdr_sizeof.c b/lib/libc/xdr/xdr_sizeof.c new file mode 100644 index 0000000..20f1c3a --- /dev/null +++ b/lib/libc/xdr/xdr_sizeof.c @@ -0,0 +1,168 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * xdr_sizeof.c + * + * Copyright 1990 Sun Microsystems, Inc. + * + * General purpose routine to see how much space something will use + * when serialized using XDR. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <sys/types.h> +#include <stdlib.h> +#include "un-namespace.h" + +/* ARGSUSED */ +static bool_t +x_putlong(xdrs, longp) + XDR *xdrs; + long *longp; +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return (TRUE); +} + +/* ARGSUSED */ +static bool_t +x_putbytes(xdrs, bp, len) + XDR *xdrs; + char *bp; + u_int len; +{ + xdrs->x_handy += len; + return (TRUE); +} + +static u_int +x_getpostn(xdrs) + XDR *xdrs; +{ + return (xdrs->x_handy); +} + +/* ARGSUSED */ +static bool_t +x_setpostn(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + /* This is not allowed */ + return (FALSE); +} + +static int32_t * +x_inline(xdrs, len) + XDR *xdrs; + u_int len; +{ + if (len == 0) { + return (NULL); + } + if (xdrs->x_op != XDR_ENCODE) { + return (NULL); + } + if (len < (u_int)xdrs->x_base) { + /* x_private was already allocated */ + xdrs->x_handy += len; + return ((int32_t *) xdrs->x_private); + } else { + /* Free the earlier space and allocate new area */ + if (xdrs->x_private) + free(xdrs->x_private); + if ((xdrs->x_private = (caddr_t) malloc(len)) == NULL) { + xdrs->x_base = 0; + return (NULL); + } + xdrs->x_base = (caddr_t) len; + xdrs->x_handy += len; + return ((int32_t *) xdrs->x_private); + } +} + +static int +harmless() +{ + /* Always return FALSE/NULL, as the case may be */ + return (0); +} + +static void +x_destroy(xdrs) + XDR *xdrs; +{ + xdrs->x_handy = 0; + xdrs->x_base = 0; + if (xdrs->x_private) { + free(xdrs->x_private); + xdrs->x_private = NULL; + } + return; +} + +unsigned long +xdr_sizeof(func, data) + xdrproc_t func; + void *data; +{ + XDR x; + struct xdr_ops ops; + bool_t stat; + /* to stop ANSI-C compiler from complaining */ + typedef bool_t (* dummyfunc1)(XDR *, long *); + typedef bool_t (* dummyfunc2)(XDR *, caddr_t, u_int); + + ops.x_putlong = x_putlong; + ops.x_putbytes = x_putbytes; + ops.x_inline = x_inline; + ops.x_getpostn = x_getpostn; + ops.x_setpostn = x_setpostn; + ops.x_destroy = x_destroy; + + /* the other harmless ones */ + ops.x_getlong = (dummyfunc1) harmless; + ops.x_getbytes = (dummyfunc2) harmless; + + x.x_op = XDR_ENCODE; + x.x_ops = &ops; + x.x_handy = 0; + x.x_private = (caddr_t) NULL; + x.x_base = (caddr_t) 0; + + stat = func(&x, data); + if (x.x_private) + free(x.x_private); + return (stat == TRUE ? (unsigned) x.x_handy: 0); +} diff --git a/lib/libc/xdr/xdr_stdio.c b/lib/libc/xdr/xdr_stdio.c new file mode 100644 index 0000000..8c1724d --- /dev/null +++ b/lib/libc/xdr/xdr_stdio.c @@ -0,0 +1,196 @@ +/* $NetBSD: xdr_stdio.c,v 1.14 2000/01/22 22:19:19 mycroft Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid2 = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * xdr_stdio.c, XDR implementation on standard i/o file. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements a XDR on a stdio stream. + * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes + * from the stream. + */ + +#include "namespace.h" +#include <stdio.h> + +#include <arpa/inet.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include "un-namespace.h" + +static void xdrstdio_destroy(XDR *); +static bool_t xdrstdio_getlong(XDR *, long *); +static bool_t xdrstdio_putlong(XDR *, const long *); +static bool_t xdrstdio_getbytes(XDR *, char *, u_int); +static bool_t xdrstdio_putbytes(XDR *, const char *, u_int); +static u_int xdrstdio_getpos(XDR *); +static bool_t xdrstdio_setpos(XDR *, u_int); +static int32_t *xdrstdio_inline(XDR *, u_int); + +/* + * Ops vector for stdio type XDR + */ +static const struct xdr_ops xdrstdio_ops = { + xdrstdio_getlong, /* deseraialize a long int */ + xdrstdio_putlong, /* seraialize a long int */ + xdrstdio_getbytes, /* deserialize counted bytes */ + xdrstdio_putbytes, /* serialize counted bytes */ + xdrstdio_getpos, /* get offset in the stream */ + xdrstdio_setpos, /* set offset in the stream */ + xdrstdio_inline, /* prime stream for inline macros */ + xdrstdio_destroy /* destroy stream */ +}; + +/* + * Initialize a stdio xdr stream. + * Sets the xdr stream handle xdrs for use on the stream file. + * Operation flag is set to op. + */ +void +xdrstdio_create(xdrs, file, op) + XDR *xdrs; + FILE *file; + enum xdr_op op; +{ + + xdrs->x_op = op; + xdrs->x_ops = &xdrstdio_ops; + xdrs->x_private = file; + xdrs->x_handy = 0; + xdrs->x_base = 0; +} + +/* + * Destroy a stdio xdr stream. + * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create. + */ +static void +xdrstdio_destroy(xdrs) + XDR *xdrs; +{ + (void)fflush((FILE *)xdrs->x_private); + /* XXX: should we close the file ?? */ +} + +static bool_t +xdrstdio_getlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + u_int32_t temp; + + if (fread(&temp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) + return (FALSE); + *lp = (long)ntohl(temp); + return (TRUE); +} + +static bool_t +xdrstdio_putlong(xdrs, lp) + XDR *xdrs; + const long *lp; +{ + int32_t mycopy = htonl((u_int32_t)*lp); + + if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) + return (FALSE); + return (TRUE); +} + +static bool_t +xdrstdio_getbytes(xdrs, addr, len) + XDR *xdrs; + char *addr; + u_int len; +{ + + if ((len != 0) && (fread(addr, (size_t)len, 1, (FILE *)xdrs->x_private) != 1)) + return (FALSE); + return (TRUE); +} + +static bool_t +xdrstdio_putbytes(xdrs, addr, len) + XDR *xdrs; + const char *addr; + u_int len; +{ + + if ((len != 0) && (fwrite(addr, (size_t)len, 1, + (FILE *)xdrs->x_private) != 1)) + return (FALSE); + return (TRUE); +} + +static u_int +xdrstdio_getpos(xdrs) + XDR *xdrs; +{ + + return ((u_int) ftell((FILE *)xdrs->x_private)); +} + +static bool_t +xdrstdio_setpos(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + + return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ? + FALSE : TRUE); +} + +/* ARGSUSED */ +static int32_t * +xdrstdio_inline(xdrs, len) + XDR *xdrs; + u_int len; +{ + + /* + * Must do some work to implement this: must insure + * enough data in the underlying stdio buffer, + * that the buffer is aligned so that we can indirect through a + * long *, and stuff this pointer in xdrs->x_buf. Doing + * a fread or fwrite to a scratch buffer would defeat + * most of the gains to be had here and require storage + * management on this buffer, so we don't do this. + */ + return (NULL); +} |