Index: /trunk/include/iprt/vfs.h
===================================================================
--- /trunk/include/iprt/vfs.h	(revision 33947)
+++ /trunk/include/iprt/vfs.h	(revision 33948)
@@ -105,4 +105,37 @@
 /** A NIL VFS symbolic link handle. */
 #define NIL_RTVFSSYMLINK                ((RTVFSSYMLINK)~(uintptr_t)0)
+
+/**
+ * The object type.
+ */
+typedef enum RTVFSOBJTYPE
+{
+    /** Invalid type. */
+    RTVFSOBJTYPE_INVALID = 0,
+    /** Pure base object.
+     * This is returned by the filesystem stream to represent directories,
+     * devices, fifos and similar that needs to be created. */
+    RTVFSOBJTYPE_BASE,
+    /** Virtual filesystem. */
+    RTVFSOBJTYPE_VFS,
+    /** Filesystem stream. */
+    RTVFSOBJTYPE_FS_STREAM,
+    /** Pure I/O stream. */
+    RTVFSOBJTYPE_IO_STREAM,
+    /** Directory. */
+    RTVFSOBJTYPE_DIR,
+    /** File. */
+    RTVFSOBJTYPE_FILE,
+    /** Symbolic link. */
+    RTVFSOBJTYPE_SYMLINK,
+    /** End of valid object types. */
+    RTVFSOBJTYPE_END,
+    /** Pure I/O stream. */
+    RTVFSOBJTYPE_32BIT_HACK = 0x7fffffff
+} RTVFSOBJTYPE;
+/** Pointer to a VFS object type. */
+typedef RTVFSOBJTYPE *PRTVFSOBJTYPE;
+
+
 
 
@@ -153,5 +186,59 @@
 RTDECL(RTVFSOBJ)        RTVfsObjFromSymlink(RTVFSSYMLINK hVfsSym);
 
+/**
+ * Query information about the object.
+ *
+ * @returns IPRT status code.
+ * @param   hVfsObj         The VFS object handle.
+ * @param   pObjInfo        Where to return the info.
+ * @param   enmAddAttr      Which additional attributes should be retrieved.
+ * @sa      RTFileQueryInfo, RTPathQueryInfo
+ */
+RTDECL(int)         RTVfsObjQueryInfo(RTVFSOBJ hVfsObj, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
 /** @} */
+
+
+/** @defgroup grp_vfs_fsstream      VFS Filesystem Stream API
+ *
+ * Filesystem streams are for tar, cpio and similar.  Any virtual filesystem can
+ * be turned into a filesystem stream using RTVfsFsStrmFromVfs.
+ *
+ * @{
+ */
+
+RTDECL(uint32_t)    RTVfsFsStrmRetain(RTVFSFSSTREAM hVfsFss);
+RTDECL(uint32_t)    RTVfsFsStrmRelease(RTVFSFSSTREAM hVfsFss);
+RTDECL(int)         RTVfsFsStrmQueryInfo(RTVFSFSSTREAM hVfsFss, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Gets the next object in the stream.
+ *
+ * This call may affect the stream posision of a previously returned object.
+ *
+ * The type of object returned here typically boils down to three types:
+ *      - I/O streams (representing files),
+ *      - symbolic links
+ *      - base object
+ * The base objects represent anything not convered by the two other, i.e.
+ * directories, device nodes, fifos, sockets and whatnot.  The details can be
+ * queried using RTVfsObjQueryInfo.
+ *
+ * That said, absolutely any object except for filesystem stream objects can be
+ * returned by this call.  Any generic code is adviced to just deal with it all.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS if a new object was retrieved.
+ * @retval  VERR_EOF when there are no more objects.
+ * @param   pvThis      The implementation specific directory data.
+ * @param   ppszName    Where to return the object name.  Must be freed by
+ *                      calling RTStrFree.
+ * @param   penmType    Where to return the object type.
+ * @param   hVfsObj     Where to return the object handle (referenced).
+ *                      This must be cast to the desired type before use.
+ */
+RTDECL(int)         RTVfsFsStrmNext(RTVFSFSSTREAM hVfsFss, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj);
+
+/** @}  */
 
 
@@ -182,4 +269,7 @@
  * @{
  */
+
+RTDECL(uint32_t)    RTVfsSymlinkRetain(RTVFSSYMLINK hVfsSym);
+RTDECL(uint32_t)    RTVfsSymlinkRelease(RTVFSSYMLINK hVfsSym);
 
 /**
Index: /trunk/include/iprt/vfslowlevel.h
===================================================================
--- /trunk/include/iprt/vfslowlevel.h	(revision 33947)
+++ /trunk/include/iprt/vfslowlevel.h	(revision 33948)
@@ -100,36 +100,4 @@
 #define RTVFSOPS_FEAT_ATTACH        RT_BIT_32(0)
 /** @}  */
-
-
-/**
- * The object type.
- */
-typedef enum RTVFSOBJTYPE
-{
-    /** Invalid type. */
-    RTVFSOBJTYPE_INVALID = 0,
-    /** Pure base object.
-     * This is returned by the filesystem stream to represent directories,
-     * devices, fifos and similar that needs to be created. */
-    RTVFSOBJTYPE_BASE,
-    /** Virtual filesystem. */
-    RTVFSOBJTYPE_VFS,
-    /** Filesystem stream. */
-    RTVFSOBJTYPE_FS_STREAM,
-    /** Pure I/O stream. */
-    RTVFSOBJTYPE_IO_STREAM,
-    /** Directory. */
-    RTVFSOBJTYPE_DIR,
-    /** File. */
-    RTVFSOBJTYPE_FILE,
-    /** Symbolic link. */
-    RTVFSOBJTYPE_SYMLINK,
-    /** End of valid object types. */
-    RTVFSOBJTYPE_END,
-    /** Pure I/O stream. */
-    RTVFSOBJTYPE_32BIT_HACK = 0x7fffffff
-} RTVFSOBJTYPE;
-/** Pointer to a VFS object type. */
-typedef RTVFSOBJTYPE *PRTVFSOBJTYPE;
 
 
Index: /trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp	(revision 33947)
+++ /trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp	(revision 33948)
@@ -440,4 +440,216 @@
     AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, UINT32_MAX);
     return rtVfsObjRelease(pThis);
+}
+
+
+RTDECL(RTVFS)           RTVfsObjToVfs(RTVFSOBJ hVfsObj)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    if (pThis != NIL_RTVFSOBJ)
+    {
+        AssertPtrReturn(pThis, NIL_RTVFS);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFS);
+
+        if (pThis->pOps->enmType == RTVFSOBJTYPE_VFS)
+        {
+            rtVfsObjRetainVoid(pThis);
+            return RT_FROM_MEMBER(pThis, RTVFSINTERNAL, Base);
+        }
+    }
+    return NIL_RTVFS;
+}
+
+
+RTDECL(RTVFSFSSTREAM)   RTVfsObjToFsStream(RTVFSOBJ hVfsObj)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    if (pThis != NIL_RTVFSOBJ)
+    {
+        AssertPtrReturn(pThis, NIL_RTVFSFSSTREAM);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSFSSTREAM);
+
+        if (pThis->pOps->enmType == RTVFSOBJTYPE_FS_STREAM)
+        {
+            rtVfsObjRetainVoid(pThis);
+            return RT_FROM_MEMBER(pThis, RTVFSFSSTREAMINTERNAL, Base);
+        }
+    }
+    return NIL_RTVFSFSSTREAM;
+}
+
+
+RTDECL(RTVFSDIR)        RTVfsObjToDir(RTVFSOBJ hVfsObj)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    if (pThis != NIL_RTVFSOBJ)
+    {
+        AssertPtrReturn(pThis, NIL_RTVFSDIR);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSDIR);
+
+        if (pThis->pOps->enmType == RTVFSOBJTYPE_VFS)
+        {
+            rtVfsObjRetainVoid(pThis);
+            return RT_FROM_MEMBER(pThis, RTVFSDIRINTERNAL, Base);
+        }
+    }
+    return NIL_RTVFSDIR;
+}
+
+
+RTDECL(RTVFSIOSTREAM)   RTVfsObjToIoStream(RTVFSOBJ hVfsObj)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    if (pThis != NIL_RTVFSOBJ)
+    {
+        AssertPtrReturn(pThis, NIL_RTVFSIOSTREAM);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSIOSTREAM);
+
+        if (pThis->pOps->enmType == RTVFSOBJTYPE_VFS)
+        {
+            rtVfsObjRetainVoid(pThis);
+            return RT_FROM_MEMBER(pThis, RTVFSIOSTREAMINTERNAL, Base);
+        }
+    }
+    return NIL_RTVFSIOSTREAM;
+}
+
+
+RTDECL(RTVFSFILE)       RTVfsObjToFile(RTVFSOBJ hVfsObj)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    if (pThis != NIL_RTVFSOBJ)
+    {
+        AssertPtrReturn(pThis, NIL_RTVFSFILE);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSFILE);
+
+        if (pThis->pOps->enmType == RTVFSOBJTYPE_VFS)
+        {
+            rtVfsObjRetainVoid(pThis);
+            return RT_FROM_MEMBER(pThis, RTVFSFILEINTERNAL, Stream.Base);
+        }
+    }
+    return NIL_RTVFSFILE;
+}
+
+
+RTDECL(RTVFSSYMLINK)    RTVfsObjToSymlink(RTVFSOBJ hVfsObj)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    if (pThis != NIL_RTVFSOBJ)
+    {
+        AssertPtrReturn(pThis, NIL_RTVFSSYMLINK);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSSYMLINK);
+
+        if (pThis->pOps->enmType == RTVFSOBJTYPE_VFS)
+        {
+            rtVfsObjRetainVoid(pThis);
+            return RT_FROM_MEMBER(pThis, RTVFSSYMLINKINTERNAL, Base);
+        }
+    }
+    return NIL_RTVFSSYMLINK;
+}
+
+
+RTDECL(RTVFSOBJ)        RTVfsObjFromVfs(RTVFS hVfs)
+{
+    if (hVfs != NIL_RTVFS)
+    {
+        RTVFSOBJINTERNAL *pThis = &hVfs->Base;
+        AssertPtrReturn(pThis, NIL_RTVFSOBJ);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSOBJ);
+
+        rtVfsObjRetainVoid(pThis);
+        return pThis;
+    }
+    return NIL_RTVFSOBJ;
+}
+
+
+RTDECL(RTVFSOBJ)        RTVfsObjFromFsStream(RTVFSFSSTREAM hVfsFss)
+{
+    if (hVfsFss != NIL_RTVFSFSSTREAM)
+    {
+        RTVFSOBJINTERNAL *pThis = &hVfsFss->Base;
+        AssertPtrReturn(pThis, NIL_RTVFSOBJ);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSOBJ);
+
+        rtVfsObjRetainVoid(pThis);
+        return pThis;
+    }
+    return NIL_RTVFSOBJ;
+}
+
+
+RTDECL(RTVFSOBJ)        RTVfsObjFromDir(RTVFSDIR hVfsDir)
+{
+    if (hVfsDir != NIL_RTVFSDIR)
+    {
+        RTVFSOBJINTERNAL *pThis = &hVfsDir->Base;
+        AssertPtrReturn(pThis, NIL_RTVFSOBJ);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSOBJ);
+
+        rtVfsObjRetainVoid(pThis);
+        return pThis;
+    }
+    return NIL_RTVFSOBJ;
+}
+
+
+RTDECL(RTVFSOBJ)        RTVfsObjFromIoStream(RTVFSIOSTREAM hVfsIos)
+{
+    if (hVfsIos != NIL_RTVFSIOSTREAM)
+    {
+        RTVFSOBJINTERNAL *pThis = &hVfsIos->Base;
+        AssertPtrReturn(pThis, NIL_RTVFSOBJ);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSOBJ);
+
+        rtVfsObjRetainVoid(pThis);
+        return pThis;
+    }
+    return NIL_RTVFSOBJ;
+}
+
+
+RTDECL(RTVFSOBJ)        RTVfsObjFromFile(RTVFSFILE hVfsFile)
+{
+    if (hVfsFile != NIL_RTVFSFILE)
+    {
+        RTVFSOBJINTERNAL *pThis = &hVfsFile->Stream.Base;
+        AssertPtrReturn(pThis, NIL_RTVFSOBJ);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSOBJ);
+
+        rtVfsObjRetainVoid(pThis);
+        return pThis;
+    }
+    return NIL_RTVFSOBJ;
+}
+
+
+RTDECL(RTVFSOBJ)        RTVfsObjFromSymlink(RTVFSSYMLINK hVfsSym)
+{
+    if (hVfsSym != NIL_RTVFSSYMLINK)
+    {
+        RTVFSOBJINTERNAL *pThis = &hVfsSym->Base;
+        AssertPtrReturn(pThis, NIL_RTVFSOBJ);
+        AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, NIL_RTVFSOBJ);
+
+        rtVfsObjRetainVoid(pThis);
+        return pThis;
+    }
+    return NIL_RTVFSOBJ;
+}
+
+
+
+RTDECL(int)         RTVfsObjQueryInfo(RTVFSOBJ hVfsObj, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
+{
+    RTVFSOBJINTERNAL *pThis = hVfsObj;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->uMagic == RTVFSOBJ_MAGIC, VERR_INVALID_HANDLE);
+
+    rtVfsObjReadLock(pThis);
+    int rc = pThis->pOps->pfnQueryInfo(pThis->pvThis, pObjInfo, enmAddAttr);
+    rtVfsObjReadUnlock(pThis);
+    return rc;
 }
 
@@ -861,4 +1073,70 @@
 
 
+
+
+/*
+ *
+ *  F I L E S Y S T E M   S T R E A M
+ *  F I L E S Y S T E M   S T R E A M
+ *  F I L E S Y S T E M   S T R E A M
+ *
+ */
+
+
+RTDECL(int) RTVfsNewIoStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTSEMRW hSemRW,
+                             PRTVFSFSSTREAM phVfsFss, void **ppvInstance)
+{
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+RTDECL(uint32_t)    RTVfsFsStrmRetain(RTVFSFSSTREAM hVfsFss)
+{
+    RTVFSFSSTREAMINTERNAL *pThis = hVfsFss;
+    AssertPtrReturn(pThis, UINT32_MAX);
+    AssertReturn(pThis->uMagic == RTVFSFSSTREAM_MAGIC, UINT32_MAX);
+    return rtVfsObjRetain(&pThis->Base);
+}
+
+
+RTDECL(uint32_t)    RTVfsFsStrmRelease(RTVFSFSSTREAM hVfsFss)
+{
+    RTVFSFSSTREAMINTERNAL *pThis = hVfsFss;
+    AssertPtrReturn(pThis, UINT32_MAX);
+    AssertReturn(pThis->uMagic == RTVFSFSSTREAM_MAGIC, UINT32_MAX);
+    return rtVfsObjRelease(&pThis->Base);
+}
+
+
+RTDECL(int)         RTVfsFsStrmQueryInfo(RTVFSFSSTREAM hVfsFss, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
+{
+    RTVFSFSSTREAMINTERNAL *pThis = hVfsFss;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->uMagic == RTVFSFSSTREAM_MAGIC, VERR_INVALID_HANDLE);
+    return RTVfsObjQueryInfo(&pThis->Base, pObjInfo, enmAddAttr);
+}
+
+
+RTDECL(int)         RTVfsFsStrmNext(RTVFSFSSTREAM hVfsFss, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj)
+{
+    RTVFSFSSTREAMINTERNAL *pThis = hVfsFss;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, VERR_INVALID_HANDLE);
+    AssertPtrNullReturn(ppszName, VERR_INVALID_POINTER);
+    if (ppszName)
+        *ppszName = NULL;
+    AssertPtrNullReturn(penmType, VERR_INVALID_POINTER);
+    if (penmType)
+        *penmType = RTVFSOBJTYPE_INVALID;
+    AssertPtrNullReturn(penmType, VERR_INVALID_POINTER);
+    if (phVfsObj)
+        *phVfsObj = NIL_RTVFSOBJ;
+
+    return pThis->pOps->pfnNext(pThis->Base.pvThis, ppszName, penmType, phVfsObj);
+}
+
+
+
+
 /*
  *
@@ -1026,9 +1304,5 @@
     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE);
-
-    rtVfsObjReadLock(&pThis->Base);
-    int rc = pThis->pOps->Obj.pfnQueryInfo(pThis->Base.pvThis, pObjInfo, enmAddAttr);
-    rtVfsObjReadUnlock(&pThis->Base);
-    return rc;
+    return RTVfsObjQueryInfo(&pThis->Base, pObjInfo, enmAddAttr);
 }
 
