Changeset 36635 in vbox
- Timestamp:
- Apr 8, 2011 11:25:37 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 71099
- Location:
- trunk/src/VBox/Storage/testcase
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/testcase/VDMemDisk.cpp
r36134 r36635 250 250 if (pSeg) 251 251 { 252 RTAvlrU64Remove(pMemDisk->pTreeSegments, pSeg->Core.Key); 252 253 if (pSeg->Core.Key < cbSize) 253 254 { 254 255 /* Cut off the part which is not in the file anymore. */ 255 256 pSeg->pvSeg = RTMemRealloc(pSeg->pvSeg, pSeg->Core.KeyLast - cbSize + 1); 257 pSeg->Core.KeyLast = cbSize - pSeg->Core.Key - 1; 258 259 bool fInserted = RTAvlrU64Insert(pMemDisk->pTreeSegments, &pSeg->Core); 260 AssertMsg(fInserted, ("Bug!\n")); 256 261 } 257 262 else -
trunk/src/VBox/Storage/testcase/tstVDIo.cpp
r36634 r36635 87 87 88 88 /** 89 * A data buffer with a pattern. 90 */ 91 typedef struct VDPATTERN 92 { 93 /** List node. */ 94 RTLISTNODE ListNode; 95 /** Name of the pattern. */ 96 char *pszName; 97 /** Size of the pattern. */ 98 size_t cbPattern; 99 /** Pointer to the buffer containing the pattern. */ 100 void *pvPattern; 101 } VDPATTERN, *PVDPATTERN; 102 103 /** 89 104 * Global VD test state. 90 105 */ … … 95 110 /** Head of the active file list. */ 96 111 RTLISTNODE ListFiles; 112 /** Head of the pattern list. */ 113 RTLISTNODE ListPatterns; 97 114 /** Memory I/O backend. */ 98 115 PVDIOBACKENDMEM pIoBackend; … … 167 184 /** Pointer to the I/O data generator. */ 168 185 PVDIORND pIoRnd; 186 /** Pointer to the data pattern to use. */ 187 PVDPATTERN pPattern; 169 188 /** Data dependent on the I/O mode (sequential or random). */ 170 189 union … … 284 303 static DECLCALLBACK(int) vdScriptHandlerIoRngCreate(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); 285 304 static DECLCALLBACK(int) vdScriptHandlerIoRngDestroy(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); 305 static DECLCALLBACK(int) vdScriptHandlerIoPatternCreateFromNumber(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); 306 static DECLCALLBACK(int) vdScriptHandlerIoPatternCreateFromFile(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); 307 static DECLCALLBACK(int) vdScriptHandlerIoPatternDestroy(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); 286 308 static DECLCALLBACK(int) vdScriptHandlerSleep(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); 287 309 static DECLCALLBACK(int) vdScriptHandlerDumpFile(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs); … … 326 348 {"blocksize", 'b', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY | VDSCRIPTARGDESC_FLAG_SIZE_SUFFIX}, 327 349 {"off", 'o', VDSCRIPTARGTYPE_UNSIGNED_RANGE, VDSCRIPTARGDESC_FLAG_SIZE_SUFFIX}, 328 {"writes", 'w', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY} 350 {"writes", 'w', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY}, 351 {"pattern", 'p', VDSCRIPTARGTYPE_STRING, 0}, 329 352 }; 330 353 … … 372 395 }; 373 396 397 /* I/O pattern create action */ 398 const VDSCRIPTARGDESC g_aArgIoPatternCreateFromNumber[] = 399 { 400 /* pcszName chId enmType fFlags */ 401 {"name", 'n', VDSCRIPTARGTYPE_STRING, VDSCRIPTARGDESC_FLAG_MANDATORY}, 402 {"size", 's', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY | VDSCRIPTARGDESC_FLAG_SIZE_SUFFIX}, 403 {"pattern", 'p', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY}, 404 }; 405 406 /* I/O pattern create action */ 407 const VDSCRIPTARGDESC g_aArgIoPatternCreateFromFile[] = 408 { 409 /* pcszName chId enmType fFlags */ 410 {"name", 'n', VDSCRIPTARGTYPE_STRING, VDSCRIPTARGDESC_FLAG_MANDATORY}, 411 {"file", 'f', VDSCRIPTARGTYPE_STRING, VDSCRIPTARGDESC_FLAG_MANDATORY}, 412 }; 413 414 /* I/O pattern destroy action */ 415 const VDSCRIPTARGDESC g_aArgIoPatternDestroy[] = 416 { 417 /* pcszName chId enmType fFlags */ 418 {"name", 'n', VDSCRIPTARGTYPE_STRING, VDSCRIPTARGDESC_FLAG_MANDATORY} 419 }; 420 374 421 /* Sleep */ 375 422 const VDSCRIPTARGDESC g_aArgSleep[] = … … 426 473 const VDSCRIPTACTION g_aScriptActions[] = 427 474 { 428 /* pcszAction paArgDesc cArgDescs pfnHandler */ 429 {"create", g_aArgCreate, RT_ELEMENTS(g_aArgCreate), vdScriptHandlerCreate}, 430 {"open", g_aArgOpen, RT_ELEMENTS(g_aArgOpen), vdScriptHandlerOpen}, 431 {"io", g_aArgIo, RT_ELEMENTS(g_aArgIo), vdScriptHandlerIo}, 432 {"flush", g_aArgFlush, RT_ELEMENTS(g_aArgFlush), vdScriptHandlerFlush}, 433 {"close", g_aArgClose, RT_ELEMENTS(g_aArgClose), vdScriptHandlerClose}, 434 {"merge", g_aArgMerge, RT_ELEMENTS(g_aArgMerge), vdScriptHandlerMerge}, 435 {"compact", g_aArgCompact, RT_ELEMENTS(g_aArgCompact), vdScriptHandlerCompact}, 436 {"iorngcreate", g_aArgIoRngCreate, RT_ELEMENTS(g_aArgIoRngCreate), vdScriptHandlerIoRngCreate}, 437 {"iorngdestroy", NULL, 0, vdScriptHandlerIoRngDestroy}, 438 {"sleep", g_aArgSleep, RT_ELEMENTS(g_aArgSleep), vdScriptHandlerSleep}, 439 {"dumpfile", g_aArgDumpFile, RT_ELEMENTS(g_aArgDumpFile), vdScriptHandlerDumpFile}, 440 {"createdisk", g_aArgCreateDisk, RT_ELEMENTS(g_aArgCreateDisk), vdScriptHandlerCreateDisk}, 441 {"destroydisk", g_aArgDestroyDisk, RT_ELEMENTS(g_aArgDestroyDisk), vdScriptHandlerDestroyDisk}, 442 {"comparedisks", g_aArgCompareDisks, RT_ELEMENTS(g_aArgCompareDisks), vdScriptHandlerCompareDisks}, 443 {"dumpdiskinfo", g_aArgDumpDiskInfo, RT_ELEMENTS(g_aArgDumpDiskInfo), vdScriptHandlerDumpDiskInfo}, 444 {"print", g_aArgPrintMsg, RT_ELEMENTS(g_aArgPrintMsg), vdScriptHandlerPrintMsg} 475 /* pcszAction paArgDesc cArgDescs pfnHandler */ 476 {"create", g_aArgCreate, RT_ELEMENTS(g_aArgCreate), vdScriptHandlerCreate}, 477 {"open", g_aArgOpen, RT_ELEMENTS(g_aArgOpen), vdScriptHandlerOpen}, 478 {"io", g_aArgIo, RT_ELEMENTS(g_aArgIo), vdScriptHandlerIo}, 479 {"flush", g_aArgFlush, RT_ELEMENTS(g_aArgFlush), vdScriptHandlerFlush}, 480 {"close", g_aArgClose, RT_ELEMENTS(g_aArgClose), vdScriptHandlerClose}, 481 {"merge", g_aArgMerge, RT_ELEMENTS(g_aArgMerge), vdScriptHandlerMerge}, 482 {"compact", g_aArgCompact, RT_ELEMENTS(g_aArgCompact), vdScriptHandlerCompact}, 483 {"iorngcreate", g_aArgIoRngCreate, RT_ELEMENTS(g_aArgIoRngCreate), vdScriptHandlerIoRngCreate}, 484 {"iorngdestroy", NULL, 0, vdScriptHandlerIoRngDestroy}, 485 {"iopatterncreatefromnumber", g_aArgIoPatternCreateFromNumber, RT_ELEMENTS(g_aArgIoPatternCreateFromNumber), vdScriptHandlerIoPatternCreateFromNumber}, 486 {"iopatterncreatefromfile", g_aArgIoPatternCreateFromFile, RT_ELEMENTS(g_aArgIoPatternCreateFromFile), vdScriptHandlerIoPatternCreateFromFile}, 487 {"iopatterndestroy", g_aArgIoPatternDestroy, RT_ELEMENTS(g_aArgIoPatternDestroy), vdScriptHandlerIoPatternDestroy}, 488 {"sleep", g_aArgSleep, RT_ELEMENTS(g_aArgSleep), vdScriptHandlerSleep}, 489 {"dumpfile", g_aArgDumpFile, RT_ELEMENTS(g_aArgDumpFile), vdScriptHandlerDumpFile}, 490 {"createdisk", g_aArgCreateDisk, RT_ELEMENTS(g_aArgCreateDisk), vdScriptHandlerCreateDisk}, 491 {"destroydisk", g_aArgDestroyDisk, RT_ELEMENTS(g_aArgDestroyDisk), vdScriptHandlerDestroyDisk}, 492 {"comparedisks", g_aArgCompareDisks, RT_ELEMENTS(g_aArgCompareDisks), vdScriptHandlerCompareDisks}, 493 {"dumpdiskinfo", g_aArgDumpDiskInfo, RT_ELEMENTS(g_aArgDumpDiskInfo), vdScriptHandlerDumpDiskInfo}, 494 {"print", g_aArgPrintMsg, RT_ELEMENTS(g_aArgPrintMsg), vdScriptHandlerPrintMsg} 445 495 }; 446 496 … … 464 514 static int tstVDIoTestInit(PVDIOTEST pIoTest, PVDTESTGLOB pGlob, bool fRandomAcc, uint64_t cbIo, 465 515 size_t cbBlkSize, uint64_t offStart, uint64_t offEnd, 466 unsigned uWriteChance );516 unsigned uWriteChance, PVDPATTERN pPattern); 467 517 static bool tstVDIoTestRunning(PVDIOTEST pIoTest); 468 518 static void tstVDIoTestDestroy(PVDIOTEST pIoTest); … … 472 522 473 523 static PVDDISK tstVDIoGetDiskByName(PVDTESTGLOB pGlob, const char *pcszDisk); 524 static PVDPATTERN tstVDIoGetPatternByName(PVDTESTGLOB pGlob, const char *pcszName); 525 static PVDPATTERN tstVDIoPatternCreate(const char *pcszName, size_t cbPattern); 526 static int tstVDIoPatternGetBuffer(PVDPATTERN pPattern, void **ppv, size_t cb); 474 527 475 528 static DECLCALLBACK(int) vdScriptHandlerCreate(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs) … … 649 702 uint8_t uWriteChance = 0; 650 703 const char *pcszDisk = NULL; 704 const char *pcszPattern = NULL; 651 705 PVDDISK pDisk = NULL; 706 PVDPATTERN pPattern = NULL; 652 707 653 708 for (unsigned i = 0; i < cScriptArgs; i++) … … 704 759 break; 705 760 } 761 case 'p': 762 { 763 pcszPattern = paScriptArgs[i].u.pcszString; 764 break; 765 } 706 766 default: 707 767 AssertMsgFailed(("Invalid argument given!\n")); … … 733 793 } 734 794 795 if ( RT_SUCCESS(rc) 796 && pcszPattern) 797 { 798 pPattern = tstVDIoGetPatternByName(pGlob, pcszPattern); 799 if (!pPattern) 800 rc = VERR_NOT_FOUND; 801 } 802 735 803 if (RT_SUCCESS(rc)) 736 804 { 737 805 VDIOTEST IoTest; 738 806 739 rc = tstVDIoTestInit(&IoTest, pGlob, fRandomAcc, cbIo, cbBlkSize, offStart, offEnd, uWriteChance );807 rc = tstVDIoTestInit(&IoTest, pGlob, fRandomAcc, cbIo, cbBlkSize, offStart, offEnd, uWriteChance, pPattern); 740 808 if (RT_SUCCESS(rc)) 741 809 { … … 820 888 } 821 889 } 890 891 ASMAtomicXchgBool(&paIoReq[idx].fOutstanding, false); 822 892 if (RT_SUCCESS(rc)) 823 893 idx++; … … 1247 1317 } 1248 1318 1319 static DECLCALLBACK(int) vdScriptHandlerIoPatternCreateFromNumber(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs) 1320 { 1321 int rc = VINF_SUCCESS; 1322 size_t cbPattern = 0; 1323 const char *pcszName = NULL; 1324 uint64_t u64Pattern = 0; 1325 1326 for (unsigned i = 0; i < cScriptArgs; i++) 1327 { 1328 switch (paScriptArgs[i].chId) 1329 { 1330 case 'n': 1331 { 1332 pcszName = paScriptArgs[i].u.pcszString; 1333 break; 1334 } 1335 case 's': 1336 { 1337 cbPattern = paScriptArgs[i].u.u64; 1338 break; 1339 } 1340 case 'p': 1341 { 1342 u64Pattern = paScriptArgs[i].u.u64; 1343 break; 1344 } 1345 default: 1346 AssertMsgFailed(("Invalid argument given!\n")); 1347 } 1348 } 1349 1350 PVDPATTERN pPattern = tstVDIoGetPatternByName(pGlob, pcszName); 1351 if (!pPattern) 1352 { 1353 pPattern = tstVDIoPatternCreate(pcszName, RT_ALIGN_Z(cbPattern, sizeof(uint64_t))); 1354 if (pPattern) 1355 { 1356 /* Fill the buffer. */ 1357 void *pv = pPattern->pvPattern; 1358 1359 while (pPattern->cbPattern > 0) 1360 { 1361 *((uint64_t*)pv) = u64Pattern; 1362 pPattern->cbPattern -= sizeof(uint64_t); 1363 pv = (uint64_t *)pv + sizeof(uint64_t); 1364 } 1365 pPattern->cbPattern = cbPattern; /* Set to the desired size. (could be unaligned) */ 1366 1367 RTListAppend(&pGlob->ListPatterns, &pPattern->ListNode); 1368 } 1369 else 1370 rc = VERR_NO_MEMORY; 1371 } 1372 else 1373 rc = VERR_ALREADY_EXISTS; 1374 1375 return rc; 1376 } 1377 1378 static DECLCALLBACK(int) vdScriptHandlerIoPatternCreateFromFile(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs) 1379 { 1380 int rc = VINF_SUCCESS; 1381 const char *pcszName = NULL; 1382 const char *pcszFile = NULL; 1383 1384 for (unsigned i = 0; i < cScriptArgs; i++) 1385 { 1386 switch (paScriptArgs[i].chId) 1387 { 1388 case 'n': 1389 { 1390 pcszName = paScriptArgs[i].u.pcszString; 1391 break; 1392 } 1393 case 'f': 1394 { 1395 pcszFile = paScriptArgs[i].u.pcszString; 1396 break; 1397 } 1398 default: 1399 AssertMsgFailed(("Invalid argument given!\n")); 1400 } 1401 } 1402 1403 PVDPATTERN pPattern = tstVDIoGetPatternByName(pGlob, pcszName); 1404 if (!pPattern) 1405 { 1406 RTFILE hFile; 1407 uint64_t cbPattern = 0; 1408 1409 rc = RTFileOpen(&hFile, pcszFile, RTFILE_O_DENY_NONE | RTFILE_O_OPEN | RTFILE_O_READ); 1410 if (RT_SUCCESS(rc)) 1411 { 1412 rc = RTFileGetSize(hFile, &cbPattern); 1413 if (RT_SUCCESS(rc)) 1414 { 1415 pPattern = tstVDIoPatternCreate(pcszName, (size_t)cbPattern); 1416 if (pPattern) 1417 { 1418 rc = RTFileRead(hFile, pPattern->pvPattern, (size_t)cbPattern, NULL); 1419 if (RT_SUCCESS(rc)) 1420 RTListAppend(&pGlob->ListPatterns, &pPattern->ListNode); 1421 else 1422 { 1423 RTMemFree(pPattern->pvPattern); 1424 RTStrFree(pPattern->pszName); 1425 RTMemFree(pPattern); 1426 } 1427 } 1428 else 1429 rc = VERR_NO_MEMORY; 1430 } 1431 RTFileClose(hFile); 1432 } 1433 } 1434 else 1435 rc = VERR_ALREADY_EXISTS; 1436 1437 return rc; 1438 } 1439 1440 static DECLCALLBACK(int) vdScriptHandlerIoPatternDestroy(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs) 1441 { 1442 int rc = VINF_SUCCESS; 1443 const char *pcszName = NULL; 1444 1445 for (unsigned i = 0; i < cScriptArgs; i++) 1446 { 1447 switch (paScriptArgs[i].chId) 1448 { 1449 case 'n': 1450 { 1451 pcszName = paScriptArgs[i].u.pcszString; 1452 break; 1453 } 1454 default: 1455 AssertMsgFailed(("Invalid argument given!\n")); 1456 } 1457 } 1458 1459 PVDPATTERN pPattern = tstVDIoGetPatternByName(pGlob, pcszName); 1460 if (pPattern) 1461 { 1462 RTListNodeRemove(&pPattern->ListNode); 1463 RTMemFree(pPattern->pvPattern); 1464 RTStrFree(pPattern->pszName); 1465 RTMemFree(pPattern); 1466 } 1467 else 1468 rc = VERR_NOT_FOUND; 1469 1470 return rc; 1471 } 1472 1249 1473 static DECLCALLBACK(int) vdScriptHandlerSleep(PVDTESTGLOB pGlob, PVDSCRIPTARG paScriptArgs, unsigned cScriptArgs) 1250 1474 { … … 1856 2080 static int tstVDIoTestInit(PVDIOTEST pIoTest, PVDTESTGLOB pGlob, bool fRandomAcc, uint64_t cbIo, 1857 2081 size_t cbBlkSize, uint64_t offStart, uint64_t offEnd, 1858 unsigned uWriteChance )2082 unsigned uWriteChance, PVDPATTERN pPattern) 1859 2083 { 1860 2084 int rc = VINF_SUCCESS; … … 1867 2091 pIoTest->uWriteChance = uWriteChance; 1868 2092 pIoTest->pIoRnd = pGlob->pIoRnd; 2093 pIoTest->pPattern = pPattern; 1869 2094 1870 2095 if (fRandomAcc) … … 1915 2140 int uRnd = VDIoRndGetU32Ex(pIoTest->pIoRnd, 0, 100); 1916 2141 1917 return (uRnd < =iPercentage); /* This should be enough for our purpose */2142 return (uRnd < iPercentage); /* This should be enough for our purpose */ 1918 2143 } 1919 2144 … … 1932 2157 if (pIoReq->enmTxDir == VDIOREQTXDIR_WRITE) 1933 2158 { 1934 rc = VDIoRndGetBuffer(pIoTest->pIoRnd, &pIoReq->DataSeg.pvSeg, pIoReq->cbReq); 2159 if (pIoTest->pPattern) 2160 rc = tstVDIoPatternGetBuffer(pIoTest->pPattern, &pIoReq->DataSeg.pvSeg, pIoReq->cbReq); 2161 else 2162 rc = VDIoRndGetBuffer(pIoTest->pIoRnd, &pIoReq->DataSeg.pvSeg, pIoReq->cbReq); 1935 2163 AssertRC(rc); 1936 2164 } … … 2076 2304 LogFlowFunc(("return %#p\n", fFound ? pIt : NULL)); 2077 2305 return fFound ? pIt : NULL; 2306 } 2307 2308 /** 2309 * Returns the I/O pattern handle by name of NULL if not found. 2310 * 2311 * @returns I/O pattern handle or NULL if the pattern could not be found. 2312 * 2313 * @param pGlob Global test state. 2314 * @param pcszName Name of the pattern. 2315 */ 2316 static PVDPATTERN tstVDIoGetPatternByName(PVDTESTGLOB pGlob, const char *pcszName) 2317 { 2318 PVDPATTERN pIt = NULL; 2319 bool fFound = false; 2320 2321 LogFlowFunc(("pGlob=%#p pcszName=%s\n", pGlob, pcszName)); 2322 2323 RTListForEach(&pGlob->ListPatterns, pIt, VDPATTERN, ListNode) 2324 { 2325 if (!RTStrCmp(pIt->pszName, pcszName)) 2326 { 2327 fFound = true; 2328 break; 2329 } 2330 } 2331 2332 LogFlowFunc(("return %#p\n", fFound ? pIt : NULL)); 2333 return fFound ? pIt : NULL; 2334 } 2335 2336 /** 2337 * Creates a new pattern with the given name and an 2338 * allocated pattern buffer. 2339 * 2340 * @returns Pointer to a new pattern buffer or NULL on failure. 2341 * @param pcszName Name of the pattern. 2342 * @param cbPattern Size of the pattern buffer. 2343 */ 2344 static PVDPATTERN tstVDIoPatternCreate(const char *pcszName, size_t cbPattern) 2345 { 2346 PVDPATTERN pPattern = (PVDPATTERN)RTMemAllocZ(sizeof(VDPATTERN)); 2347 char *pszName = RTStrDup(pcszName); 2348 void *pvPattern = RTMemAllocZ(cbPattern); 2349 2350 if (pPattern && pszName && pvPattern) 2351 { 2352 pPattern->pszName = pszName; 2353 pPattern->pvPattern = pvPattern; 2354 pPattern->cbPattern = cbPattern; 2355 } 2356 else 2357 { 2358 if (pPattern) 2359 RTMemFree(pPattern); 2360 if (pszName) 2361 RTStrFree(pszName); 2362 if (pvPattern) 2363 RTMemFree(pvPattern); 2364 2365 pPattern = NULL; 2366 pszName = NULL; 2367 pvPattern = NULL; 2368 } 2369 2370 return pPattern; 2371 } 2372 2373 static int tstVDIoPatternGetBuffer(PVDPATTERN pPattern, void **ppv, size_t cb) 2374 { 2375 AssertPtrReturn(pPattern, VERR_INVALID_POINTER); 2376 AssertPtrReturn(ppv, VERR_INVALID_POINTER); 2377 AssertReturn(cb > 0, VERR_INVALID_PARAMETER); 2378 2379 if (cb > pPattern->cbPattern) 2380 return VERR_INVALID_PARAMETER; 2381 2382 *ppv = pPattern->pvPattern; 2383 return VINF_SUCCESS; 2078 2384 } 2079 2385 … … 2541 2847 RTListInit(&GlobTest.ListFiles); 2542 2848 RTListInit(&GlobTest.ListDisks); 2849 RTListInit(&GlobTest.ListPatterns); 2543 2850 2544 2851 rc = RTStrmOpen(pcszFilename, "r", &pScriptStrm);
Note:
See TracChangeset
for help on using the changeset viewer.