Index: /trunk/src/VBox/Additions/darwin/VBoxSF/.scm-settings
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/.scm-settings	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/.scm-settings	(revision 75292)
@@ -0,0 +1,19 @@
+# $Id$
+## @file
+# Source code massager settings for the OS X shared folders driver.
+#
+
+#
+# Copyright (C) 2010-2017 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+--filter-out-files /vboxfs.git.tar.bz2
+
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/Info.plist
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/Info.plist	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/Info.plist	(revision 75292)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleDevelopmentRegion</key>           <string>English</string>
+    <key>CFBundleExecutable</key>                  <string>VBoxVFS</string>
+    <key>CFBundleIconFile</key>                    <string></string>
+    <key>CFBundleIdentifier</key>                  <string>org.virtualbox.kext.VBoxVFS</string>
+    <key>CFBundleInfoDictionaryVersion</key>       <string>6.0</string>
+    <key>CFBundleName</key>                        <string>VBoxVFS</string>
+    <key>CFBundlePackageType</key>                 <string>KEXT</string>
+    <key>CFBundleGetInfoString</key>               <string>@VBOX_PRODUCT@ @VBOX_VERSION_STRING@, © 2007-@VBOX_C_YEAR@ @VBOX_VENDOR@</string>
+    <key>CFBundleVersion</key>                     <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string>
+    <key>CFBundleShortVersionString</key>          <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string>
+    <key>OSBundleCompatibleVersion</key>           <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string>
+    <key>IOKitPersonalities</key>
+
+    <dict>
+        <key>VBoxVFS</key>
+        <dict>
+            <key>IOMatchCategory</key>             <string>org_virtualbox_VBoxVFS</string>
+            <key>IOClientClass</key>               <string>VBoxVFSClient</string>
+            <key>IOClass</key>                     <string>org_virtualbox_VBoxVFS</string>
+            <key>CFBundleIdentifier</key>          <string>org.virtualbox.kext.VBoxVFS</string>
+            <key>IOKitDebug</key>                  <integer>65535</integer>
+            <key>IOProviderClass</key>             <string>IOPCIDevice</string>
+            <key>IONameMatch</key>                 <string>pci80ee,cafe</string>
+        </dict>
+    </dict>
+
+    <key>NSHumanReadableCopyright</key>            <string>Copyright © 2013 Oracle Inc. All rights reserved.</string>
+
+    <key>OSBundleLibraries</key>
+    <dict>
+            <key>com.apple.iokit.IOPCIFamily</key> <string>2.5</string>
+            <key>com.apple.kpi.bsd</key>           <string>10.6</string>
+            <key>com.apple.kpi.iokit</key>         <string>10.6</string>
+            <key>com.apple.kpi.libkern</key>       <string>10.6</string> 
+            <key>com.apple.kpi.mach</key>          <string>10.6</string>
+            <key>com.apple.kpi.unsupported</key>   <string>10.6</string>
+            <key>org.virtualbox.kext.VBoxGuest</key>    <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string>
+    </dict>
+</dict>
+</plist>
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/Makefile.kmk	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/Makefile.kmk	(revision 75292)
@@ -0,0 +1,71 @@
+# $Id$
+## @file
+# sub-makefile for the Mac OS addition file system driver.
+#
+
+#
+# Copyright (C) 2007-2017 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+SUB_DEPTH = ../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# VBoxSF - The shared folders kernel extension.
+#
+SYSMODS        += VBoxSF
+VBoxSF_TEMPLATE = VBOXGUESTR0
+VBoxSF_INST     = $(INST_ADDITIONS)VBoxSF.kext/Contents/MacOS/
+VBoxSF_DEFS     = VBOX_WITH_HGCM
+VBoxSF_CXXFLAGS = -Wno-unused -Wno-unused-parameter
+VBoxSF_LIBS     = $(VBOX_LIB_VBGL_R0)
+VBoxSF_SOURCES  = \
+	VBoxVFS.cpp \
+	VBoxVFS-VFSOps.cpp \
+	VBoxVFS-VNODEOps.cpp \
+	VBoxVFS-utils.cpp
+
+
+#
+# Files necessary to make a darwin kernel extension bundle.
+#
+INSTALLS += VBoxSF.kext
+VBoxSF.kext_INST     = $(INST_ADDITIONS)VBoxSF.kext/Contents/
+VBoxSF.kext_SOURCES  = $(VBoxSF.kext_0_OUTDIR)/Info.plist
+VBoxSF.kext_CLEAN    = $(VBoxSF.kext_0_OUTDIR)/Info.plist
+
+$$(VBoxSF.kext_0_OUTDIR)/Info.plist: \
+		$(PATH_SUB_CURRENT)/Info.plist \
+		$(VBOX_VERSION_MK) | $$(dir $$@)
+	 $(call MSG_GENERATE,VBoxSF,$@,$<)
+	 $(QUIET)$(RM) -f $@
+	 $(QUIET)$(SED) \
+		 -e 's/@VBOX_VERSION_STRING@/$(VBOX_VERSION_STRING)/g' \
+		 -e 's/@VBOX_VERSION_MAJOR@/$(VBOX_VERSION_MAJOR)/g' \
+		 -e 's/@VBOX_VERSION_MINOR@/$(VBOX_VERSION_MINOR)/g' \
+		 -e 's/@VBOX_VERSION_BUILD@/$(VBOX_VERSION_BUILD)/g' \
+		 -e 's/@VBOX_VENDOR@/$(VBOX_VENDOR)/g' \
+		 -e 's/@VBOX_PRODUCT@/$(VBOX_PRODUCT)/g' \
+		 -e 's/@VBOX_C_YEAR@/$(VBOX_C_YEAR)/g' \
+		 --output $@ \
+		 $<
+
+#
+# mount.vboxvfs - The Shared Folders mouning tool.
+#
+PROGRAMS += mount.vboxsf
+mount.vboxsf_TEMPLATE = NewVBoxGuestR3Exe
+mount.vboxsf_SOURCES  = mount.vboxsf.c
+mount.vboxsf_INST     = $(INST_ADDITIONS)VBoxSF.kext/Contents/MacOS/
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-VFSOps.cpp
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-VFSOps.cpp	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-VFSOps.cpp	(revision 75292)
@@ -0,0 +1,575 @@
+/* $Id$ */
+/** @file
+ * VBoxVFS - Filesystem operations.
+ */
+
+/*
+ * Copyright (C) 2013-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <mach/kmod.h>
+#include <libkern/libkern.h>
+#include <mach/mach_types.h>
+
+#include <sys/mount.h>
+#include <sys/vnode.h>
+
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/asm.h>
+
+#include "vboxvfs.h"
+
+/* States of VBoxVFS object used in atomic variables
+ * in order to reach sync between several concurrently running threads. */
+#define VBOXVFS_OBJECT_UNINITIALIZED    (0)
+#define VBOXVFS_OBJECT_INITIALIZING     (1)
+#define VBOXVFS_OBJECT_INITIALIZED      (2)
+#define VBOXVFS_OBJECT_INVALID          (3)
+
+
+/**
+ * Mount helper: Get mounting parameters from user space and validate them.
+ *
+ * @param pUserData     Mounting parameters provided by user space mount tool.
+ * @param pKernelData   Buffer to store pUserData in kernel space.
+ *
+ * @return 0 on success or BSD error code otherwise.
+ */
+static int
+vboxvfs_get_mount_info(user_addr_t pUserData, struct vboxvfs_mount_info *pKernelData)
+{
+    AssertReturn(pKernelData, EINVAL);
+    AssertReturn(pUserData,   EINVAL);
+
+    /* Get mount parameters from user space */
+    if (copyin(pUserData, pKernelData, sizeof(struct vboxvfs_mount_info)) != 0)
+    {
+        PERROR("Unable to copy mount parameters from user space");
+        return EINVAL;
+    }
+
+    /* Validate data magic */
+    if (pKernelData->magic != VBOXVFS_MOUNTINFO_MAGIC)
+    {
+        PERROR("Mount parameter magic mismatch");
+        return EINVAL;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Mount helper: Provide VFS layer with a VBox share name (stored as mounted device).
+ *
+ * @param mp            Mount data provided by VFS layer.
+ * @param szShareName   VBox share name.
+ * @param cbShareName   Returning parameter which contains VBox share name string length.
+ *
+ * @return 0 on success or BSD error code otherwise.
+ */
+static int
+vboxvfs_set_share_name(struct mount *mp, char *szShareName, size_t *cbShareName)
+{
+    struct vfsstatfs *pVfsInfo;
+
+    AssertReturn(mp,          EINVAL);
+    AssertReturn(szShareName, EINVAL);
+    AssertReturn(cbShareName, EINVAL);
+
+    pVfsInfo = vfs_statfs(mp);
+    if (!pVfsInfo)
+    {
+        PERROR("Unable to get VFS data for the mount structure");
+        return EINVAL;
+    }
+
+    return copystr(szShareName, pVfsInfo->f_mntfromname, MAXPATHLEN, cbShareName);
+}
+
+
+/**
+ * Mount helper: allocate locking group attribute and locking group itself.
+ * Store allocated data into VBoxVFS private data.
+ *
+ * @param pMount   VBoxVFS global data which will be updated with
+ *                          locking group and its attribute in case of success;
+ *                          otherwise pMount unchanged.
+ *
+ * @return 0 on success or BSD error code otherwise.
+ *
+ */
+static int
+vboxvfs_prepare_locking(vboxvfs_mount_t *pMount)
+{
+    lck_grp_attr_t *pGrpAttr;
+    lck_grp_t      *pGrp;
+
+    AssertReturn(pMount, EINVAL);
+
+    pGrpAttr = lck_grp_attr_alloc_init();
+    if (pGrpAttr)
+    {
+        pGrp = lck_grp_alloc_init("VBoxVFS", pGrpAttr);
+        if (pGrp)
+        {
+            pMount->pLockGroupAttr = pGrpAttr;
+            pMount->pLockGroup      = pGrp;
+
+            return 0;
+        }
+        else
+            PERROR("Unable to allocate locking group");
+
+        lck_grp_attr_free(pGrpAttr);
+    }
+    else
+        PERROR("Unable to allocate locking group attribute");
+
+    return ENOMEM;
+}
+
+
+/**
+ * Mount and unmount helper: destroy locking group attribute and locking group itself.
+ *
+ * @param pMount   VBoxVFS global data for which locking
+ *                          group and attribute will be deallocated and set to NULL.
+ */
+static void
+vboxvfs_destroy_locking(vboxvfs_mount_t *pMount)
+{
+    AssertReturnVoid(pMount);
+
+    if (pMount->pLockGroup)
+    {
+        lck_grp_free(pMount->pLockGroup);
+        pMount->pLockGroup = NULL;
+    }
+
+    if (pMount->pLockGroupAttr)
+    {
+        lck_grp_attr_free(pMount->pLockGroupAttr);
+        pMount->pLockGroupAttr = NULL;
+    }
+}
+
+/**
+ * Mount helper: Allocate and init VBoxVFS global data.
+ *
+ * @param mp            Mount data provided by VFS layer.
+ * @param pUserData     Mounting parameters provided by user space mount tool.
+ *
+ * @return VBoxVFS global data or NULL.
+ */
+static vboxvfs_mount_t *
+vboxvfs_alloc_internal_data(struct mount *mp, user_addr_t pUserData)
+{
+    vboxvfs_mount_t             *pMount;
+    struct vboxvfs_mount_info    mountInfo;
+    struct vfsstatfs            *pVfsInfo;
+    size_t                       cbShareName;
+
+    int rc;
+
+    AssertReturn(mp,        NULL);
+    AssertReturn(pUserData, NULL);
+
+    pVfsInfo = vfs_statfs(mp);
+    AssertReturn(pVfsInfo, NULL);
+
+    /* Allocate memory for VBoxVFS internal data */
+    pMount = (vboxvfs_mount_t *)RTMemAllocZ(sizeof(vboxvfs_mount_t));
+    if (pMount)
+    {
+        rc = vboxvfs_get_mount_info(pUserData, &mountInfo);
+        if (rc == 0)
+        {
+            PDEBUG("Mounting shared folder '%s'", mountInfo.name);
+
+            /* Prepare for locking. We prepare locking group and attr data here,
+             * but allocate and initialize real lock in vboxvfs_create_vnode_internal().
+             * We use the same pLockGroup and pLockAttr for all vnodes related to this mount point. */
+            rc = vboxvfs_prepare_locking(pMount);
+            if (rc == 0)
+            {
+                rc = vboxvfs_set_share_name(mp, (char *)&mountInfo.name, &cbShareName);
+                if (rc == 0)
+                {
+                    pMount->pShareName = vboxvfs_construct_shflstring((char *)&mountInfo.name, cbShareName);
+                    if (pMount->pShareName)
+                    {
+                        /* Remember user who mounted this share */
+                        pMount->owner = pVfsInfo->f_owner;
+
+                        /* Mark root vnode as uninitialized */
+                        ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_UNINITIALIZED);
+
+                        return pMount;
+                    }
+                }
+            }
+
+            vboxvfs_destroy_locking(pMount);
+        }
+
+        RTMemFree(pMount);
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Mount and unmount helper: Release VBoxVFS internal resources.
+ * Deallocates ppMount as well.
+ *
+ * @param ppMount      Pointer to reference of VBoxVFS internal data.
+ */
+static void
+vboxvfs_destroy_internal_data(vboxvfs_mount_t **ppMount)
+{
+    AssertReturnVoid(ppMount);
+    AssertReturnVoid(*ppMount);
+    AssertReturnVoid((*ppMount)->pShareName);
+
+    RTMemFree((*ppMount)->pShareName);
+    (*ppMount)->pShareName = NULL;
+
+    vboxvfs_destroy_locking(*ppMount);
+    RTMemFree(*ppMount);
+    *ppMount = NULL;
+}
+
+
+/**
+ * Mount VBoxVFS.
+ *
+ * @param mp        Mount data provided by VFS layer.
+ * @param pDev      Device structure provided by VFS layer.
+ * @param pUserData Mounting parameters provided by user space mount tool.
+ * @param pContext  kAuth context needed in order to authentificate mount operation.
+ *
+ * @return 0 on success or BSD error code otherwise.
+ */
+static int
+vboxvfs_mount(struct mount *mp, vnode_t pDev, user_addr_t pUserData, vfs_context_t pContext)
+{
+    NOREF(pDev);
+    NOREF(pContext);
+
+    vboxvfs_mount_t *pMount;
+
+    int rc = ENOMEM;
+
+    PDEBUG("Mounting...");
+
+    pMount = vboxvfs_alloc_internal_data(mp, pUserData);
+    if (pMount)
+    {
+        rc = VbglR0SfMapFolder(&g_vboxSFClient, pMount->pShareName, &pMount->pMap);
+        if (RT_SUCCESS(rc))
+        {
+            /* Private data should be set before vboxvfs_create_vnode_internal() call
+             * because we need it in order to create vnode. */
+            vfs_setfsprivate(mp, pMount);
+
+            /* Reset root vnode */
+            pMount->pRootVnode = NULL;
+
+            vfs_setflags(mp, MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC | MNT_NOSUID | MNT_NODEV);
+
+            PDEBUG("VirtualBox shared folder successfully mounted");
+
+            return 0;
+        }
+
+        PDEBUG("Unable to map shared folder");
+        vboxvfs_destroy_internal_data(&pMount);
+    }
+    else
+        PDEBUG("Unable to allocate internal data");
+
+    return rc;
+}
+
+
+/**
+ * Unmount VBoxVFS.
+ *
+ * @param mp        Mount data provided by VFS layer.
+ * @param fFlags    Unmounting flags.
+ * @param pContext  kAuth context needed in order to authentificate mount operation.
+ *
+ * @return 0 on success or BSD error code otherwise.
+ */
+static int
+vboxvfs_unmount(struct mount *mp, int fFlags, vfs_context_t pContext)
+{
+    NOREF(pContext);
+
+    vboxvfs_mount_t *pMount;
+    int                  rc = EBUSY;
+    int                  fFlush = (fFlags & MNT_FORCE) ? FORCECLOSE : 0;
+
+    PDEBUG("Attempting to %s unmount a shared folder", (fFlags & MNT_FORCE) ? "forcibly" : "normally");
+
+    AssertReturn(mp, EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
+
+    AssertReturn(pMount,             EINVAL);
+    AssertReturn(pMount->pRootVnode, EINVAL);
+
+    /* Check if we can do unmount at the moment */
+    if (!vnode_isinuse(pMount->pRootVnode, 1))
+    {
+        /* Flush child vnodes first */
+        rc = vflush(mp, pMount->pRootVnode, fFlush);
+        if (rc == 0)
+        {
+            /* Flush root vnode */
+            rc = vflush(mp, NULL, fFlush);
+            if (rc == 0)
+            {
+                vfs_setfsprivate(mp, NULL);
+
+                rc = VbglR0SfUnmapFolder(&g_vboxSFClient, &pMount->pMap);
+                if (RT_SUCCESS(rc))
+                {
+                    vboxvfs_destroy_internal_data(&pMount);
+                    PDEBUG("A shared folder has been successfully unmounted");
+                    return 0;
+                }
+
+                PDEBUG("Unable to unmount shared folder");
+                rc = EPROTO;
+            }
+            else
+                PDEBUG("Unable to flush filesystem before unmount, some data might be lost");
+        }
+        else
+            PDEBUG("Unable to flush child vnodes");
+
+    }
+    else
+        PDEBUG("Root vnode is in use, can't unmount");
+
+    vnode_put(pMount->pRootVnode);
+
+    return rc;
+}
+
+
+/**
+ * Get VBoxVFS root vnode.
+ *
+ * Handle three cases here:
+ *  - vnode does not exist yet: create a new one
+ *  - currently creating vnode: wait till the end, increment usage count and return existing one
+ *  - vnode already created: increment usage count and return existing one
+ *  - vnode was failed to create: give a chance to try to re-create it later
+ *
+ * @param mp        Mount data provided by VFS layer.
+ * @param ppVnode   vnode to return.
+ * @param pContext  kAuth context needed in order to authentificate mount operation.
+ *
+ * @return 0 on success or BSD error code otherwise.
+ */
+static int
+vboxvfs_root(struct mount *mp, struct vnode **ppVnode, vfs_context_t pContext)
+{
+    NOREF(pContext);
+
+    vboxvfs_mount_t *pMount;
+    int rc = 0;
+    uint32_t vid;
+
+    PDEBUG("Getting root vnode...");
+
+    AssertReturn(mp,      EINVAL);
+    AssertReturn(ppVnode, EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
+    AssertReturn(pMount, EINVAL);
+
+    /* Check case when vnode does not exist yet */
+    if (ASMAtomicCmpXchgU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INITIALIZING, VBOXVFS_OBJECT_UNINITIALIZED))
+    {
+        PDEBUG("Create new root vnode");
+
+        /* Allocate empty SHFLSTRING to indicate path to root vnode within Shared Folder */
+        char        szEmpty[1];
+        SHFLSTRING *pSFVnodePath;
+
+        pSFVnodePath = vboxvfs_construct_shflstring((char *)szEmpty, 0);
+        if (pSFVnodePath)
+        {
+            int rc2;
+            rc2 = vboxvfs_create_vnode_internal(mp, VDIR, NULL, TRUE, pSFVnodePath, &pMount->pRootVnode);
+            if (rc2 != 0)
+            {
+                RTMemFree(pSFVnodePath);
+                rc = ENOTSUP;
+            }
+        }
+        else
+            rc = ENOMEM;
+
+        /* Notify other threads about result */
+        if (rc == 0)
+            ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INITIALIZED);
+        else
+            ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INVALID);
+    }
+    else
+    {
+        /* Check case if we are currently creating vnode. Wait while other thread to finish allocation. */
+        uint8_t fRootVnodeState = VBOXVFS_OBJECT_UNINITIALIZED;
+        while (fRootVnodeState != VBOXVFS_OBJECT_INITIALIZED
+            && fRootVnodeState != VBOXVFS_OBJECT_INVALID)
+        {
+            /** @todo Currently, we are burning CPU cycles while waiting. This is for a short
+             * time but we should relax here! */
+            fRootVnodeState = ASMAtomicReadU8(&pMount->fRootVnodeState);
+
+        }
+
+        /* Check if the other thread initialized root vnode and it is ready to be returned */
+        if (fRootVnodeState == VBOXVFS_OBJECT_INITIALIZED)
+        {
+            /* Take care about iocount */
+            vid = vnode_vid(pMount->pRootVnode);
+            rc = vnode_getwithvid(pMount->pRootVnode, vid);
+        }
+        else
+        {
+            /* Other thread reported initialization failure.
+             * Set vnode state VBOXVFS_OBJECT_UNINITIALIZED in order to try recreate root
+             * vnode in other attempt */
+            ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_UNINITIALIZED);
+        }
+
+    }
+
+    /* Only return vnode if we got success */
+    if (rc == 0)
+    {
+        PDEBUG("Root vnode can be returned");
+        *ppVnode = pMount->pRootVnode;
+    }
+    else
+        PDEBUG("Root vnode cannot be returned: 0x%X", rc);
+
+    return rc;
+}
+
+/**
+ * VBoxVFS get VFS layer object attribute callback.
+ *
+ * @param mp        Mount data provided by VFS layer.
+ * @param pAttr     Output buffer to return attributes.
+ * @param pContext  kAuth context needed in order to authentificate mount operation.
+ *
+ * @returns     0 for success, else an error code.
+ */
+static int
+vboxvfs_getattr(struct mount *mp, struct vfs_attr *pAttr, vfs_context_t pContext)
+{
+    NOREF(pContext);
+
+    vboxvfs_mount_t     *pMount;
+    SHFLVOLINFO          SHFLVolumeInfo;
+
+    int      rc;
+    uint32_t cbBuffer = sizeof(SHFLVolumeInfo);
+
+    uint32_t u32bsize;
+    uint64_t u64blocks;
+    uint64_t u64bfree;
+
+    PDEBUG("Getting attribute...\n");
+
+    AssertReturn(mp, EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
+    AssertReturn(pMount, EINVAL);
+    AssertReturn(pMount->pShareName, EINVAL);
+
+    rc = VbglR0SfFsInfo(&g_vboxSFClient, &pMount->pMap, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
+                        &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo);
+    AssertReturn(rc == 0, EPROTO);
+
+    u32bsize  = (uint32_t)SHFLVolumeInfo.ulBytesPerAllocationUnit;
+    AssertReturn(u32bsize > 0, ENOTSUP);
+
+    u64blocks = (uint64_t)SHFLVolumeInfo.ullTotalAllocationBytes / (uint64_t)u32bsize;
+    u64bfree  = (uint64_t)SHFLVolumeInfo.ullAvailableAllocationBytes / (uint64_t)u32bsize;
+
+    VFSATTR_RETURN(pAttr, f_bsize,  u32bsize);
+    VFSATTR_RETURN(pAttr, f_blocks, u64blocks);
+    VFSATTR_RETURN(pAttr, f_bfree,  u64bfree);
+    VFSATTR_RETURN(pAttr, f_bavail, u64bfree);
+    VFSATTR_RETURN(pAttr, f_bused,  u64blocks - u64bfree);
+
+    VFSATTR_RETURN(pAttr, f_owner,  pMount->owner);
+
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_iosize);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_files);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_ffree);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_fssubtype);
+
+    /** @todo take care about f_capabilities and f_attributes, f_fsid */
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_capabilities);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_attributes);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_fsid);
+
+    /** @todo take care about f_create_time, f_modify_time, f_access_time, f_backup_time */
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_create_time);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_modify_time);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_access_time);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_backup_time);
+
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_signature);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_carbon_fsid);
+    VFSATTR_CLEAR_ACTIVE(pAttr, f_uuid);
+
+    if (VFSATTR_IS_ACTIVE(pAttr, f_vol_name))
+    {
+        strlcpy(pAttr->f_vol_name, (char*)pMount->pShareName->String.utf8, MAXPATHLEN);
+        VFSATTR_SET_SUPPORTED(pAttr, f_vol_name);
+    }
+
+    VFSATTR_ALL_SUPPORTED(pAttr);
+
+    return 0;
+}
+
+/* VFS options */
+struct vfsops g_oVBoxVFSOpts = {
+    /* Standard operations */
+    &vboxvfs_mount,
+    NULL,               /* Skipped: vfs_start() */
+    &vboxvfs_unmount,
+    &vboxvfs_root,
+    NULL,               /* Skipped: vfs_quotactl */
+    &vboxvfs_getattr,
+    NULL,               /* Skipped: vfs_sync */
+    NULL,               /* Skipped: vfs_vget */
+    NULL,               /* Skipped: vfs_fhtovp */
+    NULL,               /* Skipped: vfs_vptofh */
+    NULL,               /* Skipped: vfs_init */
+    NULL,               /* Skipped: vfs_sysctl */
+    NULL,               /* Skipped: vfs_setattr */
+    /* Reserved */
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, },
+};
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-VNODEOps.cpp
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-VNODEOps.cpp	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-VNODEOps.cpp	(revision 75292)
@@ -0,0 +1,761 @@
+/* $Id$ */
+/** @file
+ * VBoxVFS - vnode operations.
+ */
+
+/*
+ * Copyright (C) 2013-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/errno.h>
+#include <sys/dirent.h>
+
+#include <iprt/mem.h>
+#include <iprt/assert.h>
+
+#include "vboxvfs.h"
+
+#define VNODEOPFUNC int(*)(void *)
+
+static int vboxvfs_dfl_error()
+{
+    PDEBUG("vboxvfs_dfl_error is called");
+
+    return ENOTSUP;
+}
+
+static int
+vboxvfs_vnode_getattr(struct vnop_getattr_args *args)
+{
+    vboxvfs_mount_t   *pMount;
+    struct vnode_attr *vnode_args;
+    vboxvfs_vnode_t   *pVnodeData;
+
+    struct timespec timespec;
+
+    SHFLFSOBJINFO Info;
+    mount_t       mp;
+    vnode_t       vnode;
+    int           rc;
+
+    PDEBUG("Getting vnode attribute...");
+
+    AssertReturn(args, EINVAL);
+
+    vnode                = args->a_vp;                                   AssertReturn(vnode,           EINVAL);
+    vnode_args           = args->a_vap;                                  AssertReturn(vnode_args,      EINVAL);
+    mp                   = vnode_mount(vnode);                           AssertReturn(mp,              EINVAL);
+    pMount      = (vboxvfs_mount_t *)vfs_fsprivate(mp);     AssertReturn(pMount, EINVAL);
+    pVnodeData           = (vboxvfs_vnode_t *)vnode_fsnode(vnode);  AssertReturn(pVnodeData,      EINVAL);
+
+    lck_rw_lock_shared(pVnodeData->pLock);
+
+    rc = vboxvfs_get_info_internal(mp, pVnodeData->pPath, &Info);
+    if (rc == 0)
+    {
+        /* Set timestamps */
+        RTTimeSpecGetTimespec(&Info.BirthTime,        &timespec); VATTR_RETURN(vnode_args, va_create_time, timespec);
+        RTTimeSpecGetTimespec(&Info.AccessTime,       &timespec); VATTR_RETURN(vnode_args, va_access_time, timespec);
+        RTTimeSpecGetTimespec(&Info.ModificationTime, &timespec); VATTR_RETURN(vnode_args, va_modify_time, timespec);
+        RTTimeSpecGetTimespec(&Info.ChangeTime,       &timespec); VATTR_RETURN(vnode_args, va_change_time, timespec);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_backup_time);
+
+        /* Set owner info. */
+        VATTR_RETURN(vnode_args, va_uid, pMount->owner);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_gid);
+
+        /* Access mode and flags */
+        VATTR_RETURN(vnode_args, va_mode,  vboxvfs_h2g_mode_inernal(Info.Attr.fMode));
+        VATTR_RETURN(vnode_args, va_flags, Info.Attr.u.Unix.fFlags);
+
+        /* The current generation number (0 if this information is not available) */
+        VATTR_RETURN(vnode_args, va_gen, Info.Attr.u.Unix.GenerationId);
+
+        VATTR_RETURN(vnode_args, va_rdev,  0);
+        VATTR_RETURN(vnode_args, va_nlink, 2);
+
+        VATTR_RETURN(vnode_args, va_data_size, sizeof(struct dirent)); /* Size of data returned per each readdir() request */
+
+        /* Hope, when it overflows nothing catastrophical will heppen! If we will not assign
+         * a uniq va_fileid to each vnode, `ls`, 'find' (and simmilar tools that uses fts_read() calls) will think that
+         * each sub-directory is self-cycled. */
+        VATTR_RETURN(vnode_args, va_fileid, (pMount->cFileIdCounter++));
+
+        /* Not supported */
+        VATTR_CLEAR_ACTIVE(vnode_args, va_linkid);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_parentid);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_fsid);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_filerev);
+
+        /* Not present on 10.6 */
+        //VATTR_CLEAR_ACTIVE(vnode_args, va_addedtime);
+
+        /** @todo take care about va_encoding (file name encoding) */
+        VATTR_CLEAR_ACTIVE(vnode_args, va_encoding);
+        /** @todo take care about: va_acl */
+        VATTR_CLEAR_ACTIVE(vnode_args, va_acl);
+
+        VATTR_CLEAR_ACTIVE(vnode_args, va_name);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_uuuid);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_guuid);
+
+        VATTR_CLEAR_ACTIVE(vnode_args, va_total_size);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_total_alloc);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_data_alloc);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_iosize);
+
+        VATTR_CLEAR_ACTIVE(vnode_args, va_nchildren);
+        VATTR_CLEAR_ACTIVE(vnode_args, va_dirlinkcount);
+    }
+    else
+    {
+        PDEBUG("getattr: unable to get VBoxVFS object info");
+    }
+
+    lck_rw_unlock_shared(pVnodeData->pLock);
+
+    return rc;
+}
+
+/**
+ * Helper function for vboxvfs_vnode_lookup(): create new vnode.
+ */
+static int
+vboxvfs_vnode_lookup_instantinate_vnode(vnode_t parent_vnode, char *entry_name, vnode_t *result_vnode)
+{
+    /* We need to construct full path to vnode in order to get
+     * vboxvfs_get_info_internal() to understand us! */
+
+    char *pszCurDirPath;
+    int   cbCurDirPath = MAXPATHLEN;
+
+    mount_t mp = vnode_mount(parent_vnode); AssertReturn(mp,  EINVAL);
+    vnode_t vnode;
+
+    int rc;
+
+    pszCurDirPath = (char *)RTMemAllocZ(cbCurDirPath);
+    if (pszCurDirPath)
+    {
+        rc = vn_getpath(parent_vnode, pszCurDirPath, &cbCurDirPath);
+        if (rc == 0 && cbCurDirPath < MAXPATHLEN)
+        {
+            SHFLFSOBJINFO Info;
+            PSHFLSTRING   pSHFLPath;
+
+            /* Add '/' between path parts and truncate name if it is too long */
+            strncat(pszCurDirPath, "/", 1); strncat(pszCurDirPath, entry_name, MAXPATHLEN - cbCurDirPath - 1);
+
+            rc = vboxvfs_guest_path_to_shflstring_path_internal(mp, pszCurDirPath, strlen(pszCurDirPath) + 1, &pSHFLPath);
+            if (rc == 0)
+            {
+                rc = vboxvfs_get_info_internal(mp, pSHFLPath, (PSHFLFSOBJINFO)&Info);
+                if (rc == 0)
+                {
+                    enum vtype type;
+
+                    if      (RTFS_IS_DIRECTORY(Info.Attr.fMode)) type = VDIR;
+                    else if (RTFS_IS_FILE     (Info.Attr.fMode)) type = VREG;
+                    else
+                    {
+                        PDEBUG("Not supported VFS object (%s) type: mode 0x%X",
+                               entry_name,
+                               Info.Attr.fMode);
+
+                        RTMemFree(pszCurDirPath);
+                        vboxvfs_put_path_internal((void **)&pSHFLPath);
+                        return ENOENT;
+                    }
+                    /* Create new vnode */
+                    rc = vboxvfs_create_vnode_internal(mp, type, parent_vnode, FALSE, pSHFLPath, &vnode);
+                    if (rc == 0)
+                    {
+                        PDEBUG("new vnode object '%s' has been created", entry_name);
+
+                        *result_vnode = vnode;
+                        RTMemFree(pszCurDirPath);
+
+                        return 0;
+                    }
+                    else
+                        PDEBUG("Unable to create vnode: %d", rc);
+                }
+                else
+                    PDEBUG("Unable to get host object info: %d", rc);
+
+                vboxvfs_put_path_internal((void **)&pSHFLPath);
+            }
+            else
+                PDEBUG("Unable to convert guest<->host path");
+        }
+        else
+            PDEBUG("Unable to construct vnode path: %d", rc);
+
+        RTMemFree(pszCurDirPath);
+    }
+    else
+    {
+        PDEBUG("Unable to allocate memory for path buffer");
+        rc = ENOMEM;
+    }
+
+    return rc;
+}
+
+/**
+ * Helper function for vboxvfs_vnode_lookup(): take care
+ * about '.' and '..' directory entries.
+ */
+static int
+vboxvfs_vnode_lookup_dot_handler(struct vnop_lookup_args *args, vnode_t *result_vnode)
+{
+    vnode_t vnode = NULL;
+
+    if (args->a_cnp->cn_flags & ISDOTDOT)
+    {
+        vnode = vnode_getparent(args->a_dvp);
+        if (vnode)
+        {
+            PDEBUG("return parent directory");
+            *result_vnode = vnode;
+            return 0;
+        }
+        else
+        {
+            PDEBUG("return parent directory not found, return current directory");
+            *result_vnode = args->a_dvp;
+            return 0;
+        }
+    }
+    else if ((strncmp(args->a_cnp->cn_nameptr, ".", 1) == 0) &&
+             args->a_cnp->cn_namelen == 1)
+    {
+        PDEBUG("return current directory");
+        *result_vnode = args->a_dvp;
+        return 0;
+    }
+
+    return ENOENT;
+}
+
+static int
+vboxvfs_vnode_lookup(struct vnop_lookup_args *args)
+{
+    int rc;
+
+    vnode_t          vnode;
+    vboxvfs_vnode_t *pVnodeData;
+
+    PDEBUG("Looking up for vnode...");
+
+    AssertReturn(args,                      EINVAL);
+    AssertReturn(args->a_dvp,               EINVAL);
+    AssertReturn(vnode_isdir(args->a_dvp),  EINVAL);
+    AssertReturn(args->a_cnp,               EINVAL);
+    AssertReturn(args->a_cnp->cn_nameptr,   EINVAL);
+    AssertReturn(args->a_vpp,               EINVAL);
+
+    pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(args->a_dvp);
+    AssertReturn(pVnodeData, EINVAL);
+    AssertReturn(pVnodeData->pLock, EINVAL);
+
+    /*
+    todo: take care about args->a_cnp->cn_nameiop
+    */
+
+    if      (args->a_cnp->cn_nameiop == LOOKUP) PDEBUG("LOOKUP");
+    else if (args->a_cnp->cn_nameiop == CREATE) PDEBUG("CREATE");
+    else if (args->a_cnp->cn_nameiop == RENAME) PDEBUG("RENAME");
+    else if (args->a_cnp->cn_nameiop == DELETE) PDEBUG("DELETE");
+    else PDEBUG("Unknown cn_nameiop: 0x%X", (int)args->a_cnp->cn_nameiop);
+
+    lck_rw_lock_exclusive(pVnodeData->pLock);
+
+    /* Take care about '.' and '..' entries */
+    if (vboxvfs_vnode_lookup_dot_handler(args, &vnode) == 0)
+    {
+        vnode_get(vnode);
+        *args->a_vpp = vnode;
+
+        lck_rw_unlock_exclusive(pVnodeData->pLock);
+
+        return 0;
+    }
+
+    /* Look into VFS cache and attempt to find previously allocated vnode there. */
+    rc = cache_lookup(args->a_dvp, &vnode, args->a_cnp);
+    if (rc == -1) /* Record found */
+    {
+        PDEBUG("Found record in VFS cache");
+
+        /* Check if VFS object still exist on a host side */
+        if (vboxvfs_exist_internal(vnode))
+        {
+            /* Prepare & return cached vnode */
+            vnode_get(vnode);
+            *args->a_vpp = vnode;
+
+            rc = 0;
+        }
+        else
+        {
+            /* If vnode exist in guets VFS cache, but not exist on a host -- just forget it. */
+            cache_purge(vnode);
+            /** @todo free vnode data here */
+            rc = ENOENT;
+        }
+    }
+    else
+    {
+        PDEBUG("cache_lookup() returned %d, create new VFS vnode", rc);
+
+        rc = vboxvfs_vnode_lookup_instantinate_vnode(args->a_dvp, args->a_cnp->cn_nameptr, &vnode);
+        if (rc == 0)
+        {
+            cache_enter(args->a_dvp, vnode, args->a_cnp);
+            *args->a_vpp = vnode;
+        }
+        else
+        {
+            rc = ENOENT;
+        }
+    }
+
+    lck_rw_unlock_exclusive(pVnodeData->pLock);
+
+    return rc;
+}
+
+static int
+vboxvfs_vnode_open(struct vnop_open_args *args)
+{
+    vnode_t           vnode;
+    vboxvfs_vnode_t  *pVnodeData;
+    uint32_t          fHostFlags;
+    mount_t           mp;
+    vboxvfs_mount_t  *pMount;
+
+    int rc;
+
+    PDEBUG("Opening vnode...");
+
+    AssertReturn(args, EINVAL);
+
+    vnode           = args->a_vp;                              AssertReturn(vnode,      EINVAL);
+    pVnodeData      = (vboxvfs_vnode_t *)vnode_fsnode(vnode);  AssertReturn(pVnodeData, EINVAL);
+    mp              = vnode_mount(vnode);                      AssertReturn(mp,         EINVAL);
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);             AssertReturn(pMount,     EINVAL);
+
+    lck_rw_lock_exclusive(pVnodeData->pLock);
+
+    if (vnode_isinuse(vnode, 0))
+    {
+        PDEBUG("vnode '%s' (handle 0x%X) already has VBoxVFS object handle assigned, just return ok",
+               (char *)pVnodeData->pPath->String.utf8,
+               (int)pVnodeData->pHandle);
+
+        lck_rw_unlock_exclusive(pVnodeData->pLock);
+        return 0;
+    }
+
+    /* At this point we must make sure that nobody is using VBoxVFS object handle */
+    //if (pVnodeData->Handle != SHFL_HANDLE_NIL)
+    //{
+    //    PDEBUG("vnode has active VBoxVFS object handle set, aborting");
+    //    lck_rw_unlock_exclusive(pVnodeData->pLock);
+    //    return EINVAL;
+    //}
+
+    fHostFlags  = vboxvfs_g2h_mode_inernal(args->a_mode);
+    fHostFlags |= (vnode_isdir(vnode) ? SHFL_CF_DIRECTORY : 0);
+
+    SHFLHANDLE Handle;
+    rc = vboxvfs_open_internal(pMount, pVnodeData->pPath, fHostFlags, &Handle);
+    if (rc == 0)
+    {
+        PDEBUG("Open success: '%s' (handle 0x%X)",
+               (char *)pVnodeData->pPath->String.utf8,
+               (int)Handle);
+
+        pVnodeData->pHandle = Handle;
+    }
+    else
+    {
+        PDEBUG("Unable to open: '%s': %d",
+               (char *)pVnodeData->pPath->String.utf8,
+               rc);
+    }
+
+    lck_rw_unlock_exclusive(pVnodeData->pLock);
+
+    return rc;
+}
+
+static int
+vboxvfs_vnode_close(struct vnop_close_args *args)
+{
+    vnode_t          vnode;
+    mount_t          mp;
+    vboxvfs_vnode_t *pVnodeData;
+    vboxvfs_mount_t *pMount;
+
+    int rc;
+
+    PDEBUG("Closing vnode...");
+
+    AssertReturn(args, EINVAL);
+
+    vnode           = args->a_vp;                              AssertReturn(vnode,      EINVAL);
+    pVnodeData      = (vboxvfs_vnode_t *)vnode_fsnode(vnode);  AssertReturn(pVnodeData, EINVAL);
+    mp              = vnode_mount(vnode);                      AssertReturn(mp,         EINVAL);
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);             AssertReturn(pMount,     EINVAL);
+
+    lck_rw_lock_exclusive(pVnodeData->pLock);
+
+    if (vnode_isinuse(vnode, 0))
+    {
+        PDEBUG("vnode '%s' (handle 0x%X) is still in use, just return ok",
+               (char *)pVnodeData->pPath->String.utf8,
+               (int)pVnodeData->pHandle);
+
+        lck_rw_unlock_exclusive(pVnodeData->pLock);
+        return 0;
+    }
+
+    /* At this point we must make sure that vnode has VBoxVFS object handle assigned */
+    if (pVnodeData->pHandle == SHFL_HANDLE_NIL)
+    {
+        PDEBUG("vnode has no active VBoxVFS object handle set, aborting");
+        lck_rw_unlock_exclusive(pVnodeData->pLock);
+        return EINVAL;
+    }
+
+    rc = vboxvfs_close_internal(pMount, pVnodeData->pHandle);
+    if (rc == 0)
+    {
+        PDEBUG("Close success: '%s' (handle 0x%X)",
+               (char *)pVnodeData->pPath->String.utf8,
+               (int)pVnodeData->pHandle);
+
+        /* Forget about previously assigned VBoxVFS object handle */
+        pVnodeData->pHandle = SHFL_HANDLE_NIL;
+    }
+    else
+    {
+        PDEBUG("Unable to close: '%s' (handle 0x%X): %d",
+               (char *)pVnodeData->pPath->String.utf8,
+               (int)pVnodeData->pHandle, rc);
+    }
+
+    lck_rw_unlock_exclusive(pVnodeData->pLock);
+
+    return rc;
+}
+
+/**
+ * Convert SHFLDIRINFO to struct dirent and copy it back to user.
+ */
+static int
+vboxvfs_vnode_readdir_copy_data(ino_t index, SHFLDIRINFO *Info, struct uio *uio, int *numdirent)
+{
+    struct dirent entry;
+
+    int rc;
+
+    entry.d_ino = index;
+    entry.d_reclen = (__uint16_t)sizeof(entry);
+
+    /* Detect dir entry type */
+    if (RTFS_IS_DIRECTORY(Info->Info.Attr.fMode))
+        entry.d_type = DT_DIR;
+    else if (RTFS_IS_FILE(Info->Info.Attr.fMode))
+        entry.d_type = DT_REG;
+    else
+    {
+        PDEBUG("Unknown type of host file: mode 0x%X", (int)Info->Info.Attr.fMode);
+        return ENOTSUP;
+    }
+
+    entry.d_namlen = (__uint8_t)min(sizeof(entry.d_name), Info->name.u16Size);
+    memcpy(entry.d_name, Info->name.String.utf8, entry.d_namlen);
+
+    rc = uiomove((char *)&entry, sizeof(entry), uio);
+    if (rc == 0)
+    {
+        uio_setoffset(uio, index * sizeof(struct dirent));
+        *numdirent = (int)index;
+
+        PDEBUG("discovered entry: '%s' (%d bytes), item #%d", entry.d_name, (int)entry.d_namlen, (int)index);
+    }
+    else
+    {
+        PDEBUG("Failed to return dirent data item #%d (%d)", (int)index, rc);
+    }
+
+    return rc;
+}
+
+static int
+vboxvfs_vnode_readdir(struct vnop_readdir_args *args)
+{
+    vboxvfs_mount_t *pMount;
+    vboxvfs_vnode_t *pVnodeData;
+    SHFLDIRINFO     *Info;
+    uint32_t         cbInfo;
+    mount_t          mp;
+    vnode_t          vnode;
+    struct uio      *uio;
+
+    int rc = 0, rc2;
+
+    PDEBUG("Reading directory...");
+
+    AssertReturn(args,              EINVAL);
+    AssertReturn(args->a_eofflag,   EINVAL);
+    AssertReturn(args->a_numdirent, EINVAL);
+
+    uio             = args->a_uio;                             AssertReturn(uio,        EINVAL);
+    vnode           = args->a_vp;                              AssertReturn(vnode,      EINVAL); AssertReturn(vnode_isdir(vnode), EINVAL);
+    pVnodeData      = (vboxvfs_vnode_t *)vnode_fsnode(vnode);  AssertReturn(pVnodeData, EINVAL);
+    mp              = vnode_mount(vnode);                      AssertReturn(mp,         EINVAL);
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);             AssertReturn(pMount,     EINVAL);
+
+    lck_rw_lock_shared(pVnodeData->pLock);
+
+    cbInfo = sizeof(Info) + MAXPATHLEN;
+    Info   = (SHFLDIRINFO *)RTMemAllocZ(cbInfo);
+    if (!Info)
+    {
+        PDEBUG("No memory to allocate internal data");
+        lck_rw_unlock_shared(pVnodeData->pLock);
+        return ENOMEM;
+    }
+
+    uint32_t index = (uint32_t)uio_offset(uio) / (uint32_t)sizeof(struct dirent);
+    uint32_t cFiles = 0;
+
+    PDEBUG("Exploring VBoxVFS directory (%s), handle (0x%.8X), offset (0x%X), count (%d)", (char *)pVnodeData->pPath->String.utf8, (int)pVnodeData->pHandle, index, uio_iovcnt(uio));
+
+    /* Currently, there is a problem when VbglR0SfDirInfo() is not able to
+     * continue retrieve directory content if the same VBoxVFS handle is used.
+     * This macro forces to use a new handle in readdir() callback. If enabled,
+     * the original handle (obtained in open() callback is ignored). */
+
+    SHFLHANDLE Handle;
+    rc = vboxvfs_open_internal(pMount,
+                               pVnodeData->pPath,
+                               SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW,
+                               &Handle);
+    if (rc != 0)
+    {
+        PDEBUG("Unable to open dir: %d", rc);
+        RTMemFree(Info);
+        lck_rw_unlock_shared(pVnodeData->pLock);
+        return rc;
+    }
+
+#if 0
+    rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0, 0, index, &cbInfo, (PSHFLDIRINFO)Info, &cFiles);
+#else
+    SHFLSTRING *pMask = vboxvfs_construct_shflstring("*", strlen("*"));
+    if (pMask)
+    {
+        for (uint32_t cSkip = 0; (cSkip < index + 1) && (rc == VINF_SUCCESS); cSkip++)
+        {
+            //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0 /* pMask */, 0 /* SHFL_LIST_RETURN_ONE */, 0, &cbInfo, (PSHFLDIRINFO)Info, &cFiles);
+
+            uint32_t cbReturned = cbInfo;
+            //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, pMask, SHFL_LIST_RETURN_ONE, 0, &cbReturned, (PSHFLDIRINFO)Info, &cFiles);
+            rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0, SHFL_LIST_RETURN_ONE, 0,
+                                 &cbReturned, (PSHFLDIRINFO)Info, &cFiles);
+
+        }
+
+        PDEBUG("read %d files", cFiles);
+        RTMemFree(pMask);
+    }
+    else
+    {
+        PDEBUG("Can't alloc mask");
+        rc = ENOMEM;
+    }
+#endif
+    rc2 = vboxvfs_close_internal(pMount, Handle);
+    if (rc2 != 0)
+    {
+        PDEBUG("Unable to close directory: %s: %d",
+               pVnodeData->pPath->String.utf8,
+               rc2);
+    }
+
+    switch (rc)
+    {
+        case VINF_SUCCESS:
+        {
+            rc = vboxvfs_vnode_readdir_copy_data((ino_t)(index + 1), Info, uio, args->a_numdirent);
+            break;
+        }
+
+        case VERR_NO_MORE_FILES:
+        {
+            PDEBUG("No more entries in directory");
+            *(args->a_eofflag) = 1;
+            break;
+        }
+
+        default:
+        {
+            PDEBUG("VbglR0SfDirInfo() for item #%d has failed: %d", (int)index, (int)rc);
+            rc = EINVAL;
+            break;
+        }
+    }
+
+    RTMemFree(Info);
+    lck_rw_unlock_shared(pVnodeData->pLock);
+
+    return rc;
+}
+
+static int
+vboxvfs_vnode_access(struct vnop_access_args *args)
+{
+    PDEBUG("here");
+    return 0;
+}
+
+
+static int
+vboxvfs_vnode_readdirattr(struct vnop_readdirattr_args *args)
+{
+    PDEBUG("here");
+    return 0;
+}
+
+static int
+vboxvfs_vnode_pathconf(struct vnop_pathconf_args *args)
+{
+    PDEBUG("here");
+    return 0;
+}
+
+/**
+ * VBoxVFS reclaim callback.
+ * Called when vnode is going to be deallocated. Should release
+ * all the VBoxVFS resources that correspond to current vnode object.
+ *
+ * @param pArgs     Operation arguments passed from VFS layer.
+ *
+ * @return 0 on success, BSD error code otherwise.
+ */
+static int
+vboxvfs_vnode_reclaim(struct vnop_reclaim_args *pArgs)
+{
+    PDEBUG("Releasing vnode resources...");
+
+    AssertReturn(pArgs, EINVAL);
+
+    vnode_t          pVnode;
+    vboxvfs_vnode_t *pVnodeData;
+    vboxvfs_mount_t *pMount;
+    mount_t          mp;
+
+    pVnode = pArgs->a_vp;
+    AssertReturn(pVnode, EINVAL);
+
+    mp = vnode_mount(pVnode);
+    AssertReturn(mp, EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
+    AssertReturn(pMount, EINVAL);
+
+    pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(pVnode);
+    AssertReturn(pVnodeData, EINVAL);
+    AssertReturn(pVnodeData->pPath, EINVAL);
+    AssertReturn(pVnodeData->pLockAttr, EINVAL);
+    AssertReturn(pVnodeData->pLock, EINVAL);
+
+    RTMemFree(pVnodeData->pPath);
+    pVnodeData->pPath = NULL;
+
+    lck_rw_free(pVnodeData->pLock, pMount->pLockGroup);
+    pVnodeData->pLock = NULL;
+
+    lck_attr_free(pVnodeData->pLockAttr);
+    pVnodeData->pLockAttr = NULL;
+
+    return 0;
+}
+
+/* Directory vnode operations */
+static struct vnodeopv_entry_desc oVBoxVFSDirOpsDescList[] = {
+    { &vnop_default_desc,     (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_lookup_desc,      (VNODEOPFUNC)vboxvfs_vnode_lookup },
+    { &vnop_create_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_whiteout_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_mknod_desc,       (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_open_desc,        (VNODEOPFUNC)vboxvfs_vnode_open },
+    { &vnop_close_desc,       (VNODEOPFUNC)vboxvfs_vnode_close },
+    { &vnop_access_desc,      (VNODEOPFUNC)vboxvfs_vnode_access },
+    { &vnop_getattr_desc,     (VNODEOPFUNC)vboxvfs_vnode_getattr },
+    { &vnop_setattr_desc,     (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_read_desc,        (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_write_desc,       (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_ioctl_desc,       (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_select_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_exchange_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_revoke_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_mmap_desc,        (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_mnomap_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_fsync_desc,       (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_remove_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_link_desc,        (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_rename_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_mkdir_desc,       (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_rmdir_desc,       (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_symlink_desc,     (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_readdir_desc,     (VNODEOPFUNC)vboxvfs_vnode_readdir },
+    { &vnop_readdirattr_desc, (VNODEOPFUNC)vboxvfs_vnode_readdirattr },
+    { &vnop_readlink_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_inactive_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_reclaim_desc,     (VNODEOPFUNC)vboxvfs_vnode_reclaim },
+    /* { &vnop_print_desc,       (VNODEOPFUNC)vboxvfs_dfl_error }, undefined in ML */
+    { &vnop_pathconf_desc,    (VNODEOPFUNC)vboxvfs_vnode_pathconf },
+    { &vnop_advlock_desc,     (VNODEOPFUNC)vboxvfs_dfl_error },
+    /* { &vnop_truncate_desc,    (VNODEOPFUNC)vboxvfs_dfl_error }, undefined in ML */
+    { &vnop_allocate_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_pagein_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_pageout_desc,     (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_searchfs_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_copyfile_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_blktooff_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_offtoblk_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_blockmap_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_strategy_desc,    (VNODEOPFUNC)vboxvfs_dfl_error },
+    { &vnop_bwrite_desc,      (VNODEOPFUNC)vboxvfs_dfl_error },
+    { NULL,                   (VNODEOPFUNC)NULL              },
+};
+
+int (**g_VBoxVFSVnodeDirOpsVector)(void *);
+
+static struct vnodeopv_desc oVBoxVFSVnodeDirOps = {
+    &g_VBoxVFSVnodeDirOpsVector,
+    oVBoxVFSDirOpsDescList
+};
+
+struct vnodeopv_desc *g_VBoxVFSVnodeOpvDescList[] = {
+    &oVBoxVFSVnodeDirOps,
+};
+
+int g_cVBoxVFSVnodeOpvDescListSize =
+    sizeof(**g_VBoxVFSVnodeOpvDescList) / sizeof(struct vnodeopv_desc);
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-utils.cpp
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-utils.cpp	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS-utils.cpp	(revision 75292)
@@ -0,0 +1,599 @@
+/* $Id$ */
+/** @file
+ * VBoxVFS - helper functions.
+ */
+
+/*
+ * Copyright (C) 2013-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <mach/kmod.h>
+#include <libkern/libkern.h>
+#include <mach/mach_types.h>
+
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+
+#include "vboxvfs.h"
+
+/**
+ * Helper function to create XNU VFS vnode object.
+ *
+ * @param mp        Mount data structure
+ * @param type      vnode type (directory, regular file, etc)
+ * @param pParent   Parent vnode object (NULL for VBoxVFS root vnode)
+ * @param fIsRoot   Flag that indicates if created vnode object is
+ *                  VBoxVFS root vnode (TRUE for VBoxVFS root vnode, FALSE
+ *                  for all aother vnodes)
+ * @param           Path within Shared Folder
+ * @param ret       Returned newly created vnode
+ *
+ * @return 0 on success, error code otherwise
+ */
+int
+vboxvfs_create_vnode_internal(struct mount *mp, enum vtype type, vnode_t pParent, int fIsRoot, PSHFLSTRING Path, vnode_t *ret)
+{
+    int     rc;
+    vnode_t vnode;
+
+    vboxvfs_vnode_t  *pVnodeData;
+    vboxvfs_mount_t  *pMount;
+
+    AssertReturn(mp, EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
+    AssertReturn(pMount, EINVAL);
+    AssertReturn(pMount->pLockGroup, EINVAL);
+
+    AssertReturn(Path, EINVAL);
+
+    pVnodeData = (vboxvfs_vnode_t *)RTMemAllocZ(sizeof(vboxvfs_vnode_t));
+    AssertReturn(pVnodeData, ENOMEM);
+
+    /* Initialize private data */
+    pVnodeData->pHandle = SHFL_HANDLE_NIL;
+    pVnodeData->pPath   = Path;
+
+    pVnodeData->pLockAttr = lck_attr_alloc_init();
+    if (pVnodeData->pLockAttr)
+    {
+        pVnodeData->pLock = lck_rw_alloc_init(pMount->pLockGroup, pVnodeData->pLockAttr);
+        if (pVnodeData->pLock)
+        {
+            struct vnode_fsparam vnode_params;
+
+            vnode_params.vnfs_mp         = mp;
+            vnode_params.vnfs_vtype      = type;
+            vnode_params.vnfs_str        = NULL;
+            vnode_params.vnfs_dvp        = pParent;
+            vnode_params.vnfs_fsnode     = pVnodeData;  /** Private data attached per xnu's vnode object */
+            vnode_params.vnfs_vops       = g_VBoxVFSVnodeDirOpsVector;
+
+            vnode_params.vnfs_markroot   = fIsRoot;
+            vnode_params.vnfs_marksystem = FALSE;
+            vnode_params.vnfs_rdev       = 0;
+            vnode_params.vnfs_filesize   = 0;
+            vnode_params.vnfs_cnp        = NULL;
+
+            vnode_params.vnfs_flags      = VNFS_ADDFSREF | VNFS_NOCACHE;
+
+            rc = vnode_create(VNCREATE_FLAVOR, sizeof(vnode_params), &vnode_params, &vnode);
+            if (rc == 0)
+                *ret = vnode;
+
+            return 0;
+        }
+        else
+        {
+            PDEBUG("Unable to allocate lock");
+            rc = ENOMEM;
+        }
+
+        lck_attr_free(pVnodeData->pLockAttr);
+    }
+    else
+    {
+        PDEBUG("Unable to allocate lock attr");
+        rc = ENOMEM;
+    }
+
+    return rc;
+}
+
+/**
+ * Convert guest absolute VFS path (starting from VFS root) to a host path
+ * within mounted shared folder (returning it as a char *).
+ *
+ * @param mp            Mount data structure
+ * @param pszGuestPath  Guest absolute VFS path (starting from VFS root)
+ * @param cbGuestPath   Size of pszGuestPath
+ * @param pszHostPath   Returned char * wich contains host path
+ * @param cbHostPath    Returned pszHostPath size
+ *
+ * @return 0 on success, error code otherwise
+ */
+int
+vboxvfs_guest_path_to_char_path_internal(mount_t mp, char *pszGuestPath, int cbGuestPath, char **pszHostPath, int *cbHostPath)
+{
+    vboxvfs_mount_t *pMount;
+
+    /* Guest side: mount point path buffer and its size */
+    char       *pszMntPointPath;
+    int         cbMntPointPath = MAXPATHLEN;
+
+    /* Host side: path within mounted shared folder and its size */
+    char       *pszHostPathInternal;
+    size_t      cbHostPathInternal;
+
+    int rc;
+
+    AssertReturn(mp, EINVAL);
+    AssertReturn(pszGuestPath, EINVAL); AssertReturn(cbGuestPath >= 0, EINVAL);
+    AssertReturn(pszHostPath,  EINVAL); AssertReturn(cbHostPath,       EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); AssertReturn(pMount->pRootVnode, EINVAL);
+
+    /* Get mount point path */
+    pszMntPointPath = (char *)RTMemAllocZ(cbMntPointPath);
+    if (pszMntPointPath)
+    {
+        rc = vn_getpath(pMount->pRootVnode, pszMntPointPath, &cbMntPointPath);
+        if (rc == 0 && cbGuestPath >= cbMntPointPath)
+        {
+            cbHostPathInternal  = cbGuestPath - cbMntPointPath + 1;
+            pszHostPathInternal = (char *)RTMemAllocZ(cbHostPathInternal);
+            if (pszHostPathInternal)
+            {
+                memcpy(pszHostPathInternal, pszGuestPath + cbMntPointPath, cbGuestPath - cbMntPointPath);
+                PDEBUG("guest<->host path converion result: '%s' mounted to '%s'", pszHostPathInternal, pszMntPointPath);
+
+                RTMemFree(pszMntPointPath);
+
+                *pszHostPath = pszHostPathInternal;
+                *cbHostPath  = cbGuestPath - cbMntPointPath;
+
+                return 0;
+
+            }
+            else
+            {
+                PDEBUG("No memory to allocate buffer for guest<->host path conversion (cbHostPathInternal)");
+                rc = ENOMEM;
+            }
+
+        }
+        else
+        {
+            PDEBUG("Unable to get guest vnode path: %d", rc);
+        }
+
+        RTMemFree(pszMntPointPath);
+    }
+    else
+    {
+        PDEBUG("No memory to allocate buffer for guest<->host path conversion (pszMntPointPath)");
+        rc = ENOMEM;
+    }
+
+    return rc;
+}
+
+/**
+ * Convert guest absolute VFS path (starting from VFS root) to a host path
+ * within mounted shared folder.
+ *
+ * @param mp            Mount data structure
+ * @param pszGuestPath  Guest absolute VFS path (starting from VFS root)
+ * @param cbGuestPath   Size of pszGuestPath
+ * @param ppResult      Returned PSHFLSTRING object wich contains host path
+ *
+ * @return 0 on success, error code otherwise
+ */
+int
+vboxvfs_guest_path_to_shflstring_path_internal(mount_t mp, char *pszGuestPath, int cbGuestPath, PSHFLSTRING *ppResult)
+{
+    vboxvfs_mount_t *pMount;
+
+    /* Guest side: mount point path buffer and its size */
+    char       *pszMntPointPath;
+    int         cbMntPointPath = MAXPATHLEN;
+
+    /* Host side: path within mounted shared folder and its size */
+    PSHFLSTRING pSFPath;
+    size_t      cbSFPath;
+
+    int rc;
+
+    AssertReturn(mp, EINVAL);
+    AssertReturn(pszGuestPath, EINVAL);
+    AssertReturn(cbGuestPath >= 0, EINVAL);
+
+    char *pszHostPath;
+    int   cbHostPath;
+
+    rc = vboxvfs_guest_path_to_char_path_internal(mp, pszGuestPath, cbGuestPath, &pszHostPath, &cbHostPath);
+    if (rc == 0)
+    {
+        cbSFPath = offsetof(SHFLSTRING, String.utf8) + (size_t)cbHostPath + 1;
+        pSFPath  = (PSHFLSTRING)RTMemAllocZ(cbSFPath);
+        if (pSFPath)
+        {
+            pSFPath->u16Length = cbHostPath;
+            pSFPath->u16Size   = cbHostPath + 1;
+            memcpy(pSFPath->String.utf8, pszHostPath, cbHostPath);
+            vboxvfs_put_path_internal((void **)&pszHostPath);
+
+            *ppResult = pSFPath;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Wrapper function for vboxvfs_guest_path_to_char_path_internal() which
+ * converts guest path to host path using vnode object information.
+ *
+ * @param vnode         Guest's VFS object
+ * @param ppHostPath    Allocated  char * which contain a path
+ * @param pcbPath       Size of ppPath
+ *
+ * @return 0 on success, error code otherwise.
+ */
+int
+vboxvfs_guest_vnode_to_char_path_internal(vnode_t vnode, char **ppHostPath, int *pcbHostPath)
+{
+    mount_t     mp;
+    int         rc;
+
+    char       *pszPath;
+    int         cbPath = MAXPATHLEN;
+
+    AssertReturn(ppHostPath,   EINVAL);
+    AssertReturn(pcbHostPath,  EINVAL);
+    AssertReturn(vnode,    EINVAL);
+    mp = vnode_mount(vnode); AssertReturn(mp, EINVAL);
+
+    pszPath = (char *)RTMemAllocZ(cbPath);
+    if (pszPath)
+    {
+        rc = vn_getpath(vnode, pszPath, &cbPath);
+        if (rc == 0)
+        {
+            return vboxvfs_guest_path_to_char_path_internal(mp, pszPath, cbPath, ppHostPath, pcbHostPath);
+        }
+    }
+    else
+    {
+        rc = ENOMEM;
+    }
+
+    return rc;
+}
+
+/**
+ * Wrapper function for vboxvfs_guest_path_to_shflstring_path_internal() which
+ * converts guest path to host path using vnode object information.
+ *
+ * @param vnode     Guest's VFS object
+ * @param ppResult  Allocated  PSHFLSTRING object which contain a path
+ *
+ * @return 0 on success, error code otherwise.
+ */
+int
+vboxvfs_guest_vnode_to_shflstring_path_internal(vnode_t vnode, PSHFLSTRING *ppResult)
+{
+    mount_t     mp;
+    int         rc;
+
+    char       *pszPath;
+    int         cbPath = MAXPATHLEN;
+
+    AssertReturn(ppResult, EINVAL);
+    AssertReturn(vnode,    EINVAL);
+    mp = vnode_mount(vnode); AssertReturn(mp, EINVAL);
+
+    pszPath = (char *)RTMemAllocZ(cbPath);
+    if (pszPath)
+    {
+        rc = vn_getpath(vnode, pszPath, &cbPath);
+        if (rc == 0)
+        {
+            return vboxvfs_guest_path_to_shflstring_path_internal(mp, pszPath, cbPath, ppResult);
+        }
+    }
+    else
+    {
+        rc = ENOMEM;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Free resources allocated by vboxvfs_path_internal() and vboxvfs_guest_vnode_to_shflstring_path_internal().
+ *
+ * @param ppHandle  Reference to object to be freed.
+ */
+void
+vboxvfs_put_path_internal(void **ppHandle)
+{
+    AssertReturnVoid(ppHandle);
+    AssertReturnVoid(*ppHandle);
+    RTMemFree(*ppHandle);
+}
+
+static void
+vboxvfs_g2h_mode_dump_inernal(uint32_t fHostMode)
+{
+    PDEBUG("Host VFS object  flags (0x%X) dump:", (int)fHostMode);
+
+    if (fHostMode & SHFL_CF_ACCESS_READ)                PDEBUG("SHFL_CF_ACCESS_READ");
+    if (fHostMode & SHFL_CF_ACCESS_WRITE)               PDEBUG("SHFL_CF_ACCESS_WRITE");
+    if (fHostMode & SHFL_CF_ACCESS_APPEND)              PDEBUG("SHFL_CF_ACCESS_APPEND");
+
+    if ((fHostMode & (SHFL_CF_ACT_FAIL_IF_EXISTS    |
+                      SHFL_CF_ACT_REPLACE_IF_EXISTS |
+                      SHFL_CF_ACT_OVERWRITE_IF_EXISTS)) == 0)
+                                                        PDEBUG("SHFL_CF_ACT_OPEN_IF_EXISTS");
+
+    if (fHostMode & SHFL_CF_ACT_CREATE_IF_NEW)          PDEBUG("SHFL_CF_ACT_CREATE_IF_NEW");
+    if (fHostMode & SHFL_CF_ACT_FAIL_IF_NEW)            PDEBUG("SHFL_CF_ACT_FAIL_IF_NEW");
+    if (fHostMode & SHFL_CF_ACT_OVERWRITE_IF_EXISTS)    PDEBUG("SHFL_CF_ACT_OVERWRITE_IF_EXISTS");
+    if (fHostMode & SHFL_CF_DIRECTORY)                  PDEBUG("SHFL_CF_DIRECTORY");
+
+    PDEBUG("Done");
+}
+
+
+/**
+ * Open existing VBoxVFS object and return its handle.
+ *
+ * @param pMount   Mount session data.
+ * @param pPath             VFS path to the object relative to mount point.
+ * @param fFlags            For directory object it should be
+ *                          SHFL_CF_DIRECTORY and 0 for any other object.
+ * @param pHandle           Returned handle.
+ *
+ * @return 0 on success, error code otherwise.
+ */
+int
+vboxvfs_open_internal(vboxvfs_mount_t *pMount, PSHFLSTRING pPath, uint32_t fFlags, SHFLHANDLE *pHandle)
+{
+    SHFLCREATEPARMS parms;
+
+    int rc;
+
+    AssertReturn(pMount,      EINVAL);
+    AssertReturn(pPath,                EINVAL);
+    AssertReturn(pHandle,              EINVAL);
+
+    bzero(&parms, sizeof(parms));
+
+    vboxvfs_g2h_mode_dump_inernal(fFlags);
+
+    parms.Handle        = SHFL_HANDLE_NIL;
+    parms.Info.cbObject = 0;
+    parms.CreateFlags   = fFlags;
+
+    rc = VbglR0SfCreate(&g_vboxSFClient, &pMount->pMap, pPath, &parms);
+    if (RT_SUCCESS(rc))
+    {
+        *pHandle = parms.Handle;
+    }
+    else
+    {
+        PDEBUG("vboxvfs_open_internal() failed: %d", rc);
+    }
+
+    return rc;
+}
+
+/**
+ * Release VBoxVFS object handle openned by vboxvfs_open_internal().
+ *
+ * @param pMount   Mount session data.
+ * @param pHandle           Handle to close.
+ *
+ * @return 0 on success, IPRT error code otherwise.
+ */
+int
+vboxvfs_close_internal(vboxvfs_mount_t *pMount, SHFLHANDLE pHandle)
+{
+    AssertReturn(pMount, EINVAL);
+    return VbglR0SfClose(&g_vboxSFClient, &pMount->pMap, pHandle);
+}
+
+/**
+ * Get information about host VFS object.
+ *
+ * @param mp           Mount point data
+ * @param pSHFLDPath   Path to VFS object within mounted shared folder
+ * @param Info         Returned info
+ *
+ * @return  0 on success, error code otherwise.
+ */
+int
+vboxvfs_get_info_internal(mount_t mp, PSHFLSTRING pSHFLDPath, PSHFLFSOBJINFO Info)
+{
+    vboxvfs_mount_t        *pMount;
+    SHFLCREATEPARMS         parms;
+
+    int rc;
+
+    AssertReturn(mp, EINVAL);
+    AssertReturn(pSHFLDPath, EINVAL);
+    AssertReturn(Info, EINVAL);
+
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);
+
+    parms.Handle = 0;
+    parms.Info.cbObject = 0;
+    parms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
+
+    rc = VbglR0SfCreate(&g_vboxSFClient, &pMount->pMap, pSHFLDPath, &parms);
+    if (rc == 0)
+        *Info = parms.Info;
+
+    return rc;
+}
+
+/**
+ * Check if VFS object exists on a host side.
+ *
+ * @param vnode     Guest VFS vnode that corresponds to host VFS object
+ *
+ * @return 1 if exists, 0 otherwise.
+ */
+int
+vboxvfs_exist_internal(vnode_t vnode)
+{
+    int rc;
+
+    PSHFLSTRING   pSFPath = NULL;
+    SHFLHANDLE    handle;
+    uint32_t      fFlags;
+
+    vboxvfs_mount_t        *pMount;
+    mount_t                 mp;
+
+    /* Return FALSE if invalid parameter given */
+    AssertReturn(vnode, 0);
+
+    mp = vnode_mount(vnode); AssertReturn(mp,  EINVAL);
+    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);
+
+    fFlags  = (vnode_isdir(vnode)) ? SHFL_CF_DIRECTORY : 0;
+    fFlags |= SHFL_CF_ACCESS_READ | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
+
+    rc = vboxvfs_guest_vnode_to_shflstring_path_internal(vnode, &pSFPath); AssertReturn(rc == 0, rc);
+    if (rc == 0)
+    {
+        rc = vboxvfs_open_internal(pMount, pSFPath, fFlags, &handle);
+        if (rc == 0)
+        {
+            rc = vboxvfs_close_internal(pMount, handle);
+            if (rc != 0)
+            {
+                PDEBUG("Unable to close() VBoxVFS object handle while checking if object exist on host: %d", rc);
+            }
+        }
+    }
+
+    vboxvfs_put_path_internal((void **)&pSFPath);
+
+    return (rc == 0);
+}
+
+/**
+ * Convert host VFS object mode flags into guest ones.
+ *
+ * @param fHostMode     Host flags
+ *
+ * @return Guest flags
+ */
+mode_t
+vboxvfs_h2g_mode_inernal(RTFMODE fHostMode)
+{
+    mode_t fGuestMode = 0;
+
+    fGuestMode = /* Owner */
+                 ((fHostMode & RTFS_UNIX_IRUSR)  ? S_IRUSR  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_IWUSR)  ? S_IWUSR  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_IXUSR)  ? S_IXUSR  : 0 ) |
+                 /* Group */
+                 ((fHostMode & RTFS_UNIX_IRGRP)  ? S_IRGRP  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_IWGRP)  ? S_IWGRP  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_IXGRP)  ? S_IXGRP  : 0 ) |
+                 /* Other */
+                 ((fHostMode & RTFS_UNIX_IROTH)  ? S_IROTH  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_IWOTH)  ? S_IWOTH  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_IXOTH)  ? S_IXOTH  : 0 ) |
+                 /* SUID, SGID, SVTXT */
+                 ((fHostMode & RTFS_UNIX_ISUID)  ? S_ISUID  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_ISGID)  ? S_ISGID  : 0 ) |
+                 ((fHostMode & RTFS_UNIX_ISTXT)  ? S_ISVTX  : 0 ) |
+                 /* VFS object types */
+                 ((RTFS_IS_FIFO(fHostMode))      ? S_IFIFO  : 0 ) |
+                 ((RTFS_IS_DEV_CHAR(fHostMode))  ? S_IFCHR  : 0 ) |
+                 ((RTFS_IS_DIRECTORY(fHostMode)) ? S_IFDIR  : 0 ) |
+                 ((RTFS_IS_DEV_BLOCK(fHostMode)) ? S_IFBLK  : 0 ) |
+                 ((RTFS_IS_FILE(fHostMode))      ? S_IFREG  : 0 ) |
+                 ((RTFS_IS_SYMLINK(fHostMode))   ? S_IFLNK  : 0 ) |
+                 ((RTFS_IS_SOCKET(fHostMode))    ? S_IFSOCK : 0 );
+
+    return fGuestMode;
+}
+
+/**
+ * Convert guest VFS object mode flags into host ones.
+ *
+ * @param fGuestMode     Host flags
+ *
+ * @return Host flags
+ */
+uint32_t
+vboxvfs_g2h_mode_inernal(mode_t fGuestMode)
+{
+    uint32_t fHostMode = 0;
+
+    fHostMode = ((fGuestMode & FREAD)    ? SHFL_CF_ACCESS_READ   : 0 ) |
+                ((fGuestMode & FWRITE)   ? SHFL_CF_ACCESS_WRITE  : 0 ) |
+                /* skipped: O_NONBLOCK */
+                ((fGuestMode & O_APPEND) ? SHFL_CF_ACCESS_APPEND : 0 ) |
+                /* skipped: O_SYNC */
+                /* skipped: O_SHLOCK */
+                /* skipped: O_EXLOCK */
+                /* skipped: O_ASYNC */
+                /* skipped: O_FSYNC */
+                /* skipped: O_NOFOLLOW */
+                ((fGuestMode & O_CREAT)  ? SHFL_CF_ACT_CREATE_IF_NEW | (!(fGuestMode & O_TRUNC) ? SHFL_CF_ACT_OPEN_IF_EXISTS : 0)  : SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW ) |
+                ((fGuestMode & O_TRUNC)  ? SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACCESS_WRITE                                  : 0 );
+                /* skipped: O_EXCL */
+
+    return fHostMode;
+}
+
+/**
+ * Mount helper: Contruct SHFLSTRING which contains VBox share name or path.
+ *
+ * @returns Initialize string buffer on success, NULL if out of memory.
+ * @param   pachName    The string to pack in a buffer.  Does not need to be
+ *                      zero terminated.
+ * @param   cchName     The length of pachName to use.  RTSTR_MAX for strlen.
+ */
+SHFLSTRING *
+vboxvfs_construct_shflstring(const char *pachName, size_t cchName)
+{
+    AssertReturn(pachName, NULL);
+
+    if (cchName == RTSTR_MAX)
+        cchName = strlen(pachName);
+
+    SHFLSTRING *pSHFLString = (SHFLSTRING *)RTMemAlloc(SHFLSTRING_HEADER_SIZE + cchName + 1);
+    if (pSHFLString)
+    {
+        pSHFLString->u16Length = cchName;
+        pSHFLString->u16Size   = cchName + 1;
+        memcpy(pSHFLString->String.utf8, pachName, cchName);
+        pSHFLString->String.utf8[cchName] = '\0';
+
+        return pSHFLString;
+    }
+    return NULL;
+}
+
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS.cpp
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS.cpp	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/VBoxVFS.cpp	(revision 75292)
@@ -0,0 +1,314 @@
+/* $Id$ */
+/** @file
+ * VBoxVFS - Guest Additions Shared Folders driver. KEXT entry point.
+ */
+
+/*
+ * Copyright (C) 2013-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <IOKit/IOLib.h> /* Assert as function */
+#include <IOKit/IOService.h>
+#include <mach/mach_port.h>
+
+
+#include <mach/kmod.h>
+#include <libkern/libkern.h>
+#include <mach/mach_types.h>
+#include <sys/mount.h>
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <sys/param.h>
+#include <VBox/version.h>
+#include <iprt/asm.h>
+
+#include <VBox/log.h>
+
+#include "vboxvfs.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+
+/**
+ * The service class for dealing with Share Folder filesystem.
+ */
+class org_virtualbox_VBoxVFS : public IOService
+{
+    OSDeclareDefaultStructors(org_virtualbox_VBoxVFS);
+
+private:
+    IOService * waitForCoreService(void);
+
+    IOService * coreService;
+
+public:
+    virtual bool start(IOService *pProvider);
+    virtual void stop(IOService *pProvider);
+};
+
+OSDefineMetaClassAndStructors(org_virtualbox_VBoxVFS, IOService);
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+
+/**
+ * Declare the module stuff.
+ */
+RT_C_DECLS_BEGIN
+static kern_return_t VBoxVFSModuleLoad(struct kmod_info *pKModInfo, void *pvData);
+static kern_return_t VBoxVFSModuleUnLoad(struct kmod_info *pKModInfo, void *pvData);
+extern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData);
+extern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData);
+KMOD_EXPLICIT_DECL(VBoxVFS, VBOX_VERSION_STRING, _start, _stop)
+DECLHIDDEN(kmod_start_func_t *) _realmain      = VBoxVFSModuleLoad;
+DECLHIDDEN(kmod_stop_func_t *)  _antimain      = VBoxVFSModuleUnLoad;
+DECLHIDDEN(int)                 _kext_apple_cc = __APPLE_CC__;
+RT_C_DECLS_END
+
+/** The number of IOService class instances. */
+static bool volatile        g_fInstantiated = 0;
+/* Global connection to the host service */
+VBGLSFCLIENT                  g_vboxSFClient;
+/* VBoxVFS filesystem handle. Needed for FS unregistering. */
+static vfstable_t           g_oVBoxVFSHandle;
+
+
+/**
+ * KEXT Module BSD entry point
+ */
+static kern_return_t VBoxVFSModuleLoad(struct kmod_info *pKModInfo, void *pvData)
+{
+    int rc;
+
+    /* Initialize the R0 guest library. */
+#if 0
+    rc = VbglR0SfInit();
+    if (RT_FAILURE(rc))
+        return KERN_FAILURE;
+#endif
+
+    PINFO("VirtualBox " VBOX_VERSION_STRING " shared folders "
+          "driver is loaded");
+
+    return KERN_SUCCESS;
+}
+
+
+/**
+ * KEXT Module BSD exit point
+ */
+static kern_return_t VBoxVFSModuleUnLoad(struct kmod_info *pKModInfo, void *pvData)
+{
+    int rc;
+
+#if 0
+   VbglR0SfTerm();
+#endif
+
+    PINFO("VirtualBox " VBOX_VERSION_STRING " shared folders driver is unloaded");
+
+    return KERN_SUCCESS;
+}
+
+
+/**
+ * Register VBoxFS filesystem.
+ *
+ * @returns IPRT status code.
+ */
+int VBoxVFSRegisterFilesystem(void)
+{
+    struct vfs_fsentry oVFsEntry;
+    int rc;
+
+    memset(&oVFsEntry, 0, sizeof(oVFsEntry));
+    /* Attach filesystem operations set */
+    oVFsEntry.vfe_vfsops = &g_oVBoxVFSOpts;
+    /* Attach vnode operations */
+    oVFsEntry.vfe_vopcnt = g_cVBoxVFSVnodeOpvDescListSize;
+    oVFsEntry.vfe_opvdescs = g_VBoxVFSVnodeOpvDescList;
+    /* Set flags */
+    oVFsEntry.vfe_flags =
+#if ARCH_BITS == 64
+            VFS_TBL64BITREADY |
+#endif
+            VFS_TBLTHREADSAFE |
+            VFS_TBLFSNODELOCK |
+            VFS_TBLNOTYPENUM;
+
+    memcpy(oVFsEntry.vfe_fsname, VBOXVBFS_NAME, MFSNAMELEN);
+
+    rc = vfs_fsadd(&oVFsEntry, &g_oVBoxVFSHandle);
+    if (rc)
+    {
+        PINFO("Unable to register VBoxVFS filesystem (%d)", rc);
+        return VERR_GENERAL_FAILURE;
+    }
+
+    PINFO("VBoxVFS filesystem successfully registered");
+    return VINF_SUCCESS;
+}
+
+/**
+ * Unregister VBoxFS filesystem.
+ *
+ * @returns IPRT status code.
+ */
+int VBoxVFSUnRegisterFilesystem(void)
+{
+    int rc;
+
+    if (g_oVBoxVFSHandle == 0)
+        return VERR_INVALID_PARAMETER;
+
+    rc = vfs_fsremove(g_oVBoxVFSHandle);
+    if (rc)
+    {
+        PINFO("Unable to unregister VBoxVFS filesystem (%d)", rc);
+        return VERR_GENERAL_FAILURE;
+    }
+
+    g_oVBoxVFSHandle = 0;
+
+    PINFO("VBoxVFS filesystem successfully unregistered");
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Start this service.
+ */
+bool org_virtualbox_VBoxVFS::start(IOService *pProvider)
+{
+    int rc;
+
+    if (!IOService::start(pProvider))
+        return false;
+
+    /* Low level initialization should be performed only once */
+    if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false))
+    {
+        IOService::stop(pProvider);
+        return false;
+    }
+
+    /* Wait for VBoxGuest to be started */
+    coreService = waitForCoreService();
+    if (coreService)
+    {
+        rc = VbglR0SfInit();
+        if (RT_SUCCESS(rc))
+        {
+            /* Connect to the host service. */
+            rc = VbglR0SfConnect(&g_vboxSFClient);
+            if (RT_SUCCESS(rc))
+            {
+                PINFO("VBox client connected");
+                rc = VbglR0SfSetUtf8(&g_vboxSFClient);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = VBoxVFSRegisterFilesystem();
+                    if (RT_SUCCESS(rc))
+                    {
+                        registerService();
+                        PINFO("Successfully started I/O kit class instance");
+                        return true;
+                    }
+                    PERROR("Unable to register VBoxVFS filesystem");
+                }
+                else
+                {
+                    PERROR("VbglR0SfSetUtf8 failed: rc=%d", rc);
+                }
+                VbglR0SfDisconnect(&g_vboxSFClient);
+            }
+            else
+            {
+                PERROR("Failed to get connection to host: rc=%d", rc);
+            }
+            VbglR0SfTerm();
+        }
+        else
+        {
+            PERROR("Failed to initialize low level library");
+        }
+        coreService->release();
+    }
+    else
+    {
+        PERROR("VBoxGuest KEXT not started");
+    }
+
+    ASMAtomicXchgBool(&g_fInstantiated, false);
+    IOService::stop(pProvider);
+
+    return false;
+}
+
+
+/**
+ * Stop this service.
+ */
+void org_virtualbox_VBoxVFS::stop(IOService *pProvider)
+{
+    int rc;
+
+    AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated));
+
+    rc = VBoxVFSUnRegisterFilesystem();
+    if (RT_FAILURE(rc))
+    {
+        PERROR("VBoxVFS filesystem is busy. Make sure all "
+               "shares are unmounted (%d)", rc);
+    }
+
+    VbglR0SfDisconnect(&g_vboxSFClient);
+    PINFO("VBox client disconnected");
+
+    VbglR0SfTerm();
+    PINFO("Low level uninit done");
+
+    coreService->release();
+    PINFO("VBoxGuest service released");
+
+    IOService::stop(pProvider);
+
+    ASMAtomicWriteBool(&g_fInstantiated, false);
+
+    PINFO("Successfully stopped I/O kit class instance");
+}
+
+
+/**
+ * Wait for VBoxGuest.kext to be started
+ */
+IOService * org_virtualbox_VBoxVFS::waitForCoreService(void)
+{
+    IOService *service;
+
+    OSDictionary *serviceToMatch = serviceMatching("org_virtualbox_VBoxGuest");
+    if (!serviceToMatch)
+    {
+        PINFO("unable to create matching dictionary");
+        return NULL;
+    }
+
+    /* Wait 10 seconds for VBoxGuest to be started */
+    service = waitForMatchingService(serviceToMatch, 10ULL * 1000000000ULL);
+    serviceToMatch->release();
+
+    return service;
+}
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/mount.vboxsf.c
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/mount.vboxsf.c	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/mount.vboxsf.c	(revision 75292)
@@ -0,0 +1,88 @@
+/* $Id$ */
+/** @file
+ * VBoxVFS - mount tool.
+ */
+
+/*
+ * Copyright (C) 2013-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <errno.h>
+#include <string.h>
+
+#include "vboxvfs.h"
+
+static char *progname;
+
+static void
+usage(void)
+{
+    fprintf(stderr, "usage: %s [OPTIONS] <shared folder name> "
+                    "<mount point>\n", progname);
+    exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+    int                         rc;
+    int                         c;
+    char                       *sShareName;
+    char                       *sMountPoint;
+    struct vboxvfs_mount_info   mnt_info;
+
+    /* Set program name */
+    progname = argv[0];
+
+    /* Parse command line */
+    while((c = getopt(argc, argv, "o:")) != -1)
+    {
+        switch(c)
+        {
+            case 'o': break;
+            default : usage();
+        }
+    }
+
+    /* Two arguments are rquired: <share name> and <mount point> */
+    if ((argc - optind) != 2)
+        usage();
+
+    sShareName = argv[optind++];
+    sMountPoint = argv[optind];
+
+    if (strlen(sShareName) > MAXPATHLEN)
+    {
+        fprintf(stderr, "Specified Shared Folder name too long\n");
+        return EINVAL;
+    }
+
+    mnt_info.magic = VBOXVFS_MOUNTINFO_MAGIC;
+    strcpy(mnt_info.name, sShareName);
+
+    rc = mount(VBOXVBFS_NAME, sMountPoint, 0, &mnt_info);
+    if (rc)
+    {
+        fprintf(stderr,
+                "Unable to mount shared folder (%s) '%s' to '%s': %s\n",
+                VBOXVBFS_NAME,
+                mnt_info.name,
+                sMountPoint,
+                strerror(errno));
+        return 1;
+    }
+
+    return 0;
+}
Index: /trunk/src/VBox/Additions/darwin/VBoxSF/vboxvfs.h
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxSF/vboxvfs.h	(revision 75292)
+++ /trunk/src/VBox/Additions/darwin/VBoxSF/vboxvfs.h	(revision 75292)
@@ -0,0 +1,220 @@
+/* $Id$ */
+/** @file
+ * VBoxVFS - common header used across all the driver source files.
+ */
+
+/*
+ * Copyright (C) 2013-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#define MODULE_NAME "VBoxSF"
+
+#ifdef KERNEL
+# include <libkern/libkern.h>
+# include <sys/lock.h>
+#endif
+
+#define PINFO(fmt, args...)     printf(MODULE_NAME ": INFO: " fmt "\n", ## args)
+#define PDEBUG(fmt, args...)    printf(MODULE_NAME ": %s(): DEBUG: " fmt "\n", __FUNCTION__, ## args)
+#define PERROR(fmt, args...)    printf(MODULE_NAME ": ERROR: " fmt "\n", ## args)
+
+#define VBOXVBFS_NAME               "vboxsf"
+#define VBOXVFS_MOUNTINFO_MAGIC     (0xCAFE)
+
+#ifdef KERNEL
+
+#include <iprt/types.h>
+#undef PVM
+#include <sys/vnode.h>
+
+#include <VBox/VBoxGuestLibSharedFolders.h>
+
+
+/** Global refernce to host service connection */
+extern VBGLSFCLIENT g_vboxSFClient;
+
+/** Private data assigned to each mounted shared folder. Assigned to mp structure. */
+typedef struct vboxvfs_mount_data
+{
+    VBGLSFMAP           pMap;               /** Shared folder mapping */
+    SHFLSTRING         *pShareName;         /** VBoxVFS share name */
+    uint64_t            cFileIdCounter;     /** Counter that used in order to assign unique ID to each vnode within mounted share */
+    vnode_t             pRootVnode;         /** VFS object: vnode that corresponds shared folder root */
+    uint8_t volatile    fRootVnodeState;    /** Sync flag that used in order to safely allocate pRootVnode */
+    uid_t               owner;              /** User ID tha mounted shared folder */
+    lck_grp_t          *pLockGroup;         /** BSD locking stuff */
+    lck_grp_attr_t     *pLockGroupAttr;     /** BSD locking stuff */
+} vboxvfs_mount_t;
+
+/** Private data assigned to each vnode object. */
+typedef struct vboxvfs_vnode_data
+{
+    SHFLHANDLE      pHandle;                /** VBoxVFS object handle. */
+    PSHFLSTRING     pPath;                  /** Path within shared folder */
+    lck_attr_t     *pLockAttr;              /** BSD locking stuff */
+    lck_rw_t       *pLock;                  /** BSD locking stuff */
+} vboxvfs_vnode_t;
+
+/**
+ * Helper function to create XNU VFS vnode object.
+ *
+ * @param mp        Mount data structure
+ * @param type      vnode type (directory, regular file, etc)
+ * @param pParent   Parent vnode object (NULL for VBoxVFS root vnode)
+ * @param fIsRoot   Flag that indicates if created vnode object is
+ *                  VBoxVFS root vnode (TRUE for VBoxVFS root vnode, FALSE
+ *                  for all aother vnodes)
+ * @param           Path within Shared Folder
+ * @param ret       Returned newly created vnode
+ *
+ * @return 0 on success, error code otherwise
+ */
+extern int vboxvfs_create_vnode_internal(struct mount *mp, enum vtype type, vnode_t pParent, int fIsRoot, PSHFLSTRING Path, vnode_t *ret);
+
+/**
+ * Convert guest absolute VFS path (starting from VFS root) to a host path
+ * within mounted shared folder (returning it as a char *).
+ *
+ * @param mp            Mount data structure
+ * @param pszGuestPath  Guest absolute VFS path (starting from VFS root)
+ * @param cbGuestPath   Size of pszGuestPath
+ * @param pszHostPath   Returned char * wich contains host path
+ * @param cbHostPath    Returned pszHostPath size
+ *
+ * @return 0 on success, error code otherwise
+ */
+extern int vboxvfs_guest_path_to_char_path_internal(mount_t mp, char *pszGuestPath, int cbGuestPath, char **pszHostPath, int *cbHostPath);
+
+/**
+ * Convert guest absolute VFS path (starting from VFS root) to a host path
+ * within mounted shared folder.
+ *
+ * @param mp            Mount data structure
+ * @param pszGuestPath  Guest absolute VFS path (starting from VFS root)
+ * @param cbGuestPath   Size of pszGuestPath
+ * @param ppResult      Returned PSHFLSTRING object wich contains host path
+ *
+ * @return 0 on success, error code otherwise
+ */
+extern int vboxvfs_guest_path_to_shflstring_path_internal(mount_t mp, char *pszGuestPath, int cbGuestPath, PSHFLSTRING *ppResult);
+
+/**
+ * Wrapper function for vboxvfs_guest_path_to_char_path_internal() which
+ * converts guest path to host path using vnode object information.
+ *
+ * @param vnode     Guest's VFS object
+ * @param ppPath    Allocated  char * which contain a path
+ * @param pcbPath   Size of ppPath
+ *
+ * @return 0 on success, error code otherwise.
+ */
+extern int vboxvfs_guest_vnode_to_char_path_internal(vnode_t vnode, char **ppHostPath, int *pcbHostPath);
+
+/**
+ * Wrapper function for vboxvfs_guest_path_to_shflstring_path_internal() which
+ * converts guest path to host path using vnode object information.
+ *
+ * @param vnode     Guest's VFS object
+ * @param ppResult  Allocated  PSHFLSTRING object which contain a path
+ *
+ * @return 0 on success, error code otherwise.
+ */
+extern int vboxvfs_guest_vnode_to_shflstring_path_internal(vnode_t vnode, PSHFLSTRING *ppResult);
+
+/**
+ * Free resources allocated by vboxvfs_path_internal() and vboxvfs_guest_vnode_to_shflstring_path_internal().
+ *
+ * @param ppHandle  Reference to object to be freed.
+ */
+extern void vboxvfs_put_path_internal(void **ppHandle);
+
+/**
+ * Open existing VBoxVFS object and return its handle.
+ *
+ * @param pMount            Mount session data.
+ * @param pPath             VFS path to the object relative to mount point.
+ * @param fFlags            For directory object it should be
+ *                          SHFL_CF_DIRECTORY and 0 for any other object.
+ * @param pHandle           Returned handle.
+ *
+ * @return 0 on success, error code otherwise.
+ */
+extern int vboxvfs_open_internal(vboxvfs_mount_t *pMount, PSHFLSTRING pPath, uint32_t fFlags, SHFLHANDLE *pHandle);
+
+/**
+ * Release VBoxVFS object handle openned by vboxvfs_open_internal().
+ *
+ * @param pMount            Mount session data.
+ * @param pHandle           Handle to close.
+ *
+ * @return 0 on success, IPRT error code otherwise.
+ */
+extern int vboxvfs_close_internal(vboxvfs_mount_t *pMount, SHFLHANDLE pHandle);
+
+/**
+ * Get information about host VFS object.
+ *
+ * @param mp           Mount point data
+ * @param pSHFLDPath   Path to VFS object within mounted shared folder
+ * @param Info         Returned info
+ *
+ * @return  0 on success, error code otherwise.
+ */
+extern int vboxvfs_get_info_internal(mount_t mp, PSHFLSTRING pSHFLDPath, PSHFLFSOBJINFO Info);
+
+/**
+ * Check if VFS object exists on a host side.
+ *
+ * @param vnode     Guest VFS vnode that corresponds to host VFS object
+ *
+ * @return 1 if exists, 0 otherwise.
+ */
+extern int vboxvfs_exist_internal(vnode_t vnode);
+
+/**
+ * Convert host VFS object mode flags into guest ones.
+ *
+ * @param fHostMode     Host flags
+ *
+ * @return Guest flags
+ */
+extern mode_t vboxvfs_h2g_mode_inernal(RTFMODE fHostMode);
+
+/**
+ * Convert guest VFS object mode flags into host ones.
+ *
+ * @param fGuestMode     Host flags
+ *
+ * @return Host flags
+ */
+extern uint32_t vboxvfs_g2h_mode_inernal(mode_t fGuestMode);
+
+extern SHFLSTRING *vboxvfs_construct_shflstring(const char *pszName, size_t cchName);
+
+#endif /* KERNEL */
+
+extern int vboxvfs_register_filesystem(void);
+extern int vboxvfs_unregister_filesystem(void);
+
+/* VFS options */
+extern struct vfsops g_oVBoxVFSOpts;
+
+extern int (**g_VBoxVFSVnodeDirOpsVector)(void *);
+extern int g_cVBoxVFSVnodeOpvDescListSize;
+extern struct vnodeopv_desc *g_VBoxVFSVnodeOpvDescList[];
+
+/* Mount info */
+struct vboxvfs_mount_info
+{
+    uint32_t    magic;
+    char        name[MAXPATHLEN];   /* share name */
+};
+
