VirtualBox

Ignore:
Timestamp:
Nov 24, 2017 5:32:23 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119259
Message:

IPRT/VFS: Reimplemented RTVfsDirOpen and RTVfsDirOpenDir to use pfnOpen, making pfnOpenDir optional. Fixed a couple of problems related to '.' and '..' handling in pfnQueryEntryInfo and pfnOpen implementations.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r69827 r69828  
    12601260                    break;
    12611261            }
     1262            RTVfsDirRelease(pVfsParentDir);
    12621263        }
    12631264        RTVfsParsePathFree(pPath);
     
    18851886    AssertPtr(ppVfsParentDir);
    18861887    *ppVfsParentDir = NULL;
    1887     AssertReturn(pPath->cComponents > 0, VERR_INTERNAL_ERROR_3);
    18881888    Assert(RTPATH_F_IS_VALID(fFlags, 0));
    18891889
     
    21922192                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName,
    21932193                                                  RTFILE_O_ACCESS_ATTR_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
    2194                                                   RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING, &hVfsObj);
     2194                                                  fObjFlags, &hVfsObj);
    21952195                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    21962196                if (RT_FAILURE(rc))
     
    22152215                    break;
    22162216            }
     2217            RTVfsDirRelease(pVfsParentDir);
    22172218        }
    2218 
    22192219        RTVfsParsePathFree(pPath);
    22202220    }
     
    25402540    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    25412541    AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
    2542     AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     2542    AssertReturn(!fFlags, VERR_INVALID_FLAGS); /** @todo sort out flags! */
    25432543
    25442544    /*
     
    25502550    if (RT_SUCCESS(rc))
    25512551    {
    2552         if (pPath->cComponents > 0)
     2552        /*
     2553         * Tranverse the path, resolving the parent node.
     2554         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenDir.
     2555         */
     2556        RTVFSDIRINTERNAL *pVfsParentDir;
     2557        rc = rtVfsTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir);
     2558        if (RT_SUCCESS(rc))
    25532559        {
    25542560            /*
    2555              * Tranverse the path, resolving the parent node and any symlinks
    2556              * in the final element, and ask the directory to open the subdir.
     2561             * Do the opening.  Loop if we need to follow symbolic links.
    25572562             */
    2558             RTVFSDIRINTERNAL *pVfsParentDir;
    2559             rc = rtVfsTraverseToParent(pThis, pPath, RTPATH_F_FOLLOW_LINK, &pVfsParentDir);
    2560             if (RT_SUCCESS(rc))
     2563            uint64_t fOpenFlags = RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN;
     2564            uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_DIRECTORY | RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING;
     2565            for (uint32_t cLoops = 1; ; cLoops++)
    25612566            {
     2567                /* Do the querying.  If pfnOpenDir is available, we use it first, falling
     2568                   back on pfnOpen in case of symbolic links that needs following. */
    25622569                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    2563 
    2564                 /** @todo there is a symlink creation race here. */
     2570                if (pVfsParentDir->pOps->pfnQueryEntryInfo)
     2571                {
     2572                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
     2573                    rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
     2574                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
     2575                    if (RT_SUCCESS(rc)
     2576                        || (   rc != VERR_NOT_A_DIRECTORY
     2577                            && rc != VERR_IS_A_SYMLINK))
     2578                        break;
     2579                }
     2580
     2581                RTVFSOBJ hVfsObj;
    25652582                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
    2566                 rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
     2583                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpenFlags, fObjFlags, &hVfsObj);
    25672584                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    2568 
    2569                 RTVfsDirRelease(pVfsParentDir);
    2570 
    2571                 if (RT_SUCCESS(rc))
     2585                if (RT_FAILURE(rc))
     2586                    break;
     2587
     2588                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
     2589                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
     2590                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
    25722591                {
    2573                     AssertPtr(*phVfsDir);
    2574                     Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
     2592                    *phVfsDir = RTVfsObjToDir(hVfsObj);
     2593                    AssertStmt(*phVfsDir != NIL_RTVFSDIR, rc = VERR_INTERNAL_ERROR_3);
     2594                    RTVfsObjRelease(hVfsObj);
     2595                    break;
    25752596                }
     2597
     2598                /* Follow symbolic link. */
     2599                if (cLoops < RTVFS_MAX_LINKS)
     2600                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK);
     2601                else
     2602                    rc = VERR_TOO_MANY_SYMLINKS;
     2603                RTVfsObjRelease(hVfsObj);
     2604                if (RT_FAILURE(rc))
     2605                    break;
    25762606            }
    2577         }
    2578         /*
    2579          * If the path boils down to '.' return the root directory.
    2580          */
    2581         else
    2582         {
    2583             RTVfsLockAcquireRead(pThis->Base.hLock);
    2584             rc = pThis->pOps->pfnOpenRoot(pThis->Base.pvThis, phVfsDir);
    2585             RTVfsLockReleaseRead(pThis->Base.hLock);
     2607            RTVfsDirRelease(pVfsParentDir);
    25862608        }
    25872609        RTVfsParsePathFree(pPath);
     
    26012623    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    26022624    AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
    2603     AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     2625    AssertReturn(!fFlags, VERR_INVALID_FLAGS); /** @todo sort out flags! */
    26042626
    26052627    /*
     
    26102632    if (RT_SUCCESS(rc))
    26112633    {
    2612         if (pPath->cComponents > 0)
     2634        /*
     2635         * Tranverse the path, resolving the parent node.
     2636         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenDir.
     2637         */
     2638        RTVFSDIRINTERNAL *pVfsParentDir;
     2639        rc = rtVfsDirTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir);
     2640        if (RT_SUCCESS(rc))
    26132641        {
    26142642            /*
    2615              * Tranverse the path, resolving the parent node and any symlinks
    2616              * in the final element, and ask the directory to open the subdir.
     2643             * Do the opening.  Loop if we need to follow symbolic links.
    26172644             */
    2618             RTVFSDIRINTERNAL *pVfsParentDir;
    2619             rc = rtVfsDirTraverseToParent(pThis, pPath, RTPATH_F_FOLLOW_LINK, &pVfsParentDir);
    2620             if (RT_SUCCESS(rc))
     2645            uint64_t fOpenFlags = RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN;
     2646            uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_DIRECTORY | RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING;
     2647            for (uint32_t cLoops = 1; ; cLoops++)
    26212648            {
     2649                /* Do the querying.  If pfnOpenDir is available, we use it first, falling
     2650                   back on pfnOpen in case of symbolic links that needs following. */
    26222651                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    2623 
    2624                 /** @todo there is a symlink creation race here. */
     2652                if (pVfsParentDir->pOps->pfnQueryEntryInfo)
     2653                {
     2654                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
     2655                    rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
     2656                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
     2657                    if (RT_SUCCESS(rc)
     2658                        || (   rc != VERR_NOT_A_DIRECTORY
     2659                            && rc != VERR_IS_A_SYMLINK))
     2660                        break;
     2661                }
     2662
     2663                RTVFSOBJ hVfsObj;
    26252664                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
    2626                 rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
     2665                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpenFlags, fObjFlags, &hVfsObj);
    26272666                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    2628 
    2629                 RTVfsDirRelease(pVfsParentDir);
    2630 
    2631                 if (RT_SUCCESS(rc))
     2667                if (RT_FAILURE(rc))
     2668                    break;
     2669
     2670                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
     2671                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
     2672                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
    26322673                {
    2633                     AssertPtr(*phVfsDir);
    2634                     Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
     2674                    *phVfsDir = RTVfsObjToDir(hVfsObj);
     2675                    AssertStmt(*phVfsDir != NIL_RTVFSDIR, rc = VERR_INTERNAL_ERROR_3);
     2676                    RTVfsObjRelease(hVfsObj);
     2677                    break;
    26352678                }
     2679
     2680                /* Follow symbolic link. */
     2681                if (cLoops < RTVFS_MAX_LINKS)
     2682                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK);
     2683                else
     2684                    rc = VERR_TOO_MANY_SYMLINKS;
     2685                RTVfsObjRelease(hVfsObj);
     2686                if (RT_FAILURE(rc))
     2687                    break;
    26362688            }
    2637         }
    2638         /*
    2639          * The path boils down to '.', call pfnOpenDir on pThis with '.' as input.
    2640          * The caller may wish for a new directory instance to enumerate the entries
    2641          * in parallel or some such thing.
    2642          */
    2643         else
    2644         {
    2645             RTVfsLockAcquireWrite(pThis->Base.hLock);
    2646             rc = pThis->pOps->pfnOpenDir(pThis->Base.pvThis, ".", fFlags, phVfsDir);
    2647             RTVfsLockReleaseWrite(pThis->Base.hLock);
     2689            RTVfsDirRelease(pVfsParentDir);
    26482690        }
    26492691        RTVfsParsePathFree(pPath);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette