Index: /trunk/include/iprt/vfslowlevel.h
===================================================================
--- /trunk/include/iprt/vfslowlevel.h	(revision 69827)
+++ /trunk/include/iprt/vfslowlevel.h	(revision 69828)
@@ -597,4 +597,7 @@
      *
      * @returns IPRT status code.
+     * @retval  VERR_IS_A_SYMLINK if @a pszSubDir is a symbolic link.
+     * @retval  VERR_NOT_A_DIRECTORY is okay for symbolic links too.
+     *
      * @param   pvThis      The implementation specific directory data.
      * @param   pszSubDir   The name of the immediate subdirectory to open.
Index: /trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp	(revision 69827)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp	(revision 69828)
@@ -102,4 +102,10 @@
 /** Pointer to a the internal data of a DVM volume file. */
 typedef RTVFSDVMFILE *PRTVFSDVMFILE;
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static DECLCALLBACK(int) rtDvmVfsVol_OpenRoot(void *pvThis, PRTVFSDIR phVfsDir);
 
 
@@ -722,5 +728,38 @@
 {
     PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
-    RTDVMVOLUME  hVolume;
+
+    /*
+     * Special case: '.' and '..'
+     */
+    if (   pszEntry[0] == '.'
+        && (   pszEntry[1] == '\0'
+            || (   pszEntry[1] == '.'
+                && pszEntry[2] == '\0')))
+    {
+        if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
+            || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE
+            || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
+        {
+            if (fFlags & RTVFSOBJ_F_OPEN_DIRECTORY)
+            {
+                RTVFSDIR hVfsDir;
+                int rc = rtDvmVfsVol_OpenRoot(pThis->pVfsVol, &hVfsDir);
+                if (RT_SUCCESS(rc))
+                {
+                    *phVfsObj = RTVfsObjFromDir(hVfsDir);
+                    RTVfsDirRelease(hVfsDir);
+                    AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
+                }
+                return rc;
+            }
+            return VERR_IS_A_DIRECTORY;
+        }
+        return VERR_ACCESS_DENIED;
+    }
+
+    /*
+     * Open volume file.
+     */
+    RTDVMVOLUME hVolume;
     int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume);
     if (RT_SUCCESS(rc))
@@ -775,14 +814,4 @@
 
 /**
- * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
- */
-static DECLCALLBACK(int) rtDvmVfsDir_OpenDir(void *pvThis, const char *pszSubDir, uint32_t fFlags, PRTVFSDIR phVfsDir)
-{
-    NOREF(pvThis); NOREF(pszSubDir); NOREF(fFlags); NOREF(phVfsDir);
-    return VERR_FILE_NOT_FOUND;
-}
-
-
-/**
  * @interface_method_impl{RTVFSDIROPS,pfnCreateDir}
  */
@@ -812,22 +841,4 @@
     RT_NOREF(pvThis, pszSymlink, pszTarget, enmType, phVfsSymlink);
     return VERR_NOT_SUPPORTED;
-}
-
-
-/**
- * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
- */
-static DECLCALLBACK(int) rtDvmVfsDir_QueryEntryInfo(void *pvThis, const char *pszEntry,
-                                                    PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
-{
-    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
-    RTDVMVOLUME  hVolume;
-    int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume);
-    if (RT_SUCCESS(rc))
-    {
-        rc = rtDvmVfsFile_QueryInfoWorker(hVolume, pThis->pVfsVol->hVolMgr, pThis->pVfsVol->fReadOnly, pObjInfo, enmAddAttr);
-        RTDvmVolumeRelease(hVolume);
-    }
-    return rc;
 }
 
@@ -997,9 +1008,9 @@
     NULL /* pfnFollowAbsoluteSymlink */,
     rtDvmVfsDir_OpenFile,
-    rtDvmVfsDir_OpenDir,
+    NULL /* pfnOpenDir */,
     rtDvmVfsDir_CreateDir,
     rtDvmVfsDir_OpenSymlink,
     rtDvmVfsDir_CreateSymlink,
-    rtDvmVfsDir_QueryEntryInfo,
+    NULL /* pfnQueryEntryInfo */,
     rtDvmVfsDir_UnlinkEntry,
     rtDvmVfsDir_RenameEntry,
Index: /trunk/src/VBox/Runtime/common/fs/fatvfs.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/fs/fatvfs.cpp	(revision 69827)
+++ /trunk/src/VBox/Runtime/common/fs/fatvfs.cpp	(revision 69828)
@@ -507,4 +507,5 @@
 static int  rtFsFatDirShrd_PutEntryAfterUpdate(PRTFSFATDIRSHRD pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock);
 static int  rtFsFatDirShrd_Flush(PRTFSFATDIRSHRD pThis);
+static int  rtFsFatDir_NewWithShared(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pShared, PRTVFSDIR phVfsDir);
 static int  rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
                            uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir);
@@ -4006,4 +4007,47 @@
     PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
     PRTFSFATDIRSHRD pShared = pThis->pShared;
+    int             rc;
+
+    /*
+     * Special cases '.' and '.'
+     */
+    if (pszEntry[0] == '.')
+    {
+        PRTFSFATDIRSHRD pSharedToOpen;
+        if (pszEntry[1] == '\0')
+            pSharedToOpen = pShared;
+        else if (pszEntry[1] == '.' && pszEntry[2] == '\0')
+        {
+            pSharedToOpen = pShared->Core.pParentDir;
+            if (!pSharedToOpen)
+                pSharedToOpen = pShared;
+        }
+        else
+            pSharedToOpen = NULL;
+        if (pSharedToOpen)
+        {
+            if (fFlags & RTVFSOBJ_F_OPEN_DIRECTORY)
+            {
+                if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
+                    || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE)
+                {
+                    rtFsFatDirShrd_Retain(pSharedToOpen);
+                    RTVFSDIR hVfsDir;
+                    rc = rtFsFatDir_NewWithShared(pShared->Core.pVol, pSharedToOpen, &hVfsDir);
+                    if (RT_SUCCESS(rc))
+                    {
+                        *phVfsObj = RTVfsObjFromDir(hVfsDir);
+                        RTVfsDirRelease(hVfsDir);
+                        AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
+                    }
+                }
+                else
+                    rc = VERR_ACCESS_DENIED;
+            }
+            else
+                rc = VERR_IS_A_DIRECTORY;
+            return rc;
+        }
+    }
 
     /*
@@ -4013,5 +4057,5 @@
     bool        fLong;
     FATDIRENTRY DirEntry;
-    int rc = rtFsFatDirShrd_FindEntry(pShared, pszEntry, &offEntryInDir, &fLong, &DirEntry);
+    rc = rtFsFatDirShrd_FindEntry(pShared, pszEntry, &offEntryInDir, &fLong, &DirEntry);
     if (RT_SUCCESS(rc))
     {
@@ -4195,44 +4239,4 @@
 
 /**
- * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
- */
-static DECLCALLBACK(int) rtFsFatDir_OpenDir(void *pvThis, const char *pszSubDir, uint32_t fFlags, PRTVFSDIR phVfsDir)
-{
-    PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
-    PRTFSFATDIRSHRD pShared = pThis->pShared;
-    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
-
-    /*
-     * Try open directory.
-     */
-    uint32_t    offEntryInDir;
-    bool        fLong;
-    FATDIRENTRY DirEntry;
-    int rc = rtFsFatDirShrd_FindEntry(pShared, pszSubDir, &offEntryInDir, &fLong, &DirEntry);
-    LogFlow(("rtFsFatDir_OpenDir: FindEntry(,%s,,,) -> %Rrc fLong=%d offEntryInDir=%#RX32\n", pszSubDir, rc, fLong, offEntryInDir));
-    if (RT_SUCCESS(rc))
-    {
-        switch (DirEntry.fAttrib & (FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME))
-        {
-            case FAT_ATTR_DIRECTORY:
-                rc = rtFsFatDir_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir,
-                                    RTFSFAT_GET_CLUSTER(&DirEntry, pShared->Core.pVol), UINT64_MAX /*offDisk*/,
-                                    DirEntry.cbFile, phVfsDir);
-                break;
-
-            case 0:
-                rc = VERR_NOT_A_DIRECTORY;
-                break;
-
-            default:
-                rc = VERR_PATH_NOT_FOUND;
-                break;
-        }
-    }
-    return rc;
-}
-
-
-/**
  * @interface_method_impl{RTVFSDIROPS,pfnCreateDir}
  */
@@ -4252,4 +4256,8 @@
     if (rc != VERR_FILE_NOT_FOUND)
         return RT_SUCCESS(rc) ? VERR_ALREADY_EXISTS : rc;
+
+    if (   strcmp(pszSubDir, ".") == 0
+        || strcmp(pszSubDir, "..") == 0)
+        return VERR_ALREADY_EXISTS;
 
     /*
@@ -4287,4 +4295,5 @@
 
 
+#if 0
 /**
  * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
@@ -4316,4 +4325,5 @@
     return rc;
 }
+#endif
 
 
@@ -4725,9 +4735,9 @@
     NULL /* pfnFollowAbsoluteSymlink */,
     rtFsFatDir_OpenFile,
-    rtFsFatDir_OpenDir,
+    NULL /* pfnOpenDir */,
     rtFsFatDir_CreateDir,
     rtFsFatDir_OpenSymlink,
     rtFsFatDir_CreateSymlink,
-    rtFsFatDir_QueryEntryInfo,
+    NULL /* pfnQueryEntryInfo */,
     rtFsFatDir_UnlinkEntry,
     rtFsFatDir_RenameEntry,
Index: /trunk/src/VBox/Runtime/common/fs/isovfs.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/fs/isovfs.cpp	(revision 69827)
+++ /trunk/src/VBox/Runtime/common/fs/isovfs.cpp	(revision 69828)
@@ -461,4 +461,5 @@
 static void rtFsIsoDirShrd_AddOpenChild(PRTFSISODIRSHRD pDir, PRTFSISOCORE pChild);
 static void rtFsIsoDirShrd_RemoveOpenChild(PRTFSISODIRSHRD pDir, PRTFSISOCORE pChild);
+static int  rtFsIsoDir_NewWithShared(PRTFSISOVOL pThis, PRTFSISODIRSHRD pShared, PRTVFSDIR phVfsDir);
 static int  rtFsIsoDir_New9660(PRTFSISOVOL pThis, PRTFSISODIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
                                uint32_t cDirRecs, uint64_t offDirRec, PRTVFSDIR phVfsDir);
@@ -2897,18 +2898,57 @@
     PRTFSISODIROBJ  pThis   = (PRTFSISODIROBJ)pvThis;
     PRTFSISODIRSHRD pShared = pThis->pShared;
+    int rc;
 
     /*
      * We cannot create or replace anything, just open stuff.
      */
-    if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE
-        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
+    if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
+        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE)
+    { /* likely */ }
+    else
         return VERR_WRITE_PROTECT;
 
     /*
+     * Special cases '.' and '.'
+     */
+    if (pszEntry[0] == '.')
+    {
+        PRTFSISODIRSHRD pSharedToOpen;
+        if (pszEntry[1] == '\0')
+            pSharedToOpen = pShared;
+        else if (pszEntry[1] == '.' && pszEntry[2] == '\0')
+        {
+            pSharedToOpen = pShared->Core.pParentDir;
+            if (!pSharedToOpen)
+                pSharedToOpen = pShared;
+        }
+        else
+            pSharedToOpen = NULL;
+        if (pSharedToOpen)
+        {
+            if (fFlags & RTVFSOBJ_F_OPEN_DIRECTORY)
+            {
+                rtFsIsoDirShrd_Retain(pSharedToOpen);
+                RTVFSDIR hVfsDir;
+                rc = rtFsIsoDir_NewWithShared(pShared->Core.pVol, pSharedToOpen, &hVfsDir);
+                if (RT_SUCCESS(rc))
+                {
+                    *phVfsObj = RTVfsObjFromDir(hVfsDir);
+                    RTVfsDirRelease(hVfsDir);
+                    AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
+                }
+            }
+            else
+                rc = VERR_IS_A_DIRECTORY;
+            return rc;
+        }
+    }
+
+    /*
      * Try open whatever it is.
      */
-    int rc;
     if (pShared->Core.pVol->enmType != RTFSISOVOLTYPE_UDF)
     {
+
         /*
          * ISO 9660
@@ -3112,4 +3152,5 @@
 
 
+#if 0
 /**
  * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
@@ -3185,4 +3226,5 @@
     return rc;
 }
+#endif
 
 
@@ -3218,4 +3260,5 @@
 
 
+#if 0
 /**
  * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
@@ -3281,4 +3324,5 @@
     return rc;
 }
+#endif
 
 
@@ -3693,9 +3737,9 @@
     NULL /* pfnFollowAbsoluteSymlink */,
     rtFsIsoDir_OpenFile,
-    rtFsIsoDir_OpenDir,
+    NULL /* pfnOpenDir */,
     rtFsIsoDir_CreateDir,
     rtFsIsoDir_OpenSymlink,
     rtFsIsoDir_CreateSymlink,
-    rtFsIsoDir_QueryEntryInfo,
+    NULL /* pfnQueryEntryInfo */,
     rtFsIsoDir_UnlinkEntry,
     rtFsIsoDir_RenameEntry,
Index: /trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp	(revision 69827)
+++ /trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp	(revision 69828)
@@ -1260,4 +1260,5 @@
                     break;
             }
+            RTVfsDirRelease(pVfsParentDir);
         }
         RTVfsParsePathFree(pPath);
@@ -1885,5 +1886,4 @@
     AssertPtr(ppVfsParentDir);
     *ppVfsParentDir = NULL;
-    AssertReturn(pPath->cComponents > 0, VERR_INTERNAL_ERROR_3);
     Assert(RTPATH_F_IS_VALID(fFlags, 0));
 
@@ -2192,5 +2192,5 @@
                 rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName,
                                                   RTFILE_O_ACCESS_ATTR_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
-                                                  RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING, &hVfsObj);
+                                                  fObjFlags, &hVfsObj);
                 RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
                 if (RT_FAILURE(rc))
@@ -2215,6 +2215,6 @@
                     break;
             }
+            RTVfsDirRelease(pVfsParentDir);
         }
-
         RTVfsParsePathFree(pPath);
     }
@@ -2540,5 +2540,5 @@
     AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
-    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
+    AssertReturn(!fFlags, VERR_INVALID_FLAGS); /** @todo sort out flags! */
 
     /*
@@ -2550,38 +2550,60 @@
     if (RT_SUCCESS(rc))
     {
-        if (pPath->cComponents > 0)
+        /*
+         * Tranverse the path, resolving the parent node.
+         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenDir.
+         */
+        RTVFSDIRINTERNAL *pVfsParentDir;
+        rc = rtVfsTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir);
+        if (RT_SUCCESS(rc))
         {
             /*
-             * Tranverse the path, resolving the parent node and any symlinks
-             * in the final element, and ask the directory to open the subdir.
+             * Do the opening.  Loop if we need to follow symbolic links.
              */
-            RTVFSDIRINTERNAL *pVfsParentDir;
-            rc = rtVfsTraverseToParent(pThis, pPath, RTPATH_F_FOLLOW_LINK, &pVfsParentDir);
-            if (RT_SUCCESS(rc))
+            uint64_t fOpenFlags = RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN;
+            uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_DIRECTORY | RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING;
+            for (uint32_t cLoops = 1; ; cLoops++)
             {
+                /* Do the querying.  If pfnOpenDir is available, we use it first, falling
+                   back on pfnOpen in case of symbolic links that needs following. */
                 const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
-
-                /** @todo there is a symlink creation race here. */
+                if (pVfsParentDir->pOps->pfnQueryEntryInfo)
+                {
+                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
+                    rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
+                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
+                    if (RT_SUCCESS(rc)
+                        || (   rc != VERR_NOT_A_DIRECTORY
+                            && rc != VERR_IS_A_SYMLINK))
+                        break;
+                }
+
+                RTVFSOBJ hVfsObj;
                 RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
-                rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
+                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpenFlags, fObjFlags, &hVfsObj);
                 RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
-
-                RTVfsDirRelease(pVfsParentDir);
-
-                if (RT_SUCCESS(rc))
+                if (RT_FAILURE(rc))
+                    break;
+
+                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
+                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
+                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
                 {
-                    AssertPtr(*phVfsDir);
-                    Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
+                    *phVfsDir = RTVfsObjToDir(hVfsObj);
+                    AssertStmt(*phVfsDir != NIL_RTVFSDIR, rc = VERR_INTERNAL_ERROR_3);
+                    RTVfsObjRelease(hVfsObj);
+                    break;
                 }
+
+                /* Follow symbolic link. */
+                if (cLoops < RTVFS_MAX_LINKS)
+                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK);
+                else
+                    rc = VERR_TOO_MANY_SYMLINKS;
+                RTVfsObjRelease(hVfsObj);
+                if (RT_FAILURE(rc))
+                    break;
             }
-        }
-        /*
-         * If the path boils down to '.' return the root directory.
-         */
-        else
-        {
-            RTVfsLockAcquireRead(pThis->Base.hLock);
-            rc = pThis->pOps->pfnOpenRoot(pThis->Base.pvThis, phVfsDir);
-            RTVfsLockReleaseRead(pThis->Base.hLock);
+            RTVfsDirRelease(pVfsParentDir);
         }
         RTVfsParsePathFree(pPath);
@@ -2601,5 +2623,5 @@
     AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
-    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
+    AssertReturn(!fFlags, VERR_INVALID_FLAGS); /** @todo sort out flags! */
 
     /*
@@ -2610,40 +2632,60 @@
     if (RT_SUCCESS(rc))
     {
-        if (pPath->cComponents > 0)
+        /*
+         * Tranverse the path, resolving the parent node.
+         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenDir.
+         */
+        RTVFSDIRINTERNAL *pVfsParentDir;
+        rc = rtVfsDirTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir);
+        if (RT_SUCCESS(rc))
         {
             /*
-             * Tranverse the path, resolving the parent node and any symlinks
-             * in the final element, and ask the directory to open the subdir.
+             * Do the opening.  Loop if we need to follow symbolic links.
              */
-            RTVFSDIRINTERNAL *pVfsParentDir;
-            rc = rtVfsDirTraverseToParent(pThis, pPath, RTPATH_F_FOLLOW_LINK, &pVfsParentDir);
-            if (RT_SUCCESS(rc))
+            uint64_t fOpenFlags = RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN;
+            uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_DIRECTORY | RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING;
+            for (uint32_t cLoops = 1; ; cLoops++)
             {
+                /* Do the querying.  If pfnOpenDir is available, we use it first, falling
+                   back on pfnOpen in case of symbolic links that needs following. */
                 const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
-
-                /** @todo there is a symlink creation race here. */
+                if (pVfsParentDir->pOps->pfnQueryEntryInfo)
+                {
+                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
+                    rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
+                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
+                    if (RT_SUCCESS(rc)
+                        || (   rc != VERR_NOT_A_DIRECTORY
+                            && rc != VERR_IS_A_SYMLINK))
+                        break;
+                }
+
+                RTVFSOBJ hVfsObj;
                 RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
-                rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
+                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpenFlags, fObjFlags, &hVfsObj);
                 RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
-
-                RTVfsDirRelease(pVfsParentDir);
-
-                if (RT_SUCCESS(rc))
+                if (RT_FAILURE(rc))
+                    break;
+
+                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
+                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
+                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
                 {
-                    AssertPtr(*phVfsDir);
-                    Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
+                    *phVfsDir = RTVfsObjToDir(hVfsObj);
+                    AssertStmt(*phVfsDir != NIL_RTVFSDIR, rc = VERR_INTERNAL_ERROR_3);
+                    RTVfsObjRelease(hVfsObj);
+                    break;
                 }
+
+                /* Follow symbolic link. */
+                if (cLoops < RTVFS_MAX_LINKS)
+                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK);
+                else
+                    rc = VERR_TOO_MANY_SYMLINKS;
+                RTVfsObjRelease(hVfsObj);
+                if (RT_FAILURE(rc))
+                    break;
             }
-        }
-        /*
-         * The path boils down to '.', call pfnOpenDir on pThis with '.' as input.
-         * The caller may wish for a new directory instance to enumerate the entries
-         * in parallel or some such thing.
-         */
-        else
-        {
-            RTVfsLockAcquireWrite(pThis->Base.hLock);
-            rc = pThis->pOps->pfnOpenDir(pThis->Base.pvThis, ".", fFlags, phVfsDir);
-            RTVfsLockReleaseWrite(pThis->Base.hLock);
+            RTVfsDirRelease(pVfsParentDir);
         }
         RTVfsParsePathFree(pPath);
