VirtualBox

Changeset 69828 in vbox


Ignore:
Timestamp:
Nov 24, 2017 5:32:23 PM (7 years ago)
Author:
vboxsync
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.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/vfslowlevel.h

    r69826 r69828  
    597597     *
    598598     * @returns IPRT status code.
     599     * @retval  VERR_IS_A_SYMLINK if @a pszSubDir is a symbolic link.
     600     * @retval  VERR_NOT_A_DIRECTORY is okay for symbolic links too.
     601     *
    599602     * @param   pvThis      The implementation specific directory data.
    600603     * @param   pszSubDir   The name of the immediate subdirectory to open.
  • trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp

    r69826 r69828  
    102102/** Pointer to a the internal data of a DVM volume file. */
    103103typedef RTVFSDVMFILE *PRTVFSDVMFILE;
     104
     105
     106/*********************************************************************************************************************************
     107*   Internal Functions                                                                                                           *
     108*********************************************************************************************************************************/
     109static DECLCALLBACK(int) rtDvmVfsVol_OpenRoot(void *pvThis, PRTVFSDIR phVfsDir);
    104110
    105111
     
    722728{
    723729    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
    724     RTDVMVOLUME  hVolume;
     730
     731    /*
     732     * Special case: '.' and '..'
     733     */
     734    if (   pszEntry[0] == '.'
     735        && (   pszEntry[1] == '\0'
     736            || (   pszEntry[1] == '.'
     737                && pszEntry[2] == '\0')))
     738    {
     739        if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
     740            || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE
     741            || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
     742        {
     743            if (fFlags & RTVFSOBJ_F_OPEN_DIRECTORY)
     744            {
     745                RTVFSDIR hVfsDir;
     746                int rc = rtDvmVfsVol_OpenRoot(pThis->pVfsVol, &hVfsDir);
     747                if (RT_SUCCESS(rc))
     748                {
     749                    *phVfsObj = RTVfsObjFromDir(hVfsDir);
     750                    RTVfsDirRelease(hVfsDir);
     751                    AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
     752                }
     753                return rc;
     754            }
     755            return VERR_IS_A_DIRECTORY;
     756        }
     757        return VERR_ACCESS_DENIED;
     758    }
     759
     760    /*
     761     * Open volume file.
     762     */
     763    RTDVMVOLUME hVolume;
    725764    int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume);
    726765    if (RT_SUCCESS(rc))
     
    775814
    776815/**
    777  * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
    778  */
    779 static DECLCALLBACK(int) rtDvmVfsDir_OpenDir(void *pvThis, const char *pszSubDir, uint32_t fFlags, PRTVFSDIR phVfsDir)
    780 {
    781     NOREF(pvThis); NOREF(pszSubDir); NOREF(fFlags); NOREF(phVfsDir);
    782     return VERR_FILE_NOT_FOUND;
    783 }
    784 
    785 
    786 /**
    787816 * @interface_method_impl{RTVFSDIROPS,pfnCreateDir}
    788817 */
     
    812841    RT_NOREF(pvThis, pszSymlink, pszTarget, enmType, phVfsSymlink);
    813842    return VERR_NOT_SUPPORTED;
    814 }
    815 
    816 
    817 /**
    818  * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
    819  */
    820 static DECLCALLBACK(int) rtDvmVfsDir_QueryEntryInfo(void *pvThis, const char *pszEntry,
    821                                                     PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
    822 {
    823     PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
    824     RTDVMVOLUME  hVolume;
    825     int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume);
    826     if (RT_SUCCESS(rc))
    827     {
    828         rc = rtDvmVfsFile_QueryInfoWorker(hVolume, pThis->pVfsVol->hVolMgr, pThis->pVfsVol->fReadOnly, pObjInfo, enmAddAttr);
    829         RTDvmVolumeRelease(hVolume);
    830     }
    831     return rc;
    832843}
    833844
     
    9971008    NULL /* pfnFollowAbsoluteSymlink */,
    9981009    rtDvmVfsDir_OpenFile,
    999     rtDvmVfsDir_OpenDir,
     1010    NULL /* pfnOpenDir */,
    10001011    rtDvmVfsDir_CreateDir,
    10011012    rtDvmVfsDir_OpenSymlink,
    10021013    rtDvmVfsDir_CreateSymlink,
    1003     rtDvmVfsDir_QueryEntryInfo,
     1014    NULL /* pfnQueryEntryInfo */,
    10041015    rtDvmVfsDir_UnlinkEntry,
    10051016    rtDvmVfsDir_RenameEntry,
  • trunk/src/VBox/Runtime/common/fs/fatvfs.cpp

    r69826 r69828  
    507507static int  rtFsFatDirShrd_PutEntryAfterUpdate(PRTFSFATDIRSHRD pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock);
    508508static int  rtFsFatDirShrd_Flush(PRTFSFATDIRSHRD pThis);
     509static int  rtFsFatDir_NewWithShared(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pShared, PRTVFSDIR phVfsDir);
    509510static int  rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
    510511                           uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir);
     
    40064007    PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
    40074008    PRTFSFATDIRSHRD pShared = pThis->pShared;
     4009    int             rc;
     4010
     4011    /*
     4012     * Special cases '.' and '.'
     4013     */
     4014    if (pszEntry[0] == '.')
     4015    {
     4016        PRTFSFATDIRSHRD pSharedToOpen;
     4017        if (pszEntry[1] == '\0')
     4018            pSharedToOpen = pShared;
     4019        else if (pszEntry[1] == '.' && pszEntry[2] == '\0')
     4020        {
     4021            pSharedToOpen = pShared->Core.pParentDir;
     4022            if (!pSharedToOpen)
     4023                pSharedToOpen = pShared;
     4024        }
     4025        else
     4026            pSharedToOpen = NULL;
     4027        if (pSharedToOpen)
     4028        {
     4029            if (fFlags & RTVFSOBJ_F_OPEN_DIRECTORY)
     4030            {
     4031                if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
     4032                    || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE)
     4033                {
     4034                    rtFsFatDirShrd_Retain(pSharedToOpen);
     4035                    RTVFSDIR hVfsDir;
     4036                    rc = rtFsFatDir_NewWithShared(pShared->Core.pVol, pSharedToOpen, &hVfsDir);
     4037                    if (RT_SUCCESS(rc))
     4038                    {
     4039                        *phVfsObj = RTVfsObjFromDir(hVfsDir);
     4040                        RTVfsDirRelease(hVfsDir);
     4041                        AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
     4042                    }
     4043                }
     4044                else
     4045                    rc = VERR_ACCESS_DENIED;
     4046            }
     4047            else
     4048                rc = VERR_IS_A_DIRECTORY;
     4049            return rc;
     4050        }
     4051    }
    40084052
    40094053    /*
     
    40134057    bool        fLong;
    40144058    FATDIRENTRY DirEntry;
    4015     int rc = rtFsFatDirShrd_FindEntry(pShared, pszEntry, &offEntryInDir, &fLong, &DirEntry);
     4059    rc = rtFsFatDirShrd_FindEntry(pShared, pszEntry, &offEntryInDir, &fLong, &DirEntry);
    40164060    if (RT_SUCCESS(rc))
    40174061    {
     
    41954239
    41964240/**
    4197  * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
    4198  */
    4199 static DECLCALLBACK(int) rtFsFatDir_OpenDir(void *pvThis, const char *pszSubDir, uint32_t fFlags, PRTVFSDIR phVfsDir)
    4200 {
    4201     PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
    4202     PRTFSFATDIRSHRD pShared = pThis->pShared;
    4203     AssertReturn(!fFlags, VERR_INVALID_FLAGS);
    4204 
    4205     /*
    4206      * Try open directory.
    4207      */
    4208     uint32_t    offEntryInDir;
    4209     bool        fLong;
    4210     FATDIRENTRY DirEntry;
    4211     int rc = rtFsFatDirShrd_FindEntry(pShared, pszSubDir, &offEntryInDir, &fLong, &DirEntry);
    4212     LogFlow(("rtFsFatDir_OpenDir: FindEntry(,%s,,,) -> %Rrc fLong=%d offEntryInDir=%#RX32\n", pszSubDir, rc, fLong, offEntryInDir));
    4213     if (RT_SUCCESS(rc))
    4214     {
    4215         switch (DirEntry.fAttrib & (FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME))
    4216         {
    4217             case FAT_ATTR_DIRECTORY:
    4218                 rc = rtFsFatDir_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir,
    4219                                     RTFSFAT_GET_CLUSTER(&DirEntry, pShared->Core.pVol), UINT64_MAX /*offDisk*/,
    4220                                     DirEntry.cbFile, phVfsDir);
    4221                 break;
    4222 
    4223             case 0:
    4224                 rc = VERR_NOT_A_DIRECTORY;
    4225                 break;
    4226 
    4227             default:
    4228                 rc = VERR_PATH_NOT_FOUND;
    4229                 break;
    4230         }
    4231     }
    4232     return rc;
    4233 }
    4234 
    4235 
    4236 /**
    42374241 * @interface_method_impl{RTVFSDIROPS,pfnCreateDir}
    42384242 */
     
    42524256    if (rc != VERR_FILE_NOT_FOUND)
    42534257        return RT_SUCCESS(rc) ? VERR_ALREADY_EXISTS : rc;
     4258
     4259    if (   strcmp(pszSubDir, ".") == 0
     4260        || strcmp(pszSubDir, "..") == 0)
     4261        return VERR_ALREADY_EXISTS;
    42544262
    42554263    /*
     
    42874295
    42884296
     4297#if 0
    42894298/**
    42904299 * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
     
    43164325    return rc;
    43174326}
     4327#endif
    43184328
    43194329
     
    47254735    NULL /* pfnFollowAbsoluteSymlink */,
    47264736    rtFsFatDir_OpenFile,
    4727     rtFsFatDir_OpenDir,
     4737    NULL /* pfnOpenDir */,
    47284738    rtFsFatDir_CreateDir,
    47294739    rtFsFatDir_OpenSymlink,
    47304740    rtFsFatDir_CreateSymlink,
    4731     rtFsFatDir_QueryEntryInfo,
     4741    NULL /* pfnQueryEntryInfo */,
    47324742    rtFsFatDir_UnlinkEntry,
    47334743    rtFsFatDir_RenameEntry,
  • trunk/src/VBox/Runtime/common/fs/isovfs.cpp

    r69826 r69828  
    461461static void rtFsIsoDirShrd_AddOpenChild(PRTFSISODIRSHRD pDir, PRTFSISOCORE pChild);
    462462static void rtFsIsoDirShrd_RemoveOpenChild(PRTFSISODIRSHRD pDir, PRTFSISOCORE pChild);
     463static int  rtFsIsoDir_NewWithShared(PRTFSISOVOL pThis, PRTFSISODIRSHRD pShared, PRTVFSDIR phVfsDir);
    463464static int  rtFsIsoDir_New9660(PRTFSISOVOL pThis, PRTFSISODIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
    464465                               uint32_t cDirRecs, uint64_t offDirRec, PRTVFSDIR phVfsDir);
     
    28972898    PRTFSISODIROBJ  pThis   = (PRTFSISODIROBJ)pvThis;
    28982899    PRTFSISODIRSHRD pShared = pThis->pShared;
     2900    int rc;
    28992901
    29002902    /*
    29012903     * We cannot create or replace anything, just open stuff.
    29022904     */
    2903     if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE
    2904         || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
     2905    if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
     2906        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE)
     2907    { /* likely */ }
     2908    else
    29052909        return VERR_WRITE_PROTECT;
    29062910
    29072911    /*
     2912     * Special cases '.' and '.'
     2913     */
     2914    if (pszEntry[0] == '.')
     2915    {
     2916        PRTFSISODIRSHRD pSharedToOpen;
     2917        if (pszEntry[1] == '\0')
     2918            pSharedToOpen = pShared;
     2919        else if (pszEntry[1] == '.' && pszEntry[2] == '\0')
     2920        {
     2921            pSharedToOpen = pShared->Core.pParentDir;
     2922            if (!pSharedToOpen)
     2923                pSharedToOpen = pShared;
     2924        }
     2925        else
     2926            pSharedToOpen = NULL;
     2927        if (pSharedToOpen)
     2928        {
     2929            if (fFlags & RTVFSOBJ_F_OPEN_DIRECTORY)
     2930            {
     2931                rtFsIsoDirShrd_Retain(pSharedToOpen);
     2932                RTVFSDIR hVfsDir;
     2933                rc = rtFsIsoDir_NewWithShared(pShared->Core.pVol, pSharedToOpen, &hVfsDir);
     2934                if (RT_SUCCESS(rc))
     2935                {
     2936                    *phVfsObj = RTVfsObjFromDir(hVfsDir);
     2937                    RTVfsDirRelease(hVfsDir);
     2938                    AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
     2939                }
     2940            }
     2941            else
     2942                rc = VERR_IS_A_DIRECTORY;
     2943            return rc;
     2944        }
     2945    }
     2946
     2947    /*
    29082948     * Try open whatever it is.
    29092949     */
    2910     int rc;
    29112950    if (pShared->Core.pVol->enmType != RTFSISOVOLTYPE_UDF)
    29122951    {
     2952
    29132953        /*
    29142954         * ISO 9660
     
    31123152
    31133153
     3154#if 0
    31143155/**
    31153156 * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
     
    31853226    return rc;
    31863227}
     3228#endif
    31873229
    31883230
     
    32183260
    32193261
     3262#if 0
    32203263/**
    32213264 * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
     
    32813324    return rc;
    32823325}
     3326#endif
    32833327
    32843328
     
    36933737    NULL /* pfnFollowAbsoluteSymlink */,
    36943738    rtFsIsoDir_OpenFile,
    3695     rtFsIsoDir_OpenDir,
     3739    NULL /* pfnOpenDir */,
    36963740    rtFsIsoDir_CreateDir,
    36973741    rtFsIsoDir_OpenSymlink,
    36983742    rtFsIsoDir_CreateSymlink,
    3699     rtFsIsoDir_QueryEntryInfo,
     3743    NULL /* pfnQueryEntryInfo */,
    37003744    rtFsIsoDir_UnlinkEntry,
    37013745    rtFsIsoDir_RenameEntry,
  • 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.

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