1 /* $NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2009, Sun Microsystems, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * - Neither the name of Sun Microsystems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #if defined(LIBC_SCCS) && !defined(lint) 32 static char *sccsid2 = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro"; 33 static char *sccsid = "@(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC"; 34 #endif 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 /* 39 * pmap_prot2.c 40 * Protocol for the local binder service, or pmap. 41 * 42 * Copyright (C) 1984, Sun Microsystems, Inc. 43 */ 44 45 #include "namespace.h" 46 #include <assert.h> 47 48 #include <rpc/types.h> 49 #include <rpc/xdr.h> 50 #include <rpc/pmap_prot.h> 51 #include "un-namespace.h" 52 53 54 /* 55 * What is going on with linked lists? (!) 56 * First recall the link list declaration from pmap_prot.h: 57 * 58 * struct pmaplist { 59 * struct pmap pml_map; 60 * struct pmaplist *pml_map; 61 * }; 62 * 63 * Compare that declaration with a corresponding xdr declaration that 64 * is (a) pointer-less, and (b) recursive: 65 * 66 * typedef union switch (bool_t) { 67 * 68 * case TRUE: struct { 69 * struct pmap; 70 * pmaplist_t foo; 71 * }; 72 * 73 * case FALSE: struct {}; 74 * } pmaplist_t; 75 * 76 * Notice that the xdr declaration has no nxt pointer while 77 * the C declaration has no bool_t variable. The bool_t can be 78 * interpreted as ``more data follows me''; if FALSE then nothing 79 * follows this bool_t; if TRUE then the bool_t is followed by 80 * an actual struct pmap, and then (recursively) by the 81 * xdr union, pamplist_t. 82 * 83 * This could be implemented via the xdr_union primitive, though this 84 * would cause a one recursive call per element in the list. Rather than do 85 * that we can ``unwind'' the recursion 86 * into a while loop and do the union arms in-place. 87 * 88 * The head of the list is what the C programmer wishes to past around 89 * the net, yet is the data that the pointer points to which is interesting; 90 * this sounds like a job for xdr_reference! 91 */ 92 bool_t 93 xdr_pmaplist(XDR *xdrs, struct pmaplist **rp) 94 { 95 /* 96 * more_elements is pre-computed in case the direction is 97 * XDR_ENCODE or XDR_FREE. more_elements is overwritten by 98 * xdr_bool when the direction is XDR_DECODE. 99 */ 100 bool_t more_elements; 101 int freeing; 102 struct pmaplist **next = NULL; /* pacify gcc */ 103 104 assert(xdrs != NULL); 105 assert(rp != NULL); 106 107 freeing = (xdrs->x_op == XDR_FREE); 108 109 for (;;) { 110 more_elements = (bool_t)(*rp != NULL); 111 if (! xdr_bool(xdrs, &more_elements)) 112 return (FALSE); 113 if (! more_elements) 114 return (TRUE); /* we are done */ 115 /* 116 * the unfortunate side effect of non-recursion is that in 117 * the case of freeing we must remember the next object 118 * before we free the current object ... 119 */ 120 if (freeing) 121 next = &((*rp)->pml_next); 122 if (! xdr_reference(xdrs, (caddr_t *)rp, 123 (u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap)) 124 return (FALSE); 125 rp = (freeing) ? next : &((*rp)->pml_next); 126 } 127 } 128 129 130 /* 131 * xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in 132 * functionality to xdr_pmaplist(). 133 */ 134 bool_t 135 xdr_pmaplist_ptr(XDR *xdrs, struct pmaplist *rp) 136 { 137 return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp); 138 } 139