]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Change to common source files not applicable to open-vm-tools.
authorKruti Pendharkar <kp025370@broadcom.com>
Wed, 8 Jan 2025 06:05:52 +0000 (22:05 -0800)
committerKruti Pendharkar <kp025370@broadcom.com>
Wed, 8 Jan 2025 06:05:52 +0000 (22:05 -0800)
open-vm-tools/lib/include/rpcvmx.h
open-vm-tools/lib/rpcVmx/rpcvmx.c

index d31330cfe497dd3a8ef6b5946232382f555be645..965e21d01920bd0cc048759c81b3f82713e8ebb7 100644 (file)
  *      Tools code) that provides some useful VMX interaction capability, e.g.
  *      logging to the VM's VMX log, querying config variables, etc.
  *
- *      NB: This library is *NOT* threadsafe, so if you want to avoid
- *          corrupting your log statements or other screwups, add your own
- *          locking around calls to RpcVMX_Log.  The exception is
- *          RpcVMX_LogVWithBuffer which does not use any global state but
- *          requires the caller to manage its own buffers.
+ *      Thread safety:
+ *          1. This library in general is *NOT* threadsafe.  Users of
+ *             RpcVMX_Log/RpcVMX_LogV and RpcVMX_LogSetPrefix should protect
+ *             this usage externally with their own locking, and any other
+ *             requirements for thread safety should be carefully audited.
+ *
+ *          2. If thread safety around logging is required at a finer-grained
+ *             level than a single external lock, callers should allocate
+ *             buffers externally and then initialize them with
+ *             RpcVMX_InitLogBackingBuffer. These buffers should be externally
+ *             protected in some way such that they are only used by one thread
+ *             at a time, and passed into RpcVMX_LogVWithBuffer at logging
+ *             time.
  */
 
 #ifndef _RPCVMX_H_
 #include "vm_basic_types.h"
 #include "rpcvmxext.h"
 
-#define RPCVMX_MAX_LOG_LEN          (2048) /* 2kb max - make it dynamic? */
-#define RPCVMX_LOG_BUFSIZE          (RPCVMX_MAX_LOG_LEN + sizeof "log")
+#define RPCVMX_DEFAULT_LOG_BUFSIZE  (2048 + sizeof "log")
 
-typedef struct RpcVMXState {
-   char         logBuf[RPCVMX_LOG_BUFSIZE];
+typedef struct RpcVMXLogBuffer {
+   char *       logBuf;
+   unsigned int logBufSizeBytes;
    unsigned int logOffset;
-} RpcVMXState;
-
+} RpcVMXLogBuffer;
 
 /*
  * Set a prefix to prepend to any future log statements.
@@ -58,6 +65,15 @@ void RpcVMX_LogSetPrefix(const char *prefix);
  */
 const char *RpcVMX_LogGetPrefix(const char *prefix);
 
+/*
+ * Initialize the given log buffer struct with the given caller-allocated
+ * backing buffer and prefix string.
+ */
+Bool RpcVMX_InitLogBackingBuffer(RpcVMXLogBuffer *bufferOut,
+                                 char *logBuf,
+                                 unsigned int logBufSizeBytes,
+                                 const char *prefix);
+
 /*
  * Same as RpcVMX_Log but takes a va_list instead of inline arguments.
  */
@@ -67,7 +83,7 @@ void RpcVMX_LogV(const char *fmt,
 /*
  * Same as RpcVMX_LogV but uses the caller-specified buffer to back the log.
  */
-void RpcVMX_LogVWithBuffer(RpcVMXState *rpcBuffer,
+void RpcVMX_LogVWithBuffer(RpcVMXLogBuffer *rpcBuffer,
                            const char *fmt,
                            va_list args);
 
index c3ffca613d1a24fec109c80cbbc392d6aa1bb4dc..d0c8bcd5a497abffe85ff4342f2024ac95bfbdfb 100644 (file)
 #include "rpcvmx.h"
 
 
-static RpcVMXState RpcVMX = { "log ", sizeof "log" };
+/*
+ * Global shared buffer state used to back RPCI log calls made through
+ * RpcVMX_Log and RpcVMX_LogV.
+ */
+static char gRpcVmxLogBackingBuffer[RPCVMX_DEFAULT_LOG_BUFSIZE] = "log ";
+static RpcVMXLogBuffer gRpcVmxLog = { &gRpcVmxLogBackingBuffer[0],
+                                      RPCVMX_DEFAULT_LOG_BUFSIZE,
+                                      sizeof "log" };
+
+static Bool RpcVMXBufferSetPrefix(char *logBackingBuffer,
+                                  unsigned int logBackingBufferSizeBytes,
+                                  const char *prefix,
+                                  unsigned int *logOffsetOut);
 
 
 /*
@@ -41,17 +53,18 @@ static RpcVMXState RpcVMX = { "log ", sizeof "log" };
  *
  * RpcVMX_LogSetPrefix
  *
- *      Allows callers to set a prefix to prepend to the log output. If the
- *      prefix overflows the (static) prefix space available, it is rejected
- *      and the prefix is reset to nothing.  Each call to VMXLog_SetPrefix
- *      replaces the previously set prefix.
+ *      Allows callers to set a prefix to prepend to the log output, for calls
+ *      to RpcVMX_Log and RpcVMX_LogV. If the prefix overflows the (static)
+ *      prefix space available, it is rejected and the prefix is reset to
+ *      nothing.  Each call to VMXLog_SetPrefix replaces the previously set
+ *      prefix.
  *
  * Results:
- *      TRUE if the prefix was accepted, FALSE otherwise.
+ *      None.
  *
  * Side effects:
- *      All subsequent calls to RpcVMX_Log() will have the prefix string
- *      prepended.
+ *      All subsequent calls to RpcVMX_Log() and RpcVMX_LogV() will have the
+ *      prefix string prepended.
  *
  *----------------------------------------------------------------------------
  */
@@ -59,20 +72,8 @@ static RpcVMXState RpcVMX = { "log ", sizeof "log" };
 void
 RpcVMX_LogSetPrefix(const char *prefix)
 {
-   size_t prefixLen = strlen(prefix);
-
-   if (prefixLen + sizeof "log" >= sizeof RpcVMX.logBuf - 1) {
-      /*
-       * Somebody passed a huge prefix. Don't do that!
-       */
-      RpcVMX.logOffset = sizeof "log";
-      return;
-   }
-   Str_Strcpy(RpcVMX.logBuf + sizeof "log",
-              prefix,
-              sizeof RpcVMX.logBuf - sizeof "log");
-
-   RpcVMX.logOffset = (unsigned int)(sizeof "log" + prefixLen);
+   RpcVMXBufferSetPrefix(gRpcVmxLog.logBuf, gRpcVmxLog.logBufSizeBytes, prefix,
+                         &gRpcVmxLog.logOffset);
 }
 
 
@@ -99,11 +100,119 @@ RpcVMX_LogGetPrefix(const char *prefix)
 {
    UNUSED_VARIABLE(prefix);
 
-   RpcVMX.logBuf[RpcVMX.logOffset] = '\0';
-   return RpcVMX.logBuf + sizeof "log";
+   gRpcVmxLog.logBuf[gRpcVmxLog.logOffset] = '\0';
+   return gRpcVmxLog.logBuf + sizeof "log";
 }
 
 
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RpcVMXBufferSetPrefix --
+ *
+ *    Internal helper function to set the prefix string for a log buffer.
+ *
+ *  Results:
+ *    Returns TRUE iff the prefix was successfully set.
+ *
+ *    On success, writes the buffer index immediately following "log {PREFIX}"
+ *    to *logOffsetOut.
+ *
+ * Side effects:
+ *      All subsequent calls to the RpcVMX_Log* functions using the new
+ *      backing buffer will have the prefix string prepended.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Bool
+RpcVMXBufferSetPrefix(char *logBackingBuffer,                  // OUT
+                      unsigned int logBackingBufferSizeBytes,  // IN
+                      const char *prefix,                      // IN
+                      unsigned int *logOffsetOut)              // OUT
+{
+   size_t prefixLen;
+
+   if (logBackingBuffer == NULL || prefix == NULL || logOffsetOut == NULL) {
+      return FALSE;
+   }
+
+   *logOffsetOut = 0;
+
+   prefixLen = strlen(prefix);
+
+   if (prefixLen + sizeof "log" >= logBackingBufferSizeBytes - 1) {
+      return FALSE;
+   }
+
+   Str_Strcpy(logBackingBuffer + sizeof "log", prefix,
+              logBackingBufferSizeBytes - sizeof "log");
+
+   *logOffsetOut = (unsigned int)(sizeof "log" + prefixLen);
+
+   return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * RpcVMX_InitLogBackingBuffer --
+ *
+ *      Initialize the given log buffer struct with the given caller-allocated
+ *      backing buffer and prefix string.
+ *
+ * Results:
+ *      Returns TRUE if the provided RpcVMXBuffer was initialized successfully,
+ *      or FALSE if initialization failed and the RpcVMXBuffer should not be
+ *      used.
+ *
+ * Side effects:
+ *      All subsequent calls to the RpcVMX_Log* functions using the new
+ *      backing buffer will have the prefix string prepended.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+RpcVMX_InitLogBackingBuffer(RpcVMXLogBuffer *bufferOut,       // OUT
+                            char *logBuf,                     // IN
+                            unsigned int logBufSizeBytes,     // IN
+                            const char *prefix)               // IN
+{
+   unsigned int prefixLogOffset = 0;
+
+   if (bufferOut == NULL || logBuf == NULL || prefix == NULL ||
+       logBufSizeBytes < sizeof "log ") {
+      return FALSE;
+   }
+
+   bufferOut->logBuf = logBuf;
+   bufferOut->logBufSizeBytes = logBufSizeBytes;
+
+   memset(bufferOut->logBuf, 0, bufferOut->logBufSizeBytes);
+
+   /*
+    * Copy in the RPCI command prefix "log ".
+    */
+   Str_Strcpy(bufferOut->logBuf, "log ",
+              logBufSizeBytes - sizeof "log ");
+   bufferOut->logOffset = sizeof "log";
+
+   /*
+    * Copy in the provided logging prefix after the initial "log ".
+    */
+   if (RpcVMXBufferSetPrefix(bufferOut->logBuf, bufferOut->logBufSizeBytes,
+                             prefix, &prefixLogOffset)) {
+      bufferOut->logOffset = prefixLogOffset;
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+
+
 /*
  *----------------------------------------------------------------------------
  *
@@ -155,8 +264,8 @@ RpcVMX_LogV(const char *fmt,
    int payloadLen;
    char receiveBuffer[16];
 
-   payloadLen = Str_Vsnprintf(RpcVMX.logBuf + RpcVMX.logOffset,
-                              sizeof RpcVMX.logBuf - RpcVMX.logOffset,
+   payloadLen = Str_Vsnprintf(gRpcVmxLog.logBuf + gRpcVmxLog.logOffset,
+                              gRpcVmxLog.logBufSizeBytes - gRpcVmxLog.logOffset,
                               fmt, args);
 
    if (payloadLen < 1) {
@@ -164,7 +273,7 @@ RpcVMX_LogV(const char *fmt,
        * Overflow. We need more space in the buffer. Just set the length to
        * the buffer size and send the (truncated) log message.
        */
-      payloadLen = sizeof RpcVMX.logBuf - RpcVMX.logOffset;
+      payloadLen = gRpcVmxLog.logBufSizeBytes - gRpcVmxLog.logOffset;
    }
 
    /*
@@ -175,8 +284,8 @@ RpcVMX_LogV(const char *fmt,
     * returns two character strings "1 " on success and "0 " on
     * failure, so we don't need a sizeable buffer.
     */
-   RpcOut_SendOneRawPreallocated(RpcVMX.logBuf,
-                                 (size_t)RpcVMX.logOffset + payloadLen,
+   RpcOut_SendOneRawPreallocated(gRpcVmxLog.logBuf,
+                                 (size_t)gRpcVmxLog.logOffset + payloadLen,
                                  receiveBuffer, sizeof receiveBuffer);
 }
 
@@ -190,7 +299,7 @@ RpcVMX_LogV(const char *fmt,
  *      argument list, then send it to the VMX using the RPCI "log" command.
  *
  *      Uses the caller-provided buffer to back the log, rather than the
- *      global RpcVMXState.
+ *      global gRpcVmxLog.
  *
  * Results:
  *      None.
@@ -202,7 +311,7 @@ RpcVMX_LogV(const char *fmt,
  */
 
 void
-RpcVMX_LogVWithBuffer(RpcVMXState *rpcBuffer,                     // IN/OUT
+RpcVMX_LogVWithBuffer(RpcVMXLogBuffer *rpcBuffer,                 // IN/OUT
                       const char *fmt,                            // IN
                       va_list args)                               // IN
 {
@@ -213,16 +322,16 @@ RpcVMX_LogVWithBuffer(RpcVMXState *rpcBuffer,                     // IN/OUT
       return;
    }
 
-   if (rpcBuffer->logOffset >= sizeof rpcBuffer->logBuf) {
+   if (rpcBuffer->logOffset >= rpcBuffer->logBufSizeBytes) {
       /*
-       * The RpcVMXState is not valid, because the prefix is taking up the
+       * The RpcVMXLogBuffer is not valid, because the prefix is taking up the
        * entire buffer.  Since we can't log any actual message, silently fail.
        */
       return;
    }
 
    payloadLen = Str_Vsnprintf(rpcBuffer->logBuf + rpcBuffer->logOffset,
-                              sizeof rpcBuffer->logBuf - rpcBuffer->logOffset,
+                              rpcBuffer->logBufSizeBytes - rpcBuffer->logOffset,
                               fmt, args);
 
    if (payloadLen < 1) {
@@ -230,7 +339,7 @@ RpcVMX_LogVWithBuffer(RpcVMXState *rpcBuffer,                     // IN/OUT
        * Overflow. We need more space in the buffer. Just set the length to
        * the buffer size and send the (truncated) log message.
        */
-      payloadLen = sizeof rpcBuffer->logBuf - rpcBuffer->logOffset;
+      payloadLen = rpcBuffer->logBufSizeBytes - rpcBuffer->logOffset;
    }
 
    /*