VirtualBox

Changeset 71817 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Apr 11, 2018 10:48:34 AM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121938
Message:

Guest Control/Main: Derived the copyTo/copyFrom tasks from a new base class GuestSessionCopyTask and also support copying entire directories (instead of just copying their contents).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r71796 r71817  
    263263
    264264/**
    265  * Copies a file from the guest to the host, extended version.
     265 * Main function for copying a file from guest to the host.
    266266 *
    267267 * @return VBox status code.
    268268 * @param  srcFile            Guest file (source) to copy to the host. Must be in opened and ready state already.
    269269 * @param  phDstFile          Pointer to host file handle (destination) to copy to. Must be in opened and ready state already.
    270  * @param  enmFileCopyFlags   File copy flags.
    271  * @param  uOffset            Offset (in bytes) where to start copying the source file.
     270 * @param  fFileCopyFlags     File copy flags.
     271 * @param  offCopy            Offset (in bytes) where to start copying the source file.
    272272 * @param  cbSize             Size (in bytes) to copy from the source file.
    273273 */
    274 int GuestSessionTask::fileCopyFromEx(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T enmFileCopyFlags,
    275                                      uint64_t uOffset, uint64_t cbSize)
    276 {
    277     RT_NOREF(enmFileCopyFlags);
     274int GuestSessionTask::fileCopyFromGuestInner(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T fFileCopyFlags,
     275                                            uint64_t offCopy, uint64_t cbSize)
     276{
     277    RT_NOREF(fFileCopyFlags);
    278278
    279279    BOOL fCanceled = FALSE;
     
    285285    int rc = VINF_SUCCESS;
    286286
    287     if (uOffset)
    288     {
    289         uint64_t puOffset;
    290         rc = srcFile->i_seekAt(uOffset, GUEST_FILE_SEEKTYPE_BEGIN, uTimeoutMs, &puOffset);
     287    if (offCopy)
     288    {
     289        uint64_t offActual;
     290        rc = srcFile->i_seekAt(offCopy, GUEST_FILE_SEEKTYPE_BEGIN, uTimeoutMs, &offActual);
    291291        if (RT_FAILURE(rc))
    292292        {
    293293            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    294                                 Utf8StrFmt(GuestSession::tr("Seeking to offset %RU64) failed: %Rrc"), uOffset, rc));
     294                                Utf8StrFmt(GuestSession::tr("Seeking to offset %RU64 failed: %Rrc"), offCopy, rc));
    295295            return rc;
    296296        }
     
    370370 * @param  strSource            Full path of source file on the guest to copy.
    371371 * @param  strDest              Full destination path and file name (host style) to copy file to.
    372  * @param  enmFileCopyFlags     File copy flags.
     372 * @param  fFileCopyFlags       File copy flags.
    373373 */
    374 int GuestSessionTask::fileCopyFrom(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags)
    375 {
    376     LogFlowThisFunc(("strSource=%s, strDest=%s, enmFileCopyFlags=0x%x\n", strSource.c_str(), strDest.c_str(), enmFileCopyFlags));
     374int GuestSessionTask::fileCopyFromGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags)
     375{
     376    LogFlowThisFunc(("strSource=%s, strDest=%s, enmFileCopyFlags=0x%x\n", strSource.c_str(), strDest.c_str(), fFileCopyFlags));
    377377
    378378    GuestFileOpenInfo srcOpenInfo;
     
    389389
    390390    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    391     int rc = mSession->i_fsQueryInfo(strSource.c_str(), TRUE /* fFollowSymlinks */, srcObjData, &rcGuest);
     391    int rc = mSession->i_fsQueryInfo(strSource, TRUE /* fFollowSymlinks */, srcObjData, &rcGuest);
    392392    if (RT_FAILURE(rc))
    393393    {
     
    413413
    414414            case FsObjType_Symlink:
    415                 if (!(enmFileCopyFlags & FileCopyFlag_FollowLinks))
     415                if (!(fFileCopyFlags & FileCopyFlag_FollowLinks))
    416416                {
    417417                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     
    464464        if (RT_SUCCESS(rc))
    465465        {
    466             if (enmFileCopyFlags & FileCopyFlag_NoReplace)
     466            if (fFileCopyFlags & FileCopyFlag_NoReplace)
    467467            {
    468468                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     
    471471            }
    472472
    473             if (enmFileCopyFlags & FileCopyFlag_Update)
     473            if (fFileCopyFlags & FileCopyFlag_Update)
    474474            {
    475475                RTTIMESPEC srcModificationTimeTS;
     
    504504        if (RTFS_IS_FILE(dstObjInfo.Attr.fMode))
    505505        {
    506             if (enmFileCopyFlags & FileCopyFlag_NoReplace)
     506            if (fFileCopyFlags & FileCopyFlag_NoReplace)
    507507            {
    508508                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     
    537537        else if (RTFS_IS_SYMLINK(dstObjInfo.Attr.fMode))
    538538        {
    539             if (!(enmFileCopyFlags & FileCopyFlag_FollowLinks))
     539            if (!(fFileCopyFlags & FileCopyFlag_FollowLinks))
    540540            {
    541541                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     
    573573                LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", strSource.c_str(), pszDstFile, srcObjData.mObjectSize));
    574574
    575                 rc = fileCopyFromEx(srcFile, &hDstFile, enmFileCopyFlags, 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize);
     575                rc = fileCopyFromGuestInner(srcFile, &hDstFile, fFileCopyFlags, 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize);
    576576
    577577                int rc2 = RTFileClose(hDstFile);
     
    595595
    596596/**
    597  * Copies a file from the host to the guest, extended version.
     597 * Main function for copying a file from host to the guest.
    598598 *
    599599 * @return VBox status code.
     600 * @param  phSrcFile          Pointer to host file handle (source) to copy from. Must be in opened and ready state already.
     601 * @param  dstFile            Guest file (destination) to copy to the guest. Must be in opened and ready state already.
     602 * @param  fFileCopyFlags     File copy flags.
     603 * @param  offCopy            Offset (in bytes) where to start copying the source file.
     604 * @param  cbSize             Size (in bytes) to copy from the source file.
     605 */
     606int GuestSessionTask::fileCopyToGuestInner(PRTFILE phSrcFile, ComObjPtr<GuestFile> &dstFile, FileCopyFlag_T fFileCopyFlags,
     607                                           uint64_t offCopy, uint64_t cbSize)
     608{
     609    RT_NOREF(fFileCopyFlags);
     610
     611    BOOL fCanceled = FALSE;
     612    uint64_t cbWrittenTotal = 0;
     613    uint64_t cbToRead       = cbSize;
     614
     615    uint32_t uTimeoutMs = 30 * 1000; /* 30s timeout. */
     616
     617    int rc = VINF_SUCCESS;
     618
     619    if (offCopy)
     620    {
     621        uint64_t offActual;
     622        rc = RTFileSeek(*phSrcFile, offCopy, RTFILE_SEEK_END, &offActual);
     623        if (RT_FAILURE(rc))
     624        {
     625            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     626                                Utf8StrFmt(GuestSession::tr("Seeking to offset %RU64 failed: %Rrc"), offCopy, rc));
     627            return rc;
     628        }
     629    }
     630
     631    BYTE byBuf[_64K];
     632    while (cbToRead)
     633    {
     634        size_t cbRead;
     635        const uint32_t cbChunk = RT_MIN(cbToRead, sizeof(byBuf));
     636        rc = RTFileRead(*phSrcFile, byBuf, cbChunk, &cbRead);
     637        if (RT_FAILURE(rc))
     638        {
     639            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     640                                Utf8StrFmt(GuestSession::tr("Reading %RU32 bytes @ %RU64, failed: %Rrc"), cbChunk, cbWrittenTotal, rc));
     641            break;
     642        }
     643
     644        rc = dstFile->i_writeData(uTimeoutMs, byBuf, cbRead, NULL /* No partial writes */);
     645        if (RT_FAILURE(rc))
     646        {
     647            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     648                                Utf8StrFmt(GuestSession::tr("Writing to %RU32 bytes to file failed: %Rrc"), cbRead, rc));
     649            break;
     650        }
     651
     652        Assert(cbToRead >= cbRead);
     653        cbToRead -= cbRead;
     654
     655        /* Update total bytes written to the guest. */
     656        cbWrittenTotal += cbRead;
     657        Assert(cbWrittenTotal <= cbSize);
     658
     659        /* Did the user cancel the operation above? */
     660        if (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
     661            && fCanceled)
     662            break;
     663
     664        rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)cbSize / 100.0)));
     665        if (RT_FAILURE(rc))
     666            break;
     667    }
     668
     669    if (RT_FAILURE(rc))
     670        return rc;
     671
     672    /*
     673     * Even if we succeeded until here make sure to check whether we really transfered
     674     * everything.
     675     */
     676    if (   cbSize > 0
     677        && cbWrittenTotal == 0)
     678    {
     679        /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
     680         * to the destination -> access denied. */
     681        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     682                            Utf8StrFmt(GuestSession::tr("Writing to destination file failed: Access denied")));
     683        rc = VERR_ACCESS_DENIED;
     684    }
     685    else if (cbWrittenTotal < cbSize)
     686    {
     687        /* If we did not copy all let the user know. */
     688        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     689                            Utf8StrFmt(GuestSession::tr("Copying to destination failed (%RU64/%RU64 bytes transfered)"),
     690                                       cbWrittenTotal, cbSize));
     691        rc = VERR_INTERRUPTED;
     692    }
     693
     694    LogFlowFuncLeaveRC(rc);
     695    return rc;
     696}
     697
     698/**
     699 * Copies a file from the guest to the host.
     700 *
     701 * @return VBox status code. VINF_NO_CHANGE if file was skipped.
    600702 * @param  strSource            Full path of source file on the host to copy.
    601703 * @param  strDest              Full destination path and file name (guest style) to copy file to.
    602  * @param  enmFileCopyFlags     File copy flags.
    603  * @param  pFile                Source file handle to use for accessing the host file.
    604  *                              The caller is responsible of opening / closing the file accordingly.
    605  * @param  cbOffset             Offset (in bytes) where to start copying the source file.
    606  * @param  cbSize               Size (in bytes) to copy from the source file.
     704 * @param  fFileCopyFlags       File copy flags.
    607705 */
    608 int GuestSessionTask::fileCopyToEx(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags,
    609                                    PRTFILE pFile, uint64_t cbOffset, uint64_t cbSize)
    610 {
    611     /** @todo Implement sparse file support? */
    612 
    613     if (   enmFileCopyFlags & FileCopyFlag_NoReplace
    614         || enmFileCopyFlags & FileCopyFlag_FollowLinks
    615         || enmFileCopyFlags & FileCopyFlag_Update)
    616     {
    617         return VERR_NOT_IMPLEMENTED;
    618     }
    619 
    620     RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
    621 
    622     /*
    623      * Start the actual copying process by cat'ing the source file to the
    624      * destination file on the guest.
    625      */
    626     GuestProcessStartupInfo procInfo;
    627     procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_CAT);
    628     procInfo.mFlags      = ProcessCreateFlag_Hidden;
    629 
    630     /* Set arguments.*/
    631     procInfo.mArguments.push_back(procInfo.mExecutable);                       /* Set argv0. */
    632     procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", strDest.c_str()));
    633 
    634     /* Startup process. */
    635     ComObjPtr<GuestProcess> pProcess;
    636     int rc = mSession->i_processCreateEx(procInfo, pProcess);
     706int GuestSessionTask::fileCopyToGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags)
     707{
     708    LogFlowThisFunc(("strSource=%s, strDest=%s, fFileCopyFlags=0x%x\n", strSource.c_str(), strDest.c_str(), fFileCopyFlags));
     709
     710    Utf8Str strDestFinal = strDest;
     711
     712    GuestFsObjData dstObjData;
     713    RT_ZERO(dstObjData);
    637714
    638715    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    639     if (RT_SUCCESS(rc))
    640     {
    641         Assert(!pProcess.isNull());
    642         rc = pProcess->i_startProcess(msTimeout, &rcGuest);
    643     }
     716    int rc = mSession->i_fsQueryInfo(strDest, TRUE /* fFollowSymlinks */, dstObjData, &rcGuest);
    644717    if (RT_FAILURE(rc))
    645718    {
     
    647720        {
    648721            case VERR_GSTCTL_GUEST_ERROR:
    649                 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest));
     722                if (rcGuest == VERR_FILE_NOT_FOUND) /* File might not exist on the guest yet. */
     723                {
     724                    rc = VINF_SUCCESS;
     725                }
     726                else
     727                   setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(rcGuest));
    650728                break;
    651729
    652730            default:
    653731                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    654                                     Utf8StrFmt(GuestSession::tr("Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
    655                                                strSource.c_str(), rc));
    656                 break;
    657         }
     732                                    Utf8StrFmt(GuestSession::tr("Destination file lookup for \"%s\" failed: %Rrc"),
     733                                               strDest.c_str(), rc));
     734                break;
     735        }
     736    }
     737    else
     738    {
     739        switch (dstObjData.mType)
     740        {
     741            case FsObjType_Directory:
     742            {
     743                if (   strDest.endsWith("\\")
     744                    || strDest.endsWith("/"))
     745                {
     746                    /* Build the final file name with destination path (on the host). */
     747                    char szDstPath[RTPATH_MAX];
     748                    RTStrPrintf2(szDstPath, sizeof(szDstPath), "%s", strDest.c_str());
     749
     750                    RTPathAppend(szDstPath, sizeof(szDstPath), RTPathFilename(strSource.c_str()));
     751
     752                    strDestFinal = szDstPath;
     753                }
     754                else
     755                {
     756                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     757                                        Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" already exists"),
     758                                                   strDest.c_str(), rc));
     759                    rc = VERR_ALREADY_EXISTS;
     760                }
     761                break;
     762            }
     763
     764            case FsObjType_File:
     765                if (fFileCopyFlags & FileCopyFlag_NoReplace)
     766                {
     767                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     768                                        Utf8StrFmt(GuestSession::tr("Destination file \"%s\" already exists"),
     769                                                   strDest.c_str(), rc));
     770                    rc = VERR_ALREADY_EXISTS;
     771                }
     772                break;
     773
     774            case FsObjType_Symlink:
     775                if (!(fFileCopyFlags & FileCopyFlag_FollowLinks))
     776                {
     777                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     778                                        Utf8StrFmt(GuestSession::tr("Destination file \"%s\" is a symbolic link"),
     779                                                   strDest.c_str(), rc));
     780                    rc = VERR_IS_A_SYMLINK;
     781                }
     782                break;
     783
     784            default:
     785                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     786                                    Utf8StrFmt(GuestSession::tr("Destination element \"%s\" not supported"), strDest.c_str()));
     787                rc = VERR_NOT_SUPPORTED;
     788                break;
     789        }
     790    }
     791
     792    if (RT_FAILURE(rc))
    658793        return rc;
    659     }
    660 
    661     ProcessWaitResult_T waitRes;
    662     BYTE byBuf[_64K];
    663 
    664     BOOL fCanceled = FALSE;
    665     uint64_t cbWrittenTotal = 0;
    666     uint64_t cbToRead = cbSize;
    667 
    668     for (;;)
    669     {
    670         rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn, msTimeout, waitRes, &rcGuest);
    671         if (   RT_FAILURE(rc)
    672             || (   waitRes != ProcessWaitResult_StdIn
    673                 && waitRes != ProcessWaitResult_WaitFlagNotSupported))
    674         {
    675             break;
    676         }
    677 
    678         /* If the guest does not support waiting for stdin, we now yield in
    679          * order to reduce the CPU load due to busy waiting. */
    680         if (waitRes == ProcessWaitResult_WaitFlagNotSupported)
    681             RTThreadYield(); /* Optional, don't check rc. */
    682 
    683         size_t cbRead = 0;
    684         if (cbSize) /* If we have nothing to write, take a shortcut. */
    685         {
    686             /** @todo Not very efficient, but works for now. */
    687             rc = RTFileSeek(*pFile, cbOffset + cbWrittenTotal,
    688                             RTFILE_SEEK_BEGIN, NULL /* poffActual */);
    689             if (RT_SUCCESS(rc))
    690             {
    691                 rc = RTFileRead(*pFile, (uint8_t*)byBuf,
    692                                 RT_MIN((size_t)cbToRead, sizeof(byBuf)), &cbRead);
    693                 /*
    694                  * Some other error occured? There might be a chance that RTFileRead
    695                  * could not resolve/map the native error code to an IPRT code, so just
    696                  * print a generic error.
    697                  */
    698                 if (RT_FAILURE(rc))
     794
     795    GuestFileOpenInfo dstOpenInfo;
     796    RT_ZERO(dstOpenInfo);
     797    dstOpenInfo.mFileName        = strDestFinal;
     798    if (fFileCopyFlags & FileCopyFlag_NoReplace)
     799        dstOpenInfo.mOpenAction  = FileOpenAction_CreateNew;
     800    else
     801        dstOpenInfo.mOpenAction  = FileOpenAction_CreateOrReplace;
     802    dstOpenInfo.mAccessMode      = FileAccessMode_WriteOnly;
     803    dstOpenInfo.mSharingMode     = FileSharingMode_All; /** @todo Use _Read when implemented. */
     804
     805    ComObjPtr<GuestFile> dstFile;
     806    rc = mSession->i_fileOpen(dstOpenInfo, dstFile, &rcGuest);
     807    if (RT_FAILURE(rc))
     808    {
     809        switch (rc)
     810        {
     811            case VERR_GSTCTL_GUEST_ERROR:
     812                setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(rcGuest));
     813                break;
     814
     815            default:
     816                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     817                                    Utf8StrFmt(GuestSession::tr("Destination file \"%s\" could not be opened: %Rrc"),
     818                                               strDestFinal, rc));
     819                break;
     820        }
     821    }
     822
     823    if (RT_FAILURE(rc))
     824        return rc;
     825
     826    RTFSOBJINFO srcObjInfo;
     827    RT_ZERO(srcObjInfo);
     828
     829    bool fSkip = false; /* Whether to skip handling the file. */
     830
     831    if (RT_SUCCESS(rc))
     832    {
     833        rc = RTPathQueryInfo(strSource.c_str(), &srcObjInfo, RTFSOBJATTRADD_NOTHING);
     834        if (RT_SUCCESS(rc))
     835        {
     836            if (fFileCopyFlags & FileCopyFlag_Update)
     837            {
     838                RTTIMESPEC dstModificationTimeTS;
     839                RTTimeSpecSetSeconds(&dstModificationTimeTS, dstObjData.mModificationTime);
     840                if (RTTimeSpecCompare(&dstModificationTimeTS, &srcObjInfo.ModificationTime) <= 0)
    699841                {
    700842                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    701                                         Utf8StrFmt(GuestSession::tr("Could not read from host file \"%s\" (%Rrc)"),
    702                                                    strSource.c_str(), rc));
    703                     break;
    704                 }
    705             }
    706             else
    707             {
    708                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    709                                     Utf8StrFmt(GuestSession::tr("Seeking host file \"%s\" to offset %RU64 failed: %Rrc"),
    710                                                strSource.c_str(), cbWrittenTotal, rc));
    711                 break;
    712             }
    713         }
    714 
    715         uint32_t fFlags = ProcessInputFlag_None;
    716 
    717         /* Did we reach the end of the content we want to transfer (last chunk)? */
    718         if (   (cbRead < sizeof(byBuf))
    719             /* Did we reach the last block which is exactly _64K? */
    720             || (cbToRead - cbRead == 0)
    721             /* ... or does the user want to cancel? */
    722             || (   !mProgress.isNull()
    723                 && SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
    724                 && fCanceled)
    725            )
    726         {
    727             LogFlowThisFunc(("Writing last chunk cbRead=%RU64\n", cbRead));
    728             fFlags |= ProcessInputFlag_EndOfFile;
    729         }
    730 
    731         uint32_t cbWritten;
    732         Assert(sizeof(byBuf) >= cbRead);
    733         rc = pProcess->i_writeData(0 /* StdIn */, fFlags, byBuf, cbRead, msTimeout, &cbWritten, &rcGuest);
    734         if (RT_FAILURE(rc))
    735         {
    736             switch (rc)
    737             {
    738                 case VERR_GSTCTL_GUEST_ERROR:
    739                     setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest));
    740                     break;
    741 
    742                 default:
    743                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    744                                         Utf8StrFmt(GuestSession::tr("Writing to guest file \"%s\" (offset %RU64) failed: %Rrc"),
    745                                         strDest.c_str(), cbWrittenTotal, rc));
    746                     break;
    747             }
    748 
    749             break;
    750         }
    751 
    752         /* Only subtract bytes reported written by the guest. */
    753         Assert(cbToRead >= cbWritten);
    754         cbToRead -= cbWritten;
    755 
    756         /* Update total bytes written to the guest. */
    757         cbWrittenTotal += cbWritten;
    758         Assert(cbWrittenTotal <= cbSize);
    759 
    760         LogFlowThisFunc(("rc=%Rrc, cbWritten=%RU32, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
    761                          rc, cbWritten, cbToRead, cbWrittenTotal, cbSize));
    762 
    763         /* Did the user cancel the operation above? */
    764         if (fCanceled)
    765             break;
    766 
    767         /* Update the progress.
    768          * Watch out for division by zero. */
    769         cbSize > 0
    770             ? rc = setProgress((ULONG)(cbWrittenTotal * 100 / cbSize))
    771             : rc = setProgress(100);
    772         if (RT_FAILURE(rc))
    773             break;
    774 
    775         /* End of file reached? */
    776         if (!cbToRead)
    777             break;
    778     } /* for */
    779 
    780     LogFlowThisFunc(("Copy loop ended with rc=%Rrc, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
    781                      rc, cbToRead, cbWrittenTotal, cbSize));
    782 
    783     /*
    784      * Wait on termination of guest process until it completed all operations.
    785      */
    786     if (   !fCanceled
    787         || RT_SUCCESS(rc))
    788     {
    789         rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &rcGuest);
    790         if (   RT_FAILURE(rc)
    791             || waitRes != ProcessWaitResult_Terminate)
    792         {
    793             if (RT_FAILURE(rc))
    794                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    795                                     Utf8StrFmt(
    796                                     GuestSession::tr("Waiting on termination for copying file \"%s\" to guest failed: %Rrc"),
    797                                     strSource.c_str(), rc));
    798             else
    799             {
    800                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    801                                     Utf8StrFmt(GuestSession::tr(
    802                                                "Waiting on termination for copying file \"%s\" to guest failed with wait result %ld"),
    803                                                strSource.c_str(), waitRes));
    804                 rc = VERR_GENERAL_FAILURE; /* Fudge. */
    805             }
    806         }
     843                                        Utf8StrFmt(GuestSession::tr("Destination file \"%s\" has same or newer modification date"),
     844                                                   strDestFinal.c_str()));
     845                    fSkip = true;
     846                }
     847            }
     848        }
     849        else
     850        {
     851            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     852                                Utf8StrFmt(GuestSession::tr("Source file lookup for \"%s\" failed: %Rrc"),
     853                                           strSource.c_str(), rc));
     854        }
     855    }
     856
     857    if (fSkip)
     858    {
     859        int rc2 = dstFile->i_closeFile(&rcGuest);
     860        AssertRC(rc2);
     861        return VINF_SUCCESS;
    807862    }
    808863
    809864    if (RT_SUCCESS(rc))
    810865    {
    811         /*
    812          * Newer VBoxService toolbox versions report what went wrong via exit code.
    813          * So handle this first.
    814          */
    815         /** @todo This code sequence is duplicated in CopyFrom...   */
    816         ProcessStatus_T procStatus = ProcessStatus_TerminatedAbnormally;
    817         HRESULT hrc = pProcess->COMGETTER(Status(&procStatus));
    818         if (!SUCCEEDED(hrc))
    819             procStatus = ProcessStatus_TerminatedAbnormally;
    820 
    821         LONG exitCode = 42424242;
    822         hrc = pProcess->COMGETTER(ExitCode(&exitCode));
    823         if (!SUCCEEDED(hrc))
    824             exitCode = 42424242;
    825 
    826         if (   procStatus != ProcessStatus_TerminatedNormally
    827             || exitCode != 0)
    828         {
    829             LogFlowThisFunc(("procStatus=%d, exitCode=%d\n", procStatus, exitCode));
    830             if (procStatus == ProcessStatus_TerminatedNormally)
    831                 rc = GuestProcessTool::exitCodeToRc(procInfo, exitCode);
    832             else
    833                 rc = VERR_GENERAL_FAILURE;
     866        RTFILE hSrcFile;
     867        rc = RTFileOpen(&hSrcFile, strSource.c_str(),
     868                        RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */
     869        if (RT_SUCCESS(rc))
     870        {
     871            LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n",
     872                             strSource.c_str(), strDestFinal.c_str(), srcObjInfo.cbObject));
     873
     874            rc = fileCopyToGuestInner(&hSrcFile, dstFile, fFileCopyFlags, 0 /* Offset, unused */, srcObjInfo.cbObject);
     875
     876            int rc2 = RTFileClose(hSrcFile);
     877            AssertRC(rc2);
     878        }
     879        else
    834880            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    835                                 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed: %Rrc"),
     881                                Utf8StrFmt(GuestSession::tr("Opening source file \"%s\" failed: %Rrc"),
    836882                                           strSource.c_str(), rc));
    837         }
    838         /*
    839          * Even if we succeeded until here make sure to check whether we really transfered
    840          * everything.
    841          */
    842         else if (   cbSize > 0
    843                  && cbWrittenTotal == 0)
    844         {
    845             /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
    846              * to the destination -> access denied. */
    847             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    848                                 Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to guest \"%s\""),
    849                                            strSource.c_str(), strDest.c_str()));
    850             rc = VERR_ACCESS_DENIED;
    851         }
    852         else if (cbWrittenTotal < cbSize)
    853         {
    854             /* If we did not copy all let the user know. */
    855             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    856                                 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed (%RU64/%RU64 bytes transfered)"),
    857                                            strSource.c_str(), cbWrittenTotal, cbSize));
    858             rc = VERR_INTERRUPTED;
    859         }
    860     }
    861 
    862     return rc;
    863 }
    864 
    865 /**
    866  * Copies a file from the host to the guest.
    867  *
    868  * @return VBox status code.
    869  * @param  strSource            Full path of source file on the host to copy.
    870  * @param  strDest              Full destination path and file name (guest style) to copy file to.
    871  * @param  enmFileCopyFlags     File copy flags.
    872  */
    873 int GuestSessionTask::fileCopyTo(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags)
    874 {
    875     int rc;
    876 
    877     /* Does our source file exist? */
    878     if (!RTFileExists(strSource.c_str()))
    879     {
    880         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    881                             Utf8StrFmt(GuestSession::tr("Host file \"%s\" does not exist or is not a file"),
    882                                        strSource.c_str()));
    883         rc  = VERR_FILE_NOT_FOUND;
    884     }
    885     else
    886     {
    887         RTFILE hFile;
    888         rc = RTFileOpen(&hFile, strSource.c_str(),
    889                         RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
    890         if (RT_FAILURE(rc))
    891         {
    892             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    893                                 Utf8StrFmt(GuestSession::tr("Could not open host file \"%s\" for reading: %Rrc"),
    894                                            strSource.c_str(), rc));
    895         }
    896         else
    897         {
    898             uint64_t cbSize;
    899             rc = RTFileGetSize(hFile, &cbSize);
    900             if (RT_FAILURE(rc))
    901             {
    902                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    903                                     Utf8StrFmt(GuestSession::tr("Could not query host file size of \"%s\": %Rrc"),
    904                                                strSource.c_str(), rc));
    905             }
    906             else
    907                 rc = fileCopyToEx(strSource, strDest, enmFileCopyFlags, &hFile, 0 /* Offset */, cbSize);
    908 
    909              RTFileClose(hFile);
    910         }
    911     }
    912 
     883    }
     884
     885    int rc2 = dstFile->i_closeFile(&rcGuest);
     886    AssertRC(rc2);
     887
     888    LogFlowFuncLeaveRC(rc);
    913889    return rc;
    914890}
     
    964940
    965941SessionTaskCopyDirFrom::SessionTaskCopyDirFrom(GuestSession *pSession, const Utf8Str &strSource, const Utf8Str &strDest, const Utf8Str &strFilter,
    966                                                DirectoryCopyFlag_T enmDirCopyFlags)
    967                                                : GuestSessionTask(pSession)
    968                                                , mSource(strSource)
    969                                                , mDest(strDest)
    970                                                , mFilter(strFilter)
    971                                                , mDirCopyFlags(enmDirCopyFlags)
     942                                               DirectoryCopyFlag_T fDirCopyFlags)
     943                                               : GuestSessionCopyTask(pSession)
    972944{
    973945    m_strTaskName = "gctlCpyDirFrm";
     946
     947    mSource = strSource;
     948    mDest   = strDest;
     949    mFilter = strFilter;
     950
     951    u.Dir.fCopyFlags = fDirCopyFlags;
    974952}
    975953
    976954SessionTaskCopyDirFrom::~SessionTaskCopyDirFrom(void)
    977955{
    978 
    979956}
    980957
     
    11151092                    Utf8Str strSrcFile = strSrcDir + strSrcSubDir + strName;
    11161093                    Utf8Str strDstFile = strDstDir + strSrcSubDir + strName;
    1117                     rc = fileCopyFrom(strSrcFile, strDstFile, FileCopyFlag_None);
     1094                    rc = fileCopyFromGuest(strSrcFile, strDstFile, FileCopyFlag_None);
    11181095                }
    11191096                break;
     
    11471124    int rc = VINF_SUCCESS;
    11481125
     1126    /* Figure out if we need to copy the entire source directory or just its contents. */
     1127    Utf8Str strSrcDir = mSource;
     1128    Utf8Str strDstDir = mDest;
     1129    if (   !strSrcDir.endsWith("/")
     1130        && !strSrcDir.endsWith("\\"))
     1131    {
     1132        if (   !strDstDir.endsWith("/")
     1133            && !strDstDir.endsWith("\\"))
     1134            strDstDir += "/";
     1135
     1136        strDstDir += Utf8StrFmt("%s", RTPathFilename(strSrcDir.c_str()));
     1137    }
     1138
    11491139    /* Create the root target directory on the host.
    1150      * The target directory might already exist on the host (based on mDirCopyFlags). */
    1151     const bool fExists = RTDirExists(mDest.c_str());
     1140     * The target directory might already exist on the host (based on u.Dir.fCopyFlags). */
     1141    const bool fExists = RTDirExists(strDstDir.c_str());
    11521142    if (   fExists
    1153         && !(mDirCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
     1143        && !(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
    11541144    {
    11551145        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1156                             Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), mDest.c_str()));
     1146                            Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), strDstDir.c_str()));
    11571147        rc = VERR_ALREADY_EXISTS;
    11581148    }
    11591149    else if (!fExists)
    11601150    {
    1161         rc = RTDirCreate(mDest.c_str(), fDirMode, 0);
     1151        rc = RTDirCreate(strDstDir.c_str(), fDirMode, 0);
    11621152        if (RT_FAILURE(rc))
    11631153            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    11641154                                Utf8StrFmt(GuestSession::tr("Error creating destination directory \"%s\", rc=%Rrc"),
    1165                                            mDest.c_str(), rc));
     1155                                           strDstDir.c_str(), rc));
    11661156    }
    11671157
     
    11701160
    11711161    RTDIR hDir;
    1172     rc = RTDirOpen(&hDir, mDest.c_str());
     1162    rc = RTDirOpen(&hDir, strDstDir.c_str());
    11731163    if (RT_FAILURE(rc))
    11741164    {
    11751165        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    11761166                            Utf8StrFmt(GuestSession::tr("Error opening destination directory \"%s\", rc=%Rrc"),
    1177                                        mDest.c_str(), rc));
     1167                                       strDstDir.c_str(), rc));
    11781168        return rc;
    11791169    }
     
    11811171    /* At this point the directory on the host was created and (hopefully) is ready
    11821172     * to receive further content. */
    1183     rc = directoryCopyToHost(mSource, mFilter, mDest, fRecursive, fFollowSymlinks,
     1173    rc = directoryCopyToHost(strSrcDir, mFilter, strDstDir, fRecursive, fFollowSymlinks,
    11841174                             "" /* strSubDir; for recursion */);
    11851175    if (RT_SUCCESS(rc))
     
    11941184SessionTaskCopyDirTo::SessionTaskCopyDirTo(GuestSession *pSession,
    11951185                                           const Utf8Str &strSource, const Utf8Str &strDest, const Utf8Str &strFilter,
    1196                                            DirectoryCopyFlag_T enmDirCopyFlags)
    1197                                            : GuestSessionTask(pSession)
    1198                                            , mSource(strSource)
    1199                                            , mDest(strDest)
    1200                                            , mFilter(strFilter)
    1201                                            , mDirCopyFlags(enmDirCopyFlags)
     1186                                           DirectoryCopyFlag_T fDirCopyFlags)
     1187                                           : GuestSessionCopyTask(pSession)
    12021188{
    12031189    m_strTaskName = "gctlCpyDirTo";
     1190
     1191    mSource = strSource;
     1192    mDest   = strDest;
     1193    mFilter = strFilter;
     1194
     1195    u.Dir.fCopyFlags = fDirCopyFlags;
    12041196}
    12051197
     
    13241316                        Utf8Str strSrcFile = strSrcDir + strSrcSubDir + Utf8Str(pDirEntry->szName);
    13251317                        Utf8Str strDstFile = strDstDir + strSrcSubDir + Utf8Str(pDirEntry->szName);
    1326                         rc = fileCopyTo(strSrcFile, strDstFile, FileCopyFlag_None);
     1318                        rc = fileCopyToGuest(strSrcFile, strDstFile, FileCopyFlag_None);
    13271319                    }
    13281320                    break;
     
    13551347    const uint32_t uDirMode    = 0700; /* Play safe by default. */
    13561348
     1349    /* Figure out if we need to copy the entire source directory or just its contents. */
     1350    Utf8Str strSrcDir = mSource;
     1351    Utf8Str strDstDir = mDest;
     1352    if (   !strSrcDir.endsWith("/")
     1353        && !strSrcDir.endsWith("\\"))
     1354    {
     1355        if (   !strDstDir.endsWith("/")
     1356            && !strDstDir.endsWith("\\"))
     1357            strDstDir += "/";
     1358
     1359        strDstDir += Utf8StrFmt("%s", RTPathFilename(strSrcDir.c_str()));
     1360    }
     1361
    13571362    /* Create the root target directory on the guest.
    1358      * The target directory might already exist on the guest (based on mDirCopyFlags). */
    1359     int rc = directoryCreate(mDest, DirectoryCreateFlag_None, uDirMode, fFollowSymlinks);
     1363     * The target directory might already exist on the guest (based on u.Dir.fCopyFlags). */
     1364    int rc = directoryCreate(strDstDir, DirectoryCreateFlag_None, uDirMode, fFollowSymlinks);
    13601365    if (   rc == VWRN_ALREADY_EXISTS
    1361         && !(mDirCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
     1366        && !(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
    13621367    {
    13631368        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1364                             Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), mDest.c_str()));
     1369                            Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), strDstDir.c_str()));
    13651370    }
    13661371
     
    13701375    /* At this point the directory on the guest was created and (hopefully) is ready
    13711376     * to receive further content. */
    1372     rc = directoryCopyToGuest(mSource, mFilter, mDest, fRecursive, fFollowSymlinks,
     1377    rc = directoryCopyToGuest(strSrcDir, mFilter, strDstDir, fRecursive, fFollowSymlinks,
    13731378                              "" /* strSubDir; for recursion */);
    13741379    if (RT_SUCCESS(rc))
     
    13801385
    13811386SessionTaskCopyFileTo::SessionTaskCopyFileTo(GuestSession *pSession,
    1382                                              const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags)
    1383                                              : GuestSessionTask(pSession)
    1384                                              , mSource(strSource)
    1385                                              , mSourceFile(NULL)
    1386                                              , mSourceOffset(0)
    1387                                              , mSourceSize(0)
    1388                                              , mDest(strDest)
    1389                                              , mFileCopyFlags(enmFileCopyFlags)
     1387                                             const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags)
     1388                                             : GuestSessionCopyTask(pSession)
    13901389{
    13911390    m_strTaskName = "gctlCpyFileTo";
    1392 }
    1393 
    1394 SessionTaskCopyFileTo::SessionTaskCopyFileTo(GuestSession *pSession,
    1395                                              PRTFILE pSourceFile, size_t cbSourceOffset, uint64_t cbSourceSize,
    1396                                              const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags)
    1397                                              : GuestSessionTask(pSession)
    1398                                              , mSourceFile(pSourceFile)
    1399                                              , mSourceOffset(cbSourceOffset)
    1400                                              , mSourceSize(cbSourceSize)
    1401                                              , mDest(strDest)
    1402                                              , mFileCopyFlags(enmFileCopyFlags)
    1403 {
    1404     m_strTaskName = "gctlCpyFileToH";
     1391
     1392    mSource = strSource;
     1393    mDest   = strDest;
     1394
     1395    u.File.fCopyFlags = fFileCopyFlags;
    14051396}
    14061397
     
    14171408    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    14181409
    1419     if (mSource.isEmpty())
    1420     {
    1421         setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("No source file specified")));
    1422         return VERR_INVALID_PARAMETER;
    1423     }
    1424 
    1425     if (mDest.isEmpty())
    1426     {
    1427         setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("No destintation file specified")));
    1428         return VERR_INVALID_PARAMETER;
    1429     }
    1430 
    1431     const char *pszSrcFile = mSource.c_str();
    1432 
    1433     if (   !pszSrcFile
    1434         || !RTFileExists(pszSrcFile))
    1435     {
    1436         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1437                             Utf8StrFmt(GuestSession::tr("Source file \"%s\" not valid or does not exist"), pszSrcFile));
    1438         return VERR_FILE_NOT_FOUND;
    1439     }
    1440 
    1441     if (mFileCopyFlags)
    1442     {
    1443         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1444                             Utf8StrFmt(GuestSession::tr("Copy flags (%#x) not implemented yet"),
    1445                             mFileCopyFlags));
    1446         return VERR_NOT_IMPLEMENTED;
    1447     }
    1448 
    1449     /** @todo Try to lock the destination file / directory on the guest here first? */
    1450     char *pszDstFile = NULL;
    1451 
    1452     int rc = VINF_SUCCESS;
    1453 
    1454     /*
    1455      * Query information about our destination first.
    1456      */
    1457     if (   mDest.endsWith("/")
    1458         || mDest.endsWith("\\"))
    1459     {
    1460         int rcGuest;
    1461         GuestFsObjData objData;
    1462         rc = mSession->i_fsQueryInfo(mDest, true /* fFollowSymlinks */, objData, &rcGuest);
    1463         if (RT_SUCCESS(rc))
    1464         {
    1465             if (objData.mType != FsObjType_Directory)
    1466             {
    1467                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1468                                     Utf8StrFmt(GuestSession::tr("Path \"%s\" is not a directory on guest"), pszDstFile));
    1469                 rc = VERR_NOT_A_DIRECTORY;
    1470             }
    1471             else
    1472             {
    1473                 /* Build the final file name with destination path (on the guest). */
    1474                 char szDstPath[RTPATH_MAX];
    1475                 RTStrPrintf2(szDstPath, sizeof(szDstPath), "%s", mDest.c_str());
    1476 
    1477                 RTPathAppend(szDstPath, sizeof(szDstPath), RTPathFilename(pszSrcFile));
    1478 
    1479                 pszDstFile = RTStrDup(szDstPath);
    1480             }
    1481         }
    1482         else
    1483         {
    1484             switch (rc)
    1485             {
    1486                 case VERR_GSTCTL_GUEST_ERROR:
    1487                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1488                                         GuestProcess::i_guestErrorToString(rcGuest));
    1489                     break;
    1490 
    1491                 default:
    1492                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1493                                         Utf8StrFmt(GuestSession::tr("Unable to query information for directory \"%s\" on the guest: %Rrc"),
    1494                                                    pszDstFile, rc));
    1495                     break;
    1496             }
    1497         }
    1498     }
    1499     else
    1500         pszDstFile = RTStrDup(mDest.c_str());
    1501 
     1410    int rc = fileCopyToGuest(mSource, mDest, u.File.fCopyFlags);
    15021411    if (RT_SUCCESS(rc))
    1503     {
    1504         AssertPtrReturn(pszDstFile, VERR_NO_MEMORY);
    1505 
    1506         if (mSourceFile) /* Use existing file handle. */
    1507             rc = fileCopyToEx(pszSrcFile, pszDstFile, (FileCopyFlag_T)mFileCopyFlags, mSourceFile, mSourceOffset, mSourceSize);
    1508         else
    1509             rc = fileCopyTo(pszSrcFile, pszDstFile, (FileCopyFlag_T)mFileCopyFlags);
    1510 
    1511         if (RT_SUCCESS(rc))
    1512             rc = setProgressSuccess();
    1513     }
    1514 
    1515     if (pszDstFile)
    1516         RTStrFree(pszDstFile);
     1412        rc = setProgressSuccess();
    15171413
    15181414    LogFlowFuncLeaveRC(rc);
     
    15211417
    15221418SessionTaskCopyFileFrom::SessionTaskCopyFileFrom(GuestSession *pSession,
    1523                                                  const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags)
    1524                                                  : GuestSessionTask(pSession)
    1525                                                  , mSource(strSource)
    1526                                                  , mDest(strDest)
    1527                                                  , mFileCopyFlags(enmFileCopyFlags)
     1419                                                 const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags)
     1420                                                 : GuestSessionCopyTask(pSession)
    15281421{
    15291422    m_strTaskName = "gctlCpyFileFrm";
     1423
     1424    mSource = strSource;
     1425    mDest   = strDest;
     1426
     1427    u.File.fCopyFlags = fFileCopyFlags;
    15301428}
    15311429
     
    15421440    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    15431441
    1544     int rc = fileCopyFrom(mSource, mDest, mFileCopyFlags);
     1442    int rc = fileCopyFromGuest(mSource, mDest, u.File.fCopyFlags);
    15451443    if (RT_SUCCESS(rc))
    15461444        rc = setProgressSuccess();
     
    15531451                                                       const Utf8Str &strSource,
    15541452                                                       const ProcessArguments &aArguments,
    1555                                                        uint32_t uFlags)
     1453                                                       uint32_t fFlags)
    15561454                                                       : GuestSessionTask(pSession)
    15571455{
    1558     mSource = strSource;
     1456    m_strTaskName = "gctlUpGA";
     1457
     1458    mSource    = strSource;
    15591459    mArguments = aArguments;
    1560     mFlags  = uFlags;
    1561     m_strTaskName = "gctlUpGA";
     1460    mFlags     = fFlags;
    15621461}
    15631462
     
    16071506int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
    16081507                                                Utf8Str const &strFileSource, const Utf8Str &strFileDest,
    1609                                                 bool fOptional, uint32_t *pcbSize)
     1508                                                bool fOptional)
    16101509{
    16111510    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    16121511    AssertPtrReturn(pISO, VERR_INVALID_POINTER);
    1613     /* pcbSize is optional. */
    1614 
    1615     uint32_t cbOffset;
    1616     size_t cbSize;
    1617 
    1618     int rc = RTIsoFsGetFileInfo(pISO, strFileSource.c_str(), &cbOffset, &cbSize);
     1512
     1513    uint32_t cbSrcOffset;
     1514    size_t cbSrcSize;
     1515
     1516    int rc = RTIsoFsGetFileInfo(pISO, strFileSource.c_str(), &cbSrcOffset, &cbSrcSize);
    16191517    if (RT_FAILURE(rc))
    16201518    {
     
    16251523    }
    16261524
    1627     Assert(cbOffset);
    1628     Assert(cbSize);
    1629     rc = RTFileSeek(pISO->file, cbOffset, RTFILE_SEEK_BEGIN, NULL);
    1630 
    1631     HRESULT hr = S_OK;
    1632     /* Copy over the Guest Additions file to the guest. */
     1525    Assert(cbSrcOffset);
     1526    Assert(cbSrcSize);
     1527    rc = RTFileSeek(pISO->file, cbSrcOffset, RTFILE_SEEK_BEGIN, NULL);
    16331528    if (RT_SUCCESS(rc))
    16341529    {
     
    16361531                strFileSource.c_str(), strFileDest.c_str()));
    16371532
    1638         if (RT_SUCCESS(rc))
    1639         {
    1640             SessionTaskCopyFileTo *pTask = NULL;
    1641             ComObjPtr<Progress> pProgressCopyTo;
    1642             try
    1643             {
    1644                 try
    1645                 {
    1646                     pTask = new SessionTaskCopyFileTo(pSession /* GuestSession */,
    1647                                                       &pISO->file, cbOffset, cbSize,
    1648                                                       strFileDest, FileCopyFlag_None);
    1649                 }
    1650                 catch(...)
    1651                 {
    1652                     hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1653                                   GuestSession::tr("Failed to create SessionTaskCopyTo object "));
    1654                     throw;
    1655                 }
    1656 
    1657                 hr = pTask->Init(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer file \"%s\" to \"%s\" on guest"),
    1658                                             mSource.c_str(), strFileDest.c_str()));
    1659                 if (FAILED(hr))
    1660                 {
    1661                     delete pTask;
    1662                     hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1663                                   GuestSession::tr("Creating progress object for SessionTaskCopyTo object failed"));
    1664                     throw hr;
    1665                 }
    1666 
    1667                 hr = pTask->createThreadWithType(RTTHREADTYPE_MAIN_HEAVY_WORKER);
    1668 
    1669                 if (SUCCEEDED(hr))
    1670                 {
    1671                     /* Return progress to the caller. */
    1672                     pProgressCopyTo = pTask->GetProgressObject();
    1673                 }
    1674                 else
    1675                     hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1676                                   GuestSession::tr("Starting thread for updating additions failed "));
    1677             }
    1678             catch(std::bad_alloc &)
    1679             {
    1680                 hr = E_OUTOFMEMORY;
    1681             }
    1682             catch(HRESULT eHR)
    1683             {
    1684                 hr = eHR;
    1685                 LogFlowThisFunc(("Exception was caught in the function \n"));
    1686             }
    1687 
    1688             if (SUCCEEDED(hr))
    1689             {
    1690                 BOOL fCanceled = FALSE;
    1691                 hr = pProgressCopyTo->WaitForCompletion(-1);
    1692                 if (   SUCCEEDED(pProgressCopyTo->COMGETTER(Canceled)(&fCanceled))
    1693                     && fCanceled)
    1694                 {
    1695                     rc = VERR_GENERAL_FAILURE; /* Fudge. */
    1696                 }
    1697                 else if (FAILED(hr))
    1698                 {
    1699                     Assert(FAILED(hr));
    1700                     rc = VERR_GENERAL_FAILURE; /* Fudge. */
    1701                 }
    1702             }
    1703         }
    1704     }
    1705 
    1706     /** @todo Note: Since there is no file locking involved at the moment, there can be modifications
    1707      *              between finished copying, the verification and the actual execution. */
    1708 
    1709     /* Determine where the installer image ended up and if it has the correct size. */
    1710     if (RT_SUCCESS(rc))
    1711     {
    1712         LogRel(("Verifying Guest Additions installer file \"%s\" ...\n",
    1713                 strFileDest.c_str()));
    1714 
    1715         GuestFsObjData objData;
    1716         int64_t cbSizeOnGuest;
    1717         int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    1718         rc = pSession->i_fileQuerySize(strFileDest, false /*fFollowSymlinks*/, &cbSizeOnGuest, &rcGuest);
    1719         if (   RT_SUCCESS(rc)
    1720             && cbSize == (uint64_t)cbSizeOnGuest)
    1721         {
    1722             LogFlowThisFunc(("Guest Additions installer file \"%s\" successfully verified\n",
    1723                              strFileDest.c_str()));
     1533        GuestFileOpenInfo dstOpenInfo;
     1534        RT_ZERO(dstOpenInfo);
     1535        dstOpenInfo.mFileName    = strFileDest;
     1536        dstOpenInfo.mOpenAction  = FileOpenAction_CreateOrReplace;
     1537        dstOpenInfo.mAccessMode  = FileAccessMode_WriteOnly;
     1538        dstOpenInfo.mSharingMode = FileSharingMode_All; /** @todo Use _Read when implemented. */
     1539
     1540        ComObjPtr<GuestFile> dstFile; int rcGuest;
     1541        rc = mSession->i_fileOpen(dstOpenInfo, dstFile, &rcGuest);
     1542        if (RT_FAILURE(rc))
     1543        {
     1544            switch (rc)
     1545            {
     1546                case VERR_GSTCTL_GUEST_ERROR:
     1547                    setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(rcGuest));
     1548                    break;
     1549
     1550                default:
     1551                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     1552                                        Utf8StrFmt(GuestSession::tr("Destination file \"%s\" could not be opened: %Rrc"),
     1553                                                   strFileDest, rc));
     1554                    break;
     1555            }
    17241556        }
    17251557        else
    17261558        {
    1727             if (RT_SUCCESS(rc)) /* Size does not match. */
    1728             {
    1729                 LogRel(("Size of Guest Additions installer file \"%s\" does not match: %RI64 bytes copied, %RU64 bytes expected\n",
    1730                         strFileDest.c_str(), cbSizeOnGuest, cbSize));
    1731                 rc = VERR_BROKEN_PIPE; /** @todo Find a better error. */
    1732             }
    1733             else
    1734             {
    1735                 switch (rc)
    1736                 {
    1737                     case VERR_GSTCTL_GUEST_ERROR:
    1738                         setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest));
    1739                         break;
    1740 
    1741                     default:
    1742                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1743                                             Utf8StrFmt(GuestSession::tr("Error while querying size for file \"%s\": %Rrc"),
    1744                                                        strFileDest.c_str(), rc));
    1745                         break;
    1746                 }
    1747             }
    1748         }
    1749 
    1750         if (RT_SUCCESS(rc))
    1751         {
    1752             if (pcbSize)
    1753                 *pcbSize = (uint32_t)cbSizeOnGuest;
    1754         }
     1559            rc = fileCopyToGuestInner(&pISO->file, dstFile, FileCopyFlag_None, cbSrcOffset, cbSrcSize);
     1560
     1561            int rc2 = dstFile->i_closeFile(&rcGuest);
     1562            AssertRC(rc2);
     1563        }
     1564
     1565        if (RT_FAILURE(rc))
     1566            return rc;
    17551567    }
    17561568
     
    21851997                        if (itFiles->fFlags & ISOFILE_FLAG_OPTIONAL)
    21861998                            fOptional = true;
    2187                         rc = copyFileToGuest(pSession, &iso, itFiles->strSource, itFiles->strDest,
    2188                                                fOptional, NULL /* cbSize */);
     1999                        rc = copyFileToGuest(pSession, &iso, itFiles->strSource, itFiles->strDest, fOptional);
    21892000                        if (RT_FAILURE(rc))
    21902001                        {
Note: See TracChangeset for help on using the changeset viewer.

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