Changeset 66594 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Apr 17, 2017 3:29:05 PM (8 years ago)
- Location:
- trunk/src/VBox/Runtime/common
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/message.cpp
r62477 r66594 138 138 return enmExitCode; 139 139 } 140 RT_EXPORT_SYMBOL(RTMsgErrorExit); 141 142 143 RTDECL(RTEXITCODE) RTMsgErrorExitV(RTEXITCODE enmExitCode, const char *pszFormat, va_list va) 144 { 145 RTMsgErrorV(pszFormat, va); 146 return enmExitCode; 147 } 140 148 RT_EXPORT_SYMBOL(RTMsgErrorExitV); 141 149 142 150 143 RTDECL(RTEXITCODE) RTMsgErrorExitV(RTEXITCODE enmExitCode, const char *pszFormat, va_list va) 144 { 145 RTMsgErrorV(pszFormat, va); 146 return enmExitCode; 147 } 148 RT_EXPORT_SYMBOL(RTMsgErrorExitV); 151 RTDECL(RTEXITCODE) RTMsgErrorExitFailure(const char *pszFormat, ...) 152 { 153 va_list va; 154 va_start(va, pszFormat); 155 RTMsgErrorV(pszFormat, va); 156 va_end(va); 157 return RTEXITCODE_FAILURE; 158 } 159 RT_EXPORT_SYMBOL(RTMsgErrorExitFailure); 160 161 162 RTDECL(RTEXITCODE) RTMsgErrorExitFailureV(const char *pszFormat, va_list va) 163 { 164 RTMsgErrorV(pszFormat, va); 165 return RTEXITCODE_FAILURE; 166 } 167 RT_EXPORT_SYMBOL(RTMsgErrorExitFailureV); 149 168 150 169 -
trunk/src/VBox/Runtime/common/vfs/vfschain.cpp
r62477 r66594 53 53 *********************************************************************************************************************************/ 54 54 /** Init the critical section once. */ 55 static RTONCE g_rtVfsChainElementInitOnce ;55 static RTONCE g_rtVfsChainElementInitOnce = RTONCE_INITIALIZER; 56 56 /** Critical section protecting g_rtVfsChainElementProviderList. */ 57 static RTCRITSECT 57 static RTCRITSECTRW g_rtVfsChainElementCritSect; 58 58 /** List of VFS chain element providers (RTVFSCHAINELEMENTREG). */ 59 59 static RTLISTANCHOR g_rtVfsChainElementProviderList; 60 60 61 61 62 63 62 64 /** 63 65 * Initializes the globals via RTOnce. … … 69 71 { 70 72 NOREF(pvUser); 71 return RTCritSectInit(&g_rtVfsChainElementCritSect); 73 if (!g_rtVfsChainElementProviderList.pNext) 74 RTListInit(&g_rtVfsChainElementProviderList); 75 int rc = RTCritSectRwInit(&g_rtVfsChainElementCritSect); 76 if (RT_SUCCESS(rc)) 77 { 78 } 79 return rc; 72 80 } 73 81 … … 84 92 AssertMsgReturn(pRegRec->uEndMarker == RTVFSCHAINELEMENTREG_VERSION, ("%#zx", pRegRec->uEndMarker), VERR_INVALID_POINTER); 85 93 AssertReturn(pRegRec->fReserved == 0, VERR_INVALID_POINTER); 86 AssertPtrReturn(pRegRec->pszName, VERR_INVALID_POINTER); 87 AssertPtrNullReturn(pRegRec->pfnOpenVfs, VERR_INVALID_POINTER); 88 AssertPtrNullReturn(pRegRec->pfnOpenDir, VERR_INVALID_POINTER); 89 AssertPtrNullReturn(pRegRec->pfnOpenFile, VERR_INVALID_POINTER); 90 AssertPtrNullReturn(pRegRec->pfnOpenIoStream, VERR_INVALID_POINTER); 91 AssertPtrNullReturn(pRegRec->pfnOpenFsStream, VERR_INVALID_POINTER); 94 AssertPtrReturn(pRegRec->pszName, VERR_INVALID_POINTER); 95 AssertPtrReturn(pRegRec->pfnValidate, VERR_INVALID_POINTER); 96 AssertPtrReturn(pRegRec->pfnInstantiate, VERR_INVALID_POINTER); 97 AssertPtrReturn(pRegRec->pfnCanReuseElement, VERR_INVALID_POINTER); 92 98 93 99 /* … … 99 105 if (RT_FAILURE(rc)) 100 106 return rc; 101 rc = RTCritSect Enter(&g_rtVfsChainElementCritSect);107 rc = RTCritSectRwEnterExcl(&g_rtVfsChainElementCritSect); 102 108 if (RT_FAILURE(rc)) 103 109 return rc; 104 110 } 111 else if (!g_rtVfsChainElementProviderList.pNext) 112 RTListInit(&g_rtVfsChainElementProviderList); 105 113 106 114 /* … … 129 137 */ 130 138 if (!fFromCtor) 131 RTCritSect Leave(&g_rtVfsChainElementCritSect);139 RTCritSectRwLeaveExcl(&g_rtVfsChainElementCritSect); 132 140 return rc; 133 141 } … … 144 152 if (pSpec) 145 153 { 146 pSpec->iActionElement = UINT32_MAX; 154 pSpec->fOpenFile = 0; 155 pSpec->fOpenDir = 0; 147 156 pSpec->cElements = 0; 157 pSpec->uProvider = 0; 148 158 pSpec->paElements = NULL; 149 159 } … … 213 223 * code shorter. -lazy bird) 214 224 */ 215 static PRTVFSCHAINELEMSPEC rtVfsChainSpecAddElement(PRTVFSCHAINSPEC pSpec, int *prc)225 static PRTVFSCHAINELEMSPEC rtVfsChainSpecAddElement(PRTVFSCHAINSPEC pSpec, uint16_t offSpec, int *prc) 216 226 { 217 227 AssertPtr(pSpec); … … 240 250 PRTVFSCHAINELEMSPEC pElement = &pSpec->paElements[iElement]; 241 251 pElement->pszProvider = NULL; 242 pElement->enmTypeIn = iElement ? pSpec->paElements[iElement - 1].enmTypeOut : RTVFSOBJTYPE_INVALID; 243 pElement->enmTypeOut = RTVFSOBJTYPE_INVALID; 244 pElement->enmAction = RTVFSCHAINACTION_INVALID; 252 pElement->enmTypeIn = iElement ? pSpec->paElements[iElement - 1].enmType : RTVFSOBJTYPE_INVALID; 253 pElement->enmType = RTVFSOBJTYPE_INVALID; 254 pElement->offSpec = offSpec; 255 pElement->cchSpec = 0; 245 256 pElement->cArgs = 0; 246 pElement->papszArgs = 0; 247 248 pSpec->cElements = iElement + 1; 257 pElement->paArgs = NULL; 258 pElement->pProvider = NULL; 259 pElement->hVfsObj = NIL_RTVFSOBJ; 260 261 pSpec->cElements = iElement + 1; 249 262 return pElement; 250 263 } … … 260 273 * sequences counted twice. 261 274 */ 262 static int rtVfsChainSpecElementAddArg(PRTVFSCHAINELEMSPEC pElement, const char *psz, size_t cch )275 static int rtVfsChainSpecElementAddArg(PRTVFSCHAINELEMSPEC pElement, const char *psz, size_t cch, uint16_t offSpec) 263 276 { 264 277 uint32_t iArg = pElement->cArgs; 265 278 if ((iArg % 32) == 0) 266 279 { 267 char **papszNew = (char **)RTMemTmpAlloc((iArg + 32 + 1) * sizeof(papszNew[0]));268 if (!pa pszNew)280 PRTVFSCHAINELEMENTARG paNew = (PRTVFSCHAINELEMENTARG)RTMemTmpAlloc((iArg + 32) * sizeof(paNew[0])); 281 if (!paNew) 269 282 return VERR_NO_TMP_MEMORY; 270 memcpy(pa pszNew, pElement->papszArgs, iArg * sizeof(papszNew[0]));271 RTMemTmpFree(pElement->pa pszArgs);272 pElement->pa pszArgs = papszNew;283 memcpy(paNew, pElement->paArgs, iArg * sizeof(paNew[0])); 284 RTMemTmpFree(pElement->paArgs); 285 pElement->paArgs = paNew; 273 286 } 274 287 275 288 int rc = VINF_SUCCESS; 276 pElement->pa pszArgs[iArg]= rtVfsChainSpecDupStrN(psz, cch, &rc);277 pElement->pa pszArgs[iArg + 1] = NULL;289 pElement->paArgs[iArg].psz = rtVfsChainSpecDupStrN(psz, cch, &rc); 290 pElement->paArgs[iArg].offSpec = offSpec; 278 291 pElement->cArgs = iArg + 1; 279 292 return rc; … … 291 304 uint32_t iArg = pSpec->paElements[i].cArgs; 292 305 while (iArg-- > 0) 293 RTMemTmpFree(pSpec->paElements[i].pa pszArgs[iArg]);294 RTMemTmpFree(pSpec->paElements[i].pa pszArgs);306 RTMemTmpFree(pSpec->paElements[i].paArgs[iArg].psz); 307 RTMemTmpFree(pSpec->paElements[i].paArgs); 295 308 RTMemTmpFree(pSpec->paElements[i].pszProvider); 309 if (pSpec->paElements[i].hVfsObj != NIL_RTVFSOBJ) 310 { 311 RTVfsObjRelease(pSpec->paElements[i].hVfsObj); 312 pSpec->paElements[i].hVfsObj = NIL_RTVFSOBJ; 313 } 296 314 } 297 315 … … 326 344 } 327 345 328 /** 329 * Look for action. 330 * 331 * @returns Action. 332 * @param pszSpec The current spec position. 333 * @param pcchAction Where to return the length of the action 334 * string. 335 */ 336 static RTVFSCHAINACTION rtVfsChainSpecEatAction(const char *pszSpec, size_t *pcchAction) 337 { 338 switch (*pszSpec) 339 { 340 case '|': 341 *pcchAction = 1; 342 return RTVFSCHAINACTION_PASSIVE; 343 case '>': 344 *pcchAction = 1; 345 return RTVFSCHAINACTION_PUSH; 346 default: 347 *pcchAction = 0; 348 return RTVFSCHAINACTION_NONE; 349 } 350 } 351 352 353 RTDECL(int) RTVfsChainSpecParse(const char *pszSpec, uint32_t fFlags, RTVFSCHAINACTION enmLeadingAction, 354 RTVFSCHAINACTION enmTrailingAction, 355 PRTVFSCHAINSPEC *ppSpec, const char **ppszError) 346 347 RTDECL(int) RTVfsChainSpecParse(const char *pszSpec, uint32_t fFlags, RTVFSOBJTYPE enmDesiredType, 348 PRTVFSCHAINSPEC *ppSpec, const char **ppszError) 356 349 { 357 350 AssertPtrNullReturn(ppszError, VERR_INVALID_POINTER); … … 362 355 AssertPtrReturn(pszSpec, VERR_INVALID_POINTER); 363 356 AssertReturn(!(fFlags & ~RTVFSCHAIN_PF_VALID_MASK), VERR_INVALID_PARAMETER); 364 AssertReturn(enm LeadingAction > RTVFSCHAINACTION_INVALID && enmLeadingAction < RTVFSCHAINACTION_END, VERR_INVALID_PARAMETER);357 AssertReturn(enmDesiredType > RTVFSOBJTYPE_INVALID && enmDesiredType < RTVFSOBJTYPE_END, VERR_INVALID_PARAMETER); 365 358 366 359 /* … … 369 362 if (strncmp(pszSpec, RTVFSCHAIN_SPEC_PREFIX, sizeof(RTVFSCHAIN_SPEC_PREFIX) - 1)) 370 363 return VERR_VFS_CHAIN_NO_PREFIX; 371 pszSpec = RTStrStripL(pszSpec + sizeof(RTVFSCHAIN_SPEC_PREFIX) - 1);372 if (!*pszS pec)364 const char *pszSrc = RTStrStripL(pszSpec + sizeof(RTVFSCHAIN_SPEC_PREFIX) - 1); 365 if (!*pszSrc) 373 366 return VERR_VFS_CHAIN_EMPTY; 374 367 … … 376 369 if (!pSpec) 377 370 return VERR_NO_TMP_MEMORY; 371 pSpec->enmDesiredType = enmDesiredType; 378 372 379 373 /* 380 374 * Parse the spec one element at a time. 381 375 */ 382 int rc = VINF_SUCCESS; 383 const char *pszSrc = pszSpec; 376 int rc = VINF_SUCCESS; 384 377 while (*pszSrc && RT_SUCCESS(rc)) 385 378 { 386 379 /* 387 * Pipe or redirection action symbol, except maybe the first time. 388 * The pipe symbol may occur at the end of the spec. 380 * Digest element separator, except for the first element. 389 381 */ 390 size_t cch; 391 RTVFSCHAINACTION enmAction = rtVfsChainSpecEatAction(pszSpec, &cch); 392 if (enmAction != RTVFSCHAINACTION_NONE) 393 { 394 pszSrc = RTStrStripL(pszSrc + cch); 395 if (!*pszSrc) 382 if (*pszSrc == '|' || *pszSrc == ':') 383 { 384 if (pSpec->cElements != 0) 385 pszSrc = RTStrStripL(pszSrc + 1); 386 else 396 387 { 397 /* Fail if the caller does not approve of a trailing pipe (all 398 other actions non-trailing). */ 399 if ( enmAction != enmTrailingAction 400 && !(fFlags & RTVFSCHAIN_PF_TRAILING_ACTION_OPTIONAL)) 401 rc = VERR_VFS_CHAIN_EXPECTED_ELEMENT; 388 rc = VERR_VFS_CHAIN_LEADING_SEPARATOR; 402 389 break; 403 390 } 404 405 /* There can only be one real action atm. */ 406 if (enmAction != RTVFSCHAINACTION_PASSIVE) 407 { 408 if (pSpec->iActionElement != UINT32_MAX) 409 { 410 rc = VERR_VFS_CHAIN_MULTIPLE_ACTIONS; 411 break; 412 } 413 pSpec->iActionElement = pSpec->cElements; 414 } 415 } 416 else if (pSpec->cElements > 0) 417 { 418 rc = VERR_VFS_CHAIN_EXPECTED_ACTION; 419 break; 420 } 421 422 /* Check the leading action. */ 423 if ( pSpec->cElements == 0 424 && enmAction != enmLeadingAction 425 && !(fFlags & RTVFSCHAIN_PF_LEADING_ACTION_OPTIONAL)) 426 { 427 rc = VERR_VFS_CHAIN_UNEXPECTED_ACTION_TYPE; 391 } 392 else if (pSpec->cElements != 0) 393 { 394 rc = VERR_VFS_CHAIN_EXPECTED_SEPARATOR; 428 395 break; 429 396 } … … 432 399 * Ok, there should be an element here so add one to the return struct. 433 400 */ 434 PRTVFSCHAINELEMSPEC pElement = rtVfsChainSpecAddElement(pSpec, &rc);401 PRTVFSCHAINELEMSPEC pElement = rtVfsChainSpecAddElement(pSpec, (uint16_t)(pszSrc - pszSpec), &rc); 435 402 if (!pElement) 436 403 break; 437 pElement->enmAction = enmAction;438 404 439 405 /* 440 * First up is the VFS object type followed by a parentheses. 406 * First up is the VFS object type followed by a parentheses, 407 * or this could be the trailing action. 441 408 */ 409 size_t cch; 442 410 if (strncmp(pszSrc, "base", cch = 4) == 0) 443 pElement->enmType Out= RTVFSOBJTYPE_BASE;411 pElement->enmType = RTVFSOBJTYPE_BASE; 444 412 else if (strncmp(pszSrc, "vfs", cch = 3) == 0) 445 pElement->enmType Out= RTVFSOBJTYPE_VFS;413 pElement->enmType = RTVFSOBJTYPE_VFS; 446 414 else if (strncmp(pszSrc, "fss", cch = 3) == 0) 447 pElement->enmType Out= RTVFSOBJTYPE_FS_STREAM;415 pElement->enmType = RTVFSOBJTYPE_FS_STREAM; 448 416 else if (strncmp(pszSrc, "ios", cch = 3) == 0) 449 pElement->enmType Out= RTVFSOBJTYPE_IO_STREAM;417 pElement->enmType = RTVFSOBJTYPE_IO_STREAM; 450 418 else if (strncmp(pszSrc, "dir", cch = 3) == 0) 451 pElement->enmType Out= RTVFSOBJTYPE_DIR;419 pElement->enmType = RTVFSOBJTYPE_DIR; 452 420 else if (strncmp(pszSrc, "file", cch = 4) == 0) 453 pElement->enmType Out= RTVFSOBJTYPE_FILE;421 pElement->enmType = RTVFSOBJTYPE_FILE; 454 422 else if (strncmp(pszSrc, "sym", cch = 3) == 0) 455 pElement->enmType Out= RTVFSOBJTYPE_SYMLINK;423 pElement->enmType = RTVFSOBJTYPE_SYMLINK; 456 424 else 457 425 { 458 rc = VERR_VFS_CHAIN_UNKNOWN_TYPE; 426 if (*pszSrc == '\0') 427 rc = VERR_VFS_CHAIN_TRAILING_SEPARATOR; 428 else 429 rc = VERR_VFS_CHAIN_UNKNOWN_TYPE; 459 430 break; 460 431 } … … 490 461 pszSrc = RTStrStripL(pszSrc + 1); 491 462 cch = rtVfsChainSpecFindArgEnd(pszSrc); 492 rc = rtVfsChainSpecElementAddArg(pElement, pszSrc, cch); 463 rc = rtVfsChainSpecElementAddArg(pElement, pszSrc, cch, (uint16_t)(pszSrc - pszSpec)); 464 if (RT_FAILURE(rc)) 465 break; 493 466 pszSrc += cch; 494 467 } 468 if (RT_FAILURE(rc)) 469 break; 495 470 496 471 /* Must end with a right parentheses. */ … … 500 475 break; 501 476 } 477 pElement->cchSpec = (uint16_t)(pszSrc - pszSpec) - pElement->offSpec + 1; 478 502 479 pszSrc = RTStrStripL(pszSrc + 1); 503 480 } 481 482 #if 1 483 RTAssertMsg2("dbg: cElements=%d rc=%Rrc\n", pSpec->cElements, rc); 484 for (uint32_t i = 0; i < pSpec->cElements; i++) 485 { 486 uint32_t const cArgs = pSpec->paElements[i].cArgs; 487 RTAssertMsg2("dbg: #%u: enmTypeIn=%d enmType=%d cArgs=%d", 488 i, pSpec->paElements[i].enmTypeIn, pSpec->paElements[i].enmType, cArgs); 489 for (uint32_t j = 0; j < cArgs; j++) 490 RTAssertMsg2(j == 0 ? (cArgs > 1 ? " [%s" : " [%s]") : j + 1 < cArgs ? ", %s" : ", %s]", 491 pSpec->paElements[i].paArgs[j].psz); 492 //RTAssertMsg2(" offSpec=%d cchSpec=%d", pSpec->paElements[i].offSpec, pSpec->paElements[i].cchSpec); 493 RTAssertMsg2(" spec: %.*s\n", pSpec->paElements[i].cchSpec, &pszSpec[pSpec->paElements[i].offSpec]); 494 } 495 #endif 504 496 505 497 /* … … 519 511 520 512 521 513 /** 514 * Looks up @a pszProvider among the registered providers. 515 * 516 * @returns Pointer to registration record if found, NULL if not. 517 * @param pszProvider The provider. 518 */ 519 static PCRTVFSCHAINELEMENTREG rtVfsChainFindProviderLocked(const char *pszProvider) 520 { 521 PCRTVFSCHAINELEMENTREG pIterator; 522 RTListForEach(&g_rtVfsChainElementProviderList, pIterator, RTVFSCHAINELEMENTREG, ListEntry) 523 { 524 if (strcmp(pIterator->pszName, pszProvider) == 0) 525 return pIterator; 526 } 527 return NULL; 528 } 529 530 531 /** 532 * Does reusable object type matching. 533 * 534 * @returns true if the types matches, false if not. 535 * @param pElement The target element specification. 536 * @param pReuseElement The source element specification. 537 */ 538 static bool rtVfsChainMatchReusableType(PRTVFSCHAINELEMSPEC pElement, PRTVFSCHAINELEMSPEC pReuseElement) 539 { 540 if (pElement->enmType == pReuseElement->enmType) 541 return true; 542 543 /* File objects can always be cast to I/O streams. */ 544 if ( pElement->enmType == RTVFSOBJTYPE_IO_STREAM 545 && pReuseElement->enmType == RTVFSOBJTYPE_FILE) 546 return true; 547 548 /* I/O stream objects may be file objects. */ 549 if ( pElement->enmType == RTVFSOBJTYPE_FILE 550 && pReuseElement->enmType == RTVFSOBJTYPE_IO_STREAM) 551 { 552 RTVFSFILE hVfsFile = RTVfsObjToFile(pReuseElement->hVfsObj); 553 if (hVfsFile != NIL_RTVFSFILE) 554 { 555 RTVfsFileRelease(hVfsFile); 556 return true; 557 } 558 } 559 return false; 560 } 561 562 563 RTDECL(int) RTVfsChainSpecCheckAndSetup(PRTVFSCHAINSPEC pSpec, PCRTVFSCHAINSPEC pReuseSpec, 564 PRTVFSOBJ phVfsObj, uint32_t *poffError) 565 { 566 AssertPtrReturn(poffError, VERR_INVALID_POINTER); 567 *poffError = 0; 568 AssertPtrReturn(phVfsObj, VERR_INVALID_POINTER); 569 *phVfsObj = NIL_RTVFSOBJ; 570 AssertPtrReturn(pSpec, VERR_INVALID_POINTER); 571 572 /* 573 * Enter the critical section after making sure it has been initialized. 574 */ 575 int rc = RTOnce(&g_rtVfsChainElementInitOnce, rtVfsChainElementRegisterInit, NULL); 576 if (RT_SUCCESS(rc)) 577 rc = RTCritSectRwEnterShared(&g_rtVfsChainElementCritSect); 578 if (RT_SUCCESS(rc)) 579 { 580 /* 581 * Resolve and check each element first. 582 */ 583 for (uint32_t i = 0; i < pSpec->cElements; i++) 584 { 585 PRTVFSCHAINELEMSPEC const pElement = &pSpec->paElements[i]; 586 *poffError = pElement->offSpec; 587 pElement->pProvider = rtVfsChainFindProviderLocked(pElement->pszProvider); 588 if (pElement->pProvider) 589 { 590 rc = pElement->pProvider->pfnValidate(pElement->pProvider, pSpec, pElement, poffError); 591 if (RT_SUCCESS(rc)) 592 continue; 593 } 594 else 595 rc = VERR_VFS_CHAIN_PROVIDER_NOT_FOUND; 596 break; 597 } 598 599 /* 600 * Check that the desired type is compatible with the last element. 601 */ 602 if (RT_SUCCESS(rc)) 603 { 604 if (pSpec->cElements > 0) /* paranoia */ 605 { 606 PRTVFSCHAINELEMSPEC const pLast = &pSpec->paElements[pSpec->cElements - 1]; 607 if ( pLast->enmType == pSpec->enmDesiredType 608 || ( pLast->enmType == RTVFSOBJTYPE_FILE 609 && pSpec->enmDesiredType == RTVFSOBJTYPE_IO_STREAM) ) 610 rc = VINF_SUCCESS; 611 else 612 { 613 *poffError = pLast->offSpec; 614 rc = VERR_VFS_CHAIN_FINAL_TYPE_MISMATCH; 615 } 616 } 617 else 618 rc = VERR_VFS_CHAIN_EMPTY; 619 } 620 621 if (RT_SUCCESS(rc)) 622 { 623 /* 624 * Try construct the chain. 625 */ 626 RTVFSOBJ hPrevVfsObj = NIL_RTVFSOBJ; /* No extra reference, kept in chain structure. */ 627 for (uint32_t i = 0; i < pSpec->cElements; i++) 628 { 629 PRTVFSCHAINELEMSPEC const pElement = &pSpec->paElements[i]; 630 631 /* 632 * Try reuse the VFS objects at the start of the passed in reuse chain. 633 */ 634 if (!pReuseSpec) 635 { /* likely */ } 636 else 637 { 638 if (i < pReuseSpec->cElements) 639 { 640 PRTVFSCHAINELEMSPEC const pReuseElement = &pReuseSpec->paElements[i]; 641 if (pReuseElement->hVfsObj != NIL_RTVFSOBJ) 642 { 643 if (strcmp(pElement->pszProvider, pReuseElement->pszProvider) == 0) 644 { 645 if (rtVfsChainMatchReusableType(pElement, pReuseElement)) 646 { 647 if (pElement->pProvider->pfnCanReuseElement(pElement->pProvider, pSpec, pElement, 648 pReuseSpec, pReuseElement)) 649 { 650 uint32_t cRefs = RTVfsObjRetain(pReuseElement->hVfsObj); 651 if (cRefs != UINT32_MAX) 652 { 653 pElement->hVfsObj = hPrevVfsObj = pReuseElement->hVfsObj; 654 continue; 655 } 656 } 657 } 658 } 659 } 660 } 661 pReuseSpec = NULL; 662 } 663 664 /* 665 * Instantiate a new VFS object. 666 */ 667 RTVFSOBJ hVfsObj = NIL_RTVFSOBJ; 668 rc = pElement->pProvider->pfnInstantiate(pElement->pProvider, pSpec, pElement, hPrevVfsObj, &hVfsObj, poffError); 669 if (RT_FAILURE(rc)) 670 break; 671 pElement->hVfsObj = hVfsObj; 672 hPrevVfsObj = hVfsObj; 673 } 674 675 /* 676 * Add another reference to the final object and return. 677 */ 678 if (RT_SUCCESS(rc)) 679 { 680 uint32_t cRefs = RTVfsObjRetain(hPrevVfsObj); 681 AssertStmt(cRefs != UINT32_MAX, rc = VERR_VFS_CHAIN_IPE); 682 *phVfsObj = hPrevVfsObj; 683 } 684 } 685 686 int rc2 = RTCritSectRwLeaveShared(&g_rtVfsChainElementCritSect); 687 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 688 rc = rc2; 689 } 690 return rc; 691 } 522 692 523 693 … … 538 708 */ 539 709 if (!fFromDtor) 540 RTCritSectEnter(&g_rtVfsChainElementCritSect); 710 RTCritSectRwEnterExcl(&g_rtVfsChainElementCritSect); 711 else if (!g_rtVfsChainElementProviderList.pNext) 712 RTListInit(&g_rtVfsChainElementProviderList); 541 713 542 714 /* … … 559 731 */ 560 732 if (!fFromDtor) 561 RTCritSect Leave(&g_rtVfsChainElementCritSect);733 RTCritSectRwLeaveExcl(&g_rtVfsChainElementCritSect); 562 734 return rc; 563 735 } … … 593 765 { 594 766 PRTVFSCHAINSPEC pSpec; 595 rc = RTVfsChainSpecParse(pszSpec, 596 RTVFSCHAIN_PF_NO_REAL_ACTION 597 | RTVFSCHAIN_PF_LEADING_ACTION_OPTIONAL, 598 RTVFSCHAINACTION_PASSIVE, 599 RTVFSCHAINACTION_NONE, 600 &pSpec, 601 ppszError); 767 rc = RTVfsChainSpecParse(pszSpec, 0 /*fFlags*/, RTVFSOBJTYPE_FILE, &pSpec, ppszError); 602 768 if (RT_SUCCESS(rc)) 603 769 { 604 /** @todo implement this when needed. */ 605 rc = VERR_NOT_IMPLEMENTED; 770 pSpec->fOpenFile = fOpen; 771 772 uint32_t offError = 0; 773 RTVFSOBJ hVfsObj = NIL_RTVFSOBJ; 774 rc = RTVfsChainSpecCheckAndSetup(pSpec, NULL /*pReuseSpec*/, &hVfsObj, &offError); 775 if (RT_SUCCESS(rc)) 776 { 777 *phVfsFile = RTVfsObjToFile(hVfsObj); 778 if (*phVfsFile) 779 rc = VINF_SUCCESS; 780 else 781 rc = VERR_VFS_CHAIN_CAST_FAILED; 782 RTVfsObjRelease(hVfsObj); 783 } 784 else if (ppszError) 785 *ppszError = &pszSpec[offError]; 786 606 787 RTVfsChainSpecFree(pSpec); 607 788 } … … 641 822 } 642 823 } 824 /* 825 * Do the chain thing. 826 */ 643 827 else 644 828 { 645 829 PRTVFSCHAINSPEC pSpec; 646 rc = RTVfsChainSpecParse(pszSpec, 647 RTVFSCHAIN_PF_NO_REAL_ACTION 648 | RTVFSCHAIN_PF_LEADING_ACTION_OPTIONAL, 649 RTVFSCHAINACTION_PASSIVE, 650 RTVFSCHAINACTION_NONE, 651 &pSpec, 652 ppszError); 830 rc = RTVfsChainSpecParse(pszSpec, 0 /*fFlags*/, RTVFSOBJTYPE_IO_STREAM, &pSpec, ppszError); 653 831 if (RT_SUCCESS(rc)) 654 832 { 655 656 657 rc = VERR_NOT_IMPLEMENTED; 833 pSpec->fOpenFile = fOpen; 834 835 uint32_t offError = 0; 836 RTVFSOBJ hVfsObj = NIL_RTVFSOBJ; 837 rc = RTVfsChainSpecCheckAndSetup(pSpec, NULL /*pReuseSpec*/, &hVfsObj, &offError); 838 if (RT_SUCCESS(rc)) 839 { 840 *phVfsIos = RTVfsObjToIoStream(hVfsObj); 841 if (*phVfsIos) 842 rc = VINF_SUCCESS; 843 else 844 rc = VERR_VFS_CHAIN_CAST_FAILED; 845 RTVfsObjRelease(hVfsObj); 846 } 847 else if (ppszError) 848 *ppszError = &pszSpec[offError]; 849 658 850 RTVfsChainSpecFree(pSpec); 659 851 } -
trunk/src/VBox/Runtime/common/vfs/vfsstdfile.cpp
r62477 r66594 32 32 #include <iprt/vfslowlevel.h> 33 33 34 #include <iprt/assert.h> 34 35 #include <iprt/err.h> 35 36 #include <iprt/file.h> 36 37 #include <iprt/poll.h> 38 #include <iprt/string.h> 37 39 #include <iprt/thread.h> 38 40 … … 509 511 } 510 512 513 514 515 /** 516 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate} 517 */ 518 static DECLCALLBACK(int) rtVfsChainStdFile_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec, 519 PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError) 520 { 521 RT_NOREF(pProviderReg); 522 523 /* 524 * Basic checks. 525 */ 526 if (pElement->enmTypeIn != RTVFSOBJTYPE_INVALID) 527 return VERR_VFS_CHAIN_MUST_BE_FIRST_ELEMENT; 528 if (pElement->cArgs < 1) 529 return VERR_VFS_CHAIN_AT_LEAST_ONE_ARG; 530 if (pElement->cArgs > 4) 531 return VERR_VFS_CHAIN_AT_MOST_FOUR_ARGS; 532 if (!*pElement->paArgs[0].psz) 533 return VERR_VFS_CHAIN_EMPTY_ARG; 534 if ( pElement->enmType != RTVFSOBJTYPE_FILE 535 && pElement->enmType != RTVFSOBJTYPE_IO_STREAM) 536 return VERR_VFS_CHAIN_ONLY_FILE_OR_IOS; 537 538 /* 539 * Calculate the flags, storing them in the first argument. 540 */ 541 const char *pszAccess = pElement->cArgs >= 2 ? pElement->paArgs[1].psz : ""; 542 if (!*pszAccess) 543 pszAccess = (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READWRITE ? "rw" 544 : (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ ? "r" 545 : (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_WRITE ? "w" 546 : "rw"; 547 548 const char *pszDisp = pElement->cArgs >= 3 ? pElement->paArgs[2].psz : ""; 549 if (!*pszDisp) 550 pszDisp = strchr(pszAccess, 'w') != NULL ? "open-create" : "open"; 551 552 const char *pszSharing = pElement->cArgs >= 4 ? pElement->paArgs[3].psz : ""; 553 554 int rc = RTFileModeToFlagsEx(pszAccess, pszDisp, pszSharing, &pElement->paArgs[0].uProvider); 555 if (RT_SUCCESS(rc)) 556 return VINF_SUCCESS; 557 558 /* 559 * Now try figure out which argument offended us. 560 */ 561 AssertReturn(pElement->cArgs > 1, VERR_VFS_CHAIN_IPE); 562 if ( pElement->cArgs == 2 563 || RT_FAILURE(RTFileModeToFlagsEx(pszAccess, "open-create", "", &pElement->paArgs[0].uProvider))) 564 *poffError = pElement->paArgs[1].offSpec; 565 else if ( pElement->cArgs == 3 566 || RT_FAILURE(RTFileModeToFlagsEx(pszAccess, pszDisp, "", &pElement->paArgs[0].uProvider))) 567 *poffError = pElement->paArgs[2].offSpec; 568 else 569 *poffError = pElement->paArgs[3].offSpec; 570 return VERR_VFS_CHAIN_INVALID_ARGUMENT; 571 } 572 573 574 /** 575 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate} 576 */ 577 static DECLCALLBACK(int) rtVfsChainStdFile_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec, 578 PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj, 579 PRTVFSOBJ phVfsObj, uint32_t *poffError) 580 { 581 RT_NOREF(pProviderReg, pSpec, poffError); 582 AssertReturn(hPrevVfsObj == NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE); 583 584 RTVFSFILE hVfsFile; 585 int rc = RTVfsFileOpenNormal(pElement->paArgs[0].psz, pElement->paArgs[0].uProvider, &hVfsFile); 586 if (RT_SUCCESS(rc)) 587 { 588 *phVfsObj = RTVfsObjFromFile(hVfsFile); 589 RTVfsFileRelease(hVfsFile); 590 if (*phVfsObj != NIL_RTVFSOBJ) 591 return VINF_SUCCESS; 592 rc = VERR_VFS_CHAIN_CAST_FAILED; 593 } 594 return rc; 595 } 596 597 598 /** 599 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement} 600 */ 601 static DECLCALLBACK(bool) rtVfsChainStdFile_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg, 602 PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement, 603 PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement) 604 { 605 RT_NOREF(pProviderReg, pSpec, pReuseSpec); 606 if (strcmp(pElement->paArgs[0].psz, pReuseElement->paArgs[0].psz) == 0) 607 if (pElement->paArgs[0].uProvider == pReuseElement->paArgs[0].uProvider) 608 return true; 609 return false; 610 } 611 612 613 /** VFS chain element 'file'. */ 614 static RTVFSCHAINELEMENTREG g_rtVfsChainStdFileReg = 615 { 616 /* uVersion = */ RTVFSCHAINELEMENTREG_VERSION, 617 /* fReserved = */ 0, 618 /* pszName = */ "stdfile", 619 /* ListEntry = */ { NULL, NULL }, 620 /* pszHelp = */ "Open a real file, providing either a file or an I/O stream object. Initial element.\n" 621 "First argument is the filename path.\n" 622 "Second argument is access mode, optional: r, w, rw.\n" 623 "Third argument is open disposition, optional: create, create-replace, open, open-create, open-append, open-truncate.\n" 624 "Forth argument is file sharing, optional: nr, nw, nrw, d.", 625 /* pfnValidate = */ rtVfsChainStdFile_Validate, 626 /* pfnInstantiate = */ rtVfsChainStdFile_Instantiate, 627 /* pfnCanReuseElement = */ rtVfsChainStdFile_CanReuseElement, 628 /* uEndMarker = */ RTVFSCHAINELEMENTREG_VERSION 629 }; 630 631 RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainStdFileReg, rtVfsChainStdFileReg); 632 -
trunk/src/VBox/Runtime/common/zip/gzipvfs.cpp
r62477 r66594 33 33 34 34 #include <iprt/assert.h> 35 #include <iprt/ctype.h> 35 36 #include <iprt/file.h> 36 37 #include <iprt/err.h> … … 828 829 } 829 830 831 832 833 /** 834 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate} 835 */ 836 static DECLCALLBACK(int) rtVfsChainGunzip_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec, 837 PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError) 838 { 839 RT_NOREF(pProviderReg, poffError); 840 841 if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID) 842 return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT; 843 if (pElement->cArgs != 0) 844 return VERR_VFS_CHAIN_NO_ARGS; 845 if (pElement->enmType != RTVFSOBJTYPE_IO_STREAM) 846 return VERR_VFS_CHAIN_ONLY_IOS; 847 if (pSpec->fOpenFile & RTFILE_O_WRITE) 848 return VERR_VFS_CHAIN_READ_ONLY_IOS; 849 850 return VINF_SUCCESS; 851 } 852 853 854 /** 855 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate} 856 */ 857 static DECLCALLBACK(int) rtVfsChainGunzip_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec, 858 PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj, 859 PRTVFSOBJ phVfsObj, uint32_t *poffError) 860 { 861 RT_NOREF(pProviderReg, pSpec, pElement, poffError); 862 AssertReturn(hPrevVfsObj != NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE); 863 864 RTVFSIOSTREAM hVfsIosIn = RTVfsObjToIoStream(hPrevVfsObj); 865 if (hVfsIosIn == NIL_RTVFSIOSTREAM) 866 return VERR_VFS_CHAIN_CAST_FAILED; 867 868 RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM; 869 int rc = RTZipGzipDecompressIoStream(hVfsIosIn, 0 /*fFlags*/, &hVfsIos); 870 if (RT_SUCCESS(rc)) 871 { 872 *phVfsObj = RTVfsObjFromIoStream(hVfsIos); 873 RTVfsIoStrmRelease(hVfsIos); 874 if (*phVfsObj != NIL_RTVFSOBJ) 875 return VINF_SUCCESS; 876 rc = VERR_VFS_CHAIN_CAST_FAILED; 877 } 878 return rc; 879 } 880 881 882 /** 883 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement} 884 */ 885 static DECLCALLBACK(bool) rtVfsChainGunzip_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg, 886 PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement, 887 PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement) 888 { 889 RT_NOREF(pProviderReg, pSpec, pElement, pReuseSpec, pReuseElement); 890 return false; 891 } 892 893 894 /** VFS chain element 'gunzip'. */ 895 static RTVFSCHAINELEMENTREG g_rtVfsChainGunzipReg = 896 { 897 /* uVersion = */ RTVFSCHAINELEMENTREG_VERSION, 898 /* fReserved = */ 0, 899 /* pszName = */ "gunzip", 900 /* ListEntry = */ { NULL, NULL }, 901 /* pszHelp = */ "Takes an I/O stream and gunzips it. No arguments.", 902 /* pfnValidate = */ rtVfsChainGunzip_Validate, 903 /* pfnInstantiate = */ rtVfsChainGunzip_Instantiate, 904 /* pfnCanReuseElement = */ rtVfsChainGunzip_CanReuseElement, 905 /* uEndMarker = */ RTVFSCHAINELEMENTREG_VERSION 906 }; 907 908 RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainGunzipReg, rtVfsChainGunzipReg); 909 910 911 912 /** 913 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate} 914 */ 915 static DECLCALLBACK(int) rtVfsChainGzip_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec, 916 PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError) 917 { 918 RT_NOREF(pProviderReg); 919 920 /* 921 * Basics. 922 */ 923 if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID) 924 return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT; 925 if (pElement->cArgs > 1) 926 return VERR_VFS_CHAIN_AT_MOST_ONE_ARG; 927 if (pElement->enmType != RTVFSOBJTYPE_IO_STREAM) 928 return VERR_VFS_CHAIN_ONLY_IOS; 929 if (pSpec->fOpenFile & RTFILE_O_READ) 930 return VERR_VFS_CHAIN_WRITE_ONLY_IOS; 931 932 /* 933 * Optional argument 1..9 indicating the compression level. 934 * We store it in pSpec->uProvider. 935 */ 936 if (pElement->cArgs > 0) 937 { 938 const char *psz = pElement->paArgs[0].psz; 939 if (!*psz || !strcmp(psz, "default")) 940 pSpec->uProvider = 6; 941 else if (!strcmp(psz, "fast")) 942 pSpec->uProvider = 3; 943 else if ( RT_C_IS_DIGIT(*psz) 944 && *psz != '0' 945 && *RTStrStripL(psz + 1) == '\0') 946 pSpec->uProvider = *psz - '0'; 947 else 948 { 949 *poffError = pElement->paArgs[0].offSpec; 950 return VERR_VFS_CHAIN_INVALID_ARGUMENT; 951 } 952 } 953 else 954 pSpec->uProvider = 6; 955 956 return VINF_SUCCESS; 957 } 958 959 960 /** 961 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate} 962 */ 963 static DECLCALLBACK(int) rtVfsChainGzip_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec, 964 PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj, 965 PRTVFSOBJ phVfsObj, uint32_t *poffError) 966 { 967 RT_NOREF(pProviderReg, pSpec, pElement, poffError); 968 AssertReturn(hPrevVfsObj != NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE); 969 970 RTVFSIOSTREAM hVfsIosOut = RTVfsObjToIoStream(hPrevVfsObj); 971 if (hVfsIosOut == NIL_RTVFSIOSTREAM) 972 return VERR_VFS_CHAIN_CAST_FAILED; 973 974 RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM; 975 int rc = RTZipGzipCompressIoStream(hVfsIosOut, 0 /*fFlags*/, pSpec->uProvider, &hVfsIos); 976 if (RT_SUCCESS(rc)) 977 { 978 *phVfsObj = RTVfsObjFromIoStream(hVfsIos); 979 RTVfsIoStrmRelease(hVfsIos); 980 if (*phVfsObj != NIL_RTVFSOBJ) 981 return VINF_SUCCESS; 982 rc = VERR_VFS_CHAIN_CAST_FAILED; 983 } 984 return rc; 985 } 986 987 988 /** 989 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement} 990 */ 991 static DECLCALLBACK(bool) rtVfsChainGzip_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg, 992 PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement, 993 PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement) 994 { 995 RT_NOREF(pProviderReg, pSpec, pElement, pReuseSpec, pReuseElement); 996 return false; 997 } 998 999 1000 /** VFS chain element 'gzip'. */ 1001 static RTVFSCHAINELEMENTREG g_rtVfsChainGzipReg = 1002 { 1003 /* uVersion = */ RTVFSCHAINELEMENTREG_VERSION, 1004 /* fReserved = */ 0, 1005 /* pszName = */ "gzip", 1006 /* ListEntry = */ { NULL, NULL }, 1007 /* pszHelp = */ "Takes an I/O stream and gzips it.\n" 1008 "Optional argument specifying compression level: 1-9, default, fast", 1009 /* pfnValidate = */ rtVfsChainGzip_Validate, 1010 /* pfnInstantiate = */ rtVfsChainGzip_Instantiate, 1011 /* pfnCanReuseElement = */ rtVfsChainGzip_CanReuseElement, 1012 /* uEndMarker = */ RTVFSCHAINELEMENTREG_VERSION 1013 }; 1014 1015 RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainGzipReg, rtVfsChainGzipReg); 1016
Note:
See TracChangeset
for help on using the changeset viewer.