From: Kruti Pendharkar Date: Wed, 8 Jan 2025 06:05:52 +0000 (-0800) Subject: Change to common source files not applicable to open-vm-tools. X-Git-Tag: stable-13.0.0~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bdd06ce8fc580f0ef8accff5cfc2852fae115aa5;p=thirdparty%2Fopen-vm-tools.git Change to common source files not applicable to open-vm-tools. --- diff --git a/open-vm-tools/lib/include/rpcvmx.h b/open-vm-tools/lib/include/rpcvmx.h index d31330cfe..965e21d01 100644 --- a/open-vm-tools/lib/include/rpcvmx.h +++ b/open-vm-tools/lib/include/rpcvmx.h @@ -24,11 +24,19 @@ * 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_ @@ -39,14 +47,13 @@ #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); diff --git a/open-vm-tools/lib/rpcVmx/rpcvmx.c b/open-vm-tools/lib/rpcVmx/rpcvmx.c index c3ffca613..d0c8bcd5a 100644 --- a/open-vm-tools/lib/rpcVmx/rpcvmx.c +++ b/open-vm-tools/lib/rpcVmx/rpcvmx.c @@ -33,7 +33,19 @@ #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; } /*