MXUserRecLock * MXUser_BindMXMutexRec(struct MX_MutexRec *mutex, // IN: MX_Rank rank) // IN: { char *name; MXUserRecLock *lock; ASSERT(mutex); /* * Cannot perform a binding unless MX_Init has been called. As a side * effect it registers these hook functions. */ if ((MXUserMX_LockRec == NULL) || (MXUserMX_UnlockRec == NULL) || (MXUserMX_TryLockRec == NULL) || (MXUserMX_IsLockedByCurThreadRec == NULL) || (MXUserMX_NameRec == NULL)) { return NULL; } /* * Initialize the header (so it looks correct in memory) but don't connect * this lock to the MXUser statistics or debugging tracking - the MX lock * system will take care of this. */ lock = Util_SafeCalloc(1, sizeof *lock); lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC); name = (*MXUserMX_NameRec)(mutex); if (name == NULL) { lock->header.name = Str_SafeAsprintf(NULL, "MX_%p", mutex); } else { lock->header.name = Str_SafeAsprintf(NULL, "%s *", name); } lock->header.rank = rank; lock->header.bits.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = NULL; lock->header.statsFunc = NULL; Atomic_WritePtr(&lock->acquireStatsMem, NULL); Atomic_WritePtr(&lock->heldStatsMem, NULL); Atomic_Write(&lock->refCount, 1); lock->vmmLock = mutex; return lock; }
char * MsgList_ToString(const MsgList *messages) // IN: { char *result = NULL; if (messages != NULL) { size_t len = 0; char *formatted = MsgFmt_Asprintf(&len, messages->format, messages->args, messages->numArgs); const char *eol = (len > 0 && formatted != NULL && formatted[len - 1] == '\n') ? "" : "\n"; char *tail; if (messages->next != NULL) { tail = MsgList_ToString(messages->next); } else { tail = Util_SafeStrdup(""); } result = Str_SafeAsprintf(NULL, "%s%s%s", formatted, eol, tail); free(formatted); free(tail); } return result; }
static char * FileLockLocationChecksum(ConstUnicode path) // IN: { int c; uint32 hash = 5381; #if defined(_WIN32) char *p; Unicode value = Unicode_Duplicate(path); /* Don't get fooled by mixed case; "normalize" */ Str_ToLower(value); p = value; #else char *p = (char *) path; #endif /* DBJ2 hash... good enough? */ while ((c = *p++)) { hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ } #if defined(_WIN32) Unicode_Free(value); #endif return Str_SafeAsprintf(NULL, "%u", hash); }
MXUserRecLock * MXUser_CreateRecLock(const char *userName, // IN: MX_Rank rank) // IN: { uint32 statsMode; char *properName; MXUserRecLock *lock = Util_SafeCalloc(1, sizeof *lock); if (userName == NULL) { properName = Str_SafeAsprintf(NULL, "R-%p", GetReturnAddress()); } else { properName = Util_SafeStrdup(userName); } if (!MXRecLockInit(&lock->recursiveLock)) { free(properName); free(lock); return NULL; } lock->vmmLock = NULL; Atomic_Write(&lock->refCount, 1); lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC); lock->header.name = properName; lock->header.rank = rank; lock->header.bits.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpRecLock; statsMode = MXUserStatsMode(); switch (statsMode) { case 0: MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem); lock->header.statsFunc = NULL; break; case 1: MXUserEnableStats(&lock->acquireStatsMem, NULL); lock->header.statsFunc = MXUserStatsActionRec; break; case 2: MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem); lock->header.statsFunc = MXUserStatsActionRec; break; default: Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode); } MXUserAddToList(&lock->header); return lock; }
char * TimeUtil_GetTimeFormat(int64 utcTime, // IN Bool showDate, // IN Bool showTime) // IN { #ifdef _WIN32 SYSTEMTIME systemTime = { 0 }; char dateStr[100] = ""; char timeStr[100] = ""; if (!showDate && !showTime) { return NULL; } if (!TimeUtil_UTCTimeToSystemTime((const __time64_t) utcTime, &systemTime)) { return NULL; } Win32U_GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime, NULL, dateStr, ARRAYSIZE(dateStr)); Win32U_GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systemTime, NULL, timeStr, ARRAYSIZE(timeStr)); if (showDate && showTime) { return Str_SafeAsprintf(NULL, "%s %s", dateStr, timeStr); } else { return Util_SafeStrdup(showDate ? dateStr : timeStr); } #else /* * On 32-bit systems the assignment of utcTime to time_t below will truncate * in the year 2038. Ignore it; there's nothing we can do. */ char *str; char buf[26]; const time_t t = (time_t) utcTime; // Implicit narrowing on 32-bit #if defined sun str = Util_SafeStrdup(ctime_r(&t, buf, sizeof buf)); #else str = Util_SafeStrdup(ctime_r(&t, buf)); #endif str[strlen(str) - 1] = '\0'; // Remove the trailing '\n'. return str; #endif // _WIN32 }
MXUserExclLock * MXUser_CreateExclLock(const char *userName, // IN: MX_Rank rank) // IN: { Bool doStats; char *properName; MXUserExclLock *lock; lock = Util_SafeCalloc(1, sizeof(*lock)); if (userName == NULL) { properName = Str_SafeAsprintf(NULL, "X-%p", GetReturnAddress()); } else { properName = Util_SafeStrdup(userName); } if (!MXRecLockInit(&lock->recursiveLock)) { free(properName); free(lock); return NULL; } lock->header.signature = MXUserGetSignature(MXUSER_TYPE_EXCL); lock->header.name = properName; lock->header.rank = rank; lock->header.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpExclLock; if (vmx86_stats) { doStats = MXUserStatsEnabled(); } else { doStats = FALSE; } if (doStats) { MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS); } else { lock->header.statsFunc = NULL; Atomic_WritePtr(&lock->statsMem, NULL); } MXUserAddToList(&lock->header); return lock; }
MXUserSemaphore * MXUser_CreateSemaphore(const char *userName, // IN: MX_Rank rank) // IN: { char *properName; MXUserSemaphore *sema; sema = Util_SafeCalloc(1, sizeof(*sema)); if (userName == NULL) { properName = Str_SafeAsprintf(NULL, "Sema-%p", GetReturnAddress()); } else { properName = Util_SafeStrdup(userName); } if (LIKELY(MXUserInit(&sema->nativeSemaphore) == 0)) { sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA); sema->header.name = properName; sema->header.rank = rank; sema->header.serialNumber = MXUserAllocSerialNumber(); sema->header.dumpFunc = MXUserDumpSemaphore; if (MXUserStatsMode() == 0) { sema->header.statsFunc = NULL; Atomic_WritePtr(&sema->acquireStatsMem, NULL); } else { MXUserAcquireStats *acquireStats; acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats)); MXUserAcquisitionStatsSetUp(&acquireStats->data); sema->header.statsFunc = MXUserStatsActionSema; Atomic_WritePtr(&sema->acquireStatsMem, acquireStats); } MXUserAddToList(&sema->header); } else { free(properName); free(sema); sema = NULL; } return sema; }
char * File_PrependToPath(const char *searchPath, // IN: const char *elem) // IN: { const char sep = FILE_SEARCHPATHTOKEN[0]; char *newPath; char *path; size_t n; ASSERT(searchPath); ASSERT(elem); newPath = Str_SafeAsprintf(NULL, "%s%s%s", elem, FILE_SEARCHPATHTOKEN, searchPath); n = strlen(elem); path = newPath + n + 1; for (;;) { char *next = Str_Strchr(path, sep); size_t len = next ? next - path : strlen(path); if ((len == n) && (Str_Strncmp(path, elem, len) == 0)) { if (next) { memmove(path, next + 1, strlen(next + 1) + 1); } else { *--path = '\0'; } break; } if (!next) { break; } path = next + 1; } return newPath; }
static char * CreateStagingDirectory( const char *realRoot, // IN: e.g. $HOME/.cache/vmware/drag_and_drop/ const char *apparentRoot) // IN: e.g. /tmp/VMwareDnD/ { char *result = NULL; int i; for (i = 0; i < 10 && result == NULL; i++) { char *realStagingDir = NULL; char *apparentStagingDir = NULL; // Reminder: mkdtemp updates its arg in-place. realStagingDir = Str_SafeAsprintf(NULL, "%sXXXXXX", realRoot); if (mkdtemp(realStagingDir) != NULL) { char *randomPart = strrchr(realStagingDir, '/') + 1; VERIFY(*randomPart != '\0'); apparentStagingDir = Unicode_Append(apparentRoot, randomPart); if (Posix_Symlink(realStagingDir, apparentStagingDir) == 0) { // Transfer ownership to caller. result = apparentStagingDir; apparentStagingDir = NULL; } else { Warning("dnd: symlink(%s): %s", apparentStagingDir, Err_ErrString()); Posix_Rmdir(realStagingDir); } } else { Warning("dnd: mkdtemp(%s): %s", realStagingDir, Err_ErrString()); } free(realStagingDir); free(apparentStagingDir); } return result; }
char * GuestApp_GetConfPath(void) { #if defined(_WIN32) char *path = W32Util_GetVmwareCommonAppDataFilePath(NULL); if (path != NULL) { char *tmp = Str_SafeAsprintf(NULL, "%s%c%s", path, DIRSEPC, ProductState_GetName()); free(path); path = tmp; if (!File_EnsureDirectory(path)) { free(path); path = NULL; } } return path; #else /* Just call into GuestApp_GetInstallPath. */ return GuestApp_GetInstallPath(); #endif }
ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { ProcMgrProcInfoArray *procList = NULL; ProcMgrProcInfo processInfo; Bool failed = TRUE; DIR *dir; struct dirent *ent; 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"); goto exit; } while (TRUE) { struct passwd *pwd; char tempPath[MAXPATHLEN]; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; FileIODescriptor psInfoFd; FileIOResult res; errno = 0; FileIO_Invalidate(&psInfoFd); ent = readdir(dir); if (ent == NULL) { if (errno == 0) { break; } else { goto exit; } } if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%s/psinfo", ent->d_name) == -1) { Debug("Process id '%s' too large\n", ent->d_name); continue; } res = FileIO_Open(&psInfoFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { if ((res == FILEIO_FILE_NOT_FOUND) || (res == FILEIO_NO_PERMISSION)) { continue; } else { goto exit; } } res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { goto exit; } processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * Command line strings in procInfo.pr_psargs are truncated to PRARGZ * bytes. In this case we extract the arguments from the /proc/<pid>/as * file. Since most command line strings are expected to fit within * PRARGSZ bytes, we avoid calling * ExtractCommandLineFromAddressSpaceFile for every process. */ if (strlen(procInfo.pr_psargs) + 1 == PRARGSZ) { char *tmp; tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo); if (tmp != NULL) { processInfo.procCmd = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); free(tmp); } else { processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); } } else { processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); } /* * Store the pid in dynbuf. */ processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); processInfo.procOwner = (NULL == pwd) ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the process info into a list buffer. */ 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) if (0 < ProcMgrProcInfoArray_Count(procList)) { failed = FALSE; } exit: closedir(dir); free(processInfo.procOwner); free(processInfo.procCmd); if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; } return procList; }
MXUserRWLock * MXUser_CreateRWLock(const char *userName, // IN: MX_Rank rank) // IN: { Bool lockInited; char *properName; MXUserRWLock *lock; Bool useNative = MXUserNativeRWSupported(); lock = Util_SafeCalloc(1, sizeof(*lock)); if (userName == NULL) { if (LIKELY(useNative)) { properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress()); } else { /* emulated */ properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress()); } } else { properName = Util_SafeStrdup(userName); } lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW); lock->header.name = properName; lock->header.rank = rank; lock->header.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpRWLock; /* * Always attempt to use native locks when they are available. If, for some * reason, a native lock should be available but isn't, fall back to using * an internal recursive lock - something is better than nothing. */ lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock); lockInited = MXRecLockInit(&lock->recursiveLock); if (LIKELY(lockInited)) { Bool doStats; lock->holderTable = HashTable_Alloc(256, HASH_INT_KEY | HASH_FLAG_ATOMIC, MXUserFreeHashEntry); if (vmx86_stats) { doStats = MXUserStatsEnabled(); } else { doStats = FALSE; } if (doStats) { MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS); } else { lock->header.statsFunc = NULL; Atomic_WritePtr(&lock->statsMem, NULL); } MXUserAddToList(&lock->header); } else { if (lock->useNative) { MXUserNativeRWDestroy(&lock->nativeLock); } free(properName); free(lock); lock = NULL; } return lock; }
static Bool AuthLoadPAM(void) { void *pam_library; int i; if (authPamLibraryHandle) { return TRUE; } pam_library = Posix_Dlopen(CURRENT_PAM_LIBRARY, RTLD_LAZY | RTLD_GLOBAL); if (!pam_library) { #if defined(VMX86_TOOLS) /* * XXX do we even try to configure the pam libraries? * potential nightmare on all the possible guest OSes */ Log("System PAM libraries are unusable: %s\n", dlerror()); return FALSE; #else char *liblocation; char *libdir; libdir = LocalConfig_GetPathName(DEFAULT_LIBDIRECTORY, CONFIG_VMWAREDIR); if (!libdir) { Log("System PAM library unusable and bundled one not found.\n"); return FALSE; } liblocation = Str_SafeAsprintf(NULL, "%s/lib/%s/%s", libdir, CURRENT_PAM_LIBRARY, CURRENT_PAM_LIBRARY); free(libdir); pam_library = Posix_Dlopen(liblocation, RTLD_LAZY | RTLD_GLOBAL); if (!pam_library) { Log("Neither system nor bundled (%s) PAM libraries usable: %s\n", liblocation, dlerror()); free(liblocation); return FALSE; } free(liblocation); #endif } for (i = 0; i < ARRAYSIZE(authPAMImported); i++) { void *symbol = dlsym(pam_library, authPAMImported[i].procname); if (!symbol) { Log("PAM library does not contain required function: %s\n", dlerror()); dlclose(pam_library); return FALSE; } *(authPAMImported[i].procaddr) = symbol; } authPamLibraryHandle = pam_library; Log("PAM up and running.\n"); return TRUE; }
MXUserRWLock * MXUser_CreateRWLock(const char *userName, // IN: MX_Rank rank) // IN: { Bool lockInited; char *properName; Bool useNative = MXUserNativeRWSupported(); MXUserRWLock *lock = Util_SafeCalloc(1, sizeof *lock); if (userName == NULL) { if (LIKELY(useNative)) { properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress()); } else { /* emulated */ properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress()); } } else { properName = Util_SafeStrdup(userName); } lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW); lock->header.name = properName; lock->header.rank = rank; lock->header.bits.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpRWLock; /* * Always attempt to use native locks when they are available. If, for some * reason, a native lock should be available but isn't, fall back to using * an internal recursive lock - something is better than nothing. */ lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock); lockInited = MXRecLockInit(&lock->recursiveLock); if (LIKELY(lockInited)) { uint32 statsMode; lock->holderTable = HashTable_Alloc(256, HASH_INT_KEY | HASH_FLAG_ATOMIC, MXUserFreeHashEntry); statsMode = MXUserStatsMode(); switch (MXUserStatsMode()) { case 0: MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem); lock->header.statsFunc = NULL; break; case 1: MXUserEnableStats(&lock->acquireStatsMem, NULL); lock->header.statsFunc = MXUserStatsActionRW; break; case 2: MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem); lock->header.statsFunc = MXUserStatsActionRW; break; default: Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode); } MXUserAddToList(&lock->header); } else { Panic("%s: native lock initialization routine failed\n", __FUNCTION__); } return lock; }
ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { ProcMgrProcInfoArray *procList = NULL; ProcMgrProcInfo processInfo; Bool failed = TRUE; DIR *dir; struct dirent *ent; procList = Util_SafeCalloc(1, sizeof *procList); ProcMgrProcInfoArray_Init(procList, 0); processInfo.procOwner = NULL; processInfo.procCmdLine = NULL; processInfo.procCmdName = NULL; dir = opendir("/proc"); if (NULL == dir) { Warning("ProcMgr_ListProcesses unable to open /proc\n"); goto exit; } while (TRUE) { char *tmp; char *cmdNameBegin = NULL; char *cmdNameEnd = NULL; struct passwd *pwd; char tempPath[MAXPATHLEN]; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; FileIODescriptor psInfoFd; FileIOResult res; Bool cmdNameLookup = TRUE; errno = 0; FileIO_Invalidate(&psInfoFd); ent = readdir(dir); if (ent == NULL) { if (errno == 0) { break; } else { goto exit; } } if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%s/psinfo", ent->d_name) == -1) { Debug("Process id '%s' too large\n", ent->d_name); continue; } res = FileIO_Open(&psInfoFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { if ((res == FILEIO_FILE_NOT_FOUND) || (res == FILEIO_NO_PERMISSION)) { continue; } else { goto exit; } } res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { goto exit; } processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * If the command name in the ps info struct is strictly less than the * maximum allowed size, then we can save it right now. Else we shall * need to try and parse it from the entire command line, to avoid * saving a truncated command name. */ if (strlen(procInfo.pr_fname) + 1 < sizeof procInfo.pr_fname) { processInfo.procCmdName = Unicode_Alloc(procInfo.pr_fname, STRING_ENCODING_DEFAULT); cmdNameLookup = FALSE; } /* * The logic below is this: * 1. If we are looking for the explicit command name, we need to * extract the arguments from the /proc/<pid>/as file and save argv[0]. * 2. If we are not looking for the explicit command name, but the command * line in the ps info struct is not strictly less than the maximum * allowed size, we still need to extract the arguments from the * /proc/<pid>/as file, to avoid saving truncated comand line. * 3. Else we can save the command line directly from the ps info struct. */ if (cmdNameLookup) { tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo, &processInfo.procCmdName); } else if (strlen(procInfo.pr_psargs) + 1 >= sizeof procInfo.pr_psargs) { tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo, NULL); } else { tmp = NULL; } if (tmp != NULL) { processInfo.procCmdLine = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); cmdNameLookup = FALSE; } else { /* * We had some issues reading procfs, mostly due to lack of * permissions for certain system owned precesses. So let's resort to * what the procinfo structure provides as a last resort. */ processInfo.procCmdLine = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); if (cmdNameLookup) { /* * Now let's try and get the best effort command name from the entire * command line. The method below does not take care of spaces in folder * names and executable file names. This is the best we can do at this * point, considering that spaces are not common in either file or * folder names in Solaris, specially when owned by the system. */ char *tmp2 = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); cmdNameBegin = tmp2; /* * Assuming the command name to end at the first blank space. */ cmdNameEnd = cmdNameBegin; while ('\0' != *cmdNameEnd) { if ('/' == *cmdNameEnd) { cmdNameBegin = cmdNameEnd + 1; } if (' ' == *cmdNameEnd) { break; } cmdNameEnd++; } *cmdNameEnd = '\0'; processInfo.procCmdName = Str_SafeAsprintf(NULL, "%s", cmdNameBegin); free(tmp2); } } free(tmp); tmp = NULL; /* * Store the pid. */ processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); processInfo.procOwner = (NULL == pwd) ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the process info into a list buffer. */ if (!ProcMgrProcInfoArray_Push(procList, processInfo)) { Warning("%s: failed to expand DynArray - out of memory\n", __FUNCTION__); goto exit; } processInfo.procCmdName = NULL; processInfo.procCmdLine = NULL; processInfo.procOwner = NULL; } // while (TRUE) if (0 < ProcMgrProcInfoArray_Count(procList)) { failed = FALSE; } exit: closedir(dir); free(processInfo.procOwner); free(processInfo.procCmdLine); free(processInfo.procCmdName); if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; } return procList; }