Index: trunk/src/VBox/Additions/linux/sharedfolders/dirops.c
===================================================================
--- trunk/src/VBox/Additions/linux/sharedfolders/dirops.c	(revision 77631)
+++ trunk/src/VBox/Additions/linux/sharedfolders/dirops.c	(revision 77704)
@@ -562,8 +562,13 @@
 };
 
-/* iops */
-
-/**
- * Worker for vbsf_inode_lookup() and vbsf_inode_instantiate().
+
+
+/*********************************************************************************************************************************
+*   Directory Inode Operations                                                                                                   *
+*********************************************************************************************************************************/
+
+/**
+ * Worker for vbsf_inode_lookup(), vbsf_create_worker() and
+ * vbsf_inode_instantiate().
  */
 static struct inode *vbsf_create_inode(struct inode *parent, struct dentry *dentry, PSHFLSTRING path,
@@ -614,4 +619,18 @@
     return NULL;
 }
+
+
+/** Helper for vbsf_create_worker() and vbsf_inode_lookup() that wraps
+ *  d_add() and setting d_op. */
+DECLINLINE(void) vbsf_d_add_inode(struct dentry *dentry, struct inode *pNewInode)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+    Assert(dentry->d_op == &vbsf_dentry_ops); /* (taken from the superblock) */
+#else
+    dentry->d_op = &vbsf_dentry_ops;
+#endif
+    d_add(dentry, pNewInode);
+}
+
 
 /**
@@ -702,10 +721,5 @@
             if (dret == dentry) {
                 vbsf_dentry_set_update_jiffies(dentry, jiffies);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
-                Assert(dentry->d_op == &vbsf_dentry_ops); /* (taken from the superblock) */
-#else
-                dentry->d_op = &vbsf_dentry_ops;
-#endif
-                d_add(dentry, pInode);
+                vbsf_d_add_inode(dentry, pInode);
                 dret = NULL;
             }
@@ -719,4 +733,5 @@
 }
 
+
 /**
  * This should allocate memory for vbsf_inode_info, compute a unique inode
@@ -745,4 +760,5 @@
 }
 
+
 /**
  * Create a new regular file / directory.
@@ -751,98 +767,236 @@
  * @param dentry        directory cache entry
  * @param mode          file mode
- * @param fDirectory    true if directory, false otherwise
+ * @param fCreateFlags  SHFL_CF_XXX.
  * @returns 0 on success, Linux error code otherwise
  */
-static int vbsf_create_worker(struct inode *parent, struct dentry *dentry, umode_t mode, int fDirectory)
-{
-    int rc, err;
+static int vbsf_create_worker(struct inode *parent, struct dentry *dentry, umode_t mode, uint32_t fCreateFlags,
+                              bool fStashHandle, bool fDoLookup, SHFLHANDLE *phHostFile, bool *pfCreated)
+
+{
+#ifdef SFLOG_ENABLED
+    const char * const      pszPrefix   = S_ISDIR(mode) ? "vbsf_create_worker/dir:" : "vbsf_create_worker/file:";
+#endif
     struct vbsf_inode_info *sf_parent_i = VBSF_GET_INODE_INFO(parent);
-    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
-    SHFLSTRING *path;
-    union CreateAuxReq
-    {
-        VBOXSFCREATEREQ Create;
-        VBOXSFCLOSEREQ  Close;
-    } *pReq;
-
-    TRACE();
-    BUG_ON(!sf_parent_i);
-    BUG_ON(!sf_g);
-
-    err = vbsf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
-    if (err)
-        goto fail0;
-
-    /** @todo combine with vbsf_path_from_dentry? */
-    pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size);
-    if (pReq) {
-        memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
+    struct vbsf_super_info *sf_g        = VBSF_GET_SUPER_INFO(parent->i_sb);
+    PSHFLSTRING             path;
+    int                     rc;
+
+    AssertReturn(sf_parent_i, -EINVAL);
+    AssertReturn(sf_g, -EINVAL);
+
+    /*
+     * Build a path.  We'll donate this to the inode on success.
+     */
+    rc = vbsf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
+    if (rc == 0) {
+        /*
+         * Allocate, initialize and issue the SHFL_CREATE request.
+         */
+        /** @todo combine with vbsf_path_from_dentry? */
+        union CreateAuxReq
+        {
+            VBOXSFCREATEREQ Create;
+            VBOXSFCLOSEREQ  Close;
+        } *pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size);
+        if (pReq) {
+            memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
+
+            RT_ZERO(pReq->Create.CreateParms);
+            pReq->Create.CreateParms.Handle                  = SHFL_HANDLE_NIL;
+            pReq->Create.CreateParms.CreateFlags             = fCreateFlags;
+            pReq->Create.CreateParms.Info.Attr.fMode         = (S_ISDIR(mode) ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
+                                                             | sf_access_permissions_to_vbox(mode);
+            pReq->Create.CreateParms.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
+
+            SFLOGFLOW(("%s calling VbglR0SfHostReqCreate(%s, %#x)\n", pszPrefix, path->String.ach, pReq->Create.CreateParms.CreateFlags));
+            rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
+            if (RT_SUCCESS(rc)) {
+                SFLOGFLOW(("%s VbglR0SfHostReqCreate returned %Rrc Result=%d Handle=%#llx\n",
+                           pszPrefix, rc, pReq->Create.CreateParms.Result, pReq->Create.CreateParms.Handle));
+
+                /*
+                 * Work the dentry cache and inode restatting.
+                 */
+                if (   pReq->Create.CreateParms.Result == SHFL_FILE_CREATED
+                    || pReq->Create.CreateParms.Result == SHFL_FILE_REPLACED) {
+                    vbsf_dentry_chain_increase_parent_ttl(dentry);
+                    sf_parent_i->force_restat = 1;
+                } else if (   pReq->Create.CreateParms.Result == SHFL_FILE_EXISTS
+                           || pReq->Create.CreateParms.Result == SHFL_FILE_NOT_FOUND)
+                    vbsf_dentry_chain_increase_parent_ttl(dentry);
+
+                /*
+                 * If we got a handle back, we're good.  Create an inode for it and return.
+                 */
+                if (pReq->Create.CreateParms.Handle != SHFL_HANDLE_NIL) {
+                    struct inode *pNewInode = vbsf_create_inode(parent, dentry, path, &pReq->Create.CreateParms.Info, sf_g,
+                                                                !fDoLookup /*fInstantiate*/);
+                    if (pNewInode) {
+                        struct vbsf_inode_info *sf_new_i = VBSF_GET_INODE_INFO(pNewInode);
+                        if (phHostFile) {
+                            *phHostFile = pReq->Create.CreateParms.Handle;
+                            pReq->Create.CreateParms.Handle = SHFL_HANDLE_NIL;
+                        } else if (fStashHandle) {
+                            sf_new_i->handle = pReq->Create.CreateParms.Handle;
+                            pReq->Create.CreateParms.Handle = SHFL_HANDLE_NIL;
+                        }
+                        if (fDoLookup)
+                            vbsf_d_add_inode(dentry, pNewInode);
+                        path = NULL;
+                    } else {
+                        SFLOGFLOW(("%s vbsf_create_inode failed: -ENOMEM (path %s)\n", pszPrefix, rc, path->String.ach));
+                        rc = -ENOMEM;
+                    }
+                } else if (pReq->Create.CreateParms.Result == SHFL_FILE_EXISTS) {
+                    /*
+                     * For atomic_open (at least), we should create an inode and
+                     * convert the dentry from a negative to a positive one.
+                     */
+                    SFLOGFLOW(("%s SHFL_FILE_EXISTS for %s\n", pszPrefix, sf_parent_i->path->String.ach));
+                    if (fDoLookup) {
+                        struct inode *pNewInode = vbsf_create_inode(parent, dentry, path, &pReq->Create.CreateParms.Info,
+                                                                    sf_g, false /*fInstantiate*/);
+                        if (pNewInode)
+                            vbsf_d_add_inode(dentry, pNewInode);
+                        path = NULL;
+                    }
+                    rc = -EEXIST;
+                } else if (pReq->Create.CreateParms.Result == SHFL_FILE_NOT_FOUND) {
+                    SFLOGFLOW(("%s SHFL_FILE_NOT_FOUND for %s\n", pszPrefix, sf_parent_i->path->String.ach));
+                    rc = -ENOENT;
+                } else if (pReq->Create.CreateParms.Result == SHFL_PATH_NOT_FOUND) {
+                    SFLOGFLOW(("%s SHFL_PATH_NOT_FOUND for %s\n", pszPrefix, sf_parent_i->path->String.ach));
+                    rc = -ENOENT;
+                } else {
+                    AssertMsgFailed(("result=%d creating '%s'\n", pReq->Create.CreateParms.Result, sf_parent_i->path->String.ach));
+                    rc = -EPERM;
+                }
+            } else {
+                int const vrc = rc;
+                rc = -RTErrConvertToErrno(vrc);
+                SFLOGFLOW(("%s SHFL_FN_CREATE(%s) failed vrc=%Rrc rc=%d\n", pszPrefix, path->String.ach, vrc, rc));
+            }
+
+            /* Cleanups. */
+            if (pReq->Create.CreateParms.Handle != SHFL_HANDLE_NIL) {
+                AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
+                int rc2 = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle);
+                if (RT_FAILURE(rc2))
+                    SFLOGFLOW(("%s VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", pszPrefix, rc2));
+            }
+            VbglR0PhysHeapFree(pReq);
+        } else
+            rc = -ENOMEM;
+        if (path)
+            kfree(path);
+    }
+    return rc;
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+/**
+ * More atomic way of handling creation.
+ *
+ * Older kernels would first to a lookup that created the file, followed by
+ * an open call.  We've got this horrid vbsf_inode_info::handle member because
+ * of that approach.  The call combines the lookup and open.
+ */
+static int vbsf_inode_atomic_open(struct inode *pDirInode, struct dentry *dentry, struct file *file,  unsigned fOpen, umode_t fMode)
+{
+    SFLOGFLOW(("vbsf_inode_atomic_open: pDirInode=%p dentry=%p file=%p fOpen=%#x, fMode=%#x\n", pDirInode, dentry, file, fOpen, fMode));
+    int rc;
+
+    /* Code assumes negative dentry. */
+    Assert(dentry->d_inode == NULL);
+
+    /** @todo see if we can do this for non-create calls too, as it may save us a
+     *        host call to revalidate the dentry. (Can't see anyone else doing
+     *        this, so playing it safe for now.) */
+    if (fOpen & O_CREAT) {
+        /*
+         * Prepare our file info structure.
+         */
+        struct vbsf_reg_info *sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
+        if (sf_r) {
+            bool     fCreated = false;
+            uint32_t fCreateFlags;
+
+            RTListInit(&sf_r->Handle.Entry);
+            sf_r->Handle.cRefs  = 1;
+            sf_r->Handle.fFlags = !(fOpen & O_DIRECTORY)
+                                 ? VBSF_HANDLE_F_FILE | VBSF_HANDLE_F_MAGIC
+                                 : VBSF_HANDLE_F_DIR  | VBSF_HANDLE_F_MAGIC;
+            sf_r->Handle.hHost  = SHFL_HANDLE_NIL;
+
+            /*
+             * Try create it.
+             */
+            /* vbsf_create_worker uses the type from fMode, so match it up to O_DIRECTORY. */
+            AssertMsg(!(fMode & S_IFMT) || (fMode & S_IFMT) == (fOpen & O_DIRECTORY ? S_IFDIR : S_IFREG), ("0%o\n", fMode));
+            if (!(fOpen & O_DIRECTORY))
+                fMode = (fMode & ~S_IFMT) | S_IFREG;
+            else
+                fMode = (fMode & ~S_IFMT) | S_IFDIR;
+
+            fCreateFlags = vbsf_linux_oflags_to_vbox(fOpen, &sf_r->Handle.fFlags, __FUNCTION__);
+
+            rc = vbsf_create_worker(pDirInode, dentry, fMode, fCreateFlags, false /*fStashHandle*/, true /*fDoLookup*/,
+                                    &sf_r->Handle.hHost, &fCreated);
+            if (rc == 0) {
+                struct inode           *inode = dentry->d_inode;
+                struct vbsf_inode_info *sf_i  = VBSF_GET_INODE_INFO(inode);
+
+                /*
+                 * Set FMODE_CREATED according to the action taken by SHFL_CREATE
+                 * and call finish_open() to do the remaining open() work.
+                 */
+                if (fCreated)
+                    file->f_mode |= FMODE_CREATED;
+                rc = finish_open(file, dentry, generic_file_open);
+                if (rc == 0) {
+                    /*
+                     * Now that the file is fully opened, associate sf_r with it
+                     * and link the handle to the inode.
+                     */
+                    vbsf_handle_append(sf_i, &sf_r->Handle);
+                    file->private_data = sf_r;
+                    SFLOGFLOW(("vbsf_inode_atomic_open: create succeeded; hHost=%#llx path='%s'\n",
+                               rc, sf_r->Handle.hHost, sf_i->path->String.ach));
+                    sf_r = NULL; /* don't free it */
+                } else {
+                    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pDirInode->i_sb);
+                    SFLOGFLOW(("vbsf_inode_atomic_open: finish_open failed: %d (path='%s'\n", rc, sf_i->path->String.ach));
+                    VbglR0SfHostReqCloseSimple(sf_g->map.root, sf_r->Handle.hHost);
+                    sf_r->Handle.hHost = SHFL_HANDLE_NIL;
+                }
+            } else
+                SFLOGFLOW(("vbsf_inode_atomic_open: vbsf_create_worker failed: %d\n", rc));
+            if (sf_r)
+                kfree(sf_r);
+        } else {
+            LogRelMaxFunc(64, ("could not allocate reg info\n"));
+            rc = -ENOMEM;
+        }
+    }
+    /*
+     * Not creating anything.
+     * Do we need to do a lookup or should we just fail?
+     */
+    else if (d_in_lookup(dentry)) {
+        struct dentry *pResult = vbsf_inode_lookup(pDirInode, dentry, 0 /*fFlags*/);
+        if (!IS_ERR(pResult))
+            rc = finish_no_open(file, pResult);
+        else
+            rc = PTR_ERR(pResult);
+        SFLOGFLOW(("vbsf_inode_atomic_open: open -> %d (%p)\n", rc, pResult));
     } else {
-        err = -ENOMEM;
-        goto fail1;
-    }
-
-    RT_ZERO(pReq->Create.CreateParms);
-    pReq->Create.CreateParms.Handle                  = SHFL_HANDLE_NIL;
-    pReq->Create.CreateParms.CreateFlags             = SHFL_CF_ACT_CREATE_IF_NEW
-                                                     | SHFL_CF_ACT_FAIL_IF_EXISTS
-                                                     | SHFL_CF_ACCESS_READWRITE
-                                                     | (fDirectory ? SHFL_CF_DIRECTORY : 0);
-    pReq->Create.CreateParms.Info.Attr.fMode         = (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
-                                                     | sf_access_permissions_to_vbox(mode);
-    pReq->Create.CreateParms.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
-
-    LogFunc(("calling VbglR0SfHostReqCreate, folder %s, flags %#x\n", path->String.ach, pReq->Create.CreateParms.CreateFlags));
-    rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
-    if (RT_FAILURE(rc)) {
-        err = -RTErrConvertToErrno(rc);
-        LogFunc(("(%d): SHFL_FN_CREATE(%s) failed rc=%Rrc err=%d\n", fDirectory, sf_parent_i->path->String.utf8, rc, err));
-        goto fail2;
-    }
-
-    if (pReq->Create.CreateParms.Result != SHFL_FILE_CREATED) {
-        err = -EPERM;
-        LogFunc(("(%d): could not create file %s result=%d\n",
-             fDirectory, sf_parent_i->path->String.utf8, pReq->Create.CreateParms.Result));
-        goto fail2;
-    }
-
-    vbsf_dentry_chain_increase_parent_ttl(dentry);
-
-    err = vbsf_inode_instantiate(parent, dentry, path, &pReq->Create.CreateParms.Info,
-                                 fDirectory ? SHFL_HANDLE_NIL : pReq->Create.CreateParms.Handle);
-    if (err) {
-        LogFunc(("(%d): could not instantiate dentry for %s err=%d\n", fDirectory, path->String.utf8, err));
-        goto fail3;
-    }
-
-    /*
-     * Don't close this handle right now. We assume that the same file is
-     * opened with vbsf_reg_open() and later closed with sf_reg_close(). Save
-     * the handle in between. Does not apply to directories. True?
-     */
-    if (fDirectory) {
-        AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
-        rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle);
-        if (RT_FAILURE(rc))
-            LogFunc(("(%d): VbglR0SfHostReqClose failed rc=%Rrc\n", fDirectory, rc));
-    }
-
-    sf_parent_i->force_restat = 1;
-    VbglR0PhysHeapFree(pReq);
-    return 0;
-
- fail3:
-    rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle);
-    if (RT_FAILURE(rc))
-        LogFunc(("(%d): VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", fDirectory, rc));
- fail2:
-    VbglR0PhysHeapFree(pReq);
- fail1:
-    kfree(path);
-
- fail0:
-    return err;
-}
+        SFLOGFLOW(("vbsf_inode_atomic_open: open -> -ENOENT\n"));
+        rc = -ENOENT;
+    }
+    return rc;
+}
+#endif /* 3.6.0 */
+
 
 /**
@@ -869,5 +1023,10 @@
  *        changed (investigate)... */
     TRACE();
-    return vbsf_create_worker(parent, dentry, mode, 0 /*fDirectory*/);
+    AssertMsg(!(mode & S_IFMT) || (mode & S_IFMT) == S_IFREG, ("0%o\n", mode));
+    return vbsf_create_worker(parent, dentry, (mode & ~S_IFMT) | S_IFREG,
+                                SHFL_CF_ACT_CREATE_IF_NEW
+                              | SHFL_CF_ACT_FAIL_IF_EXISTS
+                              | SHFL_CF_ACCESS_READWRITE,
+                              true /*fStashHandle*/, false /*fDoLookup*/, NULL /*phHandle*/, NULL /*fCreated*/);
 }
 
@@ -887,5 +1046,11 @@
 {
     TRACE();
-    return vbsf_create_worker(parent, dentry, mode, 1 /*fDirectory*/);
+    AssertMsg(!(mode & S_IFMT) || (mode & S_IFMT) == S_IFDIR, ("0%o\n", mode));
+    return vbsf_create_worker(parent, dentry, (mode & ~S_IFMT) | S_IFDIR,
+                                SHFL_CF_ACT_CREATE_IF_NEW
+                              | SHFL_CF_ACT_FAIL_IF_EXISTS
+                              | SHFL_CF_ACCESS_READWRITE
+                              | SHFL_CF_DIRECTORY,
+                              false /*fStashHandle*/, false /*fDoLookup*/, NULL /*phHandle*/, NULL /*fCreated*/);
 }
 
@@ -930,8 +1095,8 @@
             } else if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) {
                 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc; calling d_drop on %p\n",
-                         fDirectory, path->String.utf8, rc, dentry));
+                         fDirectory, path->String.ach, rc, dentry));
                 d_drop(dentry);
             } else {
-                LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc));
+                LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.ach, rc));
                 err = -RTErrConvertToErrno(rc);
             }
@@ -1110,4 +1275,7 @@
 struct inode_operations vbsf_dir_iops = {
     .lookup = vbsf_inode_lookup,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+    .atomic_open = vbsf_inode_atomic_open,
+#endif
     .create = vbsf_inode_create,
     .mkdir = vbsf_inode_mkdir,
Index: trunk/src/VBox/Additions/linux/sharedfolders/regops.c
===================================================================
--- trunk/src/VBox/Additions/linux/sharedfolders/regops.c	(revision 77631)
+++ trunk/src/VBox/Additions/linux/sharedfolders/regops.c	(revision 77704)
@@ -1874,4 +1874,79 @@
 
 /**
+ * Used by vbsf_reg_open() and vbsf_inode_atomic_open() to
+ *
+ * @returns shared folders create flags.
+ * @param   fLnxOpen    The linux O_XXX flags to convert.
+ * @param   pfHandle    Pointer to vbsf_handle::fFlags.
+ * @param   pszCaller   Caller, for logging purposes.
+ */
+uint32_t vbsf_linux_oflags_to_vbox(unsigned fLnxOpen, uint32_t *pfHandle, const char *pszCaller)
+{
+    uint32_t fVBoxFlags = SHFL_CF_ACCESS_DENYNONE;
+
+    /*
+     * Disposition.
+     */
+    if (fLnxOpen & O_CREAT) {
+        Log(("%s: O_CREAT set\n", pszCaller));
+        fVBoxFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
+        if (fLnxOpen & O_EXCL) {
+            Log(("%s: O_EXCL set\n", pszCaller));
+            fVBoxFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS;
+        } else if (fLnxOpen & O_TRUNC) {
+            Log(("%s: O_TRUNC set\n", pszCaller));
+            fVBoxFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
+        } else
+            fVBoxFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
+    } else {
+        fVBoxFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
+        if (fLnxOpen & O_TRUNC) {
+            Log(("%s: O_TRUNC set\n", pszCaller));
+            fVBoxFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
+        }
+    }
+
+    /*
+     * Access.
+     */
+    switch (fLnxOpen & O_ACCMODE) {
+        case O_RDONLY:
+            fVBoxFlags |= SHFL_CF_ACCESS_READ;
+            *pfHandle  |= VBSF_HANDLE_F_READ;
+            break;
+
+        case O_WRONLY:
+            fVBoxFlags |= SHFL_CF_ACCESS_WRITE;
+            *pfHandle  |= VBSF_HANDLE_F_WRITE;
+            break;
+
+        case O_RDWR:
+            fVBoxFlags |= SHFL_CF_ACCESS_READWRITE;
+            *pfHandle  |= VBSF_HANDLE_F_READ | VBSF_HANDLE_F_WRITE;
+            break;
+
+        default:
+            BUG();
+    }
+
+    if (fLnxOpen & O_APPEND) {
+        Log(("%s: O_APPEND set\n", pszCaller));
+        fVBoxFlags |= SHFL_CF_ACCESS_APPEND;
+        *pfHandle  |= VBSF_HANDLE_F_APPEND;
+    }
+
+    /*
+     * Only directories?
+     */
+    if (fLnxOpen & O_DIRECTORY) {
+        Log(("%s: O_DIRECTORY set\n", pszCaller));
+        fVBoxFlags |= SHFL_CF_DIRECTORY;
+    }
+
+    return fVBoxFlags;
+}
+
+
+/**
  * Open a regular file.
  *
@@ -1939,48 +2014,7 @@
      * to make the shared folders host service use our fMode parameter */
 
-    if (file->f_flags & O_CREAT) {
-        LogFunc(("O_CREAT set\n"));
-        pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
-        /* We ignore O_EXCL, as the Linux kernel seems to call create
-           beforehand itself, so O_EXCL should always fail. */
-        if (file->f_flags & O_TRUNC) {
-            LogFunc(("O_TRUNC set\n"));
-            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
-        } else
-            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
-    } else {
-        pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
-        if (file->f_flags & O_TRUNC) {
-            LogFunc(("O_TRUNC set\n"));
-            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
-        }
-    }
-
-    switch (file->f_flags & O_ACCMODE) {
-        case O_RDONLY:
-            pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_READ;
-            sf_r->Handle.fFlags |= VBSF_HANDLE_F_READ;
-            break;
-
-        case O_WRONLY:
-            pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_WRITE;
-            sf_r->Handle.fFlags |= VBSF_HANDLE_F_WRITE;
-            break;
-
-        case O_RDWR:
-            pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
-            sf_r->Handle.fFlags |= VBSF_HANDLE_F_READ | VBSF_HANDLE_F_WRITE;
-            break;
-
-        default:
-            BUG();
-    }
-
-    if (file->f_flags & O_APPEND) {
-        LogFunc(("O_APPEND set\n"));
-        pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_APPEND;
-        sf_r->Handle.fFlags |= VBSF_HANDLE_F_APPEND;
-    }
-
+    /* We ignore O_EXCL, as the Linux kernel seems to call create
+       beforehand itself, so O_EXCL should always fail. */
+    pReq->CreateParms.CreateFlags = vbsf_linux_oflags_to_vbox(file->f_flags & ~O_EXCL, &sf_r->Handle.fFlags, __FUNCTION__);
     pReq->CreateParms.Info.Attr.fMode = inode->i_mode;
     LogFunc(("vbsf_reg_open: calling VbglR0SfHostReqCreate, file %s, flags=%#x, %#x\n",
@@ -2036,31 +2070,29 @@
 static int vbsf_reg_release(struct inode *inode, struct file *file)
 {
-    struct vbsf_reg_info *sf_r;
-    struct vbsf_super_info *sf_g;
     struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode);
+    struct vbsf_reg_info   *sf_r = file->private_data;
 
     SFLOGFLOW(("vbsf_reg_release: inode=%p file=%p\n", inode, file));
-    sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
-    sf_r = file->private_data;
-
-    BUG_ON(!sf_g);
-    BUG_ON(!sf_r);
+    if (sf_r) {
+        struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
+        Assert(sf_g);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
-    /* See the smbfs source (file.c). mmap in particular can cause data to be
-     * written to the file after it is closed, which we can't cope with.  We
-     * copy and paste the body of filemap_write_and_wait() here as it was not
-     * defined before 2.6.6 and not exported until quite a bit later. */
-    /* filemap_write_and_wait(inode->i_mapping); */
-    if (inode->i_mapping->nrpages
-        && filemap_fdatawrite(inode->i_mapping) != -EIO)
-        filemap_fdatawait(inode->i_mapping);
+        /* See the smbfs source (file.c). mmap in particular can cause data to be
+         * written to the file after it is closed, which we can't cope with.  We
+         * copy and paste the body of filemap_write_and_wait() here as it was not
+         * defined before 2.6.6 and not exported until quite a bit later. */
+        /* filemap_write_and_wait(inode->i_mapping); */
+        if (inode->i_mapping->nrpages
+            && filemap_fdatawrite(inode->i_mapping) != -EIO)
+            filemap_fdatawait(inode->i_mapping);
 #endif
 
-    /* Release sf_r, closing the handle if we're the last user. */
-    file->private_data = NULL;
-    vbsf_handle_release(&sf_r->Handle, sf_g, "vbsf_reg_release");
-
-    sf_i->handle = SHFL_HANDLE_NIL;
+        /* Release sf_r, closing the handle if we're the last user. */
+        file->private_data = NULL;
+        vbsf_handle_release(&sf_r->Handle, sf_g, "vbsf_reg_release");
+
+        sf_i->handle = SHFL_HANDLE_NIL;
+    }
     return 0;
 }
Index: trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h
===================================================================
--- trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h	(revision 77631)
+++ trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h	(revision 77704)
@@ -286,4 +286,6 @@
 };
 
+uint32_t vbsf_linux_oflags_to_vbox(unsigned fLnxOpen, uint32_t *pfHandle, const char *pszCaller);
+
 
 /**
