/** * Performs a case insensitive string compare between two UTF-8 strings, given a * maximum string length. * * This is a simplified compare, as only the simplified lower/upper case folding * specified by the unicode specs are used. It does not consider character pairs * as they are used in some languages, just simple upper & lower case compares. * * The result is the difference between the mismatching codepoints after they * both have been lower cased. * * If the string encoding is invalid the function will assert (strict builds) * and use RTStrCmp for the remainder of the string. * * @returns < 0 if the first string less than the second string. * @returns 0 if the first string identical to the second string. * @returns > 0 if the first string greater than the second string. * @param psz1 First UTF-8 string. Null is allowed. * @param psz2 Second UTF-8 string. Null is allowed. * @param cchMax Maximum string length */ RTDECL(int) RTStrNICmp(const char *psz1, const char *psz2, size_t cchMax) { if (cchMax == 0) return 0; if (psz1 == psz2) return 0; if (!psz1) return -1; if (!psz2) return 1; for (;;) { /* Get the codepoints */ RTUNICP uc1; size_t cchMax2 = cchMax; int rc = RTStrGetCpNEx(&psz1, &cchMax, &uc1); if (RT_FAILURE(rc)) { AssertRC(rc); psz1--; cchMax++; break; } RTUNICP uc2; rc = RTStrGetCpNEx(&psz2, &cchMax2, &uc2); if (RT_FAILURE(rc)) { AssertRC(rc); psz2--; psz1 -= (cchMax - cchMax2 + 1); /* This can't overflow, can it? */ cchMax = cchMax2 + 1; break; } /* compare */ int iDiff = uc1 - uc2; if (iDiff) { iDiff = RTUniCpToUpper(uc1) != RTUniCpToUpper(uc2); if (iDiff) { iDiff = RTUniCpToLower(uc1) - RTUniCpToLower(uc2); /* lower case diff last! */ if (iDiff) return iDiff; } } /* hit the terminator? */ if (!uc1 || cchMax == 0) return 0; } /* Hit some bad encoding, continue in case insensitive mode. */ return RTStrNCmp(psz1, psz2, cchMax); }
bool getSequence(const char *pach, size_t cch, size_t *pcchRead, const char *pcszSequence, size_t cchSequence) { if ( cch - *pcchRead >= cchSequence && !RTStrNCmp(pach + *pcchRead, pcszSequence, cchSequence)) { *pcchRead += cchSequence; return true; } return false; }
RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void) { RTCPUID uOnlineCores = 0; int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */); if (RT_SUCCESS(rc)) { rc = RTCritSectEnter(&g_MpSolarisCritSect); AssertRC(rc); /* * For each core in the system, count how many are currently online. */ for (RTCPUID j = 0; j < g_cCores; j++) { uint64_t u64CoreId = g_pu64CoreIds[j]; for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++) { rc = kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0); AssertReturn(rc != -1, 0 /* rc */); uint64_t u64ThreadCoreId = rtMpSolarisGetCoreId(idCpu); if (u64ThreadCoreId == u64CoreId) { kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"state"); Assert(pStat->data_type == KSTAT_DATA_CHAR); if( !RTStrNCmp(pStat->value.c, PS_ONLINE, sizeof(PS_ONLINE) - 1) || !RTStrNCmp(pStat->value.c, PS_NOINTR, sizeof(PS_NOINTR) - 1)) { uOnlineCores++; break; /* Move to the next core. We have at least 1 hyperthread online in the current core. */ } } } } RTCritSectLeave(&g_MpSolarisCritSect); } return uOnlineCores; }
/** * This function evaluate file name. * @param pu8Payload * @param cbPayload * @param cbFileName * @return VINF_SUCCESS - * VERR_INVALID_PARAMETER - */ DECLINLINE(int) tftpSecurityFilenameCheck(PNATState pData, PCTFTPSESSION pcTftpSession) { size_t cbSessionFilename = 0; int rc = VINF_SUCCESS; AssertPtrReturn(pcTftpSession, VERR_INVALID_PARAMETER); cbSessionFilename = RTStrNLen((const char *)pcTftpSession->pszFilename, TFTP_FILENAME_MAX); if ( !RTStrNCmp((const char*)pcTftpSession->pszFilename, "../", 3) || (pcTftpSession->pszFilename[cbSessionFilename - 1] == '/') || RTStrStr((const char *)pcTftpSession->pszFilename, "/../")) rc = VERR_FILE_NOT_FOUND; /* only allow exported prefixes */ if ( RT_SUCCESS(rc) && !tftp_prefix) rc = VERR_INTERNAL_ERROR; LogFlowFuncLeaveRC(rc); return rc; }
RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, const char *pszPathFrom, const char *pszPathTo) { int rc = VINF_SUCCESS; AssertPtrReturn(pszPathDst, VERR_INVALID_POINTER); AssertReturn(cbPathDst, VERR_INVALID_PARAMETER); AssertPtrReturn(pszPathFrom, VERR_INVALID_POINTER); AssertPtrReturn(pszPathTo, VERR_INVALID_POINTER); AssertReturn(RTPathStartsWithRoot(pszPathFrom), VERR_INVALID_PARAMETER); AssertReturn(RTPathStartsWithRoot(pszPathTo), VERR_INVALID_PARAMETER); AssertReturn(RTStrCmp(pszPathFrom, pszPathTo), VERR_INVALID_PARAMETER); /* * Check for different root specifiers (drive letters), creating a relative path doesn't work here. * @todo: How to handle case insensitive root specifiers correctly? */ size_t offRootFrom = rtPathRootSpecLen(pszPathFrom); size_t offRootTo = rtPathRootSpecLen(pszPathTo); if ( offRootFrom != offRootTo || RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom)) return VERR_NOT_SUPPORTED; /* Filter out the parent path which is equal to both paths. */ while ( *pszPathFrom == *pszPathTo && *pszPathFrom != '\0' && *pszPathTo != '\0') { pszPathFrom++; pszPathTo++; } /* * Because path components can start with an equal string but differ afterwards we * need to go back to the beginning of the current component. */ while (!RTPATH_IS_SEP(*pszPathFrom)) pszPathFrom--; pszPathFrom++; /* Skip path separator. */ while (!RTPATH_IS_SEP(*pszPathTo)) pszPathTo--; pszPathTo++; /* Skip path separator. */ /* Paths point to the first non equal component now. */ char aszPathTmp[RTPATH_MAX + 1]; unsigned offPathTmp = 0; /* Create the part to go up from pszPathFrom. */ while (*pszPathFrom != '\0') { while ( !RTPATH_IS_SEP(*pszPathFrom) && *pszPathFrom != '\0') pszPathFrom++; if (RTPATH_IS_SEP(*pszPathFrom)) { if (offPathTmp + 3 >= sizeof(aszPathTmp) - 1) return VERR_FILENAME_TOO_LONG; aszPathTmp[offPathTmp++] = '.'; aszPathTmp[offPathTmp++] = '.'; aszPathTmp[offPathTmp++] = RTPATH_SLASH; pszPathFrom++; } } aszPathTmp[offPathTmp] = '\0'; /* Now append the rest of pszPathTo to the final path. */ char *pszPathTmp = &aszPathTmp[offPathTmp]; size_t cbPathTmp = sizeof(aszPathTmp) - offPathTmp - 1; rc = RTStrCatP(&pszPathTmp, &cbPathTmp, pszPathTo); if (RT_SUCCESS(rc)) { *pszPathTmp = '\0'; size_t cchPathTmp = strlen(aszPathTmp); if (cchPathTmp >= cbPathDst) return VERR_BUFFER_OVERFLOW; memcpy(pszPathDst, aszPathTmp, cchPathTmp + 1); } else rc = VERR_FILENAME_TOO_LONG; return rc; }
/** * Parses a out the next block from a version string. * * @returns true if numeric, false if not. * @param ppszVer The string cursor, IN/OUT. * @param pi32Value Where to return the value if numeric. * @param pcchBlock Where to return the block length. */ static bool rtStrVersionParseBlock(const char **ppszVer, int32_t *pi32Value, size_t *pcchBlock) { const char *psz = *ppszVer; /* * Check for end-of-string. */ if (!*psz) { *pi32Value = 0; *pcchBlock = 0; return false; } /* * Try convert the block to a number the simple way. */ char ch; bool fNumeric = RT_C_IS_DIGIT(*psz); if (fNumeric) { do ch = *++psz; while (ch && RT_C_IS_DIGIT(ch)); int rc = RTStrToInt32Ex(*ppszVer, NULL, 10, pi32Value); if (RT_FAILURE(rc) || rc == VWRN_NUMBER_TOO_BIG) { AssertRC(rc); fNumeric = false; *pi32Value = 0; } } else { /* * Find the end of the current string. Make a special case for SVN * revision numbers that immediately follows a release tag string. */ do ch = *++psz; while ( ch && !RT_C_IS_DIGIT(ch) && !RTSTRVER_IS_PUNCTUACTION(ch)); size_t cchBlock = psz - *ppszVer; if ( cchBlock > 1 && psz[-1] == 'r' && RT_C_IS_DIGIT(*psz)) { psz--; cchBlock--; } /* * Translate standard pre release terms to negative values. */ static const struct { size_t cch; const char *psz; int32_t iValue; } s_aTerms[] = { { 2, "RC", -100000 }, { 3, "PRE", -200000 }, { 5, "GAMMA", -300000 }, { 4, "BETA", -400000 }, { 5, "ALPHA", -500000 } }; int32_t iVal1 = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_aTerms); i++) if ( cchBlock == s_aTerms[i].cch && !RTStrNCmp(s_aTerms[i].psz, *ppszVer, cchBlock)) { iVal1 = s_aTerms[i].iValue; break; } if (iVal1 != 0) { /* * Does the prelease term have a trailing number? * Add it assuming BETA == BETA1. */ if (RT_C_IS_DIGIT(*psz)) { const char *psz2 = psz; do ch = *++psz; while ( ch && RT_C_IS_DIGIT(ch) && !RTSTRVER_IS_PUNCTUACTION(ch)); int rc = RTStrToInt32Ex(psz2, NULL, 10, pi32Value); if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG && *pi32Value) iVal1 += *pi32Value - 1; else { AssertRC(rc); psz = psz2; } } fNumeric = true; } *pi32Value = iVal1; } *pcchBlock = psz - *ppszVer; /* * Skip trailing punctuation. */ if (RTSTRVER_IS_PUNCTUACTION(*psz)) psz++; *ppszVer = psz; return fNumeric; }
/** * Get Parallel port address and update the shared data * structure. * @returns VBox status code. * @param pThis The host parallel port instance data. */ static int drvWinHostGetparportAddr(PDRVHOSTPARALLEL pThis) { HDEVINFO hDevInfo; SP_DEVINFO_DATA DeviceInfoData; uint32_t u32Idx; uint32_t u32ParportAddr; int rc = VINF_SUCCESS; hDevInfo = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) return VERR_INVALID_HANDLE; /* Enumerate through all devices in Set. */ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (u32Idx = 0; SetupDiEnumDeviceInfo(hDevInfo, u32Idx, &DeviceInfoData); u32Idx++) { DWORD dwDataType; uint8_t *pBuf = NULL; DWORD dwBufSize = 0; while (!SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, (PDWORD)&dwDataType, (uint8_t *)pBuf, dwBufSize, (PDWORD)&dwBufSize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { LogFlow(("ERROR_INSUFF_BUFF = %d. dwBufSz = %d\n", GetLastError(), dwBufSize)); if (pBuf) RTMemFree(pBuf); pBuf = (uint8_t *)RTMemAlloc(dwBufSize * 2); } else { /* No need to bother about this error (in most cases its errno=13, * INVALID_DATA . Just break from here and proceed to next device * enumerated item */ LogFlow(("GetDevProp Error = %d & dwBufSz = %d\n", GetLastError(), dwBufSize)); break; } } if (RTStrStr((char*)pBuf, "LPT")) { u32ParportAddr = drvHostWinFindIORangeResource(DeviceInfoData.DevInst); if (u32ParportAddr) { /* Find parallel port name and update the shared data struncture */ char *pCh = RTStrStr((char*)pBuf, "("); char *pTmpCh = RTStrStr((char *)pBuf, ")"); /* check for the confirmation for the availability of parallel port */ if (!(pCh && pTmpCh)) { LogFlowFunc(("Parallel port Not Found. \n")); return VERR_NOT_FOUND; } if (((pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf)) < 0) { LogFlowFunc(("Parallel port string not properly formatted.\n")); return VERR_NOT_FOUND; } /* check for the confirmation for the availability of parallel port */ if (RTStrCopyEx((char *)(pThis->szParportName), sizeof(pThis->szParportName), pCh+1, ((pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf)) - 1)) { LogFlowFunc(("Parallel Port Not Found.\n")); return VERR_NOT_FOUND; } *((char *)pThis->szParportName + (pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf) + 1 ) = '\0'; /* checking again to make sure that we have got a valid name and in valid format too. */ if (RTStrNCmp((char *)pThis->szParportName, "LPT", 3)) { LogFlowFunc(("Parallel Port name \"LPT\" Not Found.\n")); return VERR_NOT_FOUND; } if (!RTStrStr((char *)pThis->szParportName, "LPT") || !(pThis->szParportName[3] >= '0' && pThis->szParportName[3] <= '9')) { RT_BZERO(pThis->szParportName, sizeof(pThis->szParportName)); LogFlowFunc(("Printer Port Name Not Found.\n")); return VERR_NOT_FOUND; } pThis->fParportAvail = true; pThis->u32LptAddr = u32ParportAddr; pThis->u32LptAddrControl = pThis->u32LptAddr + CTRL_REG_OFFSET; pThis->u32LptAddrStatus = pThis->u32LptAddr + STATUS_REG_OFFSET; } else LogFlowFunc(("u32Parport Addr No Available \n")); if (pThis->fParportAvail) break; } if (pBuf) RTMemFree(pBuf); if (pThis->fParportAvail) { /* Parallel port address has been found. No need to iterate further. */ break; } } if (GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS) rc = VERR_GENERAL_FAILURE; SetupDiDestroyDeviceInfoList(hDevInfo); return rc; }
bool operator==(const PCIDeviceRecord &a) const { return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0; }