xdr_sizeof.c revision 1219:f89f56c2d9ac
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 2006 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30/*
31 * General purpose routine to see how much space something will use
32 * when serialized using XDR.
33 */
34#include "mt.h"
35#include <rpc/types.h>
36#include <rpc/xdr.h>
37#include <sys/types.h>
38#include <stdlib.h>
39
40/* ARGSUSED1 */
41static bool_t
42x_putlong(XDR *xdrs, long *ip)
43{
44	xdrs->x_handy += BYTES_PER_XDR_UNIT;
45	return (TRUE);
46}
47
48#if defined(_LP64)
49/* ARGSUSED1 */
50static bool_t
51x_putint32_t(XDR *xdrs, int32_t *ip)
52{
53	xdrs->x_handy += BYTES_PER_XDR_UNIT;
54	return (TRUE);
55}
56#endif
57
58/* ARGSUSED */
59static bool_t
60x_putbytes(XDR *xdrs, char *bp, int len)
61{
62	xdrs->x_handy += len;
63	return (TRUE);
64}
65
66static uint_t
67x_getpostn(XDR *xdrs)
68{
69	return (xdrs->x_handy);
70}
71
72/* ARGSUSED */
73static bool_t
74x_setpostn(XDR *xdrs, uint_t pos)
75{
76	/* This is not allowed */
77	return (FALSE);
78}
79
80static rpc_inline_t *
81x_inline(XDR *xdrs, int len)
82{
83	if (len == 0)
84		return (NULL);
85	if (xdrs->x_op != XDR_ENCODE)
86		return (NULL);
87	if (len < (intptr_t)xdrs->x_base) {
88		/* x_private was already allocated */
89		xdrs->x_handy += len;
90		/* LINTED pointer cast */
91		return ((rpc_inline_t *)xdrs->x_private);
92	}
93	/* Free the earlier space and allocate new area */
94	if (xdrs->x_private)
95		free(xdrs->x_private);
96	if ((xdrs->x_private = malloc(len)) == NULL) {
97		xdrs->x_base = 0;
98		return (NULL);
99	}
100	xdrs->x_base = (caddr_t)(intptr_t)len;
101	xdrs->x_handy += len;
102	/* LINTED pointer cast */
103	return ((rpc_inline_t *)xdrs->x_private);
104}
105
106static int
107harmless(void)
108{
109	/* Always return FALSE/NULL, as the case may be */
110	return (0);
111}
112
113static void
114x_destroy(XDR *xdrs)
115{
116	xdrs->x_handy = 0;
117	xdrs->x_base = 0;
118	if (xdrs->x_private) {
119		free(xdrs->x_private);
120		xdrs->x_private = NULL;
121	}
122}
123
124uint_t
125xdr_sizeof(xdrproc_t func, void *data)
126{
127	XDR x;
128	struct xdr_ops ops;
129	bool_t stat;
130	/* to stop ANSI-C compiler from complaining */
131	typedef  bool_t (* dummyfunc1)(XDR *, long *);
132	typedef  bool_t (* dummyfunc2)(XDR *, caddr_t, int);
133	typedef  bool_t (* dummyfunc3)(XDR *, int32_t *);
134
135	ops.x_putlong = x_putlong;
136	ops.x_getlong =  (dummyfunc1) harmless;
137	ops.x_putbytes = x_putbytes;
138	ops.x_inline = x_inline;
139	ops.x_getpostn = x_getpostn;
140	ops.x_setpostn = x_setpostn;
141	ops.x_destroy = x_destroy;
142#if defined(_LP64)
143	ops.x_getint32 = (dummyfunc3) harmless;
144	ops.x_putint32 = x_putint32_t;
145#endif
146
147	/* the other harmless ones */
148	ops.x_getbytes = (dummyfunc2) harmless;
149
150	x.x_op = XDR_ENCODE;
151	x.x_ops = &ops;
152	x.x_handy = 0;
153	x.x_private = NULL;
154	x.x_base = NULL;
155
156	stat = func(&x, data);
157	if (x.x_private)
158		free(x.x_private);
159	return (stat == TRUE ? (uint_t)x.x_handy : 0);
160}
161