1  /*
       2   * xdr_reference.c, Generic XDR routines implementation.
       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   * These are the "non-trivial" xdr primitives used to serialize and
      34   * de-serialize "pointers".  See xdr.h for more info on the interface to xdr.
      35   */
      36  
      37  #include <stdio.h>
      38  #include <string.h>
      39  #include <rpc/types.h>
      40  #include <rpc/xdr.h>
      41  #include <libintl.h>
      42  #include <wchar.h>
      43  #include <libio/iolibio.h>
      44  #include <shlib-compat.h>
      45  
      46  #define LASTUNSIGNED	((u_int)0-1)
      47  
      48  /*
      49   * XDR an indirect pointer
      50   * xdr_reference is for recursively translating a structure that is
      51   * referenced by a pointer inside the structure that is currently being
      52   * translated.  pp references a pointer to storage. If *pp is null
      53   * the  necessary storage is allocated.
      54   * size is the size of the referenced structure.
      55   * proc is the routine to handle the referenced structure.
      56   */
      57  bool_t
      58  xdr_reference (XDR *xdrs,
      59  	       /* the pointer to work on */
      60  	       caddr_t *pp,
      61  	       /* size of the object pointed to */
      62  	       u_int size,
      63  	       /* xdr routine to handle the object */
      64  	       xdrproc_t proc)
      65  {
      66    caddr_t loc = *pp;
      67    bool_t stat;
      68  
      69    if (loc == NULL)
      70      switch (xdrs->x_op)
      71        {
      72        case XDR_FREE:
      73  	return TRUE;
      74  
      75        case XDR_DECODE:
      76  	*pp = loc = (caddr_t) calloc (1, size);
      77  	if (loc == NULL)
      78  	  {
      79  	    (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
      80  	    return FALSE;
      81  	  }
      82  	break;
      83        default:
      84  	break;
      85        }
      86  
      87    stat = (*proc) (xdrs, loc, LASTUNSIGNED);
      88  
      89    if (xdrs->x_op == XDR_FREE)
      90      {
      91        mem_free (loc, size);
      92        *pp = NULL;
      93      }
      94    return stat;
      95  }
      96  libc_hidden_nolink_sunrpc (xdr_reference, GLIBC_2_0)
      97  
      98  
      99  /*
     100   * xdr_pointer():
     101   *
     102   * XDR a pointer to a possibly recursive data structure. This
     103   * differs with xdr_reference in that it can serialize/deserialize
     104   * trees correctly.
     105   *
     106   *  What's sent is actually a union:
     107   *
     108   *  union object_pointer switch (boolean b) {
     109   *  case TRUE: object_data data;
     110   *  case FALSE: void nothing;
     111   *  }
     112   *
     113   * > objpp: Pointer to the pointer to the object.
     114   * > obj_size: size of the object.
     115   * > xdr_obj: routine to XDR an object.
     116   *
     117   */
     118  bool_t
     119  xdr_pointer (XDR *xdrs, char **objpp, u_int obj_size, xdrproc_t xdr_obj)
     120  {
     121  
     122    bool_t more_data;
     123  
     124    more_data = (*objpp != NULL);
     125    if (!xdr_bool (xdrs, &more_data))
     126      {
     127        return FALSE;
     128      }
     129    if (!more_data)
     130      {
     131        *objpp = NULL;
     132        return TRUE;
     133      }
     134    return xdr_reference (xdrs, objpp, obj_size, xdr_obj);
     135  }
     136  #ifdef EXPORT_RPC_SYMBOLS
     137  libc_hidden_def (xdr_pointer)
     138  #else
     139  libc_hidden_nolink_sunrpc (xdr_pointer, GLIBC_2_0)
     140  #endif