1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
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 * xdr_sizeof.c
35 *
36 * General purpose routine to see how much space something will use
37 * when serialized using XDR.
38 */
39
40#include "namespace.h"
41#include <rpc/types.h>
42#include <rpc/xdr.h>
43#include <sys/types.h>
44#include <stdlib.h>
45#include "un-namespace.h"
46
47/* ARGSUSED */
48static bool_t
49x_putlong(XDR *xdrs, const long *longp)
50{
51	xdrs->x_handy += BYTES_PER_XDR_UNIT;
52	return (TRUE);
53}
54
55/* ARGSUSED */
56static bool_t
57x_putbytes(XDR *xdrs, const char *bp, u_int len)
58{
59	xdrs->x_handy += len;
60	return (TRUE);
61}
62
63static u_int
64x_getpostn(XDR *xdrs)
65{
66	return (xdrs->x_handy);
67}
68
69/* ARGSUSED */
70static bool_t
71x_setpostn(XDR *xdrs, u_int pos)
72{
73	/* This is not allowed */
74	return (FALSE);
75}
76
77static int32_t *
78x_inline(XDR *xdrs, u_int len)
79{
80	if (len == 0) {
81		return (NULL);
82	}
83	if (xdrs->x_op != XDR_ENCODE) {
84		return (NULL);
85	}
86	if (len < (u_int)(uintptr_t)xdrs->x_base) {
87		/* x_private was already allocated */
88		xdrs->x_handy += len;
89		return ((int32_t *) xdrs->x_private);
90	} else {
91		/* Free the earlier space and allocate new area */
92		if (xdrs->x_private)
93			free(xdrs->x_private);
94		if ((xdrs->x_private = (caddr_t) malloc(len)) == NULL) {
95			xdrs->x_base = 0;
96			return (NULL);
97		}
98		xdrs->x_base = (caddr_t)(uintptr_t)len;
99		xdrs->x_handy += len;
100		return ((int32_t *) xdrs->x_private);
101	}
102}
103
104static int
105harmless(void)
106{
107	/* Always return FALSE/NULL, as the case may be */
108	return (0);
109}
110
111static void
112x_destroy(XDR *xdrs)
113{
114	xdrs->x_handy = 0;
115	xdrs->x_base = 0;
116	if (xdrs->x_private) {
117		free(xdrs->x_private);
118		xdrs->x_private = NULL;
119	}
120	return;
121}
122
123unsigned long
124xdr_sizeof(xdrproc_t func, void *data)
125{
126	XDR x;
127	struct xdr_ops ops;
128	bool_t stat;
129	/* to stop ANSI-C compiler from complaining */
130	typedef  bool_t (* dummyfunc1)(XDR *, long *);
131	typedef  bool_t (* dummyfunc2)(XDR *, caddr_t, u_int);
132
133	ops.x_putlong = x_putlong;
134	ops.x_putbytes = x_putbytes;
135	ops.x_inline = x_inline;
136	ops.x_getpostn = x_getpostn;
137	ops.x_setpostn = x_setpostn;
138	ops.x_destroy = x_destroy;
139
140	/* the other harmless ones */
141	ops.x_getlong =  (dummyfunc1) harmless;
142	ops.x_getbytes = (dummyfunc2) harmless;
143
144	x.x_op = XDR_ENCODE;
145	x.x_ops = &ops;
146	x.x_handy = 0;
147	x.x_private = (caddr_t) NULL;
148	x.x_base = (caddr_t) 0;
149
150	stat = func(&x, data);
151	if (x.x_private)
152		free(x.x_private);
153	return (stat == TRUE ? (unsigned) x.x_handy: 0);
154}
155