]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
DynXdr: Implement xdr_inline operation.
authorVMware, Inc <>
Thu, 17 Dec 2009 22:51:24 +0000 (14:51 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 17 Dec 2009 22:51:24 +0000 (14:51 -0800)
While working with SIGAR => XDR serialization, I ran into segfaults
when the rpcgen-generated code called xdr_inline, an operation which
we didn't implement.

This change fixes that.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/dynxdr/dynxdr.c

index 792eb4861076cbf5112981a67746055ff3e35e4d..bfaab80739c9d3daee83fc812fffc78c00dbc8b1 100644 (file)
@@ -78,6 +78,14 @@ typedef struct DynXdrData {
 #  define DYNXDR_LONG long
 #endif
 
+#if defined(sun)
+#   define DYNXDR_INLINE_T rpc_inline_t
+#   define DYNXDR_INLINE_LEN_T int
+#else
+#   define DYNXDR_INLINE_T int32_t
+#   define DYNXDR_INLINE_LEN_T u_int
+#endif
+
 
 /*
  *-----------------------------------------------------------------------------
@@ -200,6 +208,53 @@ DynXdrPutLong(XDR *xdrs,                    // IN/OUT
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * DynXdrInline --
+ *
+ *    Return a pointer to a contiguous buffer of len bytes.  On XDR_ENCODE,
+ *    is used to preallocate chunks of the backing buffer such that the caller
+ *    may set bulk 4-byte members w/o reallocating each time.
+ *
+ * Results:
+ *    Valid pointer on success, NULL on failure.
+ *
+ * Side effects:
+ *    Backing DynBuf may be enlarged.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static DYNXDR_INLINE_T *
+DynXdrInline(XDR *xdrs,                 // IN/OUT
+             DYNXDR_INLINE_LEN_T len)   // IN
+{
+   DynXdrData *priv = (DynXdrData *)xdrs->x_private;
+   DynBuf *buf = &priv->data;
+   DYNXDR_INLINE_T *retAddr;
+
+   ASSERT(len >= 0);
+   ASSERT(xdrs->x_op == XDR_ENCODE);
+
+   if (len == 0) {
+      return (DYNXDR_INLINE_T *)&buf->data[buf->size];
+   }
+
+   if (buf->allocated - buf->size < len) {
+      /* DynBuf too small.  Grow it. */
+      if (!DynBuf_Enlarge(buf, buf->size + len)) {
+         return NULL;
+      }
+   }
+
+   retAddr = (DYNXDR_INLINE_T *)&buf->data[buf->size];
+   buf->size += len;
+
+   return retAddr;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -234,7 +289,7 @@ DynXdr_Create(XDR *in)  // IN
       DynXdrPutBytes,   /* x_putbytes */
       DynXdrGetPos,     /* x_getpostn */
       NULL,             /* x_setpostn */
-      NULL,             /* x_inline */
+      DynXdrInline,     /* x_inline */
       NULL,             /* x_destroy */
 #if defined(__GLIBC__)
       NULL,             /* x_getint32 */