/** * Strip trailing blanks (space & tab). * * @returns True if modified, false if not. * @param pIn The input stream. * @param pOut The output stream. * @param pSettings The settings. */ bool rewrite_StripTrailingBlanks(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings) { if (!pSettings->fStripTrailingBlanks) return false; bool fModified = false; SCMEOL enmEol; size_t cchLine; const char *pchLine; while ((pchLine = ScmStreamGetLine(pIn, &cchLine, &enmEol)) != NULL) { int rc; if ( cchLine == 0 || !RT_C_IS_BLANK(pchLine[cchLine - 1]) ) rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol); else { cchLine--; while (cchLine > 0 && RT_C_IS_BLANK(pchLine[cchLine - 1])) cchLine--; rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol); fModified = true; } if (RT_FAILURE(rc)) return false; } if (fModified) ScmVerbose(pState, 2, " * Stripped trailing blanks\n"); return fModified; }
/** * For converting the decomposition mappings field and similar. * * @returns Mapping array or NULL if none. * @param psz The string to convert. Can be empty. * @param pcEntries Where to store the number of entries. * @param cMax The max number of entries. */ static PRTUNICP ToMapping(char *psz, unsigned *pcEntries, unsigned cMax) { PRTUNICP paCps = NULL; unsigned cAlloc = 0; unsigned i = 0; /* Convert the code points. */ while (psz) { /* skip leading spaces */ while (RT_C_IS_BLANK(*psz)) psz++; /* the end? */ if (!*psz) break; /* room left? */ if (i >= cMax) { ParseError("Too many mappings.\n"); break; } if (i >= cAlloc) { cAlloc += 4; paCps = (PRTUNICP)realloc(paCps, cAlloc * sizeof(paCps[0])); if (!paCps) { fprintf(stderr, "out of memory (%u)\n", (unsigned)(cAlloc * sizeof(paCps[0]))); exit(1); } } /* Find the end. */ char *pszThis = psz; while (RT_C_IS_XDIGIT(*psz)) psz++; if (*psz && !RT_C_IS_BLANK(*psz)) ParseError("Malformed mappings.\n"); if (*psz) *psz++ = '\0'; /* Convert to number and add it. */ paCps[i++] = ToNum(pszThis); } *pcEntries = i; return paCps; }
static void test3(void) { RTTestISub("> 127"); for (int ch = 128; ch < 2000000; ch++) { RTTESTI_CHECK(!RT_C_IS_CNTRL(ch)); RTTESTI_CHECK(!RT_C_IS_SPACE(ch)); RTTESTI_CHECK(!RT_C_IS_BLANK(ch)); RTTESTI_CHECK(!RT_C_IS_PRINT(ch)); RTTESTI_CHECK(!RT_C_IS_PUNCT(ch)); RTTESTI_CHECK(!RT_C_IS_GRAPH(ch)); RTTESTI_CHECK(!RT_C_IS_DIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_XDIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ODIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ALPHA(ch)); RTTESTI_CHECK(!RT_C_IS_UPPER(ch)); RTTESTI_CHECK(!RT_C_IS_LOWER(ch)); } }
static void test2(void) { RTTestISub("< 0"); for (int ch = -1; ch > -2000000; ch--) { RTTESTI_CHECK(!RT_C_IS_CNTRL(ch)); RTTESTI_CHECK(!RT_C_IS_SPACE(ch)); RTTESTI_CHECK(!RT_C_IS_BLANK(ch)); RTTESTI_CHECK(!RT_C_IS_PRINT(ch)); RTTESTI_CHECK(!RT_C_IS_PUNCT(ch)); RTTESTI_CHECK(!RT_C_IS_GRAPH(ch)); RTTESTI_CHECK(!RT_C_IS_DIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_XDIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ODIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ALPHA(ch)); RTTESTI_CHECK(!RT_C_IS_UPPER(ch)); RTTESTI_CHECK(!RT_C_IS_LOWER(ch)); } }
/** * Searches for the file in the path. * * The file is first tested without any path modification, then we walk the path * looking in each directory. * * @returns VBox status code. * @param pszFilename The file to search for. * @param pszPath The search path. * @param pfnOpen The open callback function. * @param pvUser User argument for the callback. */ static int dbgfR3AsSearchPath(const char *pszFilename, const char *pszPath, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser) { char szFound[RTPATH_MAX]; /* Check the filename length. */ size_t const cchFilename = strlen(pszFilename); if (cchFilename >= sizeof(szFound)) return VERR_FILENAME_TOO_LONG; const char *pszName = RTPathFilename(pszFilename); if (!pszName) return VERR_IS_A_DIRECTORY; size_t const cchName = strlen(pszName); /* * Try default location first. */ memcpy(szFound, pszFilename, cchFilename + 1); int rc = pfnOpen(szFound, pvUser); if (RT_SUCCESS(rc)) return rc; /* * Walk the search path. */ const char *psz = pszPath; while (*psz) { /* Skip leading blanks - no directories with leading spaces, thank you. */ while (RT_C_IS_BLANK(*psz)) psz++; /* Find the end of this element. */ const char *pszNext; const char *pszEnd = strchr(psz, ';'); if (!pszEnd) pszEnd = pszNext = strchr(psz, '\0'); else pszNext = pszEnd + 1; if (pszEnd != psz) { size_t const cch = pszEnd - psz; if (cch + 1 + cchName < sizeof(szFound)) { /** @todo RTPathCompose, RTPathComposeN(). This code isn't right * for 'E:' on DOS systems. It may also create unwanted double slashes. */ memcpy(szFound, psz, cch); szFound[cch] = '/'; memcpy(szFound + cch + 1, pszName, cchName + 1); int rc2 = pfnOpen(szFound, pvUser); if (RT_SUCCESS(rc2)) return rc2; if ( rc2 != rc && ( rc == VERR_FILE_NOT_FOUND || rc == VERR_OPEN_FAILED)) rc = rc2; } } /* advance */ psz = pszNext; } /* * Walk the path once again, this time do a depth search. */ /** @todo do a depth search using the specified path. */ /* failed */ return rc; }
/** * Attempts to convert an ISO date string to a time structure. * * We're a little forgiving with zero padding, unspecified parts, and leading * and trailing spaces. * * @retval pTime on success, * @retval NULL on failure. * @param pTime Where to store the time on success. * @param pszString The ISO date string to convert. */ RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString) { /* Ignore leading spaces. */ while (RT_C_IS_SPACE(*pszString)) pszString++; /* * Init non date & time parts. */ pTime->fFlags = RTTIME_FLAGS_TYPE_LOCAL; pTime->offUTC = 0; /* * The day part. */ /* Year */ int rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->i32Year); if (rc != VWRN_TRAILING_CHARS) return NULL; bool const fLeapYear = rtTimeIsLeapYear(pTime->i32Year); if (fLeapYear) pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR; if (*pszString++ != '-') return NULL; /* Month of the year. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Month); if (rc != VWRN_TRAILING_CHARS) return NULL; if (pTime->u8Month == 0 || pTime->u8Month > 12) return NULL; if (*pszString++ != '-') return NULL; /* Day of month.*/ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8MonthDay); if (rc != VWRN_TRAILING_CHARS && rc != VINF_SUCCESS) return NULL; unsigned const cDaysInMonth = fLeapYear ? g_acDaysInMonthsLeap[pTime->u8Month - 1] : g_acDaysInMonths[pTime->u8Month - 1]; if (pTime->u8MonthDay == 0 || pTime->u8MonthDay > cDaysInMonth) return NULL; /* Calculate year day. */ pTime->u16YearDay = pTime->u8MonthDay - 1 + (fLeapYear ? g_aiDayOfYearLeap[pTime->u8Month - 1] : g_aiDayOfYear[pTime->u8Month - 1]); /* * The time part. */ if (*pszString++ != 'T') return NULL; /* Hour. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Hour); if (rc != VWRN_TRAILING_CHARS) return NULL; if (pTime->u8Hour > 23) return NULL; if (*pszString++ != ':') return NULL; /* Minute. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute); if (rc != VWRN_TRAILING_CHARS) return NULL; if (pTime->u8Minute > 59) return NULL; if (*pszString++ != ':') return NULL; /* Second. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES) return NULL; if (pTime->u8Second > 59) return NULL; /* Nanoseconds is optional and probably non-standard. */ if (*pszString == '.') { rc = RTStrToUInt32Ex(pszString + 1, (char **)&pszString, 10, &pTime->u32Nanosecond); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES) return NULL; if (pTime->u32Nanosecond >= 1000000000) return NULL; } else pTime->u32Nanosecond = 0; /* * Time zone. */ if (*pszString == 'Z') { pszString++; pTime->fFlags &= ~RTTIME_FLAGS_TYPE_MASK; pTime->fFlags |= ~RTTIME_FLAGS_TYPE_UTC; pTime->offUTC = 0; } else if ( *pszString == '+' || *pszString == '-') { rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->offUTC); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES) return NULL; } /* else: No time zone given, local with offUTC = 0. */ /* * The rest of the string should be blanks. */ char ch; while ((ch = *pszString++) != '\0') if (!RT_C_IS_BLANK(ch)) return NULL; return pTime; }
RTDECL(int) RTManifestReadStandardEx(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, char *pszErr, size_t cbErr) { /* * Validate input. */ AssertPtrNull(pszErr); if (pszErr && cbErr) *pszErr = '\0'; RTMANIFESTINT *pThis = hManifest; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE); /* * Process the stream line by line. */ uint32_t iLine = 0; for (;;) { /* * Read a line from the input stream. */ iLine++; char szLine[RTPATH_MAX + RTSHA512_DIGEST_LEN + 32]; int rc = rtManifestReadLine(hVfsIos, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) { if (rc == VERR_EOF) return VINF_SUCCESS; RTStrPrintf(pszErr, cbErr, "Error reading line #%u: %Rrc", iLine, rc); return rc; } if (rc != VINF_SUCCESS) { RTStrPrintf(pszErr, cbErr, "Line number %u is too long", iLine); return VERR_OUT_OF_RANGE; } /* * Strip it and skip if empty. */ char *psz = RTStrStrip(szLine); if (!*psz) continue; /* * Read the attribute name. */ const char * const pszAttr = psz; do psz++; while (!RT_C_IS_BLANK(*psz) && *psz); if (*psz) *psz++ = '\0'; /* * The entry name is enclosed in parenthesis and followed by a '='. */ psz = RTStrStripL(psz); if (*psz != '(') { RTStrPrintf(pszErr, cbErr, "Expected '(' after %zu on line %u", psz - szLine, iLine); return VERR_PARSE_ERROR; } const char * const pszName = ++psz; while (*psz) { if (*psz == ')') { char *psz2 = RTStrStripL(psz + 1); if (*psz2 == '=') { *psz = '\0'; psz = psz2; break; } } psz++; } if (*psz != '=') { RTStrPrintf(pszErr, cbErr, "Expected ')=' at %zu on line %u", psz - szLine, iLine); return VERR_PARSE_ERROR; } /* * The value. */ psz = RTStrStrip(psz + 1); const char * const pszValue = psz; if (!*psz) { RTStrPrintf(pszErr, cbErr, "Expected value at %zu on line %u", psz - szLine, iLine); return VERR_PARSE_ERROR; } /* * Detect attribute type and sanity check the value. */ uint32_t fType = RTMANIFEST_ATTR_UNKNOWN; static const struct { const char *pszAttr; uint32_t fType; unsigned cBits; unsigned uBase; } s_aDecAttrs[] = { { "SIZE", RTMANIFEST_ATTR_SIZE, 64, 10} }; for (unsigned i = 0; i < RT_ELEMENTS(s_aDecAttrs); i++) if (!strcmp(s_aDecAttrs[i].pszAttr, pszAttr)) { fType = s_aDecAttrs[i].fType; rc = RTStrToUInt64Full(pszValue, s_aDecAttrs[i].uBase, NULL); if (rc != VINF_SUCCESS) { RTStrPrintf(pszErr, cbErr, "Malformed value ('%s') at %zu on line %u: %Rrc", pszValue, psz - szLine, iLine, rc); return VERR_PARSE_ERROR; } break; } if (fType == RTMANIFEST_ATTR_UNKNOWN) { static const struct { const char *pszAttr; uint32_t fType; unsigned cchHex; } s_aHexAttrs[] = { { "MD5", RTMANIFEST_ATTR_MD5, RTMD5_DIGEST_LEN }, { "SHA1", RTMANIFEST_ATTR_SHA1, RTSHA1_DIGEST_LEN }, { "SHA256", RTMANIFEST_ATTR_SHA256, RTSHA256_DIGEST_LEN }, { "SHA512", RTMANIFEST_ATTR_SHA512, RTSHA512_DIGEST_LEN } }; for (unsigned i = 0; i < RT_ELEMENTS(s_aHexAttrs); i++) if (!strcmp(s_aHexAttrs[i].pszAttr, pszAttr)) { fType = s_aHexAttrs[i].fType; for (unsigned off = 0; off < s_aHexAttrs[i].cchHex; off++) if (!RT_C_IS_XDIGIT(pszValue[off])) { RTStrPrintf(pszErr, cbErr, "Expected hex digit at %zu on line %u (value '%s', pos %u)", pszValue - szLine + off, iLine, pszValue, off); return VERR_PARSE_ERROR; } break; } } /* * Finally, add it. */ rc = RTManifestEntrySetAttr(hManifest, pszName, pszAttr, pszValue, fType); if (RT_FAILURE(rc)) { RTStrPrintf(pszErr, cbErr, "RTManifestEntrySetAttr(,'%s','%s', '%s', %#x) failed on line %u: %Rrc", pszName, pszAttr, pszValue, fType, iLine, rc); return rc; } } }
/** * @callback_method_impl{dtrace_pops_t,dtps_provide} */ static void vboxDtPOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc) { PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv; AssertPtrReturnVoid(pProv); LOG_DTRACE(("%s: %p / %p pDtProbeDesc=%p\n", __FUNCTION__, pProv, pProv->TracerData.DTrace.idProvider, pDtProbeDesc)); if (pDtProbeDesc) return; /* We don't generate probes, so never mind these requests. */ if (pProv->TracerData.DTrace.fZombie) return; dtrace_provider_id_t const idProvider = pProv->TracerData.DTrace.idProvider; AssertPtrReturnVoid(idProvider); AssertPtrReturnVoid(pProv->pHdr); AssertReturnVoid(pProv->pHdr->offProbeLocs != 0); uint32_t const cProbeLocs = pProv->pHdr->cbProbeLocs / sizeof(VTGPROBELOC); /* Need a buffer for extracting the function names and mangling them in case of collision. */ size_t const cbFnNmBuf = _4K + _1K; char *pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf); if (!pszFnNmBuf) return; /* * Itereate the probe location list and register all probes related to * this provider. */ uint16_t const idxProv = (uint16_t)((PVTGDESCPROVIDER)((uintptr_t)pProv->pHdr + pProv->pHdr->offProviders) - pProv->pDesc); uint32_t idxProbeLoc; for (idxProbeLoc = 0; idxProbeLoc < cProbeLocs; idxProbeLoc++) { /* Skip probe location belonging to other providers or once that we've already reported. */ PCVTGPROBELOC pProbeLocRO = &pProv->paProbeLocsRO[idxProbeLoc]; PVTGDESCPROBE pProbeDesc = pProbeLocRO->pProbe; if (pProbeDesc->idxProvider != idxProv) continue; uint32_t *pidProbe; if (!pProv->fUmod) pidProbe = (uint32_t *)&pProbeLocRO->idProbe; else pidProbe = &pProv->paR0ProbeLocs[idxProbeLoc].idProbe; if (*pidProbe != 0) continue; /* The function name may need to be stripped since we're using C++ compilers for most of the code. ASSUMES nobody are brave/stupid enough to use function pointer returns without typedef'ing properly them (e.g. signal). */ const char *pszPrbName = vboxDtVtgGetString(pProv->pHdr, pProbeDesc->offName); const char *pszFunc = pProbeLocRO->pszFunction; const char *psz = strchr(pProbeLocRO->pszFunction, '('); size_t cch; if (psz) { /* skip blanks preceeding the parameter parenthesis. */ while ( (uintptr_t)psz > (uintptr_t)pProbeLocRO->pszFunction && RT_C_IS_BLANK(psz[-1])) psz--; /* Find the start of the function name. */ pszFunc = psz - 1; while ((uintptr_t)pszFunc > (uintptr_t)pProbeLocRO->pszFunction) { char ch = pszFunc[-1]; if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':') break; pszFunc--; } cch = psz - pszFunc; } else cch = strlen(pszFunc); RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch); /* Look up the probe, if we have one in the same function, mangle the function name a little to avoid having to deal with having multiple location entries with the same probe ID. (lazy bird) */ Assert(!*pidProbe); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) { RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u", pProbeLocRO->uLine); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) { unsigned iOrd = 2; while (iOrd < 128) { RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u", pProbeLocRO->uLine, iOrd); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE) break; iOrd++; } if (iOrd >= 128) { LogRel(("VBoxDrv: More than 128 duplicate probe location instances %s at line %u in function %s [%s], probe %s\n", pProbeLocRO->uLine, pProbeLocRO->pszFunction, pszFnNmBuf, pszPrbName)); continue; } } } /* Create the probe. */ AssertCompile(sizeof(*pidProbe) == sizeof(dtrace_id_t)); *pidProbe = dtrace_probe_create(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName, 1 /*aframes*/, (void *)(uintptr_t)idxProbeLoc); pProv->TracerData.DTrace.cProvidedProbes++; } RTMemFree(pszFnNmBuf); LOG_DTRACE(("%s: returns\n", __FUNCTION__)); }
/** * Looks for a PEM-like marker. * * @returns true if found, fasle if not. * @param pbContent Start of the content to search thru. * @param cbContent The size of the content to search. * @param offStart The offset into pbContent to start searching. * @param pszLeadWord The lead word (BEGIN/END). * @param cchLeadWord The length of the lead word. * @param paMarkers Pointer to an array of markers. * @param cMarkers Number of markers in the array. * @param ppMatch Where to return the pointer to the matching * marker. Optional. * @param poffBegin Where to return the start offset of the marker. * Optional. * @param poffEnd Where to return the end offset of the marker * (trailing whitespace and newlines will be * skipped). Optional. */ static bool rtCrPemFindMarker(uint8_t const *pbContent, size_t cbContent, size_t offStart, const char *pszLeadWord, size_t cchLeadWord, PCRTCRPEMMARKER paMarkers, size_t cMarkers, PCRTCRPEMMARKER *ppMatch, size_t *poffBegin, size_t *poffEnd) { /* Remember the start of the content for the purpose of calculating offsets. */ uint8_t const * const pbStart = pbContent; /* Skip adhead by offStart */ if (offStart >= cbContent) return false; pbContent += offStart; cbContent -= offStart; /* * Search the content. */ while (cbContent > 6) { /* * Look for dashes. */ uint8_t const *pbStartSearch = pbContent; pbContent = (uint8_t const *)memchr(pbContent, '-', cbContent); if (!pbContent) break; cbContent -= pbContent - pbStartSearch; if (cbContent < 6) break; /* * There must be at least three to interest us. */ if ( pbContent[1] == '-' && pbContent[2] == '-') { unsigned cDashes = 3; while (cDashes < cbContent && pbContent[cDashes] == '-') cDashes++; if (poffBegin) *poffBegin = pbContent - pbStart; cbContent -= cDashes; pbContent += cDashes; /* * Match lead word. */ if ( cbContent > cchLeadWord && memcmp(pbContent, pszLeadWord, cchLeadWord) == 0 && RT_C_IS_BLANK(pbContent[cchLeadWord]) ) { pbContent += cchLeadWord; cbContent -= cchLeadWord; while (cbContent > 0 && RT_C_IS_BLANK(*pbContent)) { pbContent++; cbContent--; } /* * Match one of the specified markers. */ uint8_t const *pbSavedContent = pbContent; size_t const cbSavedContent = cbContent; uint32_t iMarker = 0; while (iMarker < cMarkers) { pbContent = pbSavedContent; cbContent = cbSavedContent; uint32_t cWords = paMarkers[iMarker].cWords; PCRTCRPEMMARKERWORD pWord = paMarkers[iMarker].paWords; while (cWords > 0) { uint32_t const cchWord = pWord->cchWord; if (cbContent <= cchWord) break; if (memcmp(pbContent, pWord->pszWord, cchWord)) break; pbContent += cchWord; cbContent -= cchWord; if (!cbContent || !RT_C_IS_BLANK(*pbContent)) break; do { pbContent++; cbContent--; } while (cbContent > 0 && RT_C_IS_BLANK(*pbContent)); cWords--; if (cWords == 0) { /* * If there are three or more dashes following now, we've got a hit. */ if ( cbContent > 3 && pbContent[0] == '-' && pbContent[1] == '-' && pbContent[2] == '-') { cDashes = 3; while (cDashes < cbContent && pbContent[cDashes] == '-') cDashes++; cbContent -= cDashes; pbContent += cDashes; /* * Skip spaces and newline. */ while (cbContent > 0 && RT_C_IS_SPACE(*pbContent)) pbContent++, cbContent--; if (poffEnd) *poffEnd = pbContent - pbStart; if (*ppMatch) *ppMatch = &paMarkers[iMarker]; return true; } break; } } /* for each word in marker. */ } /* for each marker. */ } } else { pbContent++; cbContent--; } } return false; }
/** * Get the next token from the config stream and create a token structure. * * @returns VBox status code. * @param pCfgTokenizer The config tokenizer data. * @param pCfgTokenUse Allocated token structure to use or NULL to allocate * a new one. It will bee freed if an error is encountered. * @param ppCfgToken Where to store the pointer to the next token on success. */ static int autostartConfigTokenizerCreateToken(PCFGTOKENIZER pCfgTokenizer, PCFGTOKEN pCfgTokenUse, PCFGTOKEN *ppCfgToken) { const char *pszToken = NULL; size_t cchToken = 1; size_t cchAdvance = 0; CFGTOKENTYPE enmType = CFGTOKENTYPE_INVALID; int rc = VINF_SUCCESS; for (;;) { pszToken = pCfgTokenizer->pszLineCurr; /* Skip all spaces. */ while (RT_C_IS_BLANK(*pszToken)) { pszToken++; cchAdvance++; } /* Check if we have to read a new line. */ if ( *pszToken == '\0' || *pszToken == '#') { rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer); if (rc == VERR_EOF) { enmType = CFGTOKENTYPE_EOF; rc = VINF_SUCCESS; break; } else if (RT_FAILURE(rc)) break; /* start from the beginning. */ cchAdvance = 0; } else if (*pszToken == '=') { enmType = CFGTOKENTYPE_EQUAL; break; } else if (*pszToken == ',') { enmType = CFGTOKENTYPE_COMMA; break; } else if (*pszToken == '{') { enmType = CFGTOKENTYPE_CURLY_OPEN; break; } else if (*pszToken == '}') { enmType = CFGTOKENTYPE_CURLY_CLOSING; break; } else { const char *pszTmp = pszToken; cchToken = 0; enmType = CFGTOKENTYPE_ID; /* Get the complete token. */ while ( RT_C_IS_ALNUM(*pszTmp) || *pszTmp == '_' || *pszTmp == '.') { pszTmp++; cchToken++; } break; } } Assert(RT_FAILURE(rc) || enmType != CFGTOKENTYPE_INVALID); if (RT_SUCCESS(rc)) { /* Free the given token if it is an ID or the current one is an ID token. */ if ( pCfgTokenUse && ( pCfgTokenUse->enmType == CFGTOKENTYPE_ID || enmType == CFGTOKENTYPE_ID)) { autostartConfigTokenFree(pCfgTokenizer, pCfgTokenUse); pCfgTokenUse = NULL; } if (!pCfgTokenUse) { size_t cbToken = sizeof(CFGTOKEN); if (enmType == CFGTOKENTYPE_ID) cbToken += (cchToken + 1) * sizeof(char); pCfgTokenUse = (PCFGTOKEN)RTMemAllocZ(cbToken); if (!pCfgTokenUse) rc = VERR_NO_MEMORY; } if (RT_SUCCESS(rc)) { /* Copy token data. */ pCfgTokenUse->enmType = enmType; pCfgTokenUse->cchStart = pCfgTokenizer->cchCurr; pCfgTokenUse->iLine = pCfgTokenizer->iLine; if (enmType == CFGTOKENTYPE_ID) { pCfgTokenUse->u.Id.cchToken = cchToken; memcpy(pCfgTokenUse->u.Id.achToken, pszToken, cchToken); } } else if (pCfgTokenUse) autostartConfigTokenFree(pCfgTokenizer, pCfgTokenUse); if (RT_SUCCESS(rc)) { /* Set new position in config stream. */ pCfgTokenizer->pszLineCurr += cchToken + cchAdvance; pCfgTokenizer->cchCurr += cchToken + cchAdvance; *ppCfgToken = pCfgTokenUse; } } return rc; }
/** * Tries to open the file using the image search paths. * * This is currently a quick hack and the only way to specifying the path is by setting * VBOXDBG_IMAGE_PATH in the environment. It uses semicolon as separator everywhere. * * @returns VBox status code. * @param pVM The VM handle. * @param pszFilename The name of the file to locate and open. * @param pszFound Where to return the actual filename. * @param cchFound The buffer size. * @param ppFile Where to return the opened file. */ int dbgfR3ModuleLocateAndOpen(PVM pVM, const char *pszFilename, char *pszFound, size_t cchFound, FILE **ppFile) { /* Check the filename length. */ size_t const cchFilename = strlen(pszFilename); if (cchFilename >= cchFound) return VERR_FILENAME_TOO_LONG; const char *pszName = RTPathFilename(pszFilename); if (!pszName) return VERR_IS_A_DIRECTORY; size_t const cchName = strlen(pszName); /* * Try default location first. */ memcpy(pszFound, pszFilename, cchFilename + 1); FILE *pFile = *ppFile = fopen(pszFound, "rb"); if (pFile) return VINF_SUCCESS; /* * Walk the search path. */ char *pszFreeMe = RTEnvDupEx(RTENV_DEFAULT, "VBOXDBG_IMAGE_PATH"); const char *psz = pszFreeMe ? pszFreeMe : "."; while (*psz) { /* Skip leading blanks - no directories with leading spaces, thank you. */ while (RT_C_IS_BLANK(*psz)) psz++; /* Fine the end of this element. */ const char *pszNext; const char *pszEnd = strchr(psz, ';'); if (!pszEnd) pszEnd = pszNext = strchr(psz, '\0'); else pszNext = pszEnd + 1; if (pszEnd != psz) { size_t const cch = pszEnd - psz; if (cch + 1 + cchName < cchFound) { /** @todo RTPathCompose, RTPathComposeN(). This code isn't right * for 'E:' on DOS systems. It may also create unwanted double slashes. */ memcpy(pszFound, psz, cch); pszFound[cch] = '/'; memcpy(pszFound + cch + 1, pszName, cchName + 1); *ppFile = pFile = fopen(pszFound, "rb"); if (pFile) { RTStrFree(pszFreeMe); return VINF_SUCCESS; } } /** @todo do a depth search using the specified path. */ } /* advance */ psz = pszNext; } /* not found */ RTStrFree(pszFreeMe); return VERR_OPEN_FAILED; }