xref: /illumos-gate/usr/src/lib/libnsl/rpc/xdr_stdio.c (revision e3ae4b35c024af1196582063ecee3ab79367227d)
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 
23 /*
24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 /*
30  * Portions of this source code were derived from Berkeley
31  * 4.3 BSD under license from the Regents of the University of
32  * California.
33  */
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 <inttypes.h>
50 
51 static struct xdr_ops *xdrstdio_ops(void);
52 
53 /*
54  * Initialize a stdio xdr stream.
55  * Sets the xdr stream handle xdrs for use on the stream file.
56  * Operation flag is set to op.
57  */
58 void
59 xdrstdio_create(XDR *xdrs, FILE *file, const enum xdr_op op)
60 {
61 	xdrs->x_op = op;
62 	xdrs->x_ops = xdrstdio_ops();
63 	xdrs->x_private = (caddr_t)file;
64 	xdrs->x_handy = 0;
65 	xdrs->x_base = 0;
66 }
67 
68 /*
69  * Destroy a stdio xdr stream.
70  * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
71  */
72 static void
73 xdrstdio_destroy(XDR *xdrs)
74 {
75 	/* LINTED pointer cast */
76 	(void) fflush((FILE *)xdrs->x_private);
77 	/* xx should we close the file ?? */
78 }
79 
80 
81 static bool_t
82 xdrstdio_getint32(XDR *xdrs, int32_t *lp)
83 {
84 	if (fread((caddr_t)lp, sizeof (int32_t), 1,
85 			/* LINTED pointer cast */
86 			(FILE *)xdrs->x_private) != 1)
87 		return (FALSE);
88 	*lp = ntohl(*lp);
89 	return (TRUE);
90 }
91 
92 static bool_t
93 xdrstdio_putint32(XDR *xdrs, int32_t *lp)
94 {
95 
96 	int32_t mycopy = htonl(*lp);
97 	lp = &mycopy;
98 
99 	if (fwrite((caddr_t)lp, sizeof (int32_t), 1,
100 			/* LINTED pointer cast */
101 			(FILE *)xdrs->x_private) != 1)
102 		return (FALSE);
103 	return (TRUE);
104 }
105 
106 static bool_t
107 xdrstdio_getlong(XDR *xdrs, long *lp)
108 {
109 	int32_t i;
110 
111 	if (!xdrstdio_getint32(xdrs, &i))
112 		return (FALSE);
113 	*lp = (long)i;
114 	return (TRUE);
115 }
116 
117 static bool_t
118 xdrstdio_putlong(XDR *xdrs, long *lp)
119 {
120 	int32_t i;
121 
122 #if defined(_LP64)
123 	if ((*lp > INT32_MAX) || (*lp < INT32_MIN))
124 		return (FALSE);
125 #endif
126 	i = (int32_t)*lp;
127 
128 	return (xdrstdio_putint32(xdrs, &i));
129 }
130 
131 static bool_t
132 xdrstdio_getbytes(XDR *xdrs, caddr_t addr, int len)
133 {
134 	if ((len != 0) &&
135 		/* LINTED pointer cast */
136 		(fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
137 		return (FALSE);
138 	return (TRUE);
139 }
140 
141 static bool_t
142 xdrstdio_putbytes(XDR *xdrs, caddr_t addr, int len)
143 {
144 	if ((len != 0) &&
145 		/* LINTED pointer cast */
146 		(fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
147 		return (FALSE);
148 	return (TRUE);
149 }
150 
151 static uint_t
152 xdrstdio_getpos(XDR *xdrs)
153 {
154 	/* LINTED pointer cast */
155 	return ((uint_t)ftell((FILE *)xdrs->x_private));
156 }
157 
158 static bool_t
159 xdrstdio_setpos(XDR *xdrs, uint_t pos)
160 {
161 	/* LINTED pointer cast */
162 	return ((fseek((FILE *)xdrs->x_private,
163 			(int)pos, 0) < 0) ? FALSE : TRUE);
164 }
165 
166 /* ARGSUSED */
167 static rpc_inline_t *
168 xdrstdio_inline(XDR *xdrs, int len)
169 {
170 	/*
171 	 * Must do some work to implement this: must insure
172 	 * enough data in the underlying stdio buffer,
173 	 * that the buffer is aligned so that we can indirect through a
174 	 * long *, and stuff this pointer in xdrs->x_buf.  Doing
175 	 * a fread or fwrite to a scratch buffer would defeat
176 	 * most of the gains to be had here and require storage
177 	 * management on this buffer, so we don't do this.
178 	 */
179 	return (NULL);
180 }
181 
182 /* ARGSUSED */
183 static bool_t
184 xdrstdio_control(XDR *xdrs, int request, void *info)
185 {
186 	return (FALSE);
187 }
188 
189 static struct xdr_ops *
190 xdrstdio_ops(void)
191 {
192 	static struct xdr_ops ops;
193 	extern mutex_t	ops_lock;
194 
195 /* VARIABLES PROTECTED BY ops_lock: ops */
196 
197 	(void) mutex_lock(&ops_lock);
198 	if (ops.x_getlong == NULL) {
199 		ops.x_getlong = xdrstdio_getlong;
200 		ops.x_putlong = xdrstdio_putlong;
201 		ops.x_getbytes = xdrstdio_getbytes;
202 		ops.x_putbytes = xdrstdio_putbytes;
203 		ops.x_getpostn = xdrstdio_getpos;
204 		ops.x_setpostn = xdrstdio_setpos;
205 		ops.x_inline = xdrstdio_inline;
206 		ops.x_destroy = xdrstdio_destroy;
207 		ops.x_control = xdrstdio_control;
208 #if defined(_LP64)
209 		ops.x_getint32 = xdrstdio_getint32;
210 		ops.x_putint32 = xdrstdio_putint32;
211 #endif
212 	}
213 	(void) mutex_unlock(&ops_lock);
214 	return (&ops);
215 }
216