Index: /trunk/include/iprt/dir.h
===================================================================
--- /trunk/include/iprt/dir.h	(revision 78185)
+++ /trunk/include/iprt/dir.h	(revision 78186)
@@ -186,6 +186,8 @@
 /** Only delete the content of the directory, omit the directory it self. */
 #define RTDIRRMREC_F_CONTENT_ONLY       RT_BIT_32(0)
+/** Long path hack: Don't apply RTPathAbs to the path. */
+#define RTDIRRMREC_F_NO_ABS_PATH        RT_BIT_32(1)
 /** Mask of valid flags. */
-#define RTDIRRMREC_F_VALID_MASK         UINT32_C(0x00000001)
+#define RTDIRRMREC_F_VALID_MASK         UINT32_C(0x00000003)
 /** @} */
 
@@ -357,6 +359,8 @@
 /** Don't follow symbolic links in the final component. */
 #define RTDIR_F_NO_FOLLOW       RT_BIT_32(2)
+/** Long path hack: Don't apply RTPathAbs to the path. */
+#define RTDIR_F_NO_ABS_PATH     RT_BIT_32(3)
 /** Valid flag mask.   */
-#define RTDIR_F_VALID_MASK      UINT32_C(0x00000007)
+#define RTDIR_F_VALID_MASK      UINT32_C(0x0000000f)
 /** @} */
 
Index: /trunk/src/VBox/Runtime/r3/dir.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/dir.cpp	(revision 78185)
+++ /trunk/src/VBox/Runtime/r3/dir.cpp	(revision 78186)
@@ -527,4 +527,7 @@
      * for querying extra information about the objects we list.
      * As a sideeffect we also validate the path here.
+     *
+     * Note! The RTDIR_F_NO_ABS_PATH mess is there purely for allowing us to
+     *       work around PATH_MAX using CWD on linux and other unixy systems.
      */
     char  *pszAbsPath;
@@ -542,5 +545,17 @@
 
         cbFilter = cucFilter0 = 0;
-        pszAbsPath = RTPathAbsExDup(NULL, pszPath, RTPATHABS_F_ENSURE_TRAILING_SLASH);
+        if (!(fFlags & RTDIR_F_NO_ABS_PATH))
+            pszAbsPath = RTPathAbsExDup(NULL, pszPath, RTPATHABS_F_ENSURE_TRAILING_SLASH);
+        else
+        {
+            size_t cchTmp = strlen(pszPath);
+            pszAbsPath = RTStrAlloc(cchTmp + 2);
+            if (pszAbsPath)
+            {
+                memcpy(pszAbsPath, pszPath, cchTmp);
+                pszAbsPath[cchTmp] = RTPATH_SLASH;
+                pszAbsPath[cchTmp + 1 - fDirSlash] = '\0';
+            }
+        }
     }
     else
@@ -556,9 +571,19 @@
                 return VERR_NO_MEMORY;
             pszTmp[pszFilter - pszPath] = '\0';
-            pszAbsPath = RTPathAbsExDup(NULL, pszTmp, RTPATHABS_F_ENSURE_TRAILING_SLASH);
-            RTStrFree(pszTmp);
-        }
+            if (!(fFlags & RTDIR_F_NO_ABS_PATH))
+            {
+                pszAbsPath = RTPathAbsExDup(NULL, pszTmp, RTPATHABS_F_ENSURE_TRAILING_SLASH);
+                RTStrFree(pszTmp);
+            }
+            else
+            {
+                pszAbsPath = pszTmp;
+                RTPathEnsureTrailingSeparator(pszAbsPath, strlen(pszPath) + 1);
+            }
+        }
+        else if (!(fFlags & RTDIR_F_NO_ABS_PATH))
+            pszAbsPath = RTPathAbsExDup(NULL, ".", RTPATHABS_F_ENSURE_TRAILING_SLASH);
         else
-            pszAbsPath = RTPathAbsExDup(NULL, ".", RTPATHABS_F_ENSURE_TRAILING_SLASH);
+            pszAbsPath = RTStrDup("." RTPATH_SLASH_STR);
         fDirSlash = true;
     }
Index: /trunk/src/VBox/Runtime/r3/dir2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/dir2.cpp	(revision 78185)
+++ /trunk/src/VBox/Runtime/r3/dir2.cpp	(revision 78186)
@@ -56,6 +56,8 @@
  * @param   pDirEntry           The dir entry buffer.  (Shared to save stack.)
  * @param   pObjInfo            The object info buffer.  (ditto)
+ * @param   fFlags              RTDIRRMREC_F_XXX.
  */
-static int rtDirRemoveRecursiveSub(char *pszBuf, size_t cchDir, size_t cbBuf, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo)
+static int rtDirRemoveRecursiveSub(char *pszBuf, size_t cchDir, size_t cbBuf, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo,
+                                   uint32_t fFlags)
 {
     AssertReturn(RTPATH_IS_SLASH(pszBuf[cchDir - 1]), VERR_INTERNAL_ERROR_4);
@@ -65,5 +67,5 @@
      */
     RTDIR hDir;
-    int rc = RTDirOpen(&hDir, pszBuf);
+    int rc = RTDirOpenFiltered(&hDir, pszBuf, RTDIRFILTER_NONE, fFlags & RTDIRRMREC_F_NO_ABS_PATH ? RTDIR_F_NO_ABS_PATH : 0);
     if (RT_FAILURE(rc))
         return rc;
@@ -104,5 +106,5 @@
                     pszBuf[cchSubDir++] = '/';
                     pszBuf[cchSubDir]   = '\0';
-                    rc = rtDirRemoveRecursiveSub(pszBuf, cchSubDir, cbBuf, pDirEntry, pObjInfo);
+                    rc = rtDirRemoveRecursiveSub(pszBuf, cchSubDir, cbBuf, pDirEntry, pObjInfo, fFlags);
                     if (RT_SUCCESS(rc))
                     {
@@ -153,6 +155,11 @@
      * eliminates any races with changing CWD.
      */
-    /** @todo use RTPathReal here instead? */
-    int rc = RTPathAbs(pszPath, pszAbsPath, cbAbsPathBuf);
+    int rc;
+    if (!(fFlags & RTDIRRMREC_F_NO_ABS_PATH))
+        rc = RTPathAbs(pszPath, pszAbsPath, cbAbsPathBuf);
+    else if (*pszPath != '\0')
+        rc = RTStrCopy(pszAbsPath, cbAbsPathBuf, pszPath);
+    else
+        rc = VERR_PATH_ZERO_LENGTH;
     if (RT_SUCCESS(rc))
     {
@@ -160,5 +167,12 @@
          * This API is not permitted applied to the root of anything.
          */
-        if (RTPathCountComponents(pszAbsPath) <= 1)
+        union
+        {
+            RTPATHPARSED    Parsed;
+            uint8_t         abParsed[RT_UOFFSETOF(RTPATHPARSED, aComps[1])];
+        } uBuf;
+        RTPathParse(pszPath, &uBuf.Parsed, sizeof(uBuf), RTPATH_STR_F_STYLE_HOST);
+        if (   uBuf.Parsed.cComps <= 1
+            && (uBuf.Parsed.fProps & RTPATH_PROP_ROOT_SLASH))
             rc = VERR_ACCESS_DENIED;
         else
@@ -191,5 +205,6 @@
                      */
                     RTDIRENTRY SharedDirEntryBuf;
-                    rc = rtDirRemoveRecursiveSub(pszAbsPath, cchAbsPath, cbAbsPathBuf, &SharedDirEntryBuf, &SharedObjInfoBuf);
+                    rc = rtDirRemoveRecursiveSub(pszAbsPath, cchAbsPath, cbAbsPathBuf,
+                                                 &SharedDirEntryBuf, &SharedObjInfoBuf, fFlags);
 
                     /*
Index: /trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp
===================================================================
--- /trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp	(revision 78185)
+++ /trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp	(revision 78186)
@@ -1221,8 +1221,20 @@
 
 
+/**
+ * Wrapper around RTDirOpen/RTDirOpenFiltered which takes g_fRelativeDir into
+ * account.
+ */
+DECL_FORCE_INLINE(int) fsPerfOpenDirWrap(PRTDIR phDir, const char *pszPath)
+{
+    if (!g_fRelativeDir)
+        return RTDirOpen(phDir, pszPath);
+    return RTDirOpenFiltered(phDir, pszPath, RTDIRFILTER_NONE, RTDIR_F_NO_ABS_PATH);
+}
+
+
 DECL_FORCE_INLINE(int) fsPerfOpenClose(const char *pszDir)
 {
     RTDIR hDir;
-    RTTESTI_CHECK_RC_RET(RTDirOpen(&hDir, pszDir), VINF_SUCCESS, rcCheck);
+    RTTESTI_CHECK_RC_RET(fsPerfOpenDirWrap(&hDir, pszDir), VINF_SUCCESS, rcCheck);
     RTTESTI_CHECK_RC(RTDirClose(hDir), VINF_SUCCESS);
     return VINF_SUCCESS;
@@ -1238,7 +1250,7 @@
      * Non-existing files.
      */
-    RTTESTI_CHECK_RC(RTDirOpen(&hDir, InEmptyDir(RT_STR_TUPLE("no-such-file"))), VERR_FILE_NOT_FOUND);
-    RTTESTI_CHECK_RC(RTDirOpen(&hDir, InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND);
-    RTTESTI_CHECK_RC(RTDirOpen(&hDir, InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file"))), VERR_PATH_NOT_FOUND);
+    RTTESTI_CHECK_RC(fsPerfOpenDirWrap(&hDir, InEmptyDir(RT_STR_TUPLE("no-such-file"))), VERR_FILE_NOT_FOUND);
+    RTTESTI_CHECK_RC(fsPerfOpenDirWrap(&hDir, InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND);
+    RTTESTI_CHECK_RC(fsPerfOpenDirWrap(&hDir, InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file"))), VERR_PATH_NOT_FOUND);
 
     /*
@@ -1246,5 +1258,5 @@
      */
     g_szEmptyDir[g_cchEmptyDir] = '\0';
-    RTTESTI_CHECK_RC_RETV(RTDirOpen(&hDir, g_szEmptyDir), VINF_SUCCESS);
+    RTTESTI_CHECK_RC_RETV(fsPerfOpenDirWrap(&hDir, g_szEmptyDir), VINF_SUCCESS);
     RTTESTI_CHECK_RC(RTDirClose(hDir), VINF_SUCCESS);
 
@@ -1267,5 +1279,5 @@
     RTDIR hDir;
     g_szEmptyDir[g_cchEmptyDir] = '\0';
-    RTTESTI_CHECK_RC_RET(RTDirOpen(&hDir, g_szEmptyDir), VINF_SUCCESS, rcCheck);
+    RTTESTI_CHECK_RC_RET(fsPerfOpenDirWrap(&hDir, g_szEmptyDir), VINF_SUCCESS, rcCheck);
 
     RTDIRENTRY Entry;
@@ -1282,5 +1294,5 @@
 {
     RTDIR hDir;
-    RTTESTI_CHECK_RC_RET(RTDirOpen(&hDir, InDir(RT_STR_TUPLE("manyfiles"))), VINF_SUCCESS, rcCheck);
+    RTTESTI_CHECK_RC_RET(fsPerfOpenDirWrap(&hDir, InDir(RT_STR_TUPLE("manyfiles"))), VINF_SUCCESS, rcCheck);
     uint32_t cLeft = g_cManyFiles + 2;
     for (;;)
@@ -1310,5 +1322,5 @@
      */
     g_szEmptyDir[g_cchEmptyDir] = '\0';
-    RTTESTI_CHECK_RC_RETV(RTDirOpen(&hDir, g_szEmptyDir), VINF_SUCCESS);
+    RTTESTI_CHECK_RC_RETV(fsPerfOpenDirWrap(&hDir, g_szEmptyDir), VINF_SUCCESS);
 
     uint32_t   fDots = 0;
@@ -1340,5 +1352,5 @@
 
         uint32_t cFiles = 0;
-        RTTESTI_CHECK_RC_RETV(RTDirOpen(&hDir, InDir(RT_STR_TUPLE("manyfiles"))), VINF_SUCCESS);
+        RTTESTI_CHECK_RC_RETV(fsPerfOpenDirWrap(&hDir, InDir(RT_STR_TUPLE("manyfiles"))), VINF_SUCCESS);
         for (;;)
         {
@@ -4689,5 +4701,5 @@
             /* Cleanup: */
             g_szDir[g_cchDir] = '\0';
-            rc = RTDirRemoveRecursive(g_szDir, RTDIRRMREC_F_CONTENT_AND_DIR);
+            rc = RTDirRemoveRecursive(g_szDir, RTDIRRMREC_F_CONTENT_AND_DIR | (g_fRelativeDir ? RTDIRRMREC_F_NO_ABS_PATH : 0));
             if (RT_FAILURE(rc))
                 RTTestFailed(g_hTest, "RTDirRemoveRecursive(%s,) -> %Rrc\n", g_szDir, rc);
