From: VMware, Inc <> Date: Thu, 27 Oct 2011 18:17:53 +0000 (-0700) Subject: ListProcessesInGuest Cleanup for ALL OS-es. X-Git-Tag: 2011.10.26-514583~50 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7d6cc0f7a724ea67a03a01ca4b2c5a6e77bac01e;p=thirdparty%2Fopen-vm-tools.git ListProcessesInGuest Cleanup for ALL OS-es. Cleaning up memory leaks in error conditions. Re-structuring Process List to be an array of *new* Process Info structures, one per process. Affects ALL OS-es. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/procMgr.h b/open-vm-tools/lib/include/procMgr.h index 485e24332..e6c2d675e 100644 --- a/open-vm-tools/lib/include/procMgr.h +++ b/open-vm-tools/lib/include/procMgr.h @@ -30,6 +30,7 @@ #include "vm_basic_types.h" #include "auth.h" +#include "dynarray.h" #if !defined(_WIN32) # include #endif @@ -46,19 +47,23 @@ typedef struct ProcMgr_AsyncProc ProcMgr_AsyncProc; typedef pid_t ProcMgr_Pid; #endif -typedef struct ProcMgr_ProcList { - size_t procCount; - size_t cmdCount; - size_t ownerCount; +/* + * Process information structure. + * This holds basic information we return per process + * when listing process information inside the guest. + */ - ProcMgr_Pid *procIdList; - char **procCmdList; // UTF-8 - char **procOwnerList; // UTF-8 +typedef struct ProcMgrProcInfo { + ProcMgr_Pid procId; + char *procCmd; // UTF-8 + char *procOwner; // UTF-8 #if defined(_WIN32) - Bool *procDebugged; + Bool procDebugged; #endif - time_t *startTime; -} ProcMgr_ProcList; + time_t procStartTime; +} ProcMgrProcInfo; + +DEFINE_DYNARRAY_TYPE(ProcMgrProcInfo); typedef struct ProcMgr_ProcArgs { @@ -127,8 +132,8 @@ typedef HANDLE Selectable; typedef int Selectable; #endif -ProcMgr_ProcList *ProcMgr_ListProcesses(void); -void ProcMgr_FreeProcList(ProcMgr_ProcList *procList); +ProcMgrProcInfoArray *ProcMgr_ListProcesses(void); +void ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList); Bool ProcMgr_KillByPid(ProcMgr_Pid procId); diff --git a/open-vm-tools/lib/procMgr/procMgrPosix.c b/open-vm-tools/lib/procMgr/procMgrPosix.c index cab8cf789..dd95227c7 100644 --- a/open-vm-tools/lib/procMgr/procMgrPosix.c +++ b/open-vm-tools/lib/procMgr/procMgrPosix.c @@ -78,6 +78,7 @@ #undef offsetof #include "file.h" #include "dynbuf.h" +#include "dynarray.h" #include "su.h" #include "str.h" #include "fileIO.h" @@ -125,7 +126,6 @@ static Bool ProcMgrKill(pid_t pid, #if defined(__APPLE__) static int ProcMgrGetCommandLineArgs(long pid, - size_t cmdlineLen, DynBuf *argsBuf); #endif @@ -257,33 +257,30 @@ done: * * Results: * - * A ProcMgr_ProcList. + * A ProcMgrProcInfoArray. * * Side effects: * *---------------------------------------------------------------------- */ -#if !defined(sun) && !defined(__FreeBSD__) && !defined(__APPLE__) -ProcMgr_ProcList * +#if defined(linux) +ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { - ProcMgr_ProcList *procList = NULL; - Bool failed = FALSE; - DynBuf dbProcId; - DynBuf dbProcCmd; - DynBuf dbProcStartTime; - DynBuf dbProcOwner; + ProcMgrProcInfoArray *procList = NULL; + ProcMgrProcInfo procInfo; + Bool failed = TRUE; DIR *dir; struct dirent *ent; static time_t hostStartTime = 0; static unsigned long long hertz = 100; int numberFound; - DynBuf_Init(&dbProcId); - DynBuf_Init(&dbProcCmd); - DynBuf_Init(&dbProcStartTime); - DynBuf_Init(&dbProcOwner); + procList = Util_SafeCalloc(1, sizeof *procList); + ProcMgrProcInfoArray_Init(procList, 0); + procInfo.procCmd = NULL; + procInfo.procOwner = NULL; /* * Figure out when the system started. We need this number to @@ -339,7 +336,6 @@ ProcMgr_ListProcesses(void) dir = opendir("/proc"); if (NULL == dir) { Warning("ProcMgr_ListProcesses unable to open /proc\n"); - failed = TRUE; goto abort; } @@ -349,18 +345,14 @@ ProcMgr_ListProcesses(void) int statResult; int numRead = 0; /* number of bytes that read() actually read */ int cmdFd; - pid_t pid; int replaceLoop; struct passwd *pwd; char *cmdLineTemp = NULL; char *cmdStatTemp = NULL; - char *cmdLine; - char *userName = NULL; size_t strLen = 0; unsigned long long dummy; unsigned long long relativeStartTime; char *stringBegin; - time_t processStartTime; /* * We only care about dirs that look like processes. @@ -530,82 +522,59 @@ ProcMgr_ListProcesses(void) if (20 != numberFound) { goto next_entry; } - processStartTime = hostStartTime + (relativeStartTime / hertz); /* * Store the command line string pointer in dynbuf. */ if (cmdLineTemp) { - cmdLine = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT); + procInfo.procCmd = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT); } else { - cmdLine = Unicode_Alloc("", STRING_ENCODING_UTF8); + procInfo.procCmd = Unicode_Alloc("", STRING_ENCODING_UTF8); } - DynBuf_Append(&dbProcCmd, &cmdLine, sizeof cmdLine); /* * Store the pid in dynbuf. */ - pid = (pid_t) atoi(ent->d_name); - DynBuf_Append(&dbProcId, &pid, sizeof pid); + procInfo.procId = (pid_t) atoi(ent->d_name); /* * Store the owner of the process. */ pwd = getpwuid(fileStat.st_uid); - userName = (NULL == pwd) - ? Str_Asprintf(&strLen, "%d", (int) fileStat.st_uid) - : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); - DynBuf_Append(&dbProcOwner, &userName, sizeof userName); + procInfo.procOwner = (NULL == pwd) + ? Str_SafeAsprintf(&strLen, "%d", (int) fileStat.st_uid) + : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the time that the process started. */ - DynBuf_Append(&dbProcStartTime, - &processStartTime, - sizeof processStartTime); + procInfo.procStartTime = hostStartTime + (relativeStartTime / hertz); + + /* + * Store the process info pointer into a list buffer. + */ + if (!ProcMgrProcInfoArray_Push(procList, procInfo)) { + Warning("%s: failed to expand DynArray - out of memory\n", + __FUNCTION__); + goto abort; + } + procInfo.procCmd = NULL; + procInfo.procOwner = NULL; next_entry: free(cmdLineTemp); free(cmdStatTemp); } // while readdir - closedir(dir); - - if (0 == DynBuf_GetSize(&dbProcId)) { - failed = TRUE; - goto abort; + if (0 < ProcMgrProcInfoArray_Count(procList)) { + failed = FALSE; } - /* - * We're done adding to DynBuf. Trim off any unused allocated space. - * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy(). - */ - DynBuf_Trim(&dbProcId); - DynBuf_Trim(&dbProcCmd); - DynBuf_Trim(&dbProcStartTime); - DynBuf_Trim(&dbProcOwner); - /* - * Create a ProcMgr_ProcList and populate its fields. - */ - procList = (ProcMgr_ProcList *) calloc(1, sizeof(ProcMgr_ProcList)); - ASSERT_NOT_IMPLEMENTED(procList); - - procList->procCount = DynBuf_GetSize(&dbProcId) / sizeof(pid_t); - - procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId); - ASSERT_NOT_IMPLEMENTED(procList->procIdList); - procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd); - ASSERT_NOT_IMPLEMENTED(procList->procCmdList); - procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime); - ASSERT_NOT_IMPLEMENTED(procList->startTime); - procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner); - ASSERT_NOT_IMPLEMENTED(procList->procOwnerList); - abort: - DynBuf_Destroy(&dbProcId); - DynBuf_Destroy(&dbProcCmd); - DynBuf_Destroy(&dbProcStartTime); - DynBuf_Destroy(&dbProcOwner); + closedir(dir); + + free(procInfo.procCmd); + free(procInfo.procOwner); if (failed) { ProcMgr_FreeProcList(procList); @@ -614,7 +583,7 @@ abort: return procList; } -#endif // !defined(sun) & !defined(__FreeBSD__) && !defined(__APPLE__) +#endif // defined(linux) /* @@ -628,7 +597,7 @@ abort: * * Results: * - * A ProcMgr_ProcList. + * A ProcMgrProcInfoArray. * * Side effects: * @@ -636,24 +605,22 @@ abort: */ #if defined(__FreeBSD__) -ProcMgr_ProcList * +ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { - ProcMgr_ProcList *procList = NULL; + ProcMgrProcInfoArray *procList = NULL; + ProcMgrProcInfo procInfo; Bool failed = TRUE; static kvm_t *kd; struct kinfo_proc *kp; char errbuf[_POSIX2_LINE_MAX]; - int i, nentries=-1, flag=0; - DynBuf dbProcId; - DynBuf dbProcCmd; - DynBuf dbProcStartTime; - DynBuf dbProcOwner; + int i; + int nentries=-1; + int flag=0; - DynBuf_Init(&dbProcId); - DynBuf_Init(&dbProcCmd); - DynBuf_Init(&dbProcStartTime); - DynBuf_Init(&dbProcOwner); + procList = Util_SafeCalloc(1, sizeof *procList); + procInfo.procCmd = NULL; + procInfo.procOwner = NULL; /* * Get the handle to the Kernel Virtual Memory @@ -668,43 +635,40 @@ ProcMgr_ListProcesses(void) * Get the list of process info structs */ kp = kvm_getprocs(kd, KERN_PROC_PROC, flag, &nentries); - if ((kp == NULL && nentries > 0) || (kp != NULL && nentries < 0)) { + if (kp == NULL || nentries <= 0) { Warning("%s: failed to get proc infos with error: %s\n", __FUNCTION__, kvm_geterr(kd)); goto abort; } + /* + * Pre-allocate the dynamic array of required size. + */ + if (!ProcMgrProcInfoArray_Init(procList, nentries)) { + Warning("%s: failed to create DynArray - out of memory\n", + __FUNCTION__); + goto abort; + } + /* * Iterate through the list of process entries */ for (i = 0; i < nentries; ++i, ++kp) { struct passwd *pwd; - char *userName = NULL; - char *cmdLine = NULL; char **cmdLineTemp = NULL; - time_t processStartTime; /* * Store the pid of the process */ - if (!DynBuf_Append(&dbProcId, &(kp->ki_pid), sizeof(kp->ki_pid))) { - Warning("%s: failed to append pid in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } + procInfo.procId = kp->ki_pid; /* * Store the owner of the process. */ pwd = getpwuid(kp->ki_uid); - userName = (NULL == pwd) - ? Str_SafeAsprintf(NULL, "%d", (int) kp->ki_uid) - : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); - if (!DynBuf_Append(&dbProcOwner, &userName, sizeof userName)) { - Warning("%s: failed to append username in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } + procInfo.procOwner = (NULL == pwd) + ? Str_SafeAsprintf(NULL, "%d", (int) kp->ki_uid) + : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the command line string of the process @@ -738,75 +702,36 @@ ProcMgr_ListProcesses(void) goto abort; } DynBuf_Trim(&dbuf); - cmdLine = DynBuf_Detach(&dbuf); + procInfo.procCmd = DynBuf_Detach(&dbuf); DynBuf_Destroy(&dbuf); } else { - cmdLine = Unicode_Alloc(kp->ki_comm, STRING_ENCODING_DEFAULT); - } - if (!DynBuf_Append(&dbProcCmd, &cmdLine, sizeof cmdLine)) { - Warning("%s: failed to append cmdline in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; + procInfo.procCmd = Unicode_Alloc(kp->ki_comm, STRING_ENCODING_DEFAULT); } /* * Store the start time of the process */ - processStartTime = kp->ki_start.tv_sec; - if (!DynBuf_Append(&dbProcStartTime, - &processStartTime, - sizeof processStartTime)) { - Warning("%s: failed to append start time in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } - - } // for nentries - - if (0 == DynBuf_GetSize(&dbProcId)) { - goto abort; - } - - /* - * We're done adding to DynBuf. Trim off any unused allocated space. - * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy(). - */ - DynBuf_Trim(&dbProcId); - DynBuf_Trim(&dbProcCmd); - DynBuf_Trim(&dbProcStartTime); - DynBuf_Trim(&dbProcOwner); + procInfo.procStartTime = kp->ki_start.tv_sec; - /* - * Create a ProcMgr_ProcList and populate its fields. - */ - procList = (ProcMgr_ProcList *) Util_SafeCalloc(1, sizeof(ProcMgr_ProcList)); - ASSERT_NOT_IMPLEMENTED(procList); - - procList->procCount = DynBuf_GetSize(&dbProcId) / sizeof(pid_t); + /* + * Store the process info pointer into a list buffer. + */ + *ProcMgrProcInfoArray_AddressOf(procList, i) = procInfo; + procInfo.procCmd = NULL; + procInfo.procOwner = NULL; - procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId); - ASSERT_NOT_IMPLEMENTED(procList->procIdList); - procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd); - ASSERT_NOT_IMPLEMENTED(procList->procCmdList); - procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime); - ASSERT_NOT_IMPLEMENTED(procList->startTime); - procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner); - ASSERT_NOT_IMPLEMENTED(procList->procOwnerList); + } // for nentries failed = FALSE; -abort: - DynBuf_Destroy(&dbProcId); - DynBuf_Destroy(&dbProcCmd); - DynBuf_Destroy(&dbProcStartTime); - DynBuf_Destroy(&dbProcOwner); +abort: if (kd != NULL) { - /* - * Wrap up: also deallocates memory (if) allocated by kvm_getargv() - */ kvm_close(kd); } + free(procInfo.procCmd); + free(procInfo.procOwner); + if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; @@ -837,7 +762,6 @@ abort: static int ProcMgrGetCommandLineArgs(long pid, // IN: process id - size_t cmdlineLen, // IN: max command line length DynBuf *argsBuf) // OUT: Buffer with arguments { int argCount = 0; @@ -846,17 +770,31 @@ ProcMgrGetCommandLineArgs(long pid, // IN: process id char *cmdLineRaw = NULL; char *cmdLineTemp; char *cmdLineEnd; + size_t maxargs = 0; + size_t maxargsSize; + int maxargsName[] = {CTL_KERN, KERN_ARGMAX}; int argName[] = {CTL_KERN, KERN_PROCARGS2, pid}; + /* + * Get the sysctl kern argmax. + */ + maxargsSize = sizeof maxargs; + if (sysctl(maxargsName, ARRAYSIZE(maxargsName), + &maxargs, &maxargsSize, NULL, 0) < 0) { + Warning("%s: failed to get the kernel max args with errno = %d\n", + __FUNCTION__, errno); + goto abort; + } + /* * Fetch the raw command line */ - cmdLineRaw = (char *) Util_SafeCalloc(cmdlineLen, sizeof *cmdLineRaw); - if (sysctl(argName, ARRAYSIZE(argName), cmdLineRaw, &cmdlineLen, NULL, 0) < 0) { + cmdLineRaw = Util_SafeCalloc(maxargs, sizeof *cmdLineRaw); + if (sysctl(argName, ARRAYSIZE(argName), cmdLineRaw, &maxargs, NULL, 0) < 0) { Debug("%s: No command line args for pid = %ld\n", __FUNCTION__, pid); goto abort; } - cmdLineEnd = &cmdLineRaw[cmdlineLen]; + cmdLineEnd = &cmdLineRaw[maxargs]; /* * Format of the raw command line (without line breaks): @@ -973,57 +911,30 @@ abort: * UTF-8 encoded, although we do not enforce it right now. * * Results: - * A ProcMgr_ProcList. + * A ProcMgrProcInfoArray. * * Side effects: * *---------------------------------------------------------------------- */ -ProcMgr_ProcList * +ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { - ProcMgr_ProcList *procList = NULL; + ProcMgrProcInfoArray *procList = NULL; + ProcMgrProcInfo procInfo; Bool failed = TRUE; - char *userName = NULL; - char *cmdLine = NULL; struct kinfo_proc *kptmp; struct kinfo_proc *kp = NULL; - size_t maxargs; - size_t maxargsSize; size_t procsize; - size_t procCount = 0; - size_t ownerCount = 0; - size_t cmdCount = 0; int i; int nentries; - DynBuf dbProcId; - DynBuf dbProcCmd; - DynBuf dbProcStartTime; - DynBuf dbProcOwner; - - /* - * Different multi-level names used for sysctl calls. - */ - int maxargsName[] = {CTL_KERN, KERN_ARGMAX}; int procName[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; - DynBuf_Init(&dbProcId); - DynBuf_Init(&dbProcCmd); - DynBuf_Init(&dbProcStartTime); - DynBuf_Init(&dbProcOwner); + procList = Util_SafeCalloc(1, sizeof *procList); + procInfo.procCmd = NULL; + procInfo.procOwner = NULL; - procList = (ProcMgr_ProcList *) Util_SafeCalloc(1, sizeof *procList); - /* - * Get the sysctl kern argmax. - */ - maxargsSize = sizeof maxargs; - if (sysctl(maxargsName, ARRAYSIZE(maxargsName), - &maxargs, &maxargsSize, NULL, 0) < 0) { - Warning("%s: failed to get the kernel max args with errno = %d\n", - __FUNCTION__, errno); - goto abort; - } /* * Get the number of process info structs in the entire list. */ @@ -1036,7 +947,7 @@ ProcMgr_ListProcesses(void) /* * Get the list of process info structs. */ - kp = (struct kinfo_proc *) Util_SafeCalloc(nentries, sizeof *kp); + kp = Util_SafeCalloc(nentries, sizeof *kp); if (sysctl(procName, ARRAYSIZE(procName), kp, &procsize, NULL, 0) < 0) { Warning("%s: failed to get the process struct list (errno = %d)\n", __FUNCTION__, errno); @@ -1045,13 +956,22 @@ ProcMgr_ListProcesses(void) /* * Recalculate the number of entries as they may have changed. */ - nentries = (int)(procsize / sizeof *kp); + if (0 >= (nentries = (int)(procsize / sizeof *kp))) { + goto abort; + } + /* + * Pre-allocate the dynamic array of required size. + */ + if (!ProcMgrProcInfoArray_Init(procList, nentries)) { + Warning("%s: failed to create DynArray - out of memory\n", + __FUNCTION__); + goto abort; + } /* * Iterate through the list of process entries */ for (i = 0, kptmp = kp; i < nentries; ++i, ++kptmp) { DynBuf argsBuf; - time_t processStartTime; char buffer[BUFSIZ]; struct passwd pw; struct passwd *ppw = &pw; @@ -1060,95 +980,46 @@ ProcMgr_ListProcesses(void) /* * Store the pid of the process */ - if (!DynBuf_Append(&dbProcId, &(kptmp->kp_proc.p_pid), - sizeof kptmp->kp_proc.p_pid)) { - Warning("%s: failed to append pid in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } - procCount++; + procInfo.procId = kptmp->kp_proc.p_pid; /* * Store the owner of the process. */ error = Posix_Getpwuid_r(kptmp->kp_eproc.e_pcred.p_ruid, &pw, buffer, sizeof buffer, &ppw); - userName = (0 != error || NULL == ppw) - ? Str_SafeAsprintf(NULL, "%d", - (int) kptmp->kp_eproc.e_pcred.p_ruid) - : Unicode_Alloc(ppw->pw_name, STRING_ENCODING_DEFAULT); - if (!DynBuf_Append(&dbProcOwner, &userName, sizeof userName)) { - Warning("%s: failed to append username in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } - userName = NULL; - ownerCount++; + procInfo.procOwner = (0 != error || NULL == ppw) + ? Str_SafeAsprintf(NULL, "%d", (int) kptmp->kp_eproc.e_pcred.p_ruid) + : Unicode_Alloc(ppw->pw_name, STRING_ENCODING_DEFAULT); + /* - * Get the command line arguments of the process. + * Store the command line arguments of the process. * If no arguments are found, use the full command name. */ DynBuf_Init(&argsBuf); - if (ProcMgrGetCommandLineArgs(kptmp->kp_proc.p_pid, maxargs, &argsBuf) > 0) { - cmdLine = DynBuf_Detach(&argsBuf); + if (ProcMgrGetCommandLineArgs(kptmp->kp_proc.p_pid, &argsBuf) > 0) { + procInfo.procCmd = DynBuf_Detach(&argsBuf); } else { - cmdLine = Unicode_Alloc(kptmp->kp_proc.p_comm, STRING_ENCODING_DEFAULT); + procInfo.procCmd = Unicode_Alloc(kptmp->kp_proc.p_comm, STRING_ENCODING_DEFAULT); } DynBuf_Destroy(&argsBuf); /* - * Store the command line string of the process. + * Store the start time of the process */ - if (!DynBuf_Append(&dbProcCmd, &cmdLine, sizeof cmdLine)) { - Warning("%s: failed to append cmdline in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } - cmdLine = NULL; - cmdCount++; + procInfo.procStartTime = kptmp->kp_proc.p_starttime.tv_sec; /* - * Store the start time of the process + * Store the process info pointer into a list buffer. */ - processStartTime = kptmp->kp_proc.p_starttime.tv_sec; - if (!DynBuf_Append(&dbProcStartTime, &processStartTime, - sizeof processStartTime)) { - Warning("%s: failed to append start time in DynBuf - out of memory\n", - __FUNCTION__); - goto abort; - } - } - - if (0 < procCount) { - failed = FALSE; - } + *ProcMgrProcInfoArray_AddressOf(procList, i) = procInfo; + procInfo.procCmd = NULL; + procInfo.procOwner = NULL; -abort: - /* - * We're done adding to DynBuf. Trim off any unused allocated space. - * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy(). - */ - DynBuf_Trim(&dbProcId); - DynBuf_Trim(&dbProcCmd); - DynBuf_Trim(&dbProcStartTime); - DynBuf_Trim(&dbProcOwner); + } // nentries - /* - * Populate fields of ProcMgr_ProcList - */ - procList->procCount = procCount; - procList->ownerCount = ownerCount; - procList->cmdCount = cmdCount; - procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId); - procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd); - procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime); - procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner); - - DynBuf_Destroy(&dbProcId); - DynBuf_Destroy(&dbProcCmd); - DynBuf_Destroy(&dbProcStartTime); - DynBuf_Destroy(&dbProcOwner); + failed = FALSE; +abort: free(kp); - free(userName); - free(cmdLine); + free(procInfo.procCmd); + free(procInfo.procOwner); if (failed) { ProcMgr_FreeProcList(procList); @@ -1164,7 +1035,7 @@ abort: * * ProcMgr_FreeProcList -- * - * Free the memory occupied by ProcMgr_ProcList. + * Free the memory occupied by ProcMgrProcInfoArray. * * Results: * @@ -1176,37 +1047,25 @@ abort: */ void -ProcMgr_FreeProcList(ProcMgr_ProcList *procList) +ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList) { int i; + size_t procCount; if (NULL == procList) { return; } -#if defined(__APPLE__) - /* - * We need to do the following for other OSes as well. - * Each list shall have its own counter to address - * error conditions while building the list. - */ - for (i = 0; i < procList->cmdCount; i++) { - free(procList->procCmdList[i]); - } - for (i = 0; i < procList->ownerCount; i++) { - free(procList->procOwnerList[i]); - } -#else - for (i = 0; i < procList->procCount; i++) { - free(procList->procCmdList[i]); - free(procList->procOwnerList[i]); + procCount = ProcMgrProcInfoArray_Count(procList); + for (i = 0; i < procCount; i++) { + ProcMgrProcInfo *procInfo; + + procInfo = ProcMgrProcInfoArray_AddressOf(procList, i); + free(procInfo->procCmd); + free(procInfo->procOwner); } -#endif - free(procList->procIdList); - free(procList->procCmdList); - free(procList->startTime); - free(procList->procOwnerList); + ProcMgrProcInfoArray_Destroy(procList); free(procList); } diff --git a/open-vm-tools/lib/procMgr/procMgrSolaris.c b/open-vm-tools/lib/procMgr/procMgrSolaris.c index 478b704e8..a5c4142d9 100644 --- a/open-vm-tools/lib/procMgr/procMgrSolaris.c +++ b/open-vm-tools/lib/procMgr/procMgrSolaris.c @@ -85,38 +85,29 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo); *---------------------------------------------------------------------------- */ -ProcMgr_ProcList * +ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { - ProcMgr_ProcList *procList = NULL; - - Bool failed = FALSE; - DynBuf dbProcId; - DynBuf dbProcCmd; - DynBuf dbProcStartTime; - DynBuf dbProcOwner; + ProcMgrProcInfoArray *procList = NULL; + ProcMgrProcInfo processInfo; + Bool failed = TRUE; DIR *dir; struct dirent *ent; - DynBuf_Init(&dbProcId); - DynBuf_Init(&dbProcCmd); - DynBuf_Init(&dbProcStartTime); - DynBuf_Init(&dbProcOwner); + procList = Util_SafeCalloc(1, sizeof *procList); + ProcMgrProcInfoArray_Init(procList, 0); + processInfo.procOwner = NULL; + processInfo.procCmd = NULL; dir = opendir("/proc"); if (NULL == dir) { Warning("ProcMgr_ListProcesses unable to open /proc\n"); - failed = TRUE; goto exit; } while (TRUE) { - pid_t pid; struct passwd *pwd; - char *cmdLineTemp; - char *userName = NULL; char tempPath[MAXPATHLEN]; - time_t processStartTime; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; @@ -131,7 +122,6 @@ ProcMgr_ListProcesses(void) if (errno == 0) { break; } else { - failed = TRUE; goto exit; } } @@ -152,7 +142,6 @@ ProcMgr_ListProcesses(void) (res == FILEIO_NO_PERMISSION)) { continue; } else { - failed = TRUE; goto exit; } } @@ -160,11 +149,10 @@ ProcMgr_ListProcesses(void) res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { - failed = TRUE; goto exit; } - processStartTime = procInfo.pr_start.tv_sec; + processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * Command line strings in procInfo.pr_psargs are truncated to PRARGZ @@ -178,83 +166,51 @@ ProcMgr_ListProcesses(void) tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo); if (tmp != NULL) { - cmdLineTemp = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); + processInfo.procCmd = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); free(tmp); } else { - cmdLineTemp = Unicode_Alloc(procInfo.pr_psargs, - STRING_ENCODING_DEFAULT); + processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, + STRING_ENCODING_DEFAULT); } } else { - cmdLineTemp = Unicode_Alloc(procInfo.pr_psargs, - STRING_ENCODING_DEFAULT); + processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, + STRING_ENCODING_DEFAULT); } - /* - * Store the command line string pointer in dynbuf. - */ - DynBuf_Append(&dbProcCmd, &cmdLineTemp, sizeof cmdLineTemp); - /* * Store the pid in dynbuf. */ - pid = procInfo.pr_pid; - DynBuf_Append(&dbProcId, &pid, sizeof pid); + processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); - userName = (NULL == pwd) - ? Str_Asprintf(&strLen, "%d", (int) procInfo.pr_uid) - : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); - DynBuf_Append(&dbProcOwner, &userName, sizeof userName); + processInfo.procOwner = (NULL == pwd) + ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) + : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* - * Store the time that the process started. + * Store the process info into a list buffer. */ - DynBuf_Append(&dbProcStartTime, - &processStartTime, - sizeof processStartTime); + if (!ProcMgrProcInfoArray_Push(procList, processInfo)) { + Warning("%s: failed to expand DynArray - out of memory\n", + __FUNCTION__); + goto exit; + } + processInfo.procCmd = NULL; + processInfo.procOwner = NULL; } // while (TRUE) - closedir(dir); - - if (0 == DynBuf_GetSize(&dbProcId)) { - failed = TRUE; - goto exit; + if (0 < ProcMgrProcInfoArray_Count(procList)) { + failed = FALSE; } - /* - * We're done adding to DynBuf. Trim off any unused allocated space. - * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy(). - */ - DynBuf_Trim(&dbProcId); - DynBuf_Trim(&dbProcCmd); - DynBuf_Trim(&dbProcStartTime); - DynBuf_Trim(&dbProcOwner); - - /* - * Create a ProcMgr_ProcList and populate its fields. - */ - procList = (ProcMgr_ProcList *) Util_SafeCalloc(1, sizeof(ProcMgr_ProcList)); - ASSERT_MEM_ALLOC(procList); - - procList->procCount = DynBuf_GetSize(&dbProcId) / sizeof(pid_t); - - procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId); - ASSERT_MEM_ALLOC(procList->procIdList); - procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd); - ASSERT_MEM_ALLOC(procList->procCmdList); - procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime); - ASSERT_MEM_ALLOC(procList->startTime); - procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner); - ASSERT_MEM_ALLOC(procList->procOwnerList); - exit: - DynBuf_Destroy(&dbProcId); - DynBuf_Destroy(&dbProcCmd); - DynBuf_Destroy(&dbProcStartTime); - DynBuf_Destroy(&dbProcOwner); + closedir(dir); + + free(processInfo.procOwner); + free(processInfo.procCmd); if (failed) { ProcMgr_FreeProcList(procList); diff --git a/open-vm-tools/services/plugins/vix/vixTools.c b/open-vm-tools/services/plugins/vix/vixTools.c index be7e2ff03..c39aba757 100644 --- a/open-vm-tools/services/plugins/vix/vixTools.c +++ b/open-vm-tools/services/plugins/vix/vixTools.c @@ -69,6 +69,7 @@ #include "timeutil.h" #include "vm_version.h" #include "message.h" +#include "dynarray.h" #define G_LOG_DOMAIN "vix" #define Debug g_debug @@ -4319,7 +4320,8 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN VixError err = VIX_OK; int i; static char resultBuffer[GUESTMSG_MAX_IN_SIZE]; - ProcMgr_ProcList *procList = NULL; + ProcMgrProcInfoArray *procList = NULL; + ProcMgrProcInfo *procInfo; char *destPtr; char *endDestPtr; char *procBufPtr = NULL; @@ -4329,6 +4331,7 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN Bool escapeStrs; char *escapedName = NULL; char *escapedUser = NULL; + size_t procCount; ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE); @@ -4357,32 +4360,34 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN VIX_XML_ESCAPED_TAG); } - for (i = 0; i < procList->procCount; i++) { + procCount = ProcMgrProcInfoArray_Count(procList); + for (i = 0; i < procCount; i++) { const char *name; const char *user; + procInfo = ProcMgrProcInfoArray_AddressOf(procList, i); + if (escapeStrs) { name = escapedName = - VixToolsEscapeXMLString(procList->procCmdList[i]); + VixToolsEscapeXMLString(procInfo->procCmd); if (NULL == escapedName) { err = VIX_E_OUT_OF_MEMORY; goto abort; } } else { - name = procList->procCmdList[i]; + name = procInfo->procCmd; } - if ((NULL != procList->procOwnerList) && - (NULL != procList->procOwnerList[i])) { + if (NULL != procInfo->procOwner) { if (escapeStrs) { user = escapedUser = - VixToolsEscapeXMLString(procList->procOwnerList[i]); + VixToolsEscapeXMLString(procInfo->procOwner); if (NULL == escapedUser) { err = VIX_E_OUT_OF_MEMORY; goto abort; } } else { - user = procList->procOwnerList[i]; + user = procInfo->procOwner; } } else { user = ""; @@ -4395,14 +4400,12 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN #endif "%s%d", name, - (int) procList->procIdList[i], + (int) procInfo->procId, #if defined(_WIN32) - (int) procList->procDebugged[i], + (int) procInfo->procDebugged, #endif user, - (NULL == procList->startTime) - ? 0 - : (int) procList->startTime[i]); + (int) procInfo->procStartTime); if (NULL == procBufPtr) { err = VIX_E_OUT_OF_MEMORY; goto abort; @@ -4521,12 +4524,14 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN char **resultBuffer) // OUT { VixError err = VIX_OK; - ProcMgr_ProcList *procList = NULL; + ProcMgrProcInfoArray *procList = NULL; + ProcMgrProcInfo *procInfo; DynBuf dynBuffer; VixToolsExitedProgramState *epList; int i; int j; Bool bRet; + size_t procCount; DynBuf_Init(&dynBuffer); @@ -4591,22 +4596,22 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN * the Vix side with GetNthProperty, and can have a mix of live and * dead processes. */ + procCount = ProcMgrProcInfoArray_Count(procList); if (numPids > 0) { for (i = 0; i < numPids; i++) { // ignore it if its on the exited list -- we added it above if (VixToolsFindExitedProgramState(pids[i])) { continue; } - for (j = 0; j < procList->procCount; j++) { - if (pids[i] == procList->procIdList[j]) { + for (j = 0; j < procCount; j++) { + procInfo = ProcMgrProcInfoArray_AddressOf(procList, j); + if (pids[i] == procInfo->procId) { err = VixToolsPrintProcInfoEx(&dynBuffer, - procList->procCmdList[j], - procList->procIdList[j], - (NULL == procList->procOwnerList - || NULL == procList->procOwnerList[j]) - ? "" : procList->procOwnerList[j], - (NULL == procList->startTime) - ? 0 : (int) procList->startTime[j], + procInfo->procCmd, + procInfo->procId, + (NULL == procInfo->procOwner) + ? "" : procInfo->procOwner, + (int) procInfo->procStartTime, 0, 0); if (VIX_OK != err) { goto abort; @@ -4615,19 +4620,18 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN } } } else { - for (i = 0; i < procList->procCount; i++) { + for (i = 0; i < procCount; i++) { + procInfo = ProcMgrProcInfoArray_AddressOf(procList, i); // ignore it if its on the exited list -- we added it above - if (VixToolsFindExitedProgramState(procList->procIdList[i])) { + if (VixToolsFindExitedProgramState(procInfo->procId)) { continue; } err = VixToolsPrintProcInfoEx(&dynBuffer, - procList->procCmdList[i], - procList->procIdList[i], - (NULL == procList->procOwnerList - || NULL == procList->procOwnerList[i]) - ? "" : procList->procOwnerList[i], - (NULL == procList->startTime) - ? 0 : (int) procList->startTime[i], + procInfo->procCmd, + procInfo->procId, + (NULL == procInfo->procOwner) + ? "" : procInfo->procOwner, + (int) procInfo->procStartTime, 0, 0); if (VIX_OK != err) { goto abort;