1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * - Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  *   this list of conditions and the following disclaimer in the documentation
11  *   and/or other materials provided with the distribution.
12  * - Neither the name of Sun Microsystems, Inc. nor the names of its
13  *   contributors may be used to endorse or promote products derived
14  *   from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * xdr_stdio.c, XDR implementation on standard i/o file.
31  *
32  * Copyright (C) 1984, Sun Microsystems, Inc.
33  *
34  * This set of routines implements a XDR on a stdio stream.
35  * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
36  * from the stream.
37  */
38 
39 #define _DEFAULT_SOURCE
40 #include <stdio.h>
41 
42 #include <rpc/types.h>
43 #include <rpc/xdr.h>
44 
45 #include "xdr_private.h"
46 
47 #ifndef ntohl
48 # define ntohl(x) xdr_ntohl(x)
49 #endif
50 #ifndef htonl
51 # define htonl(x) xdr_htonl(x)
52 #endif
53 
54 static void xdrstdio_destroy (XDR *);
55 static bool_t xdrstdio_getlong (XDR *, long *);
56 static bool_t xdrstdio_putlong (XDR *, const long *);
57 static bool_t xdrstdio_getbytes (XDR *, char *, u_int);
58 static bool_t xdrstdio_putbytes (XDR *, const char *, u_int);
59 static u_int xdrstdio_getpos (XDR *);
60 static bool_t xdrstdio_setpos (XDR *, u_int);
61 static int32_t * xdrstdio_inline (XDR *, u_int);
62 static bool_t xdrstdio_getint32 (XDR*, int32_t *);
63 static bool_t xdrstdio_putint32 (XDR*, const int32_t *);
64 
65 /*
66  * Ops vector for stdio type XDR
67  */
68 static const struct xdr_ops xdrstdio_ops = {
69   xdrstdio_getlong,             /* deseraialize a long int */
70   xdrstdio_putlong,             /* seraialize a long int */
71   xdrstdio_getbytes,            /* deserialize counted bytes */
72   xdrstdio_putbytes,            /* serialize counted bytes */
73   xdrstdio_getpos,              /* get offset in the stream */
74   xdrstdio_setpos,              /* set offset in the stream */
75   xdrstdio_inline,              /* prime stream for inline macros */
76   xdrstdio_destroy,             /* destroy stream */
77   xdrstdio_getint32,            /* deseraialize an int */
78   xdrstdio_putint32             /* seraialize an long int */
79 };
80 
81 /*
82  * Initialize a stdio xdr stream.
83  * Sets the xdr stream handle xdrs for use on the stream file.
84  * Operation flag is set to op.
85  */
86 void
xdrstdio_create(XDR * xdrs,FILE * file,enum xdr_op op)87 xdrstdio_create (XDR * xdrs,
88 	FILE * file,
89 	enum xdr_op op)
90 {
91   xdrs->x_op = op;
92   xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops;
93   xdrs->x_private = (void *) file;
94   xdrs->x_handy = 0;
95   xdrs->x_base = 0;
96 }
97 
98 /*
99  * Destroy a stdio xdr stream.
100  * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
101  */
102 static void
xdrstdio_destroy(XDR * xdrs)103 xdrstdio_destroy (XDR * xdrs)
104 {
105   (void) fflush ((FILE *) xdrs->x_private);
106   /* XXX: should we close the file ?? */
107 }
108 
109 static bool_t
xdrstdio_getlong(XDR * xdrs,long * lp)110 xdrstdio_getlong (XDR * xdrs,
111 	long *lp)
112 {
113   u_int32_t temp;
114 
115   if (fread (&temp, sizeof (int32_t), 1, (FILE *) xdrs->x_private) != 1)
116     return FALSE;
117   *lp = (long) (int32_t) ntohl (temp);
118   return TRUE;
119 }
120 
121 static bool_t
xdrstdio_putlong(XDR * xdrs,const long * lp)122 xdrstdio_putlong (XDR * xdrs,
123 	const long *lp)
124 {
125   u_int32_t temp = htonl ((u_int32_t) * lp);
126 
127   if (fwrite (&temp, sizeof (int32_t), 1, (FILE *) xdrs->x_private) != 1)
128     return FALSE;
129   return TRUE;
130 }
131 
132 static bool_t
xdrstdio_getbytes(XDR * xdrs,char * addr,u_int len)133 xdrstdio_getbytes (XDR * xdrs,
134         char *addr,
135 	u_int len)
136 {
137   if ((len != 0) && (fread (addr, (size_t) len, 1,
138                             (FILE *) xdrs->x_private) != 1))
139     return FALSE;
140   return TRUE;
141 }
142 
143 static bool_t
xdrstdio_putbytes(XDR * xdrs,const char * addr,u_int len)144 xdrstdio_putbytes (XDR * xdrs,
145         const char *addr,
146 	u_int len)
147 {
148   if ((len != 0) && (fwrite (addr, (size_t) len, 1,
149                              (FILE *) xdrs->x_private) != 1))
150     return FALSE;
151   return TRUE;
152 }
153 
154 static u_int
xdrstdio_getpos(XDR * xdrs)155 xdrstdio_getpos (XDR * xdrs)
156 {
157   return ((u_int) ftell ((FILE *) xdrs->x_private));
158 }
159 
160 static bool_t
xdrstdio_setpos(XDR * xdrs,u_int pos)161 xdrstdio_setpos (XDR * xdrs,
162         u_int pos)
163 {
164   return ((fseek ((FILE *) xdrs->x_private, (long) pos, 0) < 0) ?
165           FALSE : TRUE);
166 }
167 
168 /* ARGSUSED */
169 static int32_t *
xdrstdio_inline(XDR * xdrs,u_int len)170 xdrstdio_inline (XDR * xdrs,
171 	u_int len)
172 {
173   (void) xdrs;
174   (void) len;
175   /*
176    * Must do some work to implement this: must insure
177    * enough data in the underlying stdio buffer,
178    * that the buffer is aligned so that we can indirect through a
179    * long *, and stuff this pointer in xdrs->x_buf.  Doing
180    * a fread or fwrite to a scratch buffer would defeat
181    * most of the gains to be had here and require storage
182    * management on this buffer, so we don't do this.
183    */
184   return NULL;
185 }
186 
187 static bool_t
xdrstdio_getint32(XDR * xdrs,int32_t * ip)188 xdrstdio_getint32 (XDR *xdrs,
189 	int32_t *ip)
190 {
191   int32_t temp;
192 
193   if (fread (&temp, sizeof (int32_t), 1, (FILE *) xdrs->x_private) != 1)
194     return FALSE;
195   *ip = ntohl (temp);
196   return TRUE;
197 }
198 
199 static bool_t
xdrstdio_putint32(XDR * xdrs,const int32_t * ip)200 xdrstdio_putint32 (XDR *xdrs,
201 	const int32_t *ip)
202 {
203   int32_t temp = htonl (*ip);
204 
205   if (fwrite (&temp, sizeof (int32_t), 1, (FILE *) xdrs->x_private) != 1)
206     return FALSE;
207   return TRUE;
208 }
209 
210