Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 39581)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 39582)
@@ -82,31 +82,58 @@
  * An entry for a source element, including an optional DOS-like wildcard (*,?).
  */
-typedef struct SOURCEFILEENTRY
-{
-    SOURCEFILEENTRY(const char *pszSource, const char *pszFilter)
-                    : mSource(pszSource),
-                      mFilter(pszFilter) {}
-    SOURCEFILEENTRY(const char *pszSource)
-                    : mSource(pszSource)
-    {
-        if (   !RTFileExists(pszSource)
-            && !RTDirExists(pszSource))
-        {
-            /* No file and no directory -- maybe a filter? */
-            char *pszFilename = RTPathFilename(pszSource);
-            if (   pszFilename
-                && strpbrk(pszFilename, "*?"))
-            {
-                /* Yep, get the actual filter part. */
-                mFilter = RTPathFilename(pszSource);
-                /* Remove the filter from actual sourcec directory name. */
-                RTPathStripFilename(mSource.mutableRaw());
-                mSource.jolt();
-            }
-        }
-    }
-    Utf8Str mSource;
-    Utf8Str mFilter;
-} SOURCEFILEENTRY, *PSOURCEFILEENTRY;
+class SOURCEFILEENTRY
+{
+    public:
+
+        SOURCEFILEENTRY(const char *pszSource, const char *pszFilter)
+                        : mSource(pszSource),
+                          mFilter(pszFilter) {}
+
+        SOURCEFILEENTRY(const char *pszSource)
+                        : mSource(pszSource)
+        {
+            Parse(pszSource);
+        }
+
+        const char* GetSource() const
+        {
+            return mSource.c_str();
+        }
+
+        const char* GetFilter() const
+        {
+            return mFilter.c_str();
+        }
+
+    private:
+
+        int Parse(const char *pszPath)
+        {
+            AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+
+            if (   !RTFileExists(pszPath)
+                && !RTDirExists(pszPath))
+            {
+                /* No file and no directory -- maybe a filter? */
+                char *pszFilename = RTPathFilename(pszPath);
+                if (   pszFilename
+                    && strpbrk(pszFilename, "*?"))
+                {
+                    /* Yep, get the actual filter part. */
+                    mFilter = RTPathFilename(pszPath);
+                    /* Remove the filter from actual sourcec directory name. */
+                    RTPathStripFilename(mSource.mutableRaw());
+                    mSource.jolt();
+                }
+            }
+
+            return VINF_SUCCESS; /* @todo */
+        }
+
+    private:
+
+        Utf8Str mSource;
+        Utf8Str mFilter;
+};
 typedef std::vector<SOURCEFILEENTRY> SOURCEVEC, *PSOURCEVEC;
 
@@ -197,4 +224,6 @@
     OUTPUTTYPE_UNIX2DOS  = 20
 };
+
+static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest, const char *pszDir, bool *fExists);
 
 #endif /* VBOX_ONLY_DOCS */
@@ -962,8 +991,37 @@
     size_t srcOff = strlen(pszSourceRoot);
     AssertReturn(srcOff, VERR_INVALID_PARAMETER);
-    int rc = RTPathJoin(szTranslated, sizeof(szTranslated),
-                        pszDest, &pszSource[srcOff]);
+
+    char *pszDestPath = RTStrDup(pszDest);
+    AssertPtrReturn(pszDestPath, VERR_NO_MEMORY);
+
+    int rc;
+    if (!RTPathFilename(pszDestPath))
+    {
+        rc = RTPathJoin(szTranslated, sizeof(szTranslated),
+                        pszDestPath, &pszSource[srcOff]);
+    }
+    else
+    {
+        char *pszDestFileName = RTStrDup(RTPathFilename(pszDestPath));
+        if (pszDestFileName)
+        {
+            RTPathStripFilename(pszDestPath);
+            rc = RTPathJoin(szTranslated, sizeof(szTranslated),
+                            pszDestPath, pszDestFileName);
+            RTStrFree(pszDestFileName);
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    RTStrFree(pszDestPath);
+
     if (RT_SUCCESS(rc))
+    {
         *ppszTranslated = RTStrDup(szTranslated);
+#ifdef DEBUG
+        RTPrintf("Root: %s, Source: %s, Dest: %s, Translated: %s\n",
+                 pszSourceRoot, pszSource, pszDest, *ppszTranslated);
+#endif
+    }
     return rc;
 }
@@ -972,4 +1030,6 @@
 static int tstTranslatePath()
 {
+    RTAssertSetMayPanic(false /* Do not freak out, please. */);
+
     static struct
     {
@@ -983,13 +1043,18 @@
         /* Invalid stuff. */
         { NULL, NULL, NULL, NULL, VERR_INVALID_POINTER },
+#ifdef RT_OS_WINDOWS
         /* Windows paths. */
         { "c:\\foo", "c:\\foo\\bar.txt", "c:\\test", "c:\\test\\bar.txt", VINF_SUCCESS },
-        { "c:\\foo", "c:\\foo\\baz\\bar.txt", "c:\\test", "c:\\test\\baz\\bar.txt", VINF_SUCCESS }
-        /* UNIX-like paths. */
+        { "c:\\foo", "c:\\foo\\baz\\bar.txt", "c:\\test", "c:\\test\\baz\\bar.txt", VINF_SUCCESS },
+#else /* RT_OS_WINDOWS */
+        { "/home/test/foo", "/home/test/foo/bar.txt", "/opt/test", "/opt/test/bar.txt", VINF_SUCCESS },
+        { "/home/test/foo", "/home/test/foo/baz/bar.txt", "/opt/test", "/opt/test/baz/bar.txt", VINF_SUCCESS },
+#endif /* !RT_OS_WINDOWS */
         /* Mixed paths*/
         /** @todo */
+        { NULL }
     };
 
-    int iTest = 0;
+    size_t iTest = 0;
     for (iTest; iTest < RT_ELEMENTS(aTests); iTest++)
     {
@@ -1037,4 +1102,12 @@
     AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
 
+    bool fDirExists;
+    if (ctrlCopyDirExists(pContext, pContext->fHostToGuest, pszDir, &fDirExists))
+    {
+        if (pContext->fVerbose)
+            RTPrintf("Directory \"%s\" already exists\n", pszDir);
+        return VINF_SUCCESS;
+    }
+
     if (pContext->fVerbose)
         RTPrintf("Creating directory \"%s\" ...\n", pszDir);
@@ -1048,5 +1121,5 @@
         HRESULT hrc = pContext->pGuest->DirectoryCreate(Bstr(pszDir).raw(),
                                                         Bstr(pContext->pszUsername).raw(), Bstr(pContext->pszPassword).raw(),
-                                                        700, DirectoryCreateFlag_Parents);
+                                                        0700, DirectoryCreateFlag_Parents);
         if (FAILED(hrc))
             rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
@@ -1286,5 +1359,5 @@
 
     if (pContext->fVerbose)
-        RTPrintf("Processing directory: %s\n", szCurDir);
+        RTPrintf("Processing host directory: %s\n", szCurDir);
 
     /* Flag indicating whether the current directory was created on the
@@ -1455,5 +1528,5 @@
 
     if (pContext->fVerbose)
-        RTPrintf("Processing directory: %s\n", szCurDir);
+        RTPrintf("Processing guest directory: %s\n", szCurDir);
 
     /* Flag indicating whether the current directory was created on the
@@ -1761,6 +1834,6 @@
             {
                 /* Last argument and no destination specified with
-                 * --target-directory yet? Then use the current argument
-                 * as destination. */
+                 * --target-directory yet? Then use the current
+                 * (= last) argument as destination. */
                 if (   pArg->argc == GetState.iNext
                     && Utf8Dest.isEmpty())
@@ -1820,11 +1893,18 @@
     /* If the destination is a path, (try to) create it. */
     const char *pszDest = Utf8Dest.c_str();
-    AssertPtr(pszDest);
-    size_t lenDest = strlen(pszDest);
-    if (   lenDest
-         ||pszDest[lenDest - 1] == '/'
-        || pszDest[lenDest - 1] == '\\')
+    if (!RTPathFilename(pszDest))
     {
         vrc = ctrlCopyDirCreate(pContext, pszDest);
+    }
+    else
+    {
+        /* We assume we got a file name as destination -- so strip
+         * the actual file name and make sure the appropriate
+         * directories get created. */
+        char *pszDestDir = RTStrDup(pszDest);
+        AssertPtr(pszDestDir);
+        RTPathStripFilename(pszDestDir);
+        vrc = ctrlCopyDirCreate(pContext, pszDestDir);
+        RTStrFree(pszDestDir);
     }
 
@@ -1837,7 +1917,7 @@
         for (unsigned long s = 0; s < vecSources.size(); s++)
         {
-            char *pszSource = RTStrDup(vecSources[s].mSource.c_str());
+            char *pszSource = RTStrDup(vecSources[s].GetSource());
             AssertPtrBreakStmt(pszSource, vrc = VERR_NO_MEMORY);
-            const char *pszFilter = vecSources[s].mFilter.c_str();
+            const char *pszFilter = vecSources[s].GetFilter();
             if (!strlen(pszFilter))
                 pszFilter = NULL; /* If empty filter then there's no filter :-) */
@@ -1855,6 +1935,6 @@
 
             /** @todo Files with filter?? */
-            bool fIsFile = false;
-            bool fExists;
+            bool fSourceIsFile = false;
+            bool fSourceExists;
 
             size_t cchSource = strlen(pszSource);
@@ -1863,9 +1943,9 @@
             {
                 if (pszFilter) /* Directory with filter (so use source root w/o the actual filter). */
-                    vrc = ctrlCopyDirExistsOnSource(pContext, pszSourceRoot, &fExists);
+                    vrc = ctrlCopyDirExistsOnSource(pContext, pszSourceRoot, &fSourceExists);
                 else /* Regular directory without filter. */
-                    vrc = ctrlCopyDirExistsOnSource(pContext, pszSource, &fExists);
-
-                if (fExists)
+                    vrc = ctrlCopyDirExistsOnSource(pContext, pszSource, &fSourceExists);
+
+                if (fSourceExists)
                 {
                     /* Strip trailing slash from our source element so that other functions
@@ -1876,16 +1956,16 @@
             else
             {
-                vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fExists);
+                vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fSourceExists);
                 if (   RT_SUCCESS(vrc)
-                    && fExists)
+                    && fSourceExists)
                 {
-                    fIsFile = true;
+                    fSourceIsFile = true;
                 }
             }
 
             if (   RT_SUCCESS(vrc)
-                && fExists)
-            {
-                if (fIsFile)
+                && fSourceExists)
+            {
+                if (fSourceIsFile)
                 {
                     /* Single file. */
@@ -1914,5 +1994,5 @@
 
             if (   RT_SUCCESS(vrc)
-                && !fExists)
+                && !fSourceExists)
             {
                 RTMsgError("Warning: Source \"%s\" does not exist, skipping!\n",
