Moving RPC stuff into libc, part 2.

This commit is contained in:
Garrett Wollman 1994-08-07 18:39:35 +00:00
parent 990647991e
commit eae561b30e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=1902
9 changed files with 2947 additions and 0 deletions

11
lib/libc/xdr/Makefile.inc Normal file
View File

@ -0,0 +1,11 @@
# @(#)Makefile 5.11 (Berkeley) 9/6/90
.PATH: ${.CURDIR}/rpc ${.CURDIR}/.
CFLAGS+=-I${.CURDIR} -I${.CURDIR}/rpc
SRCS= xdr.c xdr_array.c xdr_mem.c \
xdr_rec.c xdr_reference.c xdr_stdio.c
MAN3= xdr/xdr.3
UNSUPPORTED+= xdr_float.c

823
lib/libc/xdr/xdr.3 Normal file
View File

@ -0,0 +1,823 @@
.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI
.TH XDR 3N "16 February 1988"
.SH NAME
xdr \- library routines for external data representation
.SH SYNOPSIS AND DESCRIPTION
.LP
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.
.LP
.ft B
.nf
.sp .5
xdr_array(xdrs, arrp, sizep, maxsize, elsize, elproc)
\s-1XDR\s0 *xdrs;
char **arrp;
u_int *sizep, maxsize, elsize;
xdrproc_t elproc;
.fi
.ft R
.IP
A filter primitive that translates between variable-length
arrays
and their corresponding external representations. The
parameter
.I arrp
is the address of the pointer to the array, while
.I sizep
is the address of the element count of the array;
this element count cannot exceed
.IR maxsize .
The parameter
.I elsize
is the
.I sizeof
each of the array's elements, and
.I elproc
is an
.SM XDR
filter that translates between
the array elements' C form, and their external
representation.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
xdr_bool(xdrs, bp)
\s-1XDR\s0 *xdrs;
bool_t *bp;
.fi
.ft R
.IP
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.
.br
.if t .ne 10
.LP
.ft B
.nf
.sp .5
xdr_bytes(xdrs, sp, sizep, maxsize)
\s-1XDR\s0 *xdrs;
char **sp;
u_int *sizep, maxsize;
.fi
.ft R
.IP
A filter primitive that translates between counted byte
strings and their external representations.
The parameter
.I sp
is the address of the string pointer. The length of the
string is located at address
.IR sizep ;
strings cannot be longer than
.IR maxsize .
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_char(xdrs, cp)
\s-1XDR\s0 *xdrs;
char *cp;
.fi
.ft R
.IP
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
.BR xdr_bytes(\|) ,
.B xdr_opaque(\|)
or
.BR xdr_string(\|) .
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
void
xdr_destroy(xdrs)
\s-1XDR\s0 *xdrs;
.fi
.ft R
.IP
A macro that invokes the destroy routine associated with the
.SM XDR
stream,
.IR xdrs .
Destruction usually involves freeing private data structures
associated with the stream. Using
.I xdrs
after invoking
.B xdr_destroy(\|)
is undefined.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_double(xdrs, dp)
\s-1XDR\s0 *xdrs;
double *dp;
.fi
.ft R
.IP
A filter primitive that translates between C
.B double
precision numbers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_enum(xdrs, ep)
\s-1XDR\s0 *xdrs;
enum_t *ep;
.fi
.ft R
.IP
A filter primitive that translates between C
.BR enum s
(actually integers) and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
xdr_float(xdrs, fp)
\s-1XDR\s0 *xdrs;
float *fp;
.fi
.ft R
.IP
A filter primitive that translates between C
.BR float s
and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 9
.LP
.ft B
.nf
.sp .5
void
xdr_free(proc, objp)
xdrproc_t proc;
char *objp;
.fi
.ft R
.IP
Generic freeing routine. The first argument is the
.SM 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
.I not
freed, but what it points to
.I is
freed (recursively).
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
u_int
xdr_getpos(xdrs)
\s-1XDR\s0 *xdrs;
.fi
.ft R
.IP
A macro that invokes the get-position routine
associated with the
.SM XDR
stream,
.IR xdrs .
The routine returns an unsigned integer,
which indicates the position of the
.SM XDR
byte stream.
A desirable feature of
.SM XDR
streams is that simple arithmetic works with this number,
although the
.SM XDR
stream instances need not guarantee this.
.br
.if t .ne 4
.LP
.ft B
.nf
.sp .5
.br
long *
xdr_inline(xdrs, len)
\s-1XDR\s0 *xdrs;
int len;
.fi
.ft R
.IP
A macro that invokes the in-line routine associated with the
.SM XDR
stream,
.IR xdrs .
The routine returns a pointer
to a contiguous piece of the stream's buffer;
.I len
is the byte length of the desired buffer.
Note: pointer is cast to
.BR "long *" .
.IP
Warning:
.B xdr_inline(\|)
may return
.SM 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.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_int(xdrs, ip)
\s-1XDR\s0 *xdrs;
int *ip;
.fi
.ft R
.IP
A filter primitive that translates between C integers
and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_long(xdrs, lp)
\s-1XDR\s0 *xdrs;
long *lp;
.fi
.ft R
.IP
A filter primitive that translates between C
.B long
integers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 12
.LP
.ft B
.nf
.sp .5
void
xdrmem_create(xdrs, addr, size, op)
\s-1XDR\s0 *xdrs;
char *addr;
u_int size;
enum xdr_op op;
.fi
.ft R
.IP
This routine initializes the
.SM XDR
stream object pointed to by
.IR xdrs .
The stream's data is written to, or read from,
a chunk of memory at location
.I addr
whose length is no more than
.I size
bytes long. The
.I op
determines the direction of the
.SM XDR
stream
(either
.BR \s-1XDR_ENCODE\s0 ,
.BR \s-1XDR_DECODE\s0 ,
or
.BR \s-1XDR_FREE\s0 ).
.br
.if t .ne 10
.LP
.ft B
.nf
.sp .5
xdr_opaque(xdrs, cp, cnt)
\s-1XDR\s0 *xdrs;
char *cp;
u_int cnt;
.fi
.ft R
.IP
A filter primitive that translates between fixed size opaque
data
and its external representation.
The parameter
.I cp
is the address of the opaque object, and
.I cnt
is its size in bytes.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 10
.LP
.ft B
.nf
.sp .5
xdr_pointer(xdrs, objpp, objsize, xdrobj)
\s-1XDR\s0 *xdrs;
char **objpp;
u_int objsize;
xdrproc_t xdrobj;
.fi
.ft R
.IP
Like
.B xdr_reference(\|)
execpt that it serializes
.SM NULL
pointers, whereas
.B xdr_reference(\|)
does not. Thus,
.B xdr_pointer(\|)
can represent
recursive data structures, such as binary trees or
linked lists.
.br
.if t .ne 15
.LP
.ft B
.nf
.sp .5
void
xdrrec_create(xdrs, sendsize, recvsize, handle, readit, writeit)
\s-1XDR\s0 *xdrs;
u_int sendsize, recvsize;
char *handle;
int (*readit) (\|), (*writeit) (\|);
.fi
.ft R
.IP
This routine initializes the
.SM XDR
stream object pointed to by
.IR xdrs .
The stream's data is written to a buffer of size
.IR sendsize ;
a value of zero indicates the system should use a suitable
default. The stream's data is read from a buffer of size
.IR recvsize ;
it too can be set to a suitable default by passing a zero
value.
When a stream's output buffer is full,
.I writeit
is called. Similarly, when a stream's input buffer is empty,
.I readit
is called. The behavior of these two routines is similar to
the
system calls
.B read
and
.BR write ,
except that
.I handle
is passed to the former routines as the first parameter.
Note: the
.SM XDR
stream's
.I op
field must be set by the caller.
.IP
Warning: this
.SM XDR
stream implements an intermediate record stream.
Therefore there are additional bytes in the stream
to provide record boundary information.
.br
.if t .ne 9
.LP
.ft B
.nf
.sp .5
xdrrec_endofrecord(xdrs, sendnow)
\s-1XDR\s0 *xdrs;
int sendnow;
.fi
.ft R
.IP
This routine can be invoked only on
streams created by
.BR xdrrec_create(\|) .
The data in the output buffer is marked as a completed
record,
and the output buffer is optionally written out if
.I sendnow
is non-zero. This routine returns one if it succeeds, zero
otherwise.
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
xdrrec_eof(xdrs)
\s-1XDR\s0 *xdrs;
int empty;
.fi
.ft R
.IP
This routine can be invoked only on
streams created by
.BR 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.
.br
.if t .ne 3
.LP
.ft B
.nf
.sp .5
xdrrec_skiprecord(xdrs)
\s-1XDR\s0 *xdrs;
.fi
.ft R
.IP
This routine can be invoked only on
streams created by
.BR xdrrec_create(\|) .
It tells the
.SM 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.
.br
.if t .ne 11
.LP
.ft B
.nf
.sp .5
xdr_reference(xdrs, pp, size, proc)
\s-1XDR\s0 *xdrs;
char **pp;
u_int size;
xdrproc_t proc;
.fi
.ft R
.IP
A primitive that provides pointer chasing within structures.
The parameter
.I pp
is the address of the pointer;
.I size
is the
.I sizeof
the structure that
.I *pp
points to; and
.I proc
is an
.SM XDR
procedure that filters the structure
between its C form and its external representation.
This routine returns one if it succeeds, zero otherwise.
.IP
Warning: this routine does not understand
.SM NULL
pointers. Use
.B xdr_pointer(\|)
instead.
.br
.if t .ne 10
.LP
.ft B
.nf
.sp .5
xdr_setpos(xdrs, pos)
\s-1XDR\s0 *xdrs;
u_int pos;
.fi
.ft R
.IP
A macro that invokes the set position routine associated with
the
.SM XDR
stream
.IR xdrs .
The parameter
.I pos
is a position value obtained from
.BR xdr_getpos(\|) .
This routine returns one if the
.SM XDR
stream could be repositioned,
and zero otherwise.
.IP
Warning: it is difficult to reposition some types of
.SM XDR
streams, so this routine may fail with one
type of stream and succeed with another.
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
xdr_short(xdrs, sp)
\s-1XDR\s0 *xdrs;
short *sp;
.fi
.ft R
.IP
A filter primitive that translates between C
.B short
integers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 10
.LP
.ft B
.nf
.sp .5
void
xdrstdio_create(xdrs, file, op)
\s-1XDR\s0 *xdrs;
\s-1FILE\s0 *file;
enum xdr_op op;
.fi
.ft R
.IP
This routine initializes the
.SM XDR
stream object pointed to by
.IR xdrs .
The
.SM XDR
stream data is written to, or read from, the Standard
.B I/O
stream
.IR file .
The parameter
.I op
determines the direction of the
.SM XDR
stream (either
.BR \s-1XDR_ENCODE\s0 ,
.BR \s-1XDR_DECODE\s0 ,
or
.BR \s-1XDR_FREE\s0 ).
.IP
Warning: the destroy routine associated with such
.SM XDR
streams calls
.B fflush(\|)
on the
.I file
stream, but never
.BR fclose(\|) .
.br
.if t .ne 9
.LP
.ft B
.nf
.sp .5
xdr_string(xdrs, sp, maxsize)
\s-1XDR\s0
*xdrs;
char **sp;
u_int maxsize;
.fi
.ft R
.IP
A filter primitive that translates between C strings and
their
corresponding external representations.
Strings cannot be longer than
.IR maxsize .
Note:
.I sp
is the address of the string's pointer.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 8
.LP
.ft B
.nf
.sp .5
xdr_u_char(xdrs, ucp)
\s-1XDR\s0 *xdrs;
unsigned char *ucp;
.fi
.ft R
.IP
A filter primitive that translates between
.B unsigned
C characters and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 9
.LP
.ft B
.nf
.sp .5
xdr_u_int(xdrs, up)
\s-1XDR\s0 *xdrs;
unsigned *up;
.fi
.ft R
.IP
A filter primitive that translates between C
.B unsigned
integers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_u_long(xdrs, ulp)
\s-1XDR\s0 *xdrs;
unsigned long *ulp;
.fi
.ft R
.IP
A filter primitive that translates between C
.B "unsigned long"
integers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 7
.LP
.ft B
.nf
.sp .5
xdr_u_short(xdrs, usp)
\s-1XDR\s0 *xdrs;
unsigned short *usp;
.fi
.ft R
.IP
A filter primitive that translates between C
.B "unsigned short"
integers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 16
.LP
.ft B
.nf
.sp .5
xdr_union(xdrs, dscmp, unp, choices, dfault)
\s-1XDR\s0 *xdrs;
int *dscmp;
char *unp;
struct xdr_discrim *choices;
bool_t (*defaultarm) (\|); /* may equal \s-1NULL\s0 */
.fi
.ft R
.IP
A filter primitive that translates between a discriminated C
.B union
and its corresponding external representation. It first
translates the discriminant of the union located at
.IR dscmp .
This discriminant is always an
.BR enum_t .
Next the union located at
.I unp
is translated. The parameter
.I choices
is a pointer to an array of
.B xdr_discrim(\|)
structures. Each structure contains an ordered pair of
.RI [ value , proc ].
If the union's discriminant is equal to the associated
.IR value ,
then the
.I proc
is called to translate the union. The end of the
.B xdr_discrim(\|)
structure array is denoted by a routine of value
.SM NULL\s0.
If the discriminant is not found in the
.I choices
array, then the
.I defaultarm
procedure is called (if it is not
.SM NULL\s0).
Returns one if it succeeds, zero otherwise.
.br
.if t .ne 6
.LP
.ft B
.nf
.sp .5
xdr_vector(xdrs, arrp, size, elsize, elproc)
\s-1XDR\s0 *xdrs;
char *arrp;
u_int size, elsize;
xdrproc_t elproc;
.fi
.ft R
.IP
A filter primitive that translates between fixed-length
arrays
and their corresponding external representations. The
parameter
.I arrp
is the address of the pointer to the array, while
.I size
is is the element count of the array. The parameter
.I elsize
is the
.I sizeof
each of the array's elements, and
.I elproc
is an
.SM XDR
filter that translates between
the array elements' C form, and their external
representation.
This routine returns one if it succeeds, zero otherwise.
.br
.if t .ne 5
.LP
.ft B
.nf
.sp .5
xdr_void(\|)
.fi
.ft R
.IP
This routine always returns one.
It may be passed to
.SM RPC
routines that require a function parameter,
where nothing is to be done.
.br
.if t .ne 10
.LP
.ft B
.nf
.sp .5
xdr_wrapstring(xdrs, sp)
\s-1XDR\s0 *xdrs;
char **sp;
.fi
.ft R
.IP
A primitive that calls
.B "xdr_string(xdrs, sp,\s-1MAXUN.UNSIGNED\s0 );"
where
.B
.SM MAXUN.UNSIGNED
is the maximum value of an unsigned integer.
.B xdr_wrapstring(\|)
is handy because the
.SM RPC
package passes a maximum of two
.SM XDR
routines as parameters, and
.BR xdr_string(\|) ,
one of the most frequently used primitives, requires three.
Returns one if it succeeds, zero otherwise.
.SH SEE ALSO
.BR rpc (3N)
.LP
The following manuals:
.RS
.ft I
eXternal Data Representation Standard: Protocol Specification
.br
eXternal Data Representation: Sun Technical Notes
.ft R
.br
.IR "\s-1XDR\s0: External Data Representation Standard" ,
.SM RFC1014, Sun Microsystems, Inc.,
.SM USC-ISI\s0.

578
lib/libc/xdr/xdr.c Normal file
View File

@ -0,0 +1,578 @@
/*
* 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 *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr.c,v 1.1 1993/10/27 05:41:06 paul Exp $";
#endif
/*
* 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 <stdio.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
/*
* 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 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;
char *objp;
{
XDR x;
x.x_op = XDR_FREE;
(*proc)(&x, objp);
}
/*
* XDR nothing
*/
bool_t
xdr_void(/* xdrs, addr */)
/* XDR *xdrs; */
/* caddr_t addr; */
{
return (TRUE);
}
/*
* XDR integers
*/
bool_t
xdr_int(xdrs, ip)
XDR *xdrs;
int *ip;
{
#ifdef lint
(void) (xdr_short(xdrs, (short *)ip));
return (xdr_long(xdrs, (long *)ip));
#else
if (sizeof (int) == sizeof (long)) {
return (xdr_long(xdrs, (long *)ip));
} else {
return (xdr_short(xdrs, (short *)ip));
}
#endif
}
/*
* XDR unsigned integers
*/
bool_t
xdr_u_int(xdrs, up)
XDR *xdrs;
u_int *up;
{
#ifdef lint
(void) (xdr_short(xdrs, (short *)up));
return (xdr_u_long(xdrs, (u_long *)up));
#else
if (sizeof (u_int) == sizeof (u_long)) {
return (xdr_u_long(xdrs, (u_long *)up));
} else {
return (xdr_short(xdrs, (short *)up));
}
#endif
}
/*
* XDR long integers
* same as xdr_u_long - open coded to save a proc call!
*/
bool_t
xdr_long(xdrs, lp)
register XDR *xdrs;
long *lp;
{
if (xdrs->x_op == XDR_ENCODE)
return (XDR_PUTLONG(xdrs, lp));
if (xdrs->x_op == XDR_DECODE)
return (XDR_GETLONG(xdrs, lp));
if (xdrs->x_op == XDR_FREE)
return (TRUE);
return (FALSE);
}
/*
* XDR unsigned long integers
* same as xdr_long - open coded to save a proc call!
*/
bool_t
xdr_u_long(xdrs, ulp)
register XDR *xdrs;
u_long *ulp;
{
if (xdrs->x_op == XDR_DECODE)
return (XDR_GETLONG(xdrs, (long *)ulp));
if (xdrs->x_op == XDR_ENCODE)
return (XDR_PUTLONG(xdrs, (long *)ulp));
if (xdrs->x_op == XDR_FREE)
return (TRUE);
return (FALSE);
}
/*
* XDR short integers
*/
bool_t
xdr_short(xdrs, sp)
register 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);
}
return (FALSE);
}
/*
* XDR unsigned short integers
*/
bool_t
xdr_u_short(xdrs, usp)
register XDR *xdrs;
u_short *usp;
{
u_long l;
switch (xdrs->x_op) {
case XDR_ENCODE:
l = (u_long) *usp;
return (XDR_PUTLONG(xdrs, &l));
case XDR_DECODE:
if (!XDR_GETLONG(xdrs, &l)) {
return (FALSE);
}
*usp = (u_short) l;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
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;
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)
register 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);
}
return (FALSE);
}
/*
* XDR enumerations
*/
bool_t
xdr_enum(xdrs, ep)
XDR *xdrs;
enum_t *ep;
{
#ifndef lint
enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
/*
* enums are treated as ints
*/
if (sizeof (enum sizecheck) == sizeof (long)) {
return (xdr_long(xdrs, (long *)ep));
} else if (sizeof (enum sizecheck) == sizeof (short)) {
return (xdr_short(xdrs, (short *)ep));
} else {
return (FALSE);
}
#else
(void) (xdr_short(xdrs, (short *)ep));
return (xdr_long(xdrs, (long *)ep));
#endif
}
/*
* 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)
register XDR *xdrs;
caddr_t cp;
register u_int cnt;
{
register u_int rndup;
static 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, 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)
register XDR *xdrs;
char **cpp;
register u_int *sizep;
u_int maxsize;
{
register char *sp = *cpp; /* sp is the actual string pointer */
register 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 = (char *)mem_alloc(nodesize);
}
if (sp == NULL) {
(void) fprintf(stderr, "xdr_bytes: out of memory\n");
return (FALSE);
}
/* fall into ... */
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, nodesize));
case XDR_FREE:
if (sp != NULL) {
mem_free(sp, nodesize);
*cpp = NULL;
}
return (TRUE);
}
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)
register XDR *xdrs;
enum_t *dscmp; /* enum to decide which arm to work on */
char *unp; /* the union itself */
struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
xdrproc_t dfault; /* default xdr routine */
{
register 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, LASTUNSIGNED));
}
/*
* no match - execute the default xdr routine if there is one
*/
return ((dfault == NULL_xdrproc_t) ? FALSE :
(*dfault)(xdrs, unp, LASTUNSIGNED));
}
/*
* 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)
register XDR *xdrs;
char **cpp;
u_int maxsize;
{
register 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 */
}
/* fall through... */
case XDR_ENCODE:
size = strlen(sp);
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 = (char *)mem_alloc(nodesize);
if (sp == NULL) {
(void) fprintf(stderr, "xdr_string: out of memory\n");
return (FALSE);
}
sp[size] = 0;
/* fall into ... */
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, size));
case XDR_FREE:
mem_free(sp, nodesize);
*cpp = NULL;
return (TRUE);
}
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;
{
if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
return (TRUE);
}
return (FALSE);
}

155
lib/libc/xdr/xdr_array.c Normal file
View File

@ -0,0 +1,155 @@
/*
* 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 *sccsid = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr_array.c,v 1.1 1993/10/27 05:41:09 paul Exp $";
#endif
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#define LASTUNSIGNED ((u_int)0-1)
/*
* 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)
register 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 */
{
register u_int i;
register caddr_t target = *addrp;
register u_int c; /* the actual element count */
register bool_t stat = TRUE;
register u_int nodesize;
/* like strings, arrays are really counted arrays */
if (! xdr_u_int(xdrs, sizep)) {
return (FALSE);
}
c = *sizep;
if ((c > maxsize) && (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) {
(void) fprintf(stderr,
"xdr_array: out of memory\n");
return (FALSE);
}
bzero(target, nodesize);
break;
case XDR_FREE:
return (TRUE);
}
/*
* now we xdr each element of array
*/
for (i = 0; (i < c) && stat; i++) {
stat = (*elproc)(xdrs, target, LASTUNSIGNED);
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)
register XDR *xdrs;
register char *basep;
register u_int nelem;
register u_int elemsize;
register xdrproc_t xdr_elem;
{
register u_int i;
register char *elptr;
elptr = basep;
for (i = 0; i < nelem; i++) {
if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
return(FALSE);
}
elptr += elemsize;
}
return(TRUE);
}

283
lib/libc/xdr/xdr_float.c Normal file
View File

@ -0,0 +1,283 @@
/*
* 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 *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr_float.c,v 1.1 1993/10/27 05:41:10 paul Exp $";
#endif
/*
* xdr_float.c, Generic XDR routines impelmentation.
*
* 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 <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
/*
* NB: Not portable.
* This routine works on Suns (Sky / 68000's), i386's, MIPS, NS32k and Vaxen.
*/
#if defined(mc68000)||defined(sparc)||defined(i386)||defined(mips)||defined(ns32000)
#define IEEEFP
#endif
#ifdef 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)
register XDR *xdrs;
register 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_PUTLONG(xdrs, (long *)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_PUTLONG(xdrs, (long *)&is));
#endif
case XDR_DECODE:
#ifdef IEEEFP
return (XDR_GETLONG(xdrs, (long *)fp));
#else
vsp = (struct vax_single *)fp;
if (!XDR_GETLONG(xdrs, (long *)&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);
}
return (FALSE);
}
/*
* This routine works on Suns (Sky / 68000's), i386's, MIPS and Vaxen.
*/
#ifdef 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)
register XDR *xdrs;
double *dp;
{
register long *lp;
#ifndef IEEEFP
struct ieee_double id;
struct vax_double vd;
register struct dbl_limits *lim;
int i;
#endif
switch (xdrs->x_op) {
case XDR_ENCODE:
#ifdef IEEEFP
lp = (long *)dp;
#if BYTE_ORDER == BIG_ENDIAN
return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
#else
return (XDR_PUTLONG(xdrs, lp+1) && XDR_PUTLONG(xdrs, lp));
#endif
#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 = (long *)&id;
return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
#endif
case XDR_DECODE:
#ifdef IEEEFP
lp = (long *)dp;
#if BYTE_ORDER == BIG_ENDIAN
return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
#else
return (XDR_GETLONG(xdrs, lp+1) && XDR_GETLONG(xdrs, lp));
#endif
#else
lp = (long *)&id;
if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(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);
}
return (FALSE);
}

186
lib/libc/xdr/xdr_mem.c Normal file
View File

@ -0,0 +1,186 @@
/*
* 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 *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr_mem.c,v 1.1 1993/10/27 05:41:11 paul Exp $";
#endif
/*
* 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 <rpc/types.h>
#include <rpc/xdr.h>
#include <netinet/in.h>
static bool_t xdrmem_getlong();
static bool_t xdrmem_putlong();
static bool_t xdrmem_getbytes();
static bool_t xdrmem_putbytes();
static u_int xdrmem_getpos();
static bool_t xdrmem_setpos();
static long * xdrmem_inline();
static void xdrmem_destroy();
static struct xdr_ops xdrmem_ops = {
xdrmem_getlong,
xdrmem_putlong,
xdrmem_getbytes,
xdrmem_putbytes,
xdrmem_getpos,
xdrmem_setpos,
xdrmem_inline,
xdrmem_destroy
};
/*
* The procedure xdrmem_create initializes a stream descriptor for a
* memory buffer.
*/
void
xdrmem_create(xdrs, addr, size, op)
register XDR *xdrs;
caddr_t addr;
u_int size;
enum xdr_op op;
{
xdrs->x_op = op;
xdrs->x_ops = &xdrmem_ops;
xdrs->x_private = xdrs->x_base = addr;
xdrs->x_handy = size;
}
static void
xdrmem_destroy(/*xdrs*/)
/*XDR *xdrs;*/
{
}
static bool_t
xdrmem_getlong(xdrs, lp)
register XDR *xdrs;
long *lp;
{
if ((xdrs->x_handy -= sizeof(long)) < 0)
return (FALSE);
*lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private))));
xdrs->x_private += sizeof(long);
return (TRUE);
}
static bool_t
xdrmem_putlong(xdrs, lp)
register XDR *xdrs;
long *lp;
{
if ((xdrs->x_handy -= sizeof(long)) < 0)
return (FALSE);
*(long *)xdrs->x_private = (long)htonl((u_long)(*lp));
xdrs->x_private += sizeof(long);
return (TRUE);
}
static bool_t
xdrmem_getbytes(xdrs, addr, len)
register XDR *xdrs;
caddr_t addr;
register u_int len;
{
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
bcopy(xdrs->x_private, addr, len);
xdrs->x_private += len;
return (TRUE);
}
static bool_t
xdrmem_putbytes(xdrs, addr, len)
register XDR *xdrs;
caddr_t addr;
register u_int len;
{
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
bcopy(addr, xdrs->x_private, len);
xdrs->x_private += len;
return (TRUE);
}
static u_int
xdrmem_getpos(xdrs)
register XDR *xdrs;
{
return ((u_int)xdrs->x_private - (u_int)xdrs->x_base);
}
static bool_t
xdrmem_setpos(xdrs, pos)
register XDR *xdrs;
u_int pos;
{
register caddr_t newaddr = xdrs->x_base + pos;
register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
if ((long)newaddr > (long)lastaddr)
return (FALSE);
xdrs->x_private = newaddr;
xdrs->x_handy = (int)lastaddr - (int)newaddr;
return (TRUE);
}
static long *
xdrmem_inline(xdrs, len)
register XDR *xdrs;
int len;
{
long *buf = 0;
if (xdrs->x_handy >= len) {
xdrs->x_handy -= len;
buf = (long *) xdrs->x_private;
xdrs->x_private += len;
}
return (buf);
}

586
lib/libc/xdr/xdr_rec.c Normal file
View File

@ -0,0 +1,586 @@
/*
* 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 *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr_rec.c,v 1.1 1993/10/27 05:41:12 paul Exp $";
#endif
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <netinet/in.h>
extern long lseek();
static u_int fix_buf_size();
static bool_t flush_out();
static bool_t get_input_bytes();
static bool_t set_input_fragment();
static bool_t skip_input_bytes();
static bool_t xdrrec_getlong();
static bool_t xdrrec_putlong();
static bool_t xdrrec_getbytes();
static bool_t xdrrec_putbytes();
static u_int xdrrec_getpos();
static bool_t xdrrec_setpos();
static long * xdrrec_inline();
static void xdrrec_destroy();
static 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 two-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_long)(1 << 31))
typedef struct rec_strm {
caddr_t tcp_handle;
caddr_t the_buffer;
/*
* out-goung bits
*/
int (*writeit)();
caddr_t out_base; /* output buffer (points to frag header) */
caddr_t out_finger; /* next output position */
caddr_t out_boundry; /* data cannot up to this address */
u_long *frag_header; /* beginning of curren fragment */
bool_t frag_sent; /* true if buffer sent in middle of record */
/*
* in-coming bits
*/
int (*readit)();
u_long in_size; /* fixed size of the input buffer */
caddr_t in_base;
caddr_t in_finger; /* location of next byte to be had */
caddr_t 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;
} RECSTREAM;
/*
* 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)
register XDR *xdrs;
register u_int sendsize;
register u_int recvsize;
caddr_t tcp_handle;
int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
{
register RECSTREAM *rstrm =
(RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
if (rstrm == NULL) {
(void)fprintf(stderr, "xdrrec_create: out of memory\n");
/*
* This is bad. Should rework xdrrec_create to
* return a handle, and in this case return NULL
*/
return;
}
/*
* adjust sizes and allocate buffer quad byte aligned
*/
rstrm->sendsize = sendsize = fix_buf_size(sendsize);
rstrm->recvsize = recvsize = fix_buf_size(recvsize);
rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
if (rstrm->the_buffer == NULL) {
(void)fprintf(stderr, "xdrrec_create: out of memory\n");
return;
}
for (rstrm->out_base = rstrm->the_buffer;
(u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
rstrm->out_base++);
rstrm->in_base = rstrm->out_base + sendsize;
/*
* now the rest ...
*/
xdrs->x_ops = &xdrrec_ops;
xdrs->x_private = (caddr_t)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_long *)rstrm->out_base;
rstrm->out_finger += sizeof(u_long);
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;
}
/*
* 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;
{
register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
register long *buflp = (long *)(rstrm->in_finger);
long mylong;
/* first try the inline, fast case */
if ((rstrm->fbtbc >= sizeof(long)) &&
(((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) {
*lp = (long)ntohl((u_long)(*buflp));
rstrm->fbtbc -= sizeof(long);
rstrm->in_finger += sizeof(long);
} else {
if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long)))
return (FALSE);
*lp = (long)ntohl((u_long)mylong);
}
return (TRUE);
}
static bool_t
xdrrec_putlong(xdrs, lp)
XDR *xdrs;
long *lp;
{
register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
register long *dest_lp = ((long *)(rstrm->out_finger));
if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
/*
* this case should almost never happen so the code is
* inefficient
*/
rstrm->out_finger -= sizeof(long);
rstrm->frag_sent = TRUE;
if (! flush_out(rstrm, FALSE))
return (FALSE);
dest_lp = ((long *)(rstrm->out_finger));
rstrm->out_finger += sizeof(long);
}
*dest_lp = (long)htonl((u_long)(*lp));
return (TRUE);
}
static bool_t /* must manage buffers, fragments, and records */
xdrrec_getbytes(xdrs, addr, len)
XDR *xdrs;
register caddr_t addr;
register u_int len;
{
register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
register int current;
while (len > 0) {
current = 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;
register caddr_t addr;
register u_int len;
{
register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
register int current;
while (len > 0) {
current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger;
current = (len < current) ? len : current;
bcopy(addr, rstrm->out_finger, 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)
register XDR *xdrs;
{
register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
register long pos;
pos = lseek((int)rstrm->tcp_handle, (long) 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 = (u_int) -1;
break;
}
return ((u_int) pos);
}
static bool_t
xdrrec_setpos(xdrs, pos)
register XDR *xdrs;
u_int pos;
{
register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
u_int currpos = xdrrec_getpos(xdrs);
int delta = currpos - pos;
caddr_t newpos;
if ((int)currpos != -1)
switch (xdrs->x_op) {
case XDR_ENCODE:
newpos = rstrm->out_finger - delta;
if ((newpos > (caddr_t)(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;
}
return (FALSE);
}
static long *
xdrrec_inline(xdrs, len)
register XDR *xdrs;
int len;
{
register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
long * buf = NULL;
switch (xdrs->x_op) {
case XDR_ENCODE:
if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
buf = (long *) rstrm->out_finger;
rstrm->out_finger += len;
}
break;
case XDR_DECODE:
if ((len <= rstrm->fbtbc) &&
((rstrm->in_finger + len) <= rstrm->in_boundry)) {
buf = (long *) rstrm->in_finger;
rstrm->fbtbc -= len;
rstrm->in_finger += len;
}
break;
}
return (buf);
}
static void
xdrrec_destroy(xdrs)
register XDR *xdrs;
{
register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
mem_free(rstrm->the_buffer,
rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
mem_free((caddr_t)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;
{
register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
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 fuction.
* 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;
{
register 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;
{
register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
register u_long len; /* fragment length */
if (sendnow || rstrm->frag_sent ||
((u_long)rstrm->out_finger + sizeof(u_long) >=
(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_long);
*(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
rstrm->frag_header = (u_long *)rstrm->out_finger;
rstrm->out_finger += sizeof(u_long);
return (TRUE);
}
/*
* Internal useful routines
*/
static bool_t
flush_out(rstrm, eor)
register RECSTREAM *rstrm;
bool_t eor;
{
register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
register u_long len = (u_long)(rstrm->out_finger) -
(u_long)(rstrm->frag_header) - sizeof(u_long);
*(rstrm->frag_header) = htonl(len | eormask);
len = (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_long *)rstrm->out_base;
rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long);
return (TRUE);
}
static bool_t /* knows nothing about records! Only about input buffers */
fill_input_buf(rstrm)
register RECSTREAM *rstrm;
{
register caddr_t where;
u_int i;
register int len;
where = rstrm->in_base;
i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
where += i;
len = 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)
register RECSTREAM *rstrm;
register caddr_t addr;
register int len;
{
register int current;
while (len > 0) {
current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
if (current == 0) {
if (! fill_input_buf(rstrm))
return (FALSE);
continue;
}
current = (len < current) ? len : current;
bcopy(rstrm->in_finger, addr, 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)
register RECSTREAM *rstrm;
{
u_long header;
if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
return (FALSE);
header = (long)ntohl(header);
rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
rstrm->fbtbc = header & (~LAST_FRAG);
return (TRUE);
}
static bool_t /* consumes input bytes; knows nothing about records! */
skip_input_bytes(rstrm, cnt)
register RECSTREAM *rstrm;
long cnt;
{
register int current;
while (cnt > 0) {
current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
if (current == 0) {
if (! fill_input_buf(rstrm))
return (FALSE);
continue;
}
current = (cnt < current) ? cnt : current;
rstrm->in_finger += current;
cnt -= current;
}
return (TRUE);
}
static u_int
fix_buf_size(s)
register u_int s;
{
if (s < 100)
s = 4000;
return (RNDUP(s));
}

View File

@ -0,0 +1,134 @@
/*
* 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 *sccsid = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/
/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr_reference.c,v 1.1 1993/10/27 05:41:13 paul Exp $";
#endif
/*
* 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 <stdio.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#define LASTUNSIGNED ((u_int)0-1)
/*
* 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)
register 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 */
{
register caddr_t loc = *pp;
register 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) {
(void) fprintf(stderr,
"xdr_reference: out of memory\n");
return (FALSE);
}
bzero(loc, (int)size);
break;
}
stat = (*proc)(xdrs, loc, LASTUNSIGNED);
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)
register 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));
}

191
lib/libc/xdr/xdr_stdio.c Normal file
View File

@ -0,0 +1,191 @@
/*
* 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 *sccsid = "from: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: xdr_stdio.c,v 1.1 1993/10/27 05:41:14 paul Exp $";
#endif
/*
* 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 <rpc/types.h>
#include <stdio.h>
#include <rpc/xdr.h>
static bool_t xdrstdio_getlong();
static bool_t xdrstdio_putlong();
static bool_t xdrstdio_getbytes();
static bool_t xdrstdio_putbytes();
static u_int xdrstdio_getpos();
static bool_t xdrstdio_setpos();
static long * xdrstdio_inline();
static void xdrstdio_destroy();
/*
* Ops vector for stdio type XDR
*/
static 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)
register XDR *xdrs;
FILE *file;
enum xdr_op op;
{
xdrs->x_op = op;
xdrs->x_ops = &xdrstdio_ops;
xdrs->x_private = (caddr_t)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)
register XDR *xdrs;
{
(void)fflush((FILE *)xdrs->x_private);
/* xx should we close the file ?? */
};
static bool_t
xdrstdio_getlong(xdrs, lp)
XDR *xdrs;
register long *lp;
{
if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
return (FALSE);
#ifndef mc68000
*lp = ntohl(*lp);
#endif
return (TRUE);
}
static bool_t
xdrstdio_putlong(xdrs, lp)
XDR *xdrs;
long *lp;
{
#ifndef mc68000
long mycopy = htonl(*lp);
lp = &mycopy;
#endif
if (fwrite((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
return (FALSE);
return (TRUE);
}
static bool_t
xdrstdio_getbytes(xdrs, addr, len)
XDR *xdrs;
caddr_t addr;
u_int len;
{
if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
return (FALSE);
return (TRUE);
}
static bool_t
xdrstdio_putbytes(xdrs, addr, len)
XDR *xdrs;
caddr_t addr;
u_int len;
{
if ((len != 0) && (fwrite(addr, (int)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);
}
static long *
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);
}