VirtualBox

Changeset 55640 in vbox


Ignore:
Timestamp:
May 4, 2015 12:38:57 PM (9 years ago)
Author:
vboxsync
Message:

DnD:

  • Overhauled "dropped files" directory + general file handling: Keep the directories/files open when doing the actual transfers (only protocol >= 2)
  • Unified "dropped files" directory creation/rollback handling for guest/host parts.
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/DragAndDrop.h

    r55556 r55640  
    55
    66/*
    7  * Copyright (C) 2014 Oracle Corporation
     7 * Copyright (C) 2014-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3030#include <iprt/assert.h>
    3131#include <iprt/cdefs.h>
     32#include <iprt/dir.h>
    3233#include <iprt/err.h>
    3334#include <iprt/file.h>
     
    3738#include <iprt/cpp/ministring.h>
    3839
    39 int DnDDirCreateDroppedFilesEx(const char *pszPath, char *pszDropDir, size_t cbDropDir);
    40 int DnDDirCreateDroppedFiles(char *pszDropDir, size_t cbDropDir);
     40/**
     41 * Structure for maintaining a "dropped files" directory
     42 * on the host or guest. This will contain all received files & directories
     43 * for a single transfer.
     44 */
     45typedef struct DNDDIRDROPPEDFILES
     46{
     47    /** Directory handle for drop directory. */
     48    PRTDIR                       hDir;
     49    /** Absolute path to drop directory. */
     50    RTCString                    strPathAbs;
     51    /** List for holding created directories in the case of a rollback. */
     52    RTCList<RTCString>           lstDirs;
     53    /** List for holding created files in the case of a rollback. */
     54    RTCList<RTCString>           lstFiles;
     55
     56} DNDDIRDROPPEDFILES, *PDNDDIRDROPPEDFILES;
     57
     58int DnDDirDroppedAddFile(PDNDDIRDROPPEDFILES pDir, const char *pszFile);
     59int DnDDirDroppedAddDir(PDNDDIRDROPPEDFILES pDir, const char *pszDir);
     60int DnDDirDroppedFilesCreateAndOpenEx(const char *pszPath, PDNDDIRDROPPEDFILES pDir);
     61int DnDDirDroppedFilesCreateAndOpenTemp(PDNDDIRDROPPEDFILES pDir);
     62int DnDDirDroppedFilesClose(PDNDDIRDROPPEDFILES pDir, bool fRemove);
     63const char *DnDDirDroppedFilesGetDirAbs(PDNDDIRDROPPEDFILES pDir);
     64int DnDDirDroppedFilesRollback(PDNDDIRDROPPEDFILES pDir);
    4165
    4266bool DnDMIMEHasFileURLs(const char *pcszFormat, size_t cchFormatMax);
     
    77101    const RTCString &GetSourcePath(void) const { return m_strSrcPath; }
    78102    const RTCString &GetDestPath(void) const { return m_strTgtPath; }
    79     uint32_t GetMode(void) const { return m_fCreationMode; }
     103    uint32_t GetMode(void) const { return m_fMode; }
    80104    uint64_t GetProcessed(void) const { return m_cbProcessed; }
    81105    uint64_t GetSize(void) const { return m_cbSize; }
     
    91115    bool IsComplete(void) const;
    92116    bool IsOpen(void) const;
    93     int Open(Dest enmDest, uint64_t fOpen);
    94     int OpenEx(const RTCString &strPath, Type enmType, Dest enmDest, uint64_t fMode = 0, uint32_t fFlags = 0);
     117    int Open(Dest enmDest, uint64_t fOpen, uint32_t fMode = 0);
     118    int OpenEx(const RTCString &strPath, Type enmType, Dest enmDest, uint64_t fOpen = 0, uint32_t fMode = 0, uint32_t fFlags = 0);
    95119    int Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead);
    96120    void Reset(void);
     
    110134    RTCString m_strSrcPath;
    111135    RTCString m_strTgtPath;
    112     /** File creation mode. */
    113     uint32_t  m_fCreationMode;
     136    /** Object (file/directory) mode. */
     137    uint32_t  m_fMode;
    114138    /** Size (in bytes) to read/write. */
    115139    uint64_t  m_cbSize;
     
    144168    void RemoveFirst(void);
    145169    int RootFromURIData(const void *pvData, size_t cbData, uint32_t fFlags);
    146     RTCString RootToString(const RTCString &strBasePath = "", const RTCString &strSeparator = "\r\n");
     170    RTCString RootToString(const RTCString &strPathBase = "", const RTCString &strSeparator = "\r\n");
    147171    size_t RootCount(void) { return m_lstRoot.size(); }
    148172    uint32_t TotalCount(void) { return m_cTotal; }
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp

    r55571 r55640  
    372372    void *pvTmpData = RTMemAlloc(cbTmpData);
    373373    if (!pvTmpData)
    374         rc = VERR_NO_MEMORY;
    375 
    376     /* Create and query the (unique) drop target directory. */
     374        return VERR_NO_MEMORY;
     375
     376    /* Create and query the (unique) drop target directory in the user's temporary directory. */
     377    DNDDIRDROPPEDFILES dirDroppedFiles;
     378    const char *pszDropDir;
     379    rc = DnDDirDroppedFilesCreateAndOpenTemp(&dirDroppedFiles);
     380    if (RT_SUCCESS(rc))
     381        pszDropDir = DnDDirDroppedFilesGetDirAbs(&dirDroppedFiles);
     382
    377383    DnDURIList lstURI;
    378     char szDropDir[RTPATH_MAX];
    379     if (RT_SUCCESS(rc))
    380         rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir));
    381 
    382     if (RT_FAILURE(rc))
    383     {
    384         int rc2 = VbglR3DnDHGSetProgress(pCtx, DragAndDropSvc::DND_PROGRESS_ERROR, 100 /* Percent */, rc);
    385         AssertRC(rc2);
    386 
    387         if (pvTmpData)
    388             RTMemFree(pvTmpData);
    389         return rc;
    390     }
    391 
    392     /* Lists for holding created files & directories in the case of a rollback. */
    393     RTCList<RTCString> guestDirList;
    394     RTCList<RTCString> guestFileList;
    395 
    396384    DnDURIObject objFile(DnDURIObject::File);
    397385
     
    405393        uint32_t uNextMsg;
    406394        uint32_t cNextParms;
    407         LogFlowFunc(("Waiting for new message ...\n"));
    408395        rc = vbglR3DnDQueryNextHostMessageType(pCtx, &uNextMsg, &cNextParms, false /* fWait */);
    409396        if (RT_SUCCESS(rc))
     
    423410                                 szPathName, cbPathName, fMode, rc));
    424411
    425                     /*
    426                      * Important: HOST_DND_HG_SND_DIR sends the path (directory) name without URI specifications, that is,
    427                      *            only the pure name! To match the accounting though we have to translate the pure name into
    428                      *            a valid URI again.
    429                      *
    430                      ** @todo     Fix this URI translation!
    431                      */
    432                     RTCString strPath(szPathName);
    433                     if (RT_SUCCESS(rc))
    434                         rc = objFile.RebaseURIPath(strPath);
    435                     if (RT_SUCCESS(rc))
     412                    char *pszPathAbs = RTPathJoinA(pszDropDir, szPathName);
     413                    if (pszPathAbs)
    436414                    {
    437                         rc = DnDPathSanitize(szPathName, sizeof(szPathName));
    438                         char *pszNewDir = RTPathJoinA(szDropDir, szPathName);
    439                         if (pszNewDir)
     415                        rc = RTDirCreate(pszPathAbs, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
     416                        if (RT_SUCCESS(rc))
     417                            rc = DnDDirDroppedAddDir(&dirDroppedFiles, pszPathAbs);
     418
     419                        RTStrFree(pszPathAbs);
     420                    }
     421                    else
     422                        rc = VERR_NO_MEMORY;
     423                    break;
     424                }
     425                case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:
     426                case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:
     427                {
     428                    if (uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR)
     429                        rc = vbglR3DnDHGProcessSendFileHdrMessage(pCtx,
     430                                                                  szPathName,
     431                                                                  sizeof(szPathName),
     432                                                                  &fFlags,
     433                                                                  &fMode,
     434                                                                  &cbDataToRead);
     435                    else
     436                        rc = vbglR3DnDHGProcessSendFileMessage(pCtx,
     437                                                               szPathName,
     438                                                               sizeof(szPathName),
     439                                                               &cbPathName,
     440                                                               pvTmpData,
     441                                                               cbTmpData,
     442                                                               &cbDataRecv,
     443                                                               &fMode);
     444                    if (   RT_SUCCESS(rc)
     445                        && (   uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR
     446                             /* Protocol v1 always sends the file name, so try opening every time. */
     447                            || pCtx->uProtocol <= 1)
     448                       )
     449                    {
     450                        char *pszPathAbs = RTPathJoinA(pszDropDir, szPathName);
     451                        if (pszPathAbs)
    440452                        {
    441                             rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
    442                             RTStrFree(pszNewDir);
     453                            LogFlowFunc(("Opening pszPathName=%s, cbPathName=%RU32, fMode=0x%x, cbSize=%RU64\n",
     454                                         szPathName, cbPathName, fMode, cbDataToRead));
     455
     456                            uint64_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_ALL;
     457                            if (pCtx->uProtocol <= 1)
     458                                fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND;
     459                            else
     460                                fOpen |= RTFILE_O_CREATE_REPLACE;
     461
     462                            /* Is there already a file open, e.g. in transfer? */
     463                            if (!objFile.IsOpen())
     464                            {
     465
     466                                RTCString strPathAbs(pszPathAbs);
     467                                rc = objFile.OpenEx(strPathAbs, DnDURIObject::File, DnDURIObject::Target, fOpen,
     468                                                    (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
     469                                if (RT_SUCCESS(rc))
     470                                {
     471                                    rc = DnDDirDroppedAddFile(&dirDroppedFiles, strPathAbs.c_str());
     472                                    if (RT_SUCCESS(rc))
     473                                    {
     474                                        cbDataWritten = 0;
     475
     476                                        if (pCtx->uProtocol >= 2) /* Set the expected file size. */
     477                                            objFile.SetSize(cbDataToRead);
     478                                    }
     479                                }
     480                            }
     481                            else
     482                                rc = VERR_WRONG_ORDER;
     483
     484                            RTStrFree(pszPathAbs);
    443485                        }
    444486                        else
    445487                            rc = VERR_NO_MEMORY;
    446 
     488                    }
     489
     490                    if (   RT_SUCCESS(rc)
     491                        && uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA)
     492                    {
     493                        bool fClose = false;
     494
     495                        uint32_t cbWritten;
     496                        rc = objFile.Write(pvTmpData, cbDataRecv, &cbWritten);
    447497                        if (RT_SUCCESS(rc))
    448498                        {
    449                             if (!guestDirList.contains(strPath))
    450                                 guestDirList.append(strPath);
    451                         }
    452                     }
    453                     break;
    454                 }
    455                 case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:
    456                 {
    457                     rc = vbglR3DnDHGProcessSendFileHdrMessage(pCtx,
    458                                                               szPathName,
    459                                                               sizeof(szPathName),
    460                                                               &fFlags,
    461                                                               &fMode,
    462                                                               &cbDataToRead);
    463                     LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR pszPathName=%s, fFlags=0x%x, fMode=0x%x, cbDataToRead=%RU64, rc=%Rrc\n",
    464                                  szPathName, fFlags, fMode, cbDataToRead, rc));
    465 
    466                     cbDataWritten = 0;
    467                     break;
    468                 }
    469                 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:
    470                 {
    471                     rc = vbglR3DnDHGProcessSendFileMessage(pCtx,
    472                                                            szPathName,
    473                                                            sizeof(szPathName),
    474                                                            &cbPathName,
    475                                                            pvTmpData,
    476                                                            cbTmpData,
    477                                                            &cbDataRecv,
    478                                                            &fMode);
    479                     LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA pszPathName=%s, cbPathName=%RU32, pvData=0x%p, cbDataRecv=%RU32, fMode=0x%x, rc=%Rrc\n",
    480                                  szPathName, cbPathName, pvTmpData, cbDataRecv, fMode, rc));
    481 
    482                     /*
    483                      * Important: HOST_DND_HG_SND_FILE sends the path (directory) name without URI specifications, that is,
    484                      *            only the pure name! To match the accounting though we have to translate the pure name into
    485                      *            a valid URI again.
    486                      *
    487                      ** @todo     Fix this URI translation!
    488                      */
    489                     RTCString strPath(szPathName);
    490                     if (RT_SUCCESS(rc))
    491                         rc = objFile.RebaseURIPath(strPath);
    492                     if (RT_SUCCESS(rc))
    493                     {
    494                         rc = DnDPathSanitize(szPathName, sizeof(szPathName));
    495                         if (RT_SUCCESS(rc))
    496                         {
    497                             char *pszPathAbs = RTPathJoinA(szDropDir, szPathName);
    498                             if (pszPathAbs)
     499                            if (pCtx->uProtocol >= 2)
    499500                            {
    500                                 RTFILE hFile;
    501                                 /** @todo r=andy Keep the file open and locked during the actual file transfer. Otherwise this will
    502                                  *               create all sorts of funny races because we don't know if the guest has
    503                                  *               modified the file in between the file data send calls.
    504                                  *
    505                                  *               See HOST_DND_HG_SND_FILE_HDR for a good place to do this. */
    506                                 rc = RTFileOpen(&hFile, pszPathAbs,
    507                                                 RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
    508                                 if (RT_SUCCESS(rc))
    509                                 {
    510                                     /** @todo r=andy Not very safe to assume that we were last appending to the current file. */
    511                                     rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL);
    512                                     if (RT_SUCCESS(rc))
    513                                     {
    514                                         rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0);
    515                                         if (RT_SUCCESS(rc))
    516                                         {
    517                                             if (fMode & RTFS_UNIX_MASK) /* Valid UNIX mode? */
    518                                                 rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
    519 
    520                                             cbDataWritten += cbDataRecv;
    521                                             Assert(cbDataWritten <= cbDataToRead);
    522                                         }
    523                                     }
    524 
    525                                     RTFileClose(hFile);
    526 
    527                                     if (!guestFileList.contains(pszPathAbs)) /* Add the file to (rollback) list. */
    528                                         guestFileList.append(pszPathAbs);
    529                                 }
    530                                 else
    531                                     LogFlowFunc(("Opening file failed with rc=%Rrc\n", rc));
    532 
    533                                 RTStrFree(pszPathAbs);
     501                                /* Data transfer complete? Close the file. */
     502                                fClose = objFile.IsComplete();
    534503                            }
    535504                            else
    536                                 rc = VERR_NO_MEMORY;
     505                                fClose = true; /* Always close the file after each chunk. */
     506
     507                            cbDataWritten += cbWritten;
     508                            Assert(cbDataWritten <= cbDataToRead);
     509                        }
     510
     511                        if (fClose)
     512                        {
     513                            LogFlowFunc(("Closing file\n"));
     514                            objFile.Close();
    537515                        }
    538516                    }
     
    607585#endif
    608586        }
    609         else
    610         {
    611             /* All URI data processed? */
    612             if (rc == VERR_NO_DATA)
    613                 rc = VINF_SUCCESS;
    614             break;
    615         }
    616587
    617588        if (RT_FAILURE(rc))
     
    622593    LogFlowFunc(("Loop ended with %Rrc\n", rc));
    623594
     595    /* All URI data processed? */
     596    if (rc == VERR_NO_DATA)
     597        rc = VINF_SUCCESS;
     598
    624599    if (pvTmpData)
    625600        RTMemFree(pvTmpData);
    626601
    627     /* Cleanup on failure or if the user has canceled the operation. */
     602    /* Cleanup on failure or if the user has canceled the operation or
     603     * something else went wrong. */
    628604    if (RT_FAILURE(rc))
    629605    {
    630         LogFlowFunc(("Rolling back ...\n"));
    631 
    632         /* Rollback by removing any stuff created. */
    633         for (size_t i = 0; i < guestFileList.size(); ++i)
    634             RTFileDelete(guestFileList.at(i).c_str());
    635         for (size_t i = 0; i < guestDirList.size(); ++i)
    636             RTDirRemove(guestDirList.at(i).c_str());
     606        int rc2 = DnDDirDroppedFilesRollback(&dirDroppedFiles);
     607        AssertRC(rc2); /* Not fatal, don't report back to host. */
    637608    }
    638609    else
     
    647618            RTMemFree(pvData);
    648619
    649             RTCString strData = lstURI.RootToString(szDropDir);
     620            RTCString strData = lstURI.RootToString(pszDropDir);
    650621            LogFlowFunc(("cbDataToRead: %zu -> %zu\n", cbDataToRead, strData.length() + 1));
    651622
     
    663634    }
    664635
    665     /* Try removing the (empty) drop directory in any case. */
    666     int rc2 = RTDirRemove(szDropDir);
    667     if (RT_FAILURE(rc2))
    668         LogFunc(("Warning: Unable to remove drop directory \"%s\": %Rrc\n", szDropDir, rc2));
     636    /*
     637     * Close the dropped files directory.
     638     * Don't try to remove it here, however, as the files are being needed
     639     * by the client's drag'n drop operation lateron.
     640     */
     641    int rc2 = DnDDirDroppedFilesClose(&dirDroppedFiles, false);
     642    if (RT_FAILURE(rc2)) /* Not fatal, don't report back to host. */
     643        LogFlowFunc(("Closing dropped files directory failed with %Rrc\n", rc2));
    669644
    670645    LogFlowFuncLeaveRC(rc);
     
    872847        AssertPtr(pcbFormatRecv);
    873848        if (DnDMIMEHasFileURLs(pszFormat, *pcbFormatRecv))
     849        {
    874850            rc = vbglR3DnDHGProcessURIMessages(pCtx,
    875851                                               puScreenId,
     
    880856                                               cbData,
    881857                                               pcbDataRecv);
     858        }
    882859        else
    883860            rc = VERR_NOT_SUPPORTED;
     861
     862        if (RT_FAILURE(rc))
     863        {
     864            if (RT_FAILURE(rc))
     865            {
     866                int rc2 = VbglR3DnDHGSetProgress(pCtx, DragAndDropSvc::DND_PROGRESS_ERROR, 100 /* Percent */, rc);
     867                AssertRC(rc2);
     868            }
     869        }
    884870    }
    885871
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r55187 r55640  
    14431443void UIMachineView::dragIsPending(void)
    14441444{
    1445     /* At the moment we only support guest->host DnD. */
    14461445    /** @todo Add guest->guest DnD functionality here by getting
    14471446     *        the source of guest B (when copying from B to A). */
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDDir.cpp

    r50460 r55640  
    55
    66/*
    7  * Copyright (C) 2014 Oracle Corporation
     7 * Copyright (C) 2014-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2727#include <VBox/GuestHost/DragAndDrop.h>
    2828
    29 int DnDDirCreateDroppedFilesEx(const char *pszPath,
    30                                char *pszDropDir, size_t cbDropDir)
     29int DnDDirDroppedAddFile(PDNDDIRDROPPEDFILES pDir, const char *pszFile)
     30{
     31    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
     32    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
     33
     34    if (!pDir->lstFiles.contains(pszFile))
     35        pDir->lstFiles.append(pszFile);
     36    return VINF_SUCCESS;
     37}
     38
     39int DnDDirDroppedAddDir(PDNDDIRDROPPEDFILES pDir, const char *pszDir)
     40{
     41    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
     42    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
     43
     44    if (!pDir->lstDirs.contains(pszDir))
     45        pDir->lstDirs.append(pszDir);
     46    return VINF_SUCCESS;
     47}
     48
     49int DnDDirDroppedFilesCreateAndOpenEx(const char *pszPath, PDNDDIRDROPPEDFILES pDir)
    3150{
    3251    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    33     AssertPtrReturn(pszDropDir, VERR_INVALID_POINTER);
    34     AssertReturn(cbDropDir, VERR_INVALID_PARAMETER);
     52    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
    3553
    36     if (RTStrPrintf(pszDropDir, cbDropDir, "%s", pszPath) <= 0)
     54    char pszDropDir[RTPATH_MAX];
     55    if (RTStrPrintf(pszDropDir, sizeof(pszDropDir), "%s", pszPath) <= 0)
    3756        return VERR_NO_MEMORY;
    3857
     
    4261
    4362    /* Append our base drop directory. */
    44     int rc = RTPathAppend(pszDropDir, cbDropDir, "VirtualBox Dropped Files");
     63    int rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), "VirtualBox Dropped Files"); /** @todo Make this tag configurable? */
    4564    if (RT_FAILURE(rc))
    4665        return rc;
     
    6483        return rc;
    6584
    66     rc = RTPathAppend(pszDropDir, cbDropDir, pszTime);
     85    rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), pszTime);
    6786    if (RT_FAILURE(rc))
    6887        return rc;
    6988
    7089    /* Create it (only accessible by the current user) */
    71     return RTDirCreateUniqueNumbered(pszDropDir, cbDropDir, RTFS_UNIX_IRWXU, 3, '-');
     90    rc = RTDirCreateUniqueNumbered(pszDropDir, sizeof(pszDropDir), RTFS_UNIX_IRWXU, 3, '-');
     91    if (RT_SUCCESS(rc))
     92    {
     93        PRTDIR phDir;
     94        rc = RTDirOpen(&phDir, pszDropDir);
     95        if (RT_SUCCESS(rc))
     96        {
     97            pDir->hDir       = phDir;
     98            pDir->strPathAbs = pszDropDir;
     99        }
     100    }
     101
     102    return rc;
    72103}
    73104
    74 int DnDDirCreateDroppedFiles(char *pszDropDir, size_t cbDropDir)
     105int DnDDirDroppedFilesCreateAndOpenTemp(PDNDDIRDROPPEDFILES pDir)
    75106{
    76     AssertPtrReturn(pszDropDir, VERR_INVALID_POINTER);
    77     AssertReturn(cbDropDir, VERR_INVALID_PARAMETER);
     107    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
    78108
    79109    char szTemp[RTPATH_MAX];
    80110
    81     /* Get the user's temp directory. Don't use the user's root directory (or
     111    /*
     112     * Get the user's temp directory. Don't use the user's root directory (or
    82113     * something inside it) because we don't know for how long/if the data will
    83      * be kept after the guest OS used it. */
     114     * be kept after the guest OS used it.
     115     */
    84116    int rc = RTPathTemp(szTemp, sizeof(szTemp));
    85117    if (RT_FAILURE(rc))
    86118        return rc;
    87119
    88     return DnDDirCreateDroppedFilesEx(szTemp, pszDropDir, cbDropDir);
     120    return DnDDirDroppedFilesCreateAndOpenEx(szTemp, pDir);
    89121}
    90122
     123int DnDDirDroppedFilesClose(PDNDDIRDROPPEDFILES pDir, bool fRemove)
     124{
     125    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
     126
     127    int rc = RTDirClose(pDir->hDir);
     128    if (RT_SUCCESS(rc))
     129    {
     130        pDir->lstDirs.clear();
     131        pDir->lstFiles.clear();
     132
     133        if (fRemove)
     134        {
     135            /* Try removing the (empty) drop directory in any case. */
     136            rc = RTDirRemove(pDir->strPathAbs.c_str());
     137            if (RT_SUCCESS(rc)) /* Only clear if successfully removed. */
     138                pDir->strPathAbs = "";
     139        }
     140    }
     141
     142    return rc;
     143}
     144
     145const char *DnDDirDroppedFilesGetDirAbs(PDNDDIRDROPPEDFILES pDir)
     146{
     147    AssertPtrReturn(pDir, NULL);
     148    return pDir->strPathAbs.c_str();
     149}
     150
     151int DnDDirDroppedFilesRollback(PDNDDIRDROPPEDFILES pDir)
     152{
     153    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
     154
     155    if (pDir->strPathAbs.isEmpty())
     156        return VINF_SUCCESS;
     157
     158    int rc = VINF_SUCCESS;
     159    int rc2;
     160
     161    /* Rollback by removing any stuff created.
     162     * Note: Only remove empty directories, never ever delete
     163     *       anything recursive here! Steam (tm) knows best ... :-) */
     164    for (size_t i = 0; i < pDir->lstFiles.size(); i++)
     165    {
     166        rc2 = RTFileDelete(pDir->lstFiles.at(i).c_str());
     167        if (RT_SUCCESS(rc))
     168            rc = rc2;
     169    }
     170
     171    for (size_t i = 0; i < pDir->lstDirs.size(); i++)
     172    {
     173        rc2 = RTDirRemove(pDir->lstDirs.at(i).c_str());
     174        if (RT_SUCCESS(rc))
     175            rc = rc2;
     176    }
     177
     178    /* Try to remove the empty root dropped files directory as well. */
     179    rc2 = RTDirRemove(pDir->strPathAbs.c_str());
     180    if (RT_SUCCESS(rc))
     181        rc = rc2;
     182
     183    return rc;
     184}
     185
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp

    r55556 r55640  
    336336}
    337337
    338 int DnDURIList::RootFromURIData(const void *pvData, size_t cbData,
    339                                 uint32_t fFlags)
     338int DnDURIList::RootFromURIData(const void *pvData, size_t cbData, uint32_t fFlags)
    340339{
    341340    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     
    380379}
    381380
    382 RTCString DnDURIList::RootToString(const RTCString &strBasePath /* = "" */,
     381RTCString DnDURIList::RootToString(const RTCString &strPathBase /* = "" */,
    383382                                   const RTCString &strSeparator /* = "\r\n" */)
    384383{
     
    390389        LogFlowFunc(("pszCurRoot=%s\n", pszCurRoot));
    391390#endif
    392         if (strBasePath.isNotEmpty())
    393         {
    394             char *pszPath = RTPathJoinA(strBasePath.c_str(), pszCurRoot);
     391        if (strPathBase.isNotEmpty())
     392        {
     393            char *pszPath = RTPathJoinA(strPathBase.c_str(), pszCurRoot);
    395394            if (pszPath)
    396395            {
     
    399398                {
    400399                    strRet += RTCString(pszPathURI) + strSeparator;
    401 #ifdef DEBUG_andy
    402400                    LogFlowFunc(("URI: %s\n", strRet.c_str()));
    403 #endif
    404401                    RTStrFree(pszPathURI);
    405402                }
     
    417414            {
    418415                strRet += RTCString(pszPathURI) + strSeparator;
    419 #ifdef DEBUG_andy
    420416                LogFlowFunc(("URI: %s\n", strRet.c_str()));
    421 #endif
    422417                RTStrFree(pszPathURI);
    423418            }
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDURIObject.cpp

    r55556 r55640  
    3737DnDURIObject::DnDURIObject(void)
    3838    : m_Type(Unknown)
    39     , m_fCreationMode(0)
     39    , m_fMode(0)
    4040    , m_cbSize(0)
    4141    , m_cbProcessed(0)
     
    5151    , m_strSrcPath(strSrcPath)
    5252    , m_strTgtPath(strDstPath)
    53     , m_fCreationMode(fMode)
     53    , m_fMode(fMode)
    5454    , m_cbSize(cbSize)
    5555    , m_cbProcessed(0)
     
    155155}
    156156
    157 int DnDURIObject::Open(Dest enmDest, uint64_t fOpen)
     157int DnDURIObject::Open(Dest enmDest, uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */)
    158158{
    159159    return OpenEx(  enmDest == Source
    160160                  ? m_strSrcPath : m_strTgtPath
    161                   , m_Type, enmDest, fOpen, 0 /* fFlag s*/);
     161                  , m_Type, enmDest, fOpen, fMode, 0 /* fFlags */);
    162162}
    163163
    164164int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest,
    165                          uint64_t fOpen /* = 0 */, uint32_t fFlags /* = 0 */)
     165                         uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */, uint32_t fFlags /* = 0 */)
    166166{
    167167    int rc = VINF_SUCCESS;
     
    198198                    if (RT_SUCCESS(rc))
    199199                        rc = RTFileGetSize(u.m_hFile, &m_cbSize);
     200                    if (RT_SUCCESS(rc)
     201                        && fMode)
     202                    {
     203                        rc = RTFileSetMode(u.m_hFile, fMode);
     204                    }
    200205                    if (RT_SUCCESS(rc))
    201206                    {
    202                         LogFlowFunc(("cbSize=%RU64, fMode=%RU32\n", m_cbSize, m_fCreationMode));
     207                        LogFlowFunc(("cbSize=%RU64, fMode=%RU32\n", m_cbSize, m_fMode));
    203208                        m_cbProcessed = 0;
    204209                    }
     
    293298        case File:
    294299        {
    295             bool fDone = false;
    296 
    297300            rc = OpenEx(m_strSrcPath, File, Source,
    298301                        /* Use some sensible defaults. */
     
    307310
    308311                    /* End of file reached or error occurred? */
    309                     if (m_cbProcessed == m_cbSize)
     312                    if (   m_cbSize
     313                        && m_cbProcessed == m_cbSize)
    310314                    {
    311315                        rc = VINF_EOF;
    312                         fDone = true;
    313316                    }
    314317                }
    315                 else
    316                     fDone = true;
    317 
    318                 if (fDone)
    319                     closeInternal();
    320318            }
    321319
     
    351349    m_strSrcPath    = "";
    352350    m_strTgtPath    = "";
    353     m_fCreationMode = 0;
     351    m_fMode = 0;
    354352    m_cbSize        = 0;
    355353    m_cbProcessed   = 0;
     
    369367        case File:
    370368        {
    371             bool fDone = false;
    372 
    373369            rc = OpenEx(m_strTgtPath, File, Target,
    374370                        /* Use some sensible defaults. */
     
    379375                if (RT_SUCCESS(rc))
    380376                    m_cbProcessed += cbWritten;
    381                 else
    382                     fDone = true;
    383 
    384                 if (fDone)
    385                     closeInternal();
    386377            }
    387378
  • trunk/src/VBox/HostServices/DragAndDrop/service.cpp

    r55549 r55640  
    712712        if (m_clientMap.size()) /* At least one client on the guest connected? */
    713713        {
    714             /*
    715              * Did the host call something which needs immediate processing?
    716              * Prepend the message instead of appending to the command queue then.
    717              */
    718             bool fAppend;
    719             switch (u32Function)
    720             {
    721                 /* Cancelling the drag'n drop operation has higher priority than
    722                  * processing already buffered messages. */
    723                 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
    724                     fAppend = false;
    725                     break;
    726 
    727                 default:
    728                     fAppend = true;
    729                     break;
    730             }
    731 
    732             /*
    733              * If we prepending the message (instead of appending) this mean we need
    734              * to re-schedule the message queue in order to get the new command executed as
    735              * soon as possible.
    736              */
    737             bool fReschedule = !fAppend;
    738 
    739             rc = m_pManager->addMessage(u32Function, cParms, paParms, fAppend);
    740             if (   RT_SUCCESS(rc)
    741                 && fReschedule)
    742             {
    743                 rc = m_pManager->doReschedule();
    744             }
    745 
     714            rc = m_pManager->addMessage(u32Function, cParms, paParms, true /* fAppend */);
    746715            if (RT_SUCCESS(rc))
    747716            {
  • trunk/src/VBox/Main/include/GuestDnDPrivate.h

    r55571 r55640  
    106106    void Reset(void)
    107107    {
    108         strDropDir = "";
    109108        lstURI.Clear();
    110         lstDirs.clear();
    111         lstFiles.clear();
    112109#if 0 /* Currently the scratch buffer will be maintained elswewhere. */
    113110        if (pvScratchBuf)
     
    123120    }
    124121
    125     int Rollback(void)
    126     {
    127         if (strDropDir.isEmpty())
    128             return VINF_SUCCESS;
    129 
    130         int rc = VINF_SUCCESS;
    131         int rc2;
    132 
    133         /* Rollback by removing any stuff created.
    134          * Note: Only remove empty directories, never ever delete
    135          *       anything recursive here! Steam (tm) knows best ... :-) */
    136         for (size_t i = 0; i < lstFiles.size(); i++)
    137         {
    138             rc2 = RTFileDelete(lstFiles.at(i).c_str());
    139             if (RT_SUCCESS(rc))
    140                 rc = rc2;
    141         }
    142 
    143         for (size_t i = 0; i < lstDirs.size(); i++)
    144         {
    145             rc2 = RTDirRemove(lstDirs.at(i).c_str());
    146             if (RT_SUCCESS(rc))
    147                 rc = rc2;
    148         }
    149 
    150         rc2 = RTDirRemove(strDropDir.c_str());
    151         if (RT_SUCCESS(rc))
    152             rc = rc2;
    153 
    154         return rc;
    155     }
    156 
    157     /** Temporary drop directory on the host where to
    158      *  put the files sent from the guest. */
    159     com::Utf8Str                    strDropDir;
     122    DNDDIRDROPPEDFILES              mDropDir;
    160123    /** (Non-recursive) List of root URI objects to receive. */
    161124    DnDURIList                      lstURI;
    162125    /** Current object to receive. */
    163126    DnDURIObject                    objURI;
    164     /** List for holding created directories in the case of a rollback. */
    165     RTCList<RTCString>              lstDirs;
    166     /** List for holding created files in the case of a rollback. */
    167     RTCList<RTCString>              lstFiles;
    168127    /** Pointer to an optional scratch buffer to use for
    169128     *  doing the actual chunk transfers. */
  • trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp

    r55571 r55640  
    869869int GuestDnDBase::sendCancel(void)
    870870{
    871     LogFlowFunc(("Sending cancelation request to guest ...\n"));
    872 
    873     GuestDnDMsg MsgCancel;
    874     MsgCancel.setType(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL);
    875 
    876     return GuestDnDInst()->hostCall(MsgCancel.getType(), MsgCancel.getCount(), MsgCancel.getParms());
     871    LogFlowFunc(("Generating cancel request ...\n"));
     872
     873    int rc;
     874    try
     875    {
     876        GuestDnDMsg *pMsgCancel = new GuestDnDMsg();
     877        pMsgCancel->setType(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL);
     878
     879        rc = msgQueueAdd(pMsgCancel);
     880    }
     881    catch(std::bad_alloc & /*e*/)
     882    {
     883        rc = VERR_NO_MEMORY;
     884    }
     885
     886    return rc;
    877887}
    878888
  • trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp

    r55571 r55640  
    225225}
    226226
    227 // implementation of wrapped IDnDTarget methods.
     227// implementation of wrapped IDnDSource methods.
    228228/////////////////////////////////////////////////////////////////////////////
    229229
     
    277277    }
    278278
    279     if (RT_FAILURE(rc))
    280         hr = setError(VBOX_E_IPRT_ERROR,
    281                       tr("Error retrieving drag and drop pending status (%Rrc)\n"), rc);
    282 
    283279    LogFlowFunc(("hr=%Rhrc, defaultAction=0x%x\n", hr, defaultAction));
    284280    return hr;
     
    383379        if (fHasURIList)
    384380        {
    385             Utf8Str strURIs = pCtx->mURI.lstURI.RootToString(pCtx->mURI.strDropDir);
     381            Utf8Str strURIs = pCtx->mURI.lstURI.RootToString(RTCString(DnDDirDroppedFilesGetDirAbs(&pCtx->mURI.mDropDir)));
    386382            cbData = strURIs.length();
    387383
     
    489485
    490486    int rc;
    491     char *pszDir = RTPathJoinA(pCtx->mURI.strDropDir.c_str(), pszPath);
     487    char *pszDir = RTPathJoinA(DnDDirDroppedFilesGetDirAbs(&pCtx->mURI.mDropDir), pszPath);
    492488    if (pszDir)
    493489    {
     
    571567
    572568        char pszPathAbs[RTPATH_MAX];
    573         rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pCtx->mURI.strDropDir.c_str(), pszPath);
     569        rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), DnDDirDroppedFilesGetDirAbs(&pCtx->mURI.mDropDir), pszPath);
    574570        if (RT_FAILURE(rc))
    575571        {
     
    588584
    589585        /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
    590         /** @todo Add fMode to opening flags. */
    591586        rc = pCtx->mURI.objURI.OpenEx(pszPathAbs, DnDURIObject::File, DnDURIObject::Target,
    592                                       RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
     587                                      RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
     588                                      (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
    593589        if (RT_SUCCESS(rc))
    594590        {
     
    898894    do
    899895    {
    900         char szDropDir[RTPATH_MAX];
    901         rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir));
    902         LogFlowFunc(("rc=%Rrc, szDropDir=%s\n", rc, szDropDir));
     896        rc = DnDDirDroppedFilesCreateAndOpenTemp(&pCtx->mURI.mDropDir);
    903897        if (RT_FAILURE(rc))
    904898            break;
    905 
    906         pCtx->mURI.strDropDir = szDropDir; /** @todo Keep directory handle open? */
     899        LogFlowFunc(("strDropDir=%s\n", rc, DnDDirDroppedFilesGetDirAbs(&pCtx->mURI.mDropDir)));
     900        if (RT_FAILURE(rc))
     901            break;
    907902
    908903        /*
     
    936931#undef UNREGISTER_CALLBACK
    937932
     933    int rc2;
     934
    938935    if (rc == VERR_CANCELLED)
    939936    {
    940         int rc2 = sendCancel();
     937        rc2 = sendCancel();
    941938        AssertRC(rc2);
    942939    }
     
    944941    if (RT_FAILURE(rc))
    945942    {
    946         int rc2 = pCtx->mURI.Rollback(); /** @todo Inform user on rollback failure? */
     943        rc2 = DnDDirDroppedFilesRollback(&pCtx->mURI.mDropDir); /** @todo Inform user on rollback failure? */
    947944        LogFlowFunc(("Rolling back ended with rc=%Rrc\n", rc2));
    948945    }
     946
     947    rc2 = DnDDirDroppedFilesClose(&pCtx->mURI.mDropDir, RT_FAILURE(rc) ? true : false /* fRemove */);
     948    if (RT_SUCCESS(rc))
     949        rc = rc2;
    949950
    950951    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp

    r55571 r55640  
    821821            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    822822
    823             GuestDnDMsg *pMsg;
    824823            try
    825824            {
    826                 pMsg = new GuestDnDMsg();
     825                GuestDnDMsg *pMsg = new GuestDnDMsg();
    827826
    828827                rc = pThis->i_sendURIDataLoop(pCtx, pMsg);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette