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
xdrstdio_create(XDR * xdrs,FILE * file,const enum xdr_op op)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
xdrstdio_destroy(XDR * xdrs)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
xdrstdio_getint32(XDR * xdrs,int32_t * lp)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
xdrstdio_putint32(XDR * xdrs,int32_t * lp)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
xdrstdio_getlong(XDR * xdrs,long * lp)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
xdrstdio_putlong(XDR * xdrs,long * lp)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
xdrstdio_getbytes(XDR * xdrs,caddr_t addr,int len)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
xdrstdio_putbytes(XDR * xdrs,caddr_t addr,int len)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
xdrstdio_getpos(XDR * xdrs)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
xdrstdio_setpos(XDR * xdrs,uint_t pos)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 *
xdrstdio_inline(XDR * xdrs,int len)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
xdrstdio_control(XDR * xdrs,int request,void * info)184 xdrstdio_control(XDR *xdrs, int request, void *info)
185 {
186 return (FALSE);
187 }
188
189 static struct xdr_ops *
xdrstdio_ops(void)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