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