Changeset 33859 in vbox for trunk/src/VBox/Runtime/common/vfs
- Timestamp:
- Nov 8, 2010 4:15:07 PM (14 years ago)
- Location:
- trunk/src/VBox/Runtime/common/vfs
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp
r33822 r33859 36 36 #include <iprt/file.h> 37 37 #include <iprt/mem.h> 38 #include <iprt/param.h> 39 #include <iprt/path.h> 40 #include <iprt/semaphore.h> 41 42 #include "internal/file.h" 43 #include "internal/magics.h" 44 //#include "internal/vfs.h" 38 45 39 46 … … 43 50 #define RTVFS_MAGIC UINT32_C(0x11112222) 44 51 #define RTVFS_MAGIC_DEAD (~RTVFS_MAGIC) 52 #define RTVFSDIR_MAGIC UINT32_C(0x77778888) 53 #define RTVFSDIR_MAGIC_DEAD (~RTVFSDIR_MAGIC) 54 #define RTVFSFILE_MAGIC UINT32_C(0x55556666) 55 #define RTVFSFILE_MAGIC_DEAD (~RTVFSFILE_MAGIC) 45 56 #define RTVFSIOSTREAM_MAGIC UINT32_C(0x33334444) 46 57 #define RTVFSIOSTREAM_MAGIC_DEAD (~RTVFSIOSTREAM_MAGIC) 47 #define RTVFS FILE_MAGIC UINT32_C(0x55556666)48 #define RTVFS FILE_MAGIC_DEAD (~RTVFSFILE_MAGIC)58 #define RTVFSSYMLINK_MAGIC UINT32_C(0x9999aaaa) 59 #define RTVFSSYMLINK_MAGIC_DEAD (~RTVFSSYMLINK_MAGIC) 49 60 50 61 /** The instance data alignment. */ 51 62 #define RTVFS_INST_ALIGNMENT 16U 63 64 /** The max number of symbolic links to resolve in a path. */ 65 #define RTVFS_MAX_LINKS 20U 66 67 68 /** Takes a write lock. */ 69 #define RTVFS_WRITE_LOCK(hSemRW) \ 70 do { \ 71 if ((hSemRW) != NIL_RTSEMRW) \ 72 { \ 73 int rcSemEnter = RTSemRWRequestWrite(hSemRW, RT_INDEFINITE_WAIT); \ 74 AssertRC(rcSemEnter); \ 75 } \ 76 } while (0) 77 78 /** Releases a write lock. */ 79 #define RTVFS_WRITE_UNLOCK(hSemRW) \ 80 do { \ 81 if ((hSemRW) != NIL_RTSEMRW) \ 82 { \ 83 int rcSemLeave = RTSemRWReleaseWrite(hSemRW); \ 84 AssertRC(rcSemLeave); \ 85 } \ 86 } while (0) 87 88 /** Takes a read lock. */ 89 #define RTVFS_READ_LOCK(hSemRW) \ 90 do { \ 91 if ((hSemRW) != NIL_RTSEMRW) \ 92 { \ 93 int rcSemEnter = RTSemRWRequestRead(hSemRW, RT_INDEFINITE_WAIT); \ 94 AssertRC(rcSemEnter); \ 95 } \ 96 } while (0) 97 98 /** Releases a read lock. */ 99 #define RTVFS_READ_UNLOCK(hSemRW) \ 100 do { \ 101 if ((hSemRW) != NIL_RTSEMRW) \ 102 { \ 103 int rcSemLeave = RTSemRWReleaseRead(hSemRW); \ 104 AssertRC(rcSemLeave); \ 105 } \ 106 } while (0) 52 107 53 108 … … 104 159 105 160 /** 161 * The VFS symbolic link handle data. 162 */ 163 typedef struct RTVFSSYMLINKINTERNAL 164 { 165 /** The VFS magic (RTVFSSYMLINK_MAGIC). */ 166 uint32_t uMagic; 167 /** Reserved for flags or something. */ 168 uint32_t fReserved; 169 /** Pointer to the instance data. */ 170 void *pvThis; 171 /** The vtable. */ 172 PCRTVFSSYMLINKOPS pOps; 173 /** The VFS RW sem if serialized. */ 174 RTSEMRW hSemRW; 175 /** Reference back to the VFS containing this symbolic link. */ 176 RTVFS hVfs; 177 /** The number of references to this symbolic link handle. */ 178 uint32_t volatile cRefs; 179 } RTVFSSYMLINKINTERNAL; 180 181 182 /** 106 183 * The VFS I/O stream handle data. 107 184 * … … 145 222 146 223 224 147 225 /** 148 226 * Internal object retainer that asserts sanity in strict builds. … … 183 261 } 184 262 263 264 /* 265 * 266 * U T I L U T I L U T I L 267 * U T I L U T I L U T I L 268 * U T I L U T I L U T I L 269 * 270 */ 271 272 273 274 /** 275 * Removes dots from the path. 276 * 277 * @returns The new @a pszDst value. 278 * @param pPath The path parsing buffer. 279 * @param pszDst The current szPath position. This will be 280 * updated and returned. 281 * @param fTheEnd Indicates whether we're at the end of the path 282 * or not. 283 * @param piRestartComp The component to restart parsing at. 284 */ 285 static char *rtVfsParsePathHandleDots(PRTVFSPARSEDPATH pPath, char *pszDst, bool fTheEnd, uint16_t *piRestartComp) 286 { 287 if (pszDst[-1] != '.') 288 return pszDst; 289 290 if (pszDst[-2] == '/') 291 { 292 pPath->cComponents--; 293 pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]]; 294 } 295 else if (pszDst[-2] == '.' && pszDst[-3] == '/') 296 { 297 pPath->cComponents -= pPath->cComponents > 1 ? 2 : 1; 298 pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]]; 299 if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents) 300 *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0; 301 } 302 else 303 return pszDst; 304 305 /* 306 * Drop the trailing slash if we're at the end of the source path. 307 */ 308 if (fTheEnd && pPath->cComponents == 0) 309 pszDst--; 310 return pszDst; 311 } 312 313 314 RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp) 315 { 316 AssertReturn(*pszPath != '/', VERR_INTERNAL_ERROR_4); 317 318 /* In case *piRestartComp was set higher than the number of components 319 before making the call to this function. */ 320 if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents) 321 *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0; 322 323 /* 324 * Append a slash to the destination path if necessary. 325 */ 326 char *pszDst = &pPath->szPath[pPath->cch]; 327 if (pPath->cComponents > 0) 328 { 329 *pszDst++ = '/'; 330 if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX) 331 return VERR_FILENAME_TOO_LONG; 332 } 333 Assert(pszDst[-1] == '/'); 334 335 /* 336 * Parse and append the relative path. 337 */ 338 const char *pszSrc = pszPath; 339 pPath->fDirSlash = false; 340 while (pszSrc[0]) 341 { 342 /* Skip unncessary slashes. */ 343 while (pszSrc[0] == '/') 344 pszSrc++; 345 346 /* Copy until we encounter the next slash. */ 347 pPath->aoffComponents[pPath->cComponents++] = pszDst - &pPath->szPath[0]; 348 while (pszSrc[0]) 349 { 350 if (pszSrc[0] == '/') 351 { 352 pszSrc++; 353 if (pszSrc[0]) 354 *pszDst++ = '/'; 355 else 356 pPath->fDirSlash = true; 357 pszDst = rtVfsParsePathHandleDots(pPath, pszDst, pszSrc[0] == '\0', piRestartComp); 358 break; 359 } 360 361 *pszDst++ = *pszSrc++; 362 if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX) 363 return VERR_FILENAME_TOO_LONG; 364 } 365 } 366 pszDst = rtVfsParsePathHandleDots(pPath, pszDst, true /*fTheEnd*/, piRestartComp); 367 368 /* Terminate the string and enter its length. */ 369 pszDst[0] = '\0'; 370 pszDst[1] = '\0'; /* for aoffComponents */ 371 pPath->cch = (uint16_t)(pszDst - &pPath->szPath[0]); 372 pPath->aoffComponents[pPath->cComponents] = pPath->cch + 1; 373 374 return VINF_SUCCESS; 375 } 376 377 378 RTDECL(int) RTVfsParsePath(PRTVFSPARSEDPATH pPath, const char *pszPath, const char *pszCwd) 379 { 380 if (*pszPath != '/') 381 { 382 /* 383 * Relative, recurse and parse pszCwd first. 384 */ 385 int rc = RTVfsParsePath(pPath, pszCwd, NULL /*crash if pszCwd is not absolute*/); 386 if (RT_FAILURE(rc)) 387 return rc; 388 } 389 else 390 { 391 /* 392 * Make pszPath relative, i.e. set up pPath for the root and skip 393 * leading slashes in pszPath before appending it. 394 */ 395 pPath->cch = 1; 396 pPath->cComponents = 0; 397 pPath->fDirSlash = false; 398 pPath->aoffComponents[0] = 1; 399 pPath->aoffComponents[1] = 2; 400 pPath->szPath[0] = '/'; 401 pPath->szPath[1] = '\0'; 402 pPath->szPath[2] = '\0'; 403 while (pszPath[0] == '/') 404 pszPath++; 405 if (!pszPath[0]) 406 return VINF_SUCCESS; 407 } 408 return RTVfsParsePathAppend(pPath, pszPath, NULL); 409 } 410 411 412 413 RTDECL(int) RTVfsParsePathA(const char *pszPath, const char *pszCwd, PRTVFSPARSEDPATH *ppPath) 414 { 415 /* 416 * Allocate the output buffer and hand the problem to rtVfsParsePath. 417 */ 418 int rc; 419 PRTVFSPARSEDPATH pPath = (PRTVFSPARSEDPATH)RTMemTmpAlloc(sizeof(RTVFSPARSEDPATH)); 420 if (pPath) 421 { 422 rc = RTVfsParsePath(pPath, pszPath, pszCwd); 423 if (RT_FAILURE(rc)) 424 { 425 RTMemTmpFree(pPath); 426 pPath = NULL; 427 } 428 } 429 else 430 rc = VERR_NO_TMP_MEMORY; 431 *ppPath = pPath; /* always set it */ 432 return rc; 433 } 434 435 436 RTDECL(void) RTVfsParsePathFree(PRTVFSPARSEDPATH pPath) 437 { 438 if (pPath) 439 { 440 pPath->cch = UINT16_MAX; 441 pPath->cComponents = UINT16_MAX; 442 pPath->aoffComponents[0] = UINT16_MAX; 443 pPath->aoffComponents[1] = UINT16_MAX; 444 RTMemTmpFree(pPath); 445 } 446 } 447 448 449 /** 450 * Handles a symbolic link, adding it to 451 * 452 * @returns IPRT status code. 453 * @param pPath The parsed path to update. 454 * @param piComponent The component iterator to update. 455 * @param hSymlink The symbolic link to process. 456 */ 457 static int rtVfsTraverseHandleSymlink(PRTVFSPARSEDPATH pPath, uint16_t *piComponent, RTVFSSYMLINK hSymlink) 458 { 459 /* 460 * Read the link. 461 */ 462 char szPath[RTPATH_MAX]; 463 int rc = RTVfsSymlinkRead(hSymlink, szPath, sizeof(szPath) - 1); 464 if (RT_SUCCESS(rc)) 465 { 466 szPath[sizeof(szPath) - 1] = '\0'; 467 if (szPath[0] == '/') 468 { 469 /* 470 * Absolute symlink. 471 */ 472 rc = RTVfsParsePath(pPath, szPath, NULL); 473 if (RT_SUCCESS(rc)) 474 { 475 *piComponent = 0; 476 return VINF_SUCCESS; 477 } 478 } 479 else 480 { 481 /* 482 * Relative symlink, must replace the current component with the 483 * link value. We do that by using the remainder of the symlink 484 * buffer as temporary storage. 485 */ 486 uint16_t iComponent = *piComponent; 487 if (iComponent + 1 < pPath->cComponents) 488 rc = RTPathAppend(szPath, sizeof(szPath), &pPath->szPath[pPath->aoffComponents[iComponent + 1]]); 489 if (RT_SUCCESS(rc)) 490 { 491 pPath->cch = pPath->aoffComponents[iComponent] - (iComponent > 0); 492 pPath->aoffComponents[iComponent + 1] = pPath->cch + 1; 493 pPath->szPath[pPath->cch] = '\0'; 494 pPath->szPath[pPath->cch + 1] = '\0'; 495 496 rc = RTVfsParsePathAppend(pPath, szPath, &iComponent); 497 if (RT_SUCCESS(rc)) 498 { 499 *piComponent = iComponent; 500 return VINF_SUCCESS; 501 } 502 } 503 } 504 } 505 return rc == VERR_BUFFER_OVERFLOW ? VERR_FILENAME_TOO_LONG : rc; 506 } 507 508 509 /** 510 * Internal worker for various open functions as well as RTVfsTraverseToParent. 511 * 512 * @returns IPRT status code. 513 * @param pThis The VFS. 514 * @param pPath The parsed path. This may be changed as symbolic 515 * links are processed during the path traversal. 516 * @param fFollowSymlink Whether to follow the final component if it is a 517 * symbolic link. 518 * @param ppVfsParentDir Where to return the parent directory handle 519 * (referenced). 520 */ 521 static int rtVfsTraverseToParent(RTVFSINTERNAL *pThis, PRTVFSPARSEDPATH pPath, bool fFollowSymlink, 522 RTVFSDIRINTERNAL **ppVfsParentDir) 523 { 524 /* 525 * Assert sanity. 526 */ 527 AssertPtr(pThis); 528 Assert(pThis->uMagic == RTVFS_MAGIC); 529 Assert(pThis->cRefs > 0); 530 AssertPtr(pPath); 531 AssertPtr(ppVfsParentDir); 532 AssertReturn(pPath->cComponents > 0, VERR_INTERNAL_ERROR_3); 533 534 /* 535 * Open the root directory. 536 */ 537 /** @todo Union mounts, traversal optimization methods, races, ++ */ 538 RTVFSDIRINTERNAL *pCurDir; 539 RTVFS_READ_LOCK(pThis->hSemRW); 540 int rc = pThis->pOps->pfnOpenRoot(pThis->pvThis, &pCurDir); 541 RTVFS_READ_UNLOCK(pThis->hSemRW); 542 if (RT_FAILURE(rc)) 543 return rc; 544 Assert(pCurDir->uMagic == RTVFSDIR_MAGIC); 545 546 /* 547 * The traversal loop. 548 */ 549 unsigned cLinks = 0; 550 uint16_t iComponent = 0; 551 for (;;) 552 { 553 /* 554 * Are we done yet? 555 */ 556 bool fFinal = iComponent + 1 >= pPath->cComponents; 557 if (fFinal && !fFollowSymlink) 558 { 559 *ppVfsParentDir = pCurDir; 560 return VINF_SUCCESS; 561 } 562 563 /* 564 * Try open the next entry. 565 */ 566 const char *pszEntry = &pPath->szPath[pPath->aoffComponents[iComponent]]; 567 char *pszEntryEnd = &pPath->szPath[pPath->aoffComponents[iComponent + 1] - 1]; 568 *pszEntryEnd = '\0'; 569 RTVFSDIR hDir = NIL_RTVFSDIR; 570 RTVFSSYMLINK hSymlink = NIL_RTVFSSYMLINK; 571 RTVFS hVfsMnt = NIL_RTVFS; 572 if (fFinal) 573 { 574 RTVFS_READ_LOCK(pCurDir->hSemRW); 575 rc = pCurDir->pOps->pfnTraversalOpen(pCurDir->pvThis, pszEntry, NULL, &hSymlink, NULL); 576 RTVFS_READ_UNLOCK(pCurDir->hSemRW); 577 *pszEntryEnd = '\0'; 578 if (rc == VERR_PATH_NOT_FOUND) 579 rc = VINF_SUCCESS; 580 if (RT_FAILURE(rc)) 581 break; 582 583 if (hSymlink == NIL_RTVFSSYMLINK) 584 { 585 *ppVfsParentDir = pCurDir; 586 return VINF_SUCCESS; 587 } 588 } 589 else 590 { 591 RTVFS_READ_LOCK(pCurDir->hSemRW); 592 rc = pCurDir->pOps->pfnTraversalOpen(pCurDir->pvThis, pszEntry, &hDir, &hSymlink, &hVfsMnt); 593 RTVFS_READ_UNLOCK(pCurDir->hSemRW); 594 *pszEntryEnd = '/'; 595 if (RT_FAILURE(rc)) 596 break; 597 598 if ( hDir == NIL_RTVFSDIR 599 && hSymlink == NIL_RTVFSSYMLINK 600 && hVfsMnt == NIL_RTVFS) 601 { 602 rc = VERR_NOT_A_DIRECTORY; 603 break; 604 } 605 } 606 Assert( (hDir != NIL_RTVFSDIR && hSymlink == NIL_RTVFSSYMLINK && hVfsMnt == NIL_RTVFS) 607 || (hDir == NIL_RTVFSDIR && hSymlink != NIL_RTVFSSYMLINK && hVfsMnt == NIL_RTVFS) 608 || (hDir == NIL_RTVFSDIR && hSymlink == NIL_RTVFSSYMLINK && hVfsMnt != NIL_RTVFS)); 609 610 if (hDir != NIL_RTVFSDIR) 611 { 612 /* 613 * Directory - advance down the path. 614 */ 615 AssertPtr(hDir); 616 Assert(hDir->uMagic == RTVFSDIR_MAGIC); 617 RTVfsDirRelease(pCurDir); 618 pCurDir = hDir; 619 iComponent++; 620 } 621 else if (hSymlink != NIL_RTVFSSYMLINK) 622 { 623 /* 624 * Symbolic link - deal with it and retry the current component. 625 */ 626 AssertPtr(hSymlink); 627 Assert(hSymlink->uMagic == RTVFSSYMLINK_MAGIC); 628 cLinks++; 629 if (cLinks >= RTVFS_MAX_LINKS) 630 { 631 rc = VERR_TOO_MANY_SYMLINKS; 632 break; 633 } 634 uint16_t iRestartComp = iComponent; 635 rc = rtVfsTraverseHandleSymlink(pPath, &iRestartComp, hSymlink); 636 if (RT_FAILURE(rc)) 637 break; 638 if (iRestartComp != iComponent) 639 { 640 /* Must restart from the root (optimize this). */ 641 RTVfsDirRelease(pCurDir); 642 RTVFS_READ_LOCK(pThis->hSemRW); 643 rc = pThis->pOps->pfnOpenRoot(pThis->pvThis, &pCurDir); 644 RTVFS_READ_UNLOCK(pThis->hSemRW); 645 if (RT_FAILURE(rc)) 646 { 647 pCurDir = NULL; 648 break; 649 } 650 iComponent = 0; 651 } 652 } 653 else 654 { 655 /* 656 * Mount point - deal with it and retry the current component. 657 */ 658 RTVfsDirRelease(pCurDir); 659 RTVFS_READ_LOCK(hVfsMnt->hSemRW); 660 rc = pThis->pOps->pfnOpenRoot(hVfsMnt->pvThis, &pCurDir); 661 RTVFS_READ_UNLOCK(hVfsMnt->hSemRW); 662 if (RT_FAILURE(rc)) 663 { 664 pCurDir = NULL; 665 break; 666 } 667 iComponent = 0; 668 /** @todo union mounts. */ 669 } 670 } 671 672 if (pCurDir) 673 RTVfsDirRelease(pCurDir); 674 675 return rc; 676 } 677 678 679 680 /* 681 * 682 * D I R D I R D I R 683 * D I R D I R D I R 684 * D I R D I R D I R 685 * 686 */ 687 688 RTDECL(uint32_t) RTVfsDirRetain(RTVFSDIR hVfsDir) 689 { 690 RTVFSDIRINTERNAL *pThis = hVfsDir; 691 AssertPtrReturn(pThis, UINT32_MAX); 692 AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, UINT32_MAX); 693 return rtVfsRetain(&pThis->cRefs); 694 } 695 696 697 RTDECL(uint32_t) RTVfsDirRelease(RTVFSDIR hVfsDir) 698 { 699 RTVFSDIRINTERNAL *pThis = hVfsDir; 700 AssertPtrReturn(pThis, UINT32_MAX); 701 AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, UINT32_MAX); 702 703 uint32_t cRefs = rtVfsRelease(&pThis->cRefs); 704 if (!cRefs) 705 { 706 RTVFS_WRITE_LOCK(pThis->hSemRW); 707 ASMAtomicWriteU32(&pThis->uMagic, RTVFSDIR_MAGIC_DEAD); 708 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 709 pThis->pOps->Obj.pfnClose(pThis->pvThis); 710 RTMemFree(pThis); 711 } 712 713 return cRefs; 714 } 715 716 717 718 /* 719 * 720 * S Y M B O L I C L I N K 721 * S Y M B O L I C L I N K 722 * S Y M B O L I C L I N K 723 * 724 */ 725 726 RTDECL(uint32_t) RTVfsSymlinkRetain(RTVFSSYMLINK hVfsSym) 727 { 728 RTVFSSYMLINKINTERNAL *pThis = hVfsSym; 729 AssertPtrReturn(pThis, UINT32_MAX); 730 AssertReturn(pThis->uMagic == RTVFSSYMLINK_MAGIC, UINT32_MAX); 731 return rtVfsRetain(&pThis->cRefs); 732 } 733 734 735 RTDECL(uint32_t) RTVfsSymlinkRelease(RTVFSSYMLINK hVfsSym) 736 { 737 RTVFSSYMLINKINTERNAL *pThis = hVfsSym; 738 AssertPtrReturn(pThis, UINT32_MAX); 739 AssertReturn(pThis->uMagic == RTVFSSYMLINK_MAGIC, UINT32_MAX); 740 741 uint32_t cRefs = rtVfsRelease(&pThis->cRefs); 742 if (!cRefs) 743 { 744 RTVFS_WRITE_LOCK(pThis->hSemRW); 745 ASMAtomicWriteU32(&pThis->uMagic, RTVFSSYMLINK_MAGIC_DEAD); 746 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 747 pThis->pOps->Obj.pfnClose(pThis->pvThis); 748 RTMemFree(pThis); 749 } 750 751 return cRefs; 752 } 753 754 755 RTDECL(int) RTVfsSymlinkRead(RTVFSSYMLINK hVfsSym, char *pszTarget, size_t cbTarget) 756 { 757 RTVFSSYMLINKINTERNAL *pThis = hVfsSym; 758 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 759 AssertReturn(pThis->uMagic == RTVFSSYMLINK_MAGIC, VERR_INVALID_HANDLE); 760 761 RTVFS_WRITE_LOCK(pThis->hSemRW); 762 int rc = pThis->pOps->pfnRead(pThis->pvThis, pszTarget, cbTarget); 763 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 764 765 return rc; 766 } 767 768 769 770 /* 771 * 772 * I / O S T R E A M I / O S T R E A M I / O S T R E A M 773 * I / O S T R E A M I / O S T R E A M I / O S T R E A M 774 * I / O S T R E A M I / O S T R E A M I / O S T R E A M 775 * 776 */ 185 777 186 778 RTDECL(uint32_t) RTVfsIoStrmRetain(RTVFSIOSTREAM hVfsIos) … … 209 801 * need to get to the real one before handing it to RTMemFree. 210 802 */ 803 RTVFS_WRITE_LOCK(pThis->hSemRW); 211 804 ASMAtomicWriteU32(&pThis->uMagic, RTVFSIOSTREAM_MAGIC_DEAD); 805 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 212 806 pThis->pOps->Obj.pfnClose(pThis->pvThis); 213 807 … … 262 856 AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE); 263 857 264 return pThis->pOps->Obj.pfnQueryInfo(pThis->pvThis, pObjInfo, enmAddAttr); 858 RTVFS_READ_LOCK(pThis->hSemRW); 859 int rc = pThis->pOps->Obj.pfnQueryInfo(pThis->pvThis, pObjInfo, enmAddAttr); 860 RTVFS_READ_UNLOCK(pThis->hSemRW); 861 return rc; 265 862 } 266 863 … … 275 872 RTSGBUF SgBuf; 276 873 RTSgBufInit(&SgBuf, &Seg, 1); 277 return pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, &SgBuf, pcbRead == NULL /*fBlocking*/, pcbRead); 874 875 RTVFS_WRITE_LOCK(pThis->hSemRW); 876 int rc = pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, &SgBuf, pcbRead == NULL /*fBlocking*/, pcbRead); 877 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 878 return rc; 278 879 } 279 880 … … 288 889 RTSGBUF SgBuf; 289 890 RTSgBufInit(&SgBuf, &Seg, 1); 290 return pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, &SgBuf, pcbWritten == NULL /*fBlocking*/, pcbWritten); 891 892 RTVFS_WRITE_LOCK(pThis->hSemRW); 893 int rc = pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, &SgBuf, pcbWritten == NULL /*fBlocking*/, pcbWritten); 894 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 895 return rc; 291 896 } 292 897 … … 300 905 AssertReturn(fBlocking || VALID_PTR(pcbRead), VERR_INVALID_PARAMETER); 301 906 302 return pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbRead); 907 RTVFS_WRITE_LOCK(pThis->hSemRW); 908 int rc = pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbRead); 909 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 910 return rc; 303 911 } 304 912 … … 312 920 AssertReturn(fBlocking || VALID_PTR(pcbWritten), VERR_INVALID_PARAMETER); 313 921 314 return pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbWritten); 922 RTVFS_WRITE_LOCK(pThis->hSemRW); 923 int rc = pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbWritten); 924 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 925 return rc; 315 926 } 316 927 … … 322 933 AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE); 323 934 324 return pThis->pOps->pfnFlush(pThis->pvThis); 935 RTVFS_WRITE_LOCK(pThis->hSemRW); 936 int rc = pThis->pOps->pfnFlush(pThis->pvThis); 937 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 938 return rc; 325 939 } 326 940 … … 333 947 AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE); 334 948 335 return pThis->pOps->pfnPollOne(pThis->pvThis, fEvents, cMillies, fIntr, pfRetEvents); 949 RTVFS_WRITE_LOCK(pThis->hSemRW); 950 int rc = pThis->pOps->pfnPollOne(pThis->pvThis, fEvents, cMillies, fIntr, pfRetEvents); 951 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 952 return rc; 336 953 } 337 954 … … 344 961 345 962 RTFOFF off; 963 RTVFS_READ_LOCK(pThis->hSemRW); 346 964 int rc = pThis->pOps->pfnTell(pThis->pvThis, &off); 965 RTVFS_READ_UNLOCK(pThis->hSemRW); 347 966 if (RT_FAILURE(rc)) 348 967 off = rc; … … 351 970 352 971 972 RTDECL(int) RTVfsIoStrmSkip(RTVFSIOSTREAM hVfsIos, RTFOFF cb) 973 { 974 RTVFSIOSTREAMINTERNAL *pThis = hVfsIos; 975 AssertPtrReturn(pThis, -1); 976 AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, -1); 977 AssertReturn(cb >= 0, VERR_INVALID_PARAMETER); 978 979 int rc; 980 if (pThis->pOps->pfnSkip) 981 { 982 RTVFS_WRITE_LOCK(pThis->hSemRW); 983 rc = pThis->pOps->pfnSkip(pThis->pvThis, cb); 984 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 985 } 986 else 987 { 988 void *pvBuf = RTMemTmpAlloc(_64K); 989 if (pvBuf) 990 { 991 rc = VINF_SUCCESS; 992 while (cb > 0) 993 { 994 size_t cbToRead = RT_MIN(cb, _64K); 995 RTVFS_WRITE_LOCK(pThis->hSemRW); 996 rc = RTVfsIoStrmRead(hVfsIos, pvBuf, cbToRead, NULL); 997 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 998 if (RT_FAILURE(rc)) 999 break; 1000 cb -= cbToRead; 1001 } 1002 1003 RTMemTmpFree(pvBuf); 1004 } 1005 else 1006 rc = VERR_NO_TMP_MEMORY; 1007 } 1008 return rc; 1009 } 1010 1011 1012 RTDECL(int) RTVfsIoStrmZeroFill(RTVFSIOSTREAM hVfsIos, RTFOFF cb) 1013 { 1014 RTVFSIOSTREAMINTERNAL *pThis = hVfsIos; 1015 AssertPtrReturn(pThis, -1); 1016 AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, -1); 1017 1018 int rc; 1019 if (pThis->pOps->pfnSkip) 1020 { 1021 RTVFS_WRITE_LOCK(pThis->hSemRW); 1022 rc = pThis->pOps->pfnZeroFill(pThis->pvThis, cb); 1023 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 1024 } 1025 else 1026 { 1027 void *pvBuf = RTMemTmpAllocZ(_64K); 1028 if (pvBuf) 1029 { 1030 rc = VINF_SUCCESS; 1031 while (cb > 0) 1032 { 1033 size_t cbToWrite = RT_MIN(cb, _64K); 1034 RTVFS_WRITE_LOCK(pThis->hSemRW); 1035 rc = RTVfsIoStrmWrite(hVfsIos, pvBuf, cbToWrite, NULL); 1036 RTVFS_WRITE_UNLOCK(pThis->hSemRW); 1037 if (RT_FAILURE(rc)) 1038 break; 1039 cb -= cbToWrite; 1040 } 1041 1042 RTMemTmpFree(pvBuf); 1043 } 1044 else 1045 rc = VERR_NO_TMP_MEMORY; 1046 } 1047 return rc; 1048 } 1049 1050 1051 1052 1053 1054 1055 /* 1056 * 1057 * F I L E F I L E F I L E 1058 * F I L E F I L E F I L E 1059 * F I L E F I L E F I L E 1060 * 1061 */ 353 1062 354 1063 RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, … … 403 1112 404 1113 1114 RTDECL(int) RTVfsFileOpen(RTVFS hVfs, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile) 1115 { 1116 /* 1117 * Validate input. 1118 */ 1119 RTVFSINTERNAL *pThis = hVfs; 1120 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1121 AssertReturn(pThis->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE); 1122 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 1123 AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER); 1124 1125 int rc = rtFileRecalcAndValidateFlags(&fOpen); 1126 if (RT_FAILURE(rc)) 1127 return rc; 1128 1129 /* 1130 * Parse the path, assume current directory is root since we've got no 1131 * caller context here. 1132 */ 1133 PRTVFSPARSEDPATH pPath; 1134 rc = RTVfsParsePathA(pszFilename, "/", &pPath); 1135 if (RT_SUCCESS(rc)) 1136 { 1137 if (!pPath->fDirSlash) 1138 { 1139 /* 1140 * Tranverse the path, resolving the parent node and any symlinks 1141 * in the final element, and ask the directory to open the file. 1142 */ 1143 RTVFSDIRINTERNAL *pVfsParentDir; 1144 rc = rtVfsTraverseToParent(pThis, pPath, true /*fFollowSymlink*/, &pVfsParentDir); 1145 if (RT_SUCCESS(rc)) 1146 { 1147 const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]]; 1148 1149 /** @todo there is a symlink creation race here. */ 1150 RTVFS_WRITE_LOCK(pVfsParentDir->hSemRW); 1151 rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->pvThis, pszEntryName, fOpen, phVfsFile); 1152 RTVFS_WRITE_UNLOCK(pVfsParentDir->hSemRW); 1153 1154 RTVfsDirRelease(pVfsParentDir); 1155 1156 if (RT_SUCCESS(rc)) 1157 { 1158 AssertPtr(*phVfsFile); 1159 Assert((*phVfsFile)->uMagic == RTVFSFILE_MAGIC); 1160 } 1161 } 1162 } 1163 else 1164 rc = VERR_INVALID_PARAMETER; 1165 RTVfsParsePathFree(pPath); 1166 } 1167 return rc; 1168 } 1169 1170 405 1171 RTDECL(uint32_t) RTVfsFileRetain(RTVFSFILE hVfsFile) 406 1172 { … … 421 1187 if (!cRefs) 422 1188 { 1189 RTVFS_WRITE_LOCK(pThis->Stream.hSemRW); 423 1190 ASMAtomicWriteU32(&pThis->uMagic, RTVFSFILE_MAGIC_DEAD); 424 1191 ASMAtomicWriteU32(&pThis->Stream.uMagic, RTVFSIOSTREAM_MAGIC_DEAD); 1192 RTVFS_WRITE_UNLOCK(pThis->Stream.hSemRW); 1193 425 1194 pThis->pOps->Stream.Obj.pfnClose(pThis->Stream.pvThis); 426 1195 RTMemFree(pThis); -
trunk/src/VBox/Runtime/common/vfs/vfsstdfile.cpp
r33821 r33859 243 243 244 244 /** 245 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnSkip} 246 */ 247 static DECLCALLBACK(int) rtVfsStdFile_Skip(void *pvThis, RTFOFF cb) 248 { 249 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis; 250 uint64_t offIgnore; 251 return RTFileSeek(pThis->hFile, cb, RTFILE_SEEK_CURRENT, &offIgnore); 252 } 253 254 255 /** 245 256 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode} 246 257 */ … … 339 350 rtVfsStdFile_PollOne, 340 351 rtVfsStdFile_Tell, 352 rtVfsStdFile_Skip, 353 NULL /*ZeroFill*/, 341 354 RTVFSIOSTREAMOPS_VERSION, 342 355 },
Note:
See TracChangeset
for help on using the changeset viewer.