MXUserHisto * MXUserHistoSetUp(char *typeName, // type (name) of histogram uint64 minValue, // IN: ns; 1, 10, 100, 1000... uint32 decades) // IN: decimal decades to cover from min { MXUserHisto *histo; ASSERT(decades > 0); ASSERT((minValue != 0) && ((minValue == 1) || ((minValue % 10) == 0))); histo = Util_SafeCalloc(1, sizeof *histo); histo->typeName = Util_SafeStrdup(typeName); histo->numBins = BINS_PER_DECADE * decades; histo->binData = Util_SafeCalloc(histo->numBins, sizeof(uint64)); histo->totalSamples = 0; histo->minValue = minValue; histo->maxValue = histo->minValue; while (decades--) { histo->maxValue *= 10; } return histo; }
VMGuestLibError VMGuestLib_OpenHandle(VMGuestLibHandle *handle) // OUT { VMGuestLibHandleType *data; VMTools_SetGuestSDKMode(); if (!VmCheck_IsVirtualWorld()) { Debug("VMGuestLib_OpenHandle: Not in a VM.\n"); return VMGUESTLIB_ERROR_NOT_RUNNING_IN_VM; } if (NULL == handle) { return VMGUESTLIB_ERROR_INVALID_ARG; } data = Util_SafeCalloc(1, sizeof *data); if (!data) { Debug("VMGuestLib_OpenHandle: Unable to allocate memory\n"); return VMGUESTLIB_ERROR_MEMORY; } *handle = (VMGuestLibHandle)data; return VMGUESTLIB_ERROR_SUCCESS; }
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; }
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; }
BasicHttpBandwidthGroup * BasicHttp_CreateBandwidthGroup(uint64 uploadLimit, // IN uint64 downloadLimit) // IN { BasicHttpBandwidthGroup *group = NULL; group = (BasicHttpBandwidthGroup *) Util_SafeCalloc(1, sizeof *group); group->limits[BASICHTTP_UPLOAD] = uploadLimit; group->limits[BASICHTTP_DOWNLOAD] = downloadLimit; return group; }
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; }
LONG Win32U_RegEnumValue(HKEY keyName, // IN DWORD index, // IN LPSTR valueName, // OUT: buffer LPDWORD valueNameSize, // IN/OUT: LPDWORD reserved, // IN: reserved LPDWORD type, // OUT: can be NULL LPBYTE data, // OUT: can be NULL LPDWORD dataSize) // OUT: can be NULL { LONG ret; utf16_t *valueNameW; DWORD valueNameSizeW = REG_MAX_VALUE_NAME_LEN+1; char *dataTemp = NULL; DWORD dataSizeTemp = 0; DWORD valueType; valueNameW = Util_SafeCalloc(valueNameSizeW, sizeof *valueNameW); if (data) { ASSERT(dataSize != NULL); dataSizeTemp = *dataSize * 2; dataTemp = Util_SafeMalloc(dataSizeTemp); } ret = RegEnumValueW(keyName, index, valueNameW, &valueNameSizeW /* # of characters */, reserved, &valueType, dataTemp, &dataSizeTemp /* # of bytes */); if (ret != ERROR_NO_MORE_ITEMS) { /* valueName is valid */ /* Attempt to convert value name back to UTF-8 */ if (!Win32UCodeSetUtf16leToUtf8(valueNameW, valueNameSizeW * 2, valueName, valueNameSize)) { ret = ERROR_MORE_DATA; } } ret = Win32UWriteBackRegData(dataTemp, dataSizeTemp, data, dataSize, valueType, ret); /* Write back the type information if asked for */ if (type) { *type = valueType; } free(valueNameW); free(dataTemp); return ret; }
MXUserCondVar * MXUserCreateCondVar(MXUserHeader *header, // IN: MXRecLock *lock) // IN: { MXUserCondVar *condVar = Util_SafeCalloc(1, sizeof *condVar); if (UNLIKELY(!MXUserCreateInternal(condVar))) { Panic("%s: native lock initialization routine failed\n", __FUNCTION__); } condVar->signature = MXUserGetSignature(MXUSER_TYPE_CONDVAR); condVar->header = header; condVar->ownerLock = lock; return condVar; }
static Bool ReadOffsetsFromAddressSpaceFile(FileIODescriptor asFd, //IN psinfo_t *psInfo, //IN uintptr_t *argOffs) //OUT { int argc; int i; uintptr_t argv; FileIOResult res; argc = psInfo->pr_argc; argv = psInfo->pr_argv; /* * The offsets for the command line argument are located at an offset of * argv in the /proc/<pid>/as file. If the process data model is NATIVE, * each offset is a unitptr_t; else if the data model is ILP32 or LP64, each * offset is uint32_t. */ if (psInfo->pr_dmodel == PR_MODEL_NATIVE) { /* * The offset for each arguments is sizeof uintptr_t bytes. */ res = FileIO_Pread(&asFd, argOffs, argc * sizeof argv, argv); if (res != FILEIO_SUCCESS) { return FALSE; } } else { /* * The offset for each arguments is sizeof uint32_t bytes. */ uint32_t *argOffs32; argOffs32 = Util_SafeCalloc(argc, sizeof *argOffs32); if (argOffs32 == NULL) { return FALSE; } res = FileIO_Pread(&asFd, argOffs32, argc * sizeof *argOffs32, argv); if (res != FILEIO_SUCCESS) { free (argOffs32); return FALSE; } for (i = 0; i < argc; i++) { argOffs[i] = argOffs32[i]; } free(argOffs32); } return TRUE; }
MXUserCondVar * MXUserCreateCondVar(MXUserHeader *header, // IN: MXRecLock *lock) // IN: { MXUserCondVar *condVar = Util_SafeCalloc(1, sizeof(*condVar)); if (MXUserCreateInternal(condVar)) { condVar->signature = MXUserGetSignature(MXUSER_TYPE_CONDVAR); condVar->header = header; condVar->ownerLock = lock; } else { free(condVar); condVar = NULL; } return condVar; }
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; }
Bool MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT: uint32 command, // IN: ...) // IN: { Bool result; ASSERT(lock); MXUserValidateHeader(&lock->header, MXUSER_TYPE_RW); switch (command) { case MXUSER_CONTROL_ACQUISITION_HISTO: { if (vmx86_stats) { MXUserAcquireStats *acquireStats; acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); if (acquireStats == NULL) { result = FALSE; } else { va_list a; uint32 decades; uint64 minValue; va_start(a, command); minValue = va_arg(a, uint64); decades = va_arg(a, uint32); va_end(a); MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, minValue, decades); result = TRUE; } } else { result = FALSE; } break; } case MXUSER_CONTROL_HELD_HISTO: { if (vmx86_stats) { MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); if (heldStats == NULL) { result = FALSE; } else { va_list a; uint32 decades; uint32 minValue; va_start(a, command); minValue = va_arg(a, uint64); decades = va_arg(a, uint32); va_end(a); MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD, minValue, decades); result = TRUE; } } else { result = FALSE; } break; } case MXUSER_CONTROL_ENABLE_STATS: { if (vmx86_stats) { va_list a; Bool trackHeldTimes; MXUserHeldStats *heldStats; MXUserAcquireStats *acquireStats; acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); if (LIKELY(acquireStats == NULL)) { MXUserAcquireStats *before; acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats)); MXUserAcquisitionStatsSetUp(&acquireStats->data); before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL, (void *) acquireStats); if (before) { free(acquireStats); } } va_start(a, command); trackHeldTimes = va_arg(a, int); va_end(a); heldStats = Atomic_ReadPtr(&lock->heldStatsMem); if ((heldStats == NULL) && trackHeldTimes) { MXUserHeldStats *before; heldStats = Util_SafeCalloc(1, sizeof(*heldStats)); MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD); before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL, (void *) heldStats); if (before) { free(heldStats); } } lock->header.statsFunc = MXUserStatsActionRW; result = TRUE; } else { result = FALSE; } break; } default: result = FALSE; }
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; }
static gboolean GuestInfoGather(gpointer data) { char name[256]; // Size is derived from the SUS2 specification // "Host names are limited to 255 bytes" char *osString = NULL; #if !defined(USERWORLD) gboolean disableQueryDiskInfo; GuestDiskInfo *diskInfo = NULL; #endif NicInfoV3 *nicInfo = NULL; ToolsAppCtx *ctx = data; g_debug("Entered guest info gather.\n"); /* Send tools version. */ if (!GuestInfoUpdateVmdb(ctx, INFO_BUILD_NUMBER, BUILD_NUMBER, 0)) { /* * An older vmx talking to new tools wont be able to handle * this message. Continue, if thats the case. */ g_warning("Failed to update VMDB with tools version.\n"); } /* Gather all the relevant guest information. */ osString = Hostinfo_GetOSName(); if (osString == NULL) { g_warning("Failed to get OS info.\n"); } else { if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME_FULL, osString, 0)) { g_warning("Failed to update VMDB\n"); } } free(osString); osString = Hostinfo_GetOSGuestString(); if (osString == NULL) { g_warning("Failed to get OS info.\n"); } else { if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME, osString, 0)) { g_warning("Failed to update VMDB\n"); } } free(osString); #if !defined(USERWORLD) disableQueryDiskInfo = g_key_file_get_boolean(ctx->config, CONFGROUPNAME_GUESTINFO, CONFNAME_GUESTINFO_DISABLEQUERYDISKINFO, NULL); if (!disableQueryDiskInfo) { if ((diskInfo = GuestInfo_GetDiskInfo()) == NULL) { g_warning("Failed to get disk info.\n"); } else { if (GuestInfoUpdateVmdb(ctx, INFO_DISK_FREE_SPACE, diskInfo, 0)) { GuestInfo_FreeDiskInfo(gInfoCache.diskInfo); gInfoCache.diskInfo = diskInfo; } else { g_warning("Failed to update VMDB\n."); GuestInfo_FreeDiskInfo(diskInfo); } } } #endif if (!System_GetNodeName(sizeof name, name)) { g_warning("Failed to get netbios name.\n"); } else if (!GuestInfoUpdateVmdb(ctx, INFO_DNS_NAME, name, 0)) { g_warning("Failed to update VMDB.\n"); } /* Get NIC information. */ if (!GuestInfo_GetNicInfo(&nicInfo)) { g_warning("Failed to get nic info.\n"); /* * Return an empty nic info. */ nicInfo = Util_SafeCalloc(1, sizeof (struct NicInfoV3)); } if (GuestInfo_IsEqual_NicInfoV3(nicInfo, gInfoCache.nicInfo)) { g_debug("Nic info not changed.\n"); GuestInfo_FreeNicInfo(nicInfo); } else if (GuestInfoUpdateVmdb(ctx, INFO_IPADDRESS, nicInfo, 0)) { /* * Since the update succeeded, free the old cached object, and assign * ours to the cache. */ GuestInfo_FreeNicInfo(gInfoCache.nicInfo); gInfoCache.nicInfo = nicInfo; } else { g_warning("Failed to update VMDB.\n"); GuestInfo_FreeNicInfo(nicInfo); } /* Send the uptime to VMX so that it can detect soft resets. */ SendUptime(ctx); return TRUE; }
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; }
static void RecordResolverNS(DnsConfigInfo *dnsConfigInfo) // IN { int i; #if defined RESOLVER_IPV6_GETSERVERS { union res_sockaddr_union *ns; ns = Util_SafeCalloc(_res.nscount, sizeof *ns); if (res_getservers(&_res, ns, _res.nscount) != _res.nscount) { g_warning("%s: res_getservers failed.\n", __func__); return; } for (i = 0; i < _res.nscount; i++) { struct sockaddr *sa = (struct sockaddr *)&ns[i]; if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) { TypedIpAddress *ip; /* Check to see if we're going above our limit. See bug 605821. */ if (dnsConfigInfo->serverList.serverList_len == DNSINFO_MAX_SERVERS) { g_message("%s: dns server limit (%d) reached, skipping overflow.", __FUNCTION__, DNSINFO_MAX_SERVERS); break; } ip = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, serverList, 1); ASSERT_MEM_ALLOC(ip); GuestInfoSockaddrToTypedIpAddress(sa, ip); } } } #else // if defined RESOLVER_IPV6_GETSERVERS { /* * Name servers (IPv4). */ for (i = 0; i < MAXNS; i++) { struct sockaddr_in *sin = &_res.nsaddr_list[i]; if (sin->sin_family == AF_INET) { TypedIpAddress *ip; /* Check to see if we're going above our limit. See bug 605821. */ if (dnsConfigInfo->serverList.serverList_len == DNSINFO_MAX_SERVERS) { g_message("%s: dns server limit (%d) reached, skipping overflow.", __FUNCTION__, DNSINFO_MAX_SERVERS); break; } ip = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, serverList, 1); ASSERT_MEM_ALLOC(ip); GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin, ip); } } # if defined RESOLVER_IPV6_EXT /* * Name servers (IPv6). */ for (i = 0; i < MAXNS; i++) { struct sockaddr_in6 *sin6 = _res._u._ext.nsaddrs[i]; if (sin6) { TypedIpAddress *ip; /* Check to see if we're going above our limit. See bug 605821. */ if (dnsConfigInfo->serverList.serverList_len == DNSINFO_MAX_SERVERS) { g_message("%s: dns server limit (%d) reached, skipping overflow.", __FUNCTION__, DNSINFO_MAX_SERVERS); break; } ip = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, serverList, 1); ASSERT_MEM_ALLOC(ip); GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin6, ip); } } # endif // if defined RESOLVER_IPV6_EXT } #endif // if !defined RESOLVER_IPV6_GETSERVERS }
static Bool RecordResolverInfo(NicInfoV3 *nicInfo) // OUT { DnsConfigInfo *dnsConfigInfo = NULL; char namebuf[DNSINFO_MAX_ADDRLEN + 1]; char **s; if (res_init() == -1) { return FALSE; } dnsConfigInfo = Util_SafeCalloc(1, sizeof *dnsConfigInfo); /* * Copy in the host name. not this */ if (!GuestInfoGetFqdn(sizeof namebuf, namebuf)) { goto fail; } dnsConfigInfo->hostName = Util_SafeCalloc(1, sizeof *dnsConfigInfo->hostName); *dnsConfigInfo->hostName = Util_SafeStrdup(namebuf); /* * Repeat with the domain name. not this */ dnsConfigInfo->domainName = Util_SafeCalloc(1, sizeof *dnsConfigInfo->domainName); *dnsConfigInfo->domainName = Util_SafeStrdup(_res.defdname); /* * Name servers. */ RecordResolverNS(dnsConfigInfo); /* * Search suffixes. */ for (s = _res.dnsrch; *s; s++) { DnsHostname *suffix; /* Check to see if we're going above our limit. See bug 605821. */ if (dnsConfigInfo->searchSuffixes.searchSuffixes_len == DNSINFO_MAX_SUFFIXES) { g_message("%s: dns search suffix limit (%d) reached, skipping overflow.", __FUNCTION__, DNSINFO_MAX_SUFFIXES); break; } suffix = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, searchSuffixes, 1); ASSERT_MEM_ALLOC(suffix); *suffix = Util_SafeStrdup("test suffix"); } /* * "Commit" dnsConfigInfo to nicInfo. */ nicInfo->dnsConfigInfo = dnsConfigInfo; return TRUE; fail: VMX_XDR_FREE(xdr_DnsConfigInfo, dnsConfigInfo); free(dnsConfigInfo); return FALSE; }
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; }
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; }
Bool MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT: uint32 command, // IN: ...) // IN: { Bool result; ASSERT(lock); MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL); switch (command) { case MXUSER_CONTROL_ACQUISITION_HISTO: { if (vmx86_stats) { MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); if (stats == NULL) { result = FALSE; } else { va_list a; uint32 decades; uint64 minValue; va_start(a, command); minValue = va_arg(a, uint64); decades = va_arg(a, uint32); va_end(a); MXUserForceHisto(&stats->acquisitionHisto, MXUSER_STAT_CLASS_ACQUISITION, minValue, decades); result = TRUE; } } else { result = FALSE; } break; } case MXUSER_CONTROL_HELD_HISTO: { if (vmx86_stats) { MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); if (stats == NULL) { result = FALSE; } else { va_list a; uint32 decades; uint32 minValue; va_start(a, command); minValue = va_arg(a, uint64); decades = va_arg(a, uint32); va_end(a); MXUserForceHisto(&stats->heldHisto, MXUSER_STAT_CLASS_HELD, minValue, decades); result = TRUE; } } else { result = FALSE; } break; } case MXUSER_CONTROL_ENABLE_STATS: { if (vmx86_stats) { MXUserStats *stats; MXUserStats *before; stats = Util_SafeCalloc(1, sizeof(*stats)); MXUserAcquisitionStatsSetUp(&stats->acquisitionStats); MXUserBasicStatsSetUp(&stats->heldStats, MXUSER_STAT_CLASS_HELD); before = Atomic_ReadIfEqualWritePtr(&lock->statsMem, NULL, (void *) stats); if (before) { free(stats); } lock->header.statsFunc = MXUserStatsActionExcl; result = TRUE; } else { result = FALSE; } break; } default: result = FALSE; } return result; }
static void VThreadBaseSimpleNoID(void) { VThreadID newID; Bool reused = FALSE; Bool result; void *newNative = VThreadBaseGetNative(); HashTable *ht = VThreadBaseGetNativeHash(); VThreadBaseData *base; /* Require key allocation before TLS read */ VThreadBaseGetKey(); /* Before allocating a new ID, try to reclaim any old IDs. */ for (newID = 0; newID < Atomic_Read(&vthreadBaseGlobals.dynamicID); newID++) { void *newKey = (void *)(uintptr_t)newID; /* * Windows: any entry that is found and not (alive or NULL) * is reclaimable. The check is slightly racy, but the race * would only cause missing a reclaim which isn't a problem. * Posix: thread exit is hooked (via TLS destructor) and sets * entries to NULL, so any entry that is NULL is reclaimable. */ #ifdef _WIN32 void *oldNative; reused = HashTable_Lookup(ht, newKey, &oldNative) && (oldNative == NULL || !VThreadBaseNativeIsAlive(oldNative)) && HashTable_ReplaceIfEqual(ht, newKey, oldNative, newNative); #else reused = HashTable_ReplaceIfEqual(ht, newKey, NULL, newNative); #endif if (reused) { break; } } if (!reused) { void *newKey; newID = Atomic_FetchAndInc(&vthreadBaseGlobals.dynamicID); /* * Detect VThreadID overflow (~0 is used as a sentinel). * Leave a space of ~10 IDs, since the increment and bounds-check * are not atomic. */ ASSERT_NOT_IMPLEMENTED(newID < VTHREAD_INVALID_ID - 10); newKey = (void *)(uintptr_t)newID; result = HashTable_Insert(ht, newKey, newNative); ASSERT_NOT_IMPLEMENTED(result); } /* ID picked. Now do the important stuff. */ base = Util_SafeCalloc(1, sizeof *base); base->id = newID; Str_Sprintf(base->name, sizeof base->name, "vthread-%u", newID); result = VThreadBase_InitWithTLS(base); ASSERT(result); if (vmx86_debug && reused) { Log("VThreadBase reused VThreadID %d.\n", newID); } if (Atomic_Read(&vthreadBaseGlobals.numThreads) > 1) { LOG_ONCE(("VThreadBase detected multiple threads.\n")); } }
static Bool RecordRoutingInfoIPv6(NicInfoV3 *nicInfo) { GPtrArray *routes = NULL; guint i; Bool ret = FALSE; if ((routes = SlashProcNet_GetRoute6()) == NULL) { return FALSE; } for (i = 0; i < routes->len; i++) { struct sockaddr_storage ss; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; struct in6_rtmsg *in6_rtmsg; InetCidrRouteEntry *icre; uint32_t ifIndex = -1; /* Check to see if we're going above our limit. See bug 605821. */ if (nicInfo->routes.routes_len == NICINFO_MAX_ROUTES) { g_message("%s: route limit (%d) reached, skipping overflow.", __FUNCTION__, NICINFO_MAX_ROUTES); break; } in6_rtmsg = g_ptr_array_index(routes, i); if ((in6_rtmsg->rtmsg_flags & RTF_UP) == 0 || !GuestInfoGetNicInfoIfIndex(nicInfo, in6_rtmsg->rtmsg_ifindex, &ifIndex)) { continue; } icre = XDRUTIL_ARRAYAPPEND(nicInfo, routes, 1); ASSERT_MEM_ALLOC(icre); /* * Destination. */ sin6->sin6_family = AF_INET6; sin6->sin6_addr = in6_rtmsg->rtmsg_dst; GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin6, &icre->inetCidrRouteDest); icre->inetCidrRoutePfxLen = in6_rtmsg->rtmsg_dst_len; /* * Next hop. */ if (in6_rtmsg->rtmsg_flags & RTF_GATEWAY) { TypedIpAddress *ip = Util_SafeCalloc(1, sizeof *ip); sin6->sin6_addr = in6_rtmsg->rtmsg_gateway; GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin6, ip); icre->inetCidrRouteNextHop = ip; } /* * Interface, metric. */ icre->inetCidrRouteIfIndex = ifIndex; icre->inetCidrRouteMetric = in6_rtmsg->rtmsg_metric; } ret = TRUE; SlashProcNet_FreeRoute6(routes); return ret; }
static VMGuestLibError VMGuestLibUpdateInfo(VMGuestLibHandle handle) // IN { char *reply = NULL; size_t replyLen; VMGuestLibError ret = VMGUESTLIB_ERROR_INVALID_ARG; uint32 hostVersion = HANDLE_VERSION(handle); /* * Starting with the highest supported protocol (major) version, negotiate * down to the highest host supported version. Host supports minimum version * 2. */ if (hostVersion == 0) { hostVersion = VMGUESTLIB_DATA_VERSION; } do { char commandBuf[64]; unsigned int index = 0; /* Free the last reply when retrying. */ free(reply); reply = NULL; /* * Construct command string with the command name and the version * of the data struct that we want. */ Str_Sprintf(commandBuf, sizeof commandBuf, "%s %d", VMGUESTLIB_BACKDOOR_COMMAND_STRING, hostVersion); /* Send the request. */ if (RpcChannel_SendOne(&reply, &replyLen, commandBuf)) { VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply; VMSessionId sessionId = HANDLE_SESSIONID(handle); ASSERT(hostVersion == v2reply->hdr.version); if (sessionId != 0 && sessionId != v2reply->hdr.sessionId) { /* Renegotiate protocol if sessionId changed. */ hostVersion = VMGUESTLIB_DATA_VERSION; HANDLE_SESSIONID(handle) = 0; continue; } ret = VMGUESTLIB_ERROR_SUCCESS; break; } /* * Host is older and doesn't support the requested protocol version. * Request the highest version the host supports. */ Debug("Failed to retrieve info: %s\n", reply ? reply : "NULL"); if (hostVersion == 2 || Str_Strncmp(reply, "Unknown command", sizeof "Unknown command") == 0) { /* * Host does not support this feature. Older (v2) host would return * "Unsupported version" if it doesn't recognize the requested version. * * XXX: Maybe use another error code for this case where the host * product doesn't support this feature? */ ret = VMGUESTLIB_ERROR_NOT_ENABLED; break; } else if (hostVersion == 3) { /* * Host supports v2 at a minimum. If request for v3 fails, then just use * v2, since v2 host does not send the highest supported version in the * reply. */ hostVersion = 2; HANDLE_SESSIONID(handle) = 0; continue; } else if (!StrUtil_GetNextUintToken(&hostVersion, &index, reply, ":")) { /* * v3 and onwards, the host returns the highest major version it supports, * if the requested version is not supported. So parse out the host * version from the reply and return error if it didn't. */ Debug("Bad reply received from host.\n"); ret = VMGUESTLIB_ERROR_OTHER; break; } ASSERT(hostVersion < VMGUESTLIB_DATA_VERSION); } while (ret != VMGUESTLIB_ERROR_SUCCESS); if (ret != VMGUESTLIB_ERROR_SUCCESS) { goto done; } /* Sanity check the results. */ if (replyLen < sizeof hostVersion) { Debug("Unable to retrieve version\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (hostVersion == 2) { VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply; size_t dataSize = sizeof *v2reply; /* More sanity checks. */ if (v2reply->hdr.version != hostVersion) { Debug("Incorrect data version returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (replyLen != dataSize) { Debug("Incorrect data size returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } /* Store the reply in the handle. */ HANDLE_VERSION(handle) = v2reply->hdr.version; HANDLE_SESSIONID(handle) = v2reply->hdr.sessionId; if (HANDLE_DATASIZE(handle) < dataSize) { /* [Re]alloc if the local handle buffer is not big enough. */ free(HANDLE_DATA(handle)); HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize); HANDLE_DATASIZE(handle) = dataSize; } memcpy(HANDLE_DATA(handle), reply, replyLen); /* Make sure resourcePoolPath is NUL terminated. */ v2reply = HANDLE_DATA(handle); v2reply->resourcePoolPath.value[sizeof v2reply->resourcePoolPath.value - 1] = '\0'; ret = VMGUESTLIB_ERROR_SUCCESS; } else if (hostVersion == 3) { VMGuestLibDataV3 *v3reply = (VMGuestLibDataV3 *)reply; size_t dataSize; XDR xdrs; GuestLibV3StatCount count; VMGuestLibStatisticsV3 *v3stats; /* More sanity checks. */ if (v3reply->hdr.version != hostVersion) { Debug("Incorrect data version returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (replyLen < sizeof *v3reply) { Debug("Incorrect data size returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } /* 0. Copy the reply version and sessionId to the handle. */ HANDLE_VERSION(handle) = v3reply->hdr.version; HANDLE_SESSIONID(handle) = v3reply->hdr.sessionId; /* * 1. Retrieve the length of the statistics array from the XDR encoded * part of the reply. */ xdrmem_create(&xdrs, v3reply->data, v3reply->dataSize, XDR_DECODE); if (!xdr_GuestLibV3StatCount(&xdrs, &count)) { xdr_destroy(&xdrs); goto done; } if (count >= GUESTLIB_MAX_STATISTIC_ID) { /* * Host has more than we can process. So process only what this side * can. */ count = GUESTLIB_MAX_STATISTIC_ID - 1; } /* 2. [Re]alloc if the local handle buffer is not big enough. */ dataSize = sizeof *v3stats + (count * sizeof (GuestLibV3Stat)); if (HANDLE_DATASIZE(handle) < dataSize) { free(HANDLE_DATA(handle)); HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize); HANDLE_DATASIZE(handle) = dataSize; } /* 3. Unmarshal the array of statistics. */ v3stats = HANDLE_DATA(handle); v3stats->numStats = count; for (count = 0; count < v3stats->numStats; count++) { GuestLibV3TypeIds statId = count + 1; /* Unmarshal the statistic. */ if (!xdr_GuestLibV3Stat(&xdrs, &v3stats->stats[count])) { break; } /* Host sends all the V3 statistics it supports, in order. */ if (v3stats->stats[count].d != statId) { break; } } if (count >= v3stats->numStats) { ret = VMGUESTLIB_ERROR_SUCCESS; } else { /* * Error while unmarshalling. Deep-free already unmarshalled * statistics and invalidate the data in the handle. */ GuestLibV3StatCount c; for (c = 0; c < count; c++) { VMX_XDR_FREE(xdr_GuestLibV3Stat, &v3stats->stats[c]); } HANDLE_SESSIONID(handle) = 0; } /* 4. Free resources. */ xdr_destroy(&xdrs); } else { /* * Host should never reply with a higher version protocol than requested. */ ret = VMGUESTLIB_ERROR_OTHER; } done: free(reply); return ret; }
static Bool ReadArgsFromAddressSpaceFile(FileIODescriptor asFd, //IN psinfo_t *psInfo, //IN DynBufArray *cmdLineArr) //OUT { uintptr_t *argOffs; uintptr_t argOff; uintptr_t nextArgOff; int argc; int i; char *argBuf; char *argBufPtr; DynBuf *arg; argc = psInfo->pr_argc; DynBufArray_Init(cmdLineArr, argc); for (i = 0; i < argc; i++) { DynBuf_Init(DynBufArray_AddressOf(cmdLineArr, i)); } if (argc == 0) { return TRUE; } argOffs = Util_SafeCalloc(argc, sizeof *argOffs); if (argOffs == NULL) { return FALSE; } if (!ReadOffsetsFromAddressSpaceFile(asFd, psInfo, argOffs)) { goto fail; } /* Read the command line arguments into the cmdLineArr array. */ nextArgOff = argc > 0 ? argOffs[0] : 0; i = 0; while (i < argc) { argOff = argOffs[i]; /* * The argument strings are contiguous in the address space file. So * argOff[i] + strlen(arg[i]) + 1 should be equal to argOff[i + 1]. */ if ((argOff == 0) || (argOff != nextArgOff)) { goto fail; } argBuf = ExtractArgStringFromAddressSpaceFile(asFd, argOff); if (argBuf == NULL) { goto fail; } nextArgOff = argOff + strlen(argBuf) + 1; argBufPtr = argBuf + strlen(argBuf); while ((argBufPtr > argBuf) && isspace(*(argBufPtr - 1))) { argBufPtr--; } *argBufPtr = '\0'; arg = DynBufArray_AddressOf(cmdLineArr, i); if (!DynBuf_Append(arg, argBuf, strlen(argBuf) + 1)) { free(argBuf); goto fail; } free(argBuf); i++; } return TRUE; fail: Warning("Failed to read command line arguments\n"); argc = DynBufArray_Count(cmdLineArr); for (i = 0; i < argc; i++) { arg = DynArray_AddressOf(cmdLineArr, i); DynBuf_Destroy(arg); } DynBufArray_SetCount(cmdLineArr, 0); DynBufArray_Destroy(cmdLineArr); free(argOffs); return FALSE; }
static Bool RecordRoutingInfoIPv4(NicInfoV3 *nicInfo) { GPtrArray *routes = NULL; guint i; Bool ret = FALSE; if ((routes = SlashProcNet_GetRoute()) == NULL) { return FALSE; } for (i = 0; i < routes->len; i++) { struct rtentry *rtentry; struct sockaddr_in *sin_dst; struct sockaddr_in *sin_gateway; struct sockaddr_in *sin_genmask; InetCidrRouteEntry *icre; uint32_t ifIndex; /* Check to see if we're going above our limit. See bug 605821. */ if (nicInfo->routes.routes_len == NICINFO_MAX_ROUTES) { g_message("%s: route limit (%d) reached, skipping overflow.", __FUNCTION__, NICINFO_MAX_ROUTES); break; } rtentry = g_ptr_array_index(routes, i); if ((rtentry->rt_flags & RTF_UP) == 0 || !GuestInfoGetNicInfoIfIndex(nicInfo, if_nametoindex(rtentry->rt_dev), &ifIndex)) { continue; } icre = XDRUTIL_ARRAYAPPEND(nicInfo, routes, 1); ASSERT_MEM_ALLOC(icre); sin_dst = (struct sockaddr_in *)&rtentry->rt_dst; sin_gateway = (struct sockaddr_in *)&rtentry->rt_gateway; sin_genmask = (struct sockaddr_in *)&rtentry->rt_genmask; GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_dst, &icre->inetCidrRouteDest); addr_stob((struct sockaddr *)sin_genmask, (uint16_t *)&icre->inetCidrRoutePfxLen); /* * Gateways are optional (ex: one can bind a route to an interface w/o * specifying a next hop address). */ if (rtentry->rt_flags & RTF_GATEWAY) { TypedIpAddress *ip = Util_SafeCalloc(1, sizeof *ip); GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_gateway, ip); icre->inetCidrRouteNextHop = ip; } /* * Interface, metric. */ icre->inetCidrRouteIfIndex = ifIndex; icre->inetCidrRouteMetric = rtentry->rt_metric; } ret = TRUE; SlashProcNet_FreeRoute(routes); return ret; }
Bool FileIO_AtomicUpdate(FileIODescriptor *newFD, // IN/OUT: file IO descriptor FileIODescriptor *currFD) // IN/OUT: file IO descriptor { char *currPath = NULL; char *newPath = NULL; #if defined(_WIN32) uint32 currAccess; uint32 newAccess; FileIOResult status; FileIODescriptor tmpFD; #else int fd; #endif int savedErrno = 0; Bool ret = FALSE; ASSERT(FileIO_IsValid(newFD)); ASSERT(FileIO_IsValid(currFD)); if (HostType_OSIsVMK()) { #if defined(VMX86_SERVER) FS_SwapFilesArgs *args = NULL; char *dirName = NULL; char *fileName = NULL; char *dstDirName = NULL; char *dstFileName = NULL; currPath = File_FullPath(FileIO_Filename(currFD)); if (!currPath) { savedErrno = errno; Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__, FileIO_Filename(currFD)); goto swapdone; } newPath = File_FullPath(FileIO_Filename(newFD)); if (!newPath) { savedErrno = errno; Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__, FileIO_Filename(newFD)); goto swapdone; } File_GetPathName(newPath, &dirName, &fileName); File_GetPathName(currPath, &dstDirName, &dstFileName); ASSERT(dirName && *dirName); ASSERT(fileName && *fileName); ASSERT(dstDirName && *dstDirName); ASSERT(dstFileName && *dstFileName); ASSERT(!strcmp(dirName, dstDirName)); args = (FS_SwapFilesArgs *) Util_SafeCalloc(1, sizeof(*args)); if (Str_Snprintf(args->srcFile, sizeof(args->srcFile), "%s", fileName) < 0) { Log("%s: Path too long \"%s\".\n", __FUNCTION__, fileName); savedErrno = ENAMETOOLONG; goto swapdone; } if (Str_Snprintf(args->dstFilePath, sizeof(args->dstFilePath), "%s/%s", dstDirName, dstFileName) < 0) { Log("%s: Path too long \"%s\".\n", __FUNCTION__, dstFileName); savedErrno = ENAMETOOLONG; goto swapdone; } /* * Issue the ioctl on the directory rather than on the file, * because the file could be open. */ fd = Posix_Open(dirName, O_RDONLY); if (fd < 0) { Log("%s: Open failed \"%s\" %d.\n", __FUNCTION__, dirName, errno); ASSERT(errno != EBUSY); /* #615124. */ savedErrno = errno; goto swapdone; } if (ioctl(fd, IOCTLCMD_VMFS_SWAP_FILES, args) != 0) { savedErrno = errno; if (errno != ENOSYS && errno != ENOTTY) { Log("%s: ioctl failed %d.\n", __FUNCTION__, errno); ASSERT(errno != EBUSY); /* #615124. */ } } else { ret = TRUE; } close(fd); /* * Did we fail because we are on a file system that does not * support the IOCTLCMD_VMFS_SWAP_FILES ioctl? If so fallback to * using rename. * * Check for both ENOSYS and ENOTTY. PR 957695 */ if (savedErrno == ENOSYS || savedErrno == ENOTTY) { /* * NFS allows renames of locked files, even if both files * are locked. The file lock follows the file handle, not * the name, so after the rename we can swap the underlying * file descriptors instead of closing and reopening the * target file. * * This is different than the hosted path below because * ESX uses native file locks and hosted does not. * * We assume that all ESX file systems that support rename * have the same file lock semantics as NFS. */ if (File_Rename(newPath, currPath)) { Log("%s: rename of '%s' to '%s' failed %d.\n", __FUNCTION__, newPath, currPath, errno); savedErrno = errno; goto swapdone; } ret = TRUE; fd = newFD->posix; newFD->posix = currFD->posix; currFD->posix = fd; FileIO_Close(newFD); } swapdone: free(args); free(dirName); free(fileName); free(dstDirName); free(dstFileName); free(currPath); free(newPath); errno = savedErrno; return ret; #else NOT_REACHED(); #endif } #if defined(_WIN32) currPath = Unicode_Duplicate(FileIO_Filename(currFD)); newPath = Unicode_Duplicate(FileIO_Filename(newFD)); newAccess = newFD->flags; currAccess = currFD->flags; FileIO_Close(newFD); /* * The current file needs to be closed and reopened, * but we don't want to drop the file lock by calling * FileIO_Close() on it. Instead, use native close primitives. * We'll reopen it later with FileIO_Open. Set the * descriptor/handle to an invalid value while we're in the * middle of transferring ownership. */ CloseHandle(currFD->win32); currFD->win32 = INVALID_HANDLE_VALUE; if (File_RenameRetry(newPath, currPath, 10) == 0) { ret = TRUE; } else { savedErrno = errno; ASSERT(!ret); } FileIO_Invalidate(&tmpFD); /* * Clear the locking bits from the requested access so that reopening * the file ignores the advisory lock. */ ASSERT((currAccess & FILEIO_OPEN_LOCK_MANDATORY) == 0); currAccess &= ~(FILEIO_OPEN_LOCK_MANDATORY | FILEIO_OPEN_LOCK_ADVISORY | FILEIO_OPEN_LOCK_BEST | FILEIO_OPEN_LOCKED); status = FileIO_Open(&tmpFD, currPath, currAccess, FILEIO_OPEN); if (!FileIO_IsSuccess(status)) { Panic("Failed to reopen dictionary after renaming " "\"%s\" to \"%s\": %s (%d)\n", newPath, currPath, FileIO_ErrorEnglish(status), status); } ASSERT(tmpFD.lockToken == NULL); currFD->win32 = tmpFD.win32; FileIO_Cleanup(&tmpFD); Unicode_Free(currPath); Unicode_Free(newPath); errno = savedErrno; return ret; #else currPath = (char *)FileIO_Filename(currFD); newPath = (char *)FileIO_Filename(newFD); if (File_Rename(newPath, currPath)) { Log("%s: rename of '%s' to '%s' failed %d.\n", __FUNCTION__, newPath, currPath, errno); savedErrno = errno; } else { ret = TRUE; fd = newFD->posix; newFD->posix = currFD->posix; currFD->posix = fd; FileIO_Close(newFD); } errno = savedErrno; return ret; #endif }