1 /* $OpenBSD: xdr_array.c,v 1.10 2010/09/01 14:43:34 millert 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_array.c, Generic XDR routines implementation. 36 * 37 * These are the "non-trivial" xdr primitives used to serialize and de-serialize 38 * arrays. See xdr.h for more info on the interface to xdr. 39 */ 40 41 42 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <limits.h> 47 #include <rpc/types.h> 48 #include <rpc/xdr.h> 49 50 /* 51 * XDR an array of arbitrary elements 52 * *addrp is a pointer to the array, *sizep is the number of elements. 53 * If addrp is NULL (*sizep * elsize) bytes are allocated. 54 * elsize is the size (in bytes) of each element, and elproc is the 55 * xdr procedure to call to handle each element of the array. 56 */ 57 bool_t 58 xdr_array(XDR *xdrs, 59 caddr_t *addrp, /* array pointer */ 60 u_int *sizep, /* number of elements */ 61 u_int maxsize, /* max numberof elements */ 62 u_int elsize, /* size in bytes of each element */ 63 xdrproc_t elproc) /* xdr routine to handle each element */ 64 { 65 caddr_t target = *addrp; 66 u_int nodesize, c, i; 67 bool_t stat = TRUE; 68 69 /* like strings, arrays are really counted arrays */ 70 if (!xdr_u_int(xdrs, sizep)) 71 return (FALSE); 72 73 c = *sizep; 74 if ((c > maxsize || c > UINT_MAX/elsize) && 75 xdrs->x_op != XDR_FREE) 76 return (FALSE); 77 nodesize = c * elsize; 78 79 /* 80 * if we are deserializing, we may need to allocate an array. 81 * We also save time by checking for a null array if we are freeing. 82 */ 83 if (target == NULL) { 84 switch (xdrs->x_op) { 85 case XDR_DECODE: 86 if (c == 0) 87 return (TRUE); 88 *addrp = target = mem_alloc(nodesize); 89 if (target == NULL) { 90 (void) fprintf(stderr, 91 "xdr_array: out of memory\n"); 92 return (FALSE); 93 } 94 memset(target, 0, nodesize); 95 break; 96 case XDR_FREE: 97 return (TRUE); 98 } 99 } 100 101 /* 102 * now we xdr each element of array 103 */ 104 for (i = 0; (i < c) && stat; i++) { 105 stat = (*elproc)(xdrs, target); 106 target += elsize; 107 } 108 109 /* 110 * the array may need freeing 111 */ 112 if (xdrs->x_op == XDR_FREE) { 113 mem_free(*addrp, nodesize); 114 *addrp = NULL; 115 } 116 return (stat); 117 } 118 119 /* 120 * xdr_vector(): 121 * 122 * XDR a fixed length array. Unlike variable-length arrays, 123 * the storage of fixed length arrays is static and unfreeable. 124 * > basep: base of the array 125 * > size: size of the array 126 * > elemsize: size of each element 127 * > xdr_elem: routine to XDR each element 128 */ 129 bool_t 130 xdr_vector(XDR *xdrs, char *basep, u_int nelem, u_int elemsize, 131 xdrproc_t xdr_elem) 132 { 133 char *elptr; 134 u_int i; 135 136 elptr = basep; 137 for (i = 0; i < nelem; i++) { 138 if (!(*xdr_elem)(xdrs, elptr)) 139 return(FALSE); 140 elptr += elemsize; 141 } 142 return(TRUE); 143 } 144