xref: /illumos-gate/usr/src/lib/libnsl/rpc/xdr_stdio.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
27 /*
28  * Portions of this source code were derived from Berkeley
29  * 4.3 BSD under license from the Regents of the University of
30  * California.
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
34 
35 /*
36  * xdr_stdio.c, XDR implementation on standard i/o file.
37  *
38  * This set of routines implements a XDR on a stdio stream.
39  * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
40  * from the stream.
41  */
42 
43 #include "mt.h"
44 #include "rpc_mt.h"
45 #include <rpc/types.h>
46 #include <stdio.h>
47 #include <rpc/xdr.h>
48 #include <sys/types.h>
49 #include <rpc/trace.h>
50 #include <inttypes.h>
51 
52 static struct xdr_ops *xdrstdio_ops(void);
53 
54 /*
55  * Initialize a stdio xdr stream.
56  * Sets the xdr stream handle xdrs for use on the stream file.
57  * Operation flag is set to op.
58  */
59 void
60 xdrstdio_create(XDR *xdrs, FILE *file, enum xdr_op op)
61 {
62 	trace1(TR_xdrstdio_create, 0);
63 	xdrs->x_op = op;
64 	xdrs->x_ops = xdrstdio_ops();
65 	xdrs->x_private = (caddr_t)file;
66 	xdrs->x_handy = 0;
67 	xdrs->x_base = 0;
68 	trace1(TR_xdrstdio_create, 1);
69 }
70 
71 /*
72  * Destroy a stdio xdr stream.
73  * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
74  */
75 static void
76 xdrstdio_destroy(XDR *xdrs)
77 {
78 	trace1(TR_xdrstdio_destroy, 0);
79 	(void) fflush((FILE *)xdrs->x_private);
80 	/* xx should we close the file ?? */
81 	trace1(TR_xdrstdio_destroy, 1);
82 }
83 
84 
85 static bool_t
86 xdrstdio_getint32(XDR *xdrs, int32_t *lp)
87 {
88 	trace1(TR_xdrstdio_getint32, 0);
89 	if (fread((caddr_t)lp, sizeof (int32_t), 1,
90 			(FILE *)xdrs->x_private) != 1) {
91 		trace1(TR_xdrstdio_getint32, 1);
92 		return (FALSE);
93 	}
94 	*lp = ntohl(*lp);
95 	trace1(TR_xdrstdio_getint32, 1);
96 	return (TRUE);
97 }
98 
99 static bool_t
100 xdrstdio_putint32(XDR *xdrs, int32_t *lp)
101 {
102 
103 	int32_t mycopy = htonl(*lp);
104 	lp = &mycopy;
105 
106 	trace1(TR_xdrstdio_putint32, 0);
107 	if (fwrite((caddr_t)lp, sizeof (int32_t), 1,
108 			(FILE *)xdrs->x_private) != 1) {
109 		trace1(TR_xdrstdio_putint32, 1);
110 		return (FALSE);
111 	}
112 	trace1(TR_xdrstdio_putint32, 1);
113 	return (TRUE);
114 }
115 
116 static bool_t
117 xdrstdio_getlong(xdrs, lp)
118 	XDR *xdrs;
119 	long *lp;
120 {
121 	int32_t i;
122 
123 	if (!xdrstdio_getint32(xdrs, &i))
124 		return (FALSE);
125 
126 	*lp = (long)i;
127 
128 	return (TRUE);
129 }
130 
131 static bool_t
132 xdrstdio_putlong(xdrs, lp)
133 	XDR *xdrs;
134 	long *lp;
135 {
136 	int32_t i;
137 
138 #if defined(_LP64)
139 	if ((*lp > INT32_MAX) || (*lp < INT32_MIN)) {
140 		return (FALSE);
141 	}
142 #endif
143 
144 	i = (int32_t)*lp;
145 
146 	return (xdrstdio_putint32(xdrs, &i));
147 }
148 
149 static bool_t
150 xdrstdio_getbytes(XDR *xdrs, caddr_t addr, int len)
151 {
152 	trace2(TR_xdrstdio_getbytes, 0, len);
153 	if ((len != 0) &&
154 		(fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) {
155 		trace1(TR_xdrstdio_getbytes, 1);
156 		return (FALSE);
157 	}
158 	trace1(TR_xdrstdio_getbytes, 1);
159 	return (TRUE);
160 }
161 
162 static bool_t
163 xdrstdio_putbytes(XDR *xdrs, caddr_t addr, int len)
164 {
165 	trace2(TR_xdrstdio_putbytes, 0, len);
166 	if ((len != 0) &&
167 		(fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) {
168 		trace1(TR_xdrstdio_putbytes, 1);
169 		return (FALSE);
170 	}
171 	trace1(TR_xdrstdio_putbytes, 1);
172 	return (TRUE);
173 }
174 
175 static uint_t
176 xdrstdio_getpos(XDR *xdrs)
177 {
178 	uint_t dummy1;
179 
180 	trace1(TR_xdrstdio_getpos, 0);
181 	dummy1 = (uint_t)ftell((FILE *)xdrs->x_private);
182 	trace1(TR_xdrstdio_getpos, 1);
183 	return (dummy1);
184 }
185 
186 static bool_t
187 xdrstdio_setpos(XDR *xdrs, uint_t pos)
188 {
189 	bool_t dummy2;
190 
191 	trace2(TR_xdrstdio_setpos, 0, pos);
192 	dummy2 = (fseek((FILE *)xdrs->x_private,
193 			(int)pos, 0) < 0) ? FALSE : TRUE;
194 	trace1(TR_xdrstdio_setpos, 1);
195 	return (dummy2);
196 }
197 
198 static rpc_inline_t *
199 xdrstdio_inline(XDR *xdrs, int len)
200 {
201 
202 	/*
203 	 * Must do some work to implement this: must insure
204 	 * enough data in the underlying stdio buffer,
205 	 * that the buffer is aligned so that we can indirect through a
206 	 * long *, and stuff this pointer in xdrs->x_buf.  Doing
207 	 * a fread or fwrite to a scratch buffer would defeat
208 	 * most of the gains to be had here and require storage
209 	 * management on this buffer, so we don't do this.
210 	 */
211 	trace2(TR_xdrstdio_inline, 0, len);
212 	trace2(TR_xdrstdio_inline, 1, len);
213 	return (NULL);
214 }
215 
216 static bool_t
217 xdrstdio_control(XDR *xdrs, int request, void *info)
218 {
219 	switch (request) {
220 
221 	default:
222 		return (FALSE);
223 	}
224 }
225 
226 static struct xdr_ops *
227 xdrstdio_ops()
228 {
229 	static struct xdr_ops ops;
230 	extern mutex_t	ops_lock;
231 
232 /* VARIABLES PROTECTED BY ops_lock: ops */
233 
234 	trace1(TR_xdrstdio_ops, 0);
235 	mutex_lock(&ops_lock);
236 	if (ops.x_getlong == NULL) {
237 		ops.x_getlong = xdrstdio_getlong;
238 		ops.x_putlong = xdrstdio_putlong;
239 		ops.x_getbytes = xdrstdio_getbytes;
240 		ops.x_putbytes = xdrstdio_putbytes;
241 		ops.x_getpostn = xdrstdio_getpos;
242 		ops.x_setpostn = xdrstdio_setpos;
243 		ops.x_inline = xdrstdio_inline;
244 		ops.x_destroy = xdrstdio_destroy;
245 		ops.x_control = xdrstdio_control;
246 #if defined(_LP64)
247 		ops.x_getint32 = xdrstdio_getint32;
248 		ops.x_putint32 = xdrstdio_putint32;
249 #endif
250 	}
251 	mutex_unlock(&ops_lock);
252 	trace1(TR_xdrstdio_ops, 1);
253 	return (&ops);
254 }
255