VirtualBox

Changeset 42573 in vbox


Ignore:
Timestamp:
Aug 3, 2012 10:59:11 AM (12 years ago)
Author:
vboxsync
Message:

Guest Control 2.0: Update.

File:
1 edited

Legend:

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

    r42567 r42573  
    3232
    3333#include <iprt/env.h>
     34#include <iprt/file.h> /* For CopyTo/From. */
    3435
    3536#include <VBox/com/array.h>
     
    132133int SessionTaskCopyTo::Run(void)
    133134{
    134     return 0;
     135    LogFlowThisFuncEnter();
     136
     137    ComObjPtr<GuestSession> pSession = mSession;
     138    Assert(!pSession.isNull());
     139
     140    AutoCaller autoCaller(pSession);
     141    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     142
     143    int rc;
     144
     145    /** @todo Make use of exception (+ finally block) here! */
     146
     147    try
     148    {
     149        /* Does our source file exist? */
     150        if (!RTFileExists(mSource.c_str()))
     151        {
     152            rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     153                                     Utf8StrFmt(GuestSession::tr("Source file \"%s\" does not exist or is not a file"),
     154                                     mSource.c_str()));
     155        }
     156        else
     157        {
     158            RTFILE fileSource;
     159            rc = RTFileOpen(&fileSource, mSource.c_str(),
     160                            RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
     161            if (RT_FAILURE(rc))
     162            {
     163                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     164                                         Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading (%Rrc)"),
     165                                         mSource.c_str(), rc));
     166            }
     167            else
     168            {
     169                uint64_t cbFileSize;
     170                rc = RTFileGetSize(fileSource, &cbFileSize);
     171                if (RT_FAILURE(rc))
     172                {
     173                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     174                                        Utf8StrFmt(GuestSession::tr("Could not query file size of \"%s\" (%Rrc)"),
     175                                        mSource.c_str(), rc));
     176                }
     177                else
     178                {
     179                    GuestProcessInfo procInfo;
     180                    procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to the guest to \"%s\" (%RU64 bytes)"),
     181                                                                    mSource.c_str(), mDest.c_str(), cbFileSize);
     182                    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
     183                    procInfo.mFlags   = ProcessCreateFlag_None;
     184
     185                    /* Set arguments.*/
     186                    procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */
     187
     188                    /* Startup process. */
     189                    ComObjPtr<GuestProcess> pProcess;
     190                    int rc = pSession->processCreateExInteral(procInfo, pProcess);
     191                    if (RT_SUCCESS(rc))
     192                    {
     193                        GuestProcessWaitResult waitRes;
     194                        BYTE byBuf[_64K];
     195
     196                        BOOL fCanceled = FALSE;
     197                        uint64_t cbWrittenTotal = 0;
     198                        uint64_t cbToRead = cbFileSize;
     199
     200                        for (;;)
     201                        {
     202                            rc = pProcess->waitFor(ProcessWaitForFlag_StdIn,
     203                                                   30 * 1000 /* Timeout */, waitRes);
     204                            if (   RT_FAILURE(rc)
     205                                || waitRes.mResult != ProcessWaitResult_StdIn)
     206                            {
     207                                break;
     208                            }
     209
     210                            size_t cbRead = 0;
     211                            if (cbFileSize) /* If we have nothing to write, take a shortcut. */
     212                            {
     213                                /** @todo Not very efficient, but works for now. */
     214                                rc = RTFileSeek(fileSource, cbWrittenTotal,
     215                                                RTFILE_SEEK_BEGIN, NULL /* poffActual */);
     216                                if (RT_SUCCESS(rc))
     217                                {
     218                                    rc = RTFileRead(fileSource, (uint8_t*)byBuf,
     219                                                    RT_MIN(cbToRead, sizeof(byBuf)), &cbRead);
     220                                    /*
     221                                     * Some other error occured? There might be a chance that RTFileRead
     222                                     * could not resolve/map the native error code to an IPRT code, so just
     223                                     * print a generic error.
     224                                     */
     225                                    if (RT_FAILURE(rc))
     226                                    {
     227                                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     228                                                            Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
     229                                                            mSource.c_str(), rc));
     230                                        break;
     231                                    }
     232                                }
     233                                else
     234                                {
     235                                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     236                                                        Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" offset %RU64 failed: %Rrc"),
     237                                                        mSource.c_str(), cbWrittenTotal, rc));
     238                                    break;
     239                                }
     240                            }
     241
     242                            uint32_t fFlags = ProcessInputFlag_None;
     243
     244                            /* Did we reach the end of the content we want to transfer (last chunk)? */
     245                            if (   (cbRead < sizeof(byBuf))
     246                                /* Did we reach the last block which is exactly _64K? */
     247                                || (cbToRead - cbRead == 0)
     248                                /* ... or does the user want to cancel? */
     249                                || (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
     250                                    && fCanceled)
     251                               )
     252                            {
     253                                fFlags |= ProcessInputFlag_EndOfFile;
     254                            }
     255
     256                            uint32_t cbWritten;
     257                            rc = pProcess->writeData(0 /* StdIn */, fFlags,
     258                                                     byBuf, sizeof(byBuf),
     259                                                     30 * 1000 /* Timeout */, &cbWritten);
     260                            if (RT_FAILURE(rc))
     261                            {
     262                                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     263                                                    Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
     264                                                    mSource.c_str(), cbWrittenTotal, rc));
     265                                break;
     266                            }
     267
     268                            /* Safety first. */
     269                            Assert(cbRead <= cbToRead);
     270                            Assert(cbToRead >= cbRead);
     271
     272                            /* Only subtract bytes reported written by the guest. */
     273                            cbToRead -= cbWritten;
     274
     275                            /* Update total bytes written to the guest. */
     276                            cbWrittenTotal += cbWritten;
     277                            Assert(cbWrittenTotal <= cbFileSize);
     278
     279                            /* Did the user cancel the operation above? */
     280                            if (fCanceled)
     281                                break;
     282
     283                            /* Update the progress. */
     284                            HRESULT hr = mProgress->SetCurrentOperationProgress((ULONG)(cbWrittenTotal * 100 / cbFileSize));
     285                            if (FAILED(hr))
     286                            {
     287                                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     288                                                         Utf8StrFmt(GuestSession::tr("Error updating the progress of copying files \"%s\" to \"%s\""),
     289                                                         mSource.c_str(), mDest.c_str()));
     290                                break;
     291                            }
     292
     293                            /* End of file reached? */
     294                            if (cbToRead == 0)
     295                                break;
     296                        } /* for */
     297
     298                        if (   !fCanceled
     299                            || RT_SUCCESS(rc))
     300                        {
     301                            /*
     302                             * Even if we succeeded until here make sure to check whether we really transfered
     303                             * everything.
     304                             */
     305                            if (   cbFileSize > 0
     306                                && cbWrittenTotal == 0)
     307                            {
     308                                /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
     309                                 * to the destination -> access denied. */
     310                                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     311                                                         Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
     312                                                         mSource.c_str(), mDest.c_str()));
     313                            }
     314                            else if (cbWrittenTotal < cbFileSize)
     315                            {
     316                                /* If we did not copy all let the user know. */
     317                                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     318                                                         Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
     319                                                         mSource.c_str(), cbWrittenTotal, cbFileSize));
     320                            }
     321                            else /* Yay, all went fine! */
     322                                rc = setProgressSuccess();
     323                        }
     324                    } /* processCreateExInteral */
     325                } /* RTFileGetSize */
     326
     327                RTFileClose(fileSource);
     328
     329            } /* RTFileOpen */
     330        } /* RTFileExists */
     331    }
     332    catch (int rc2)
     333    {
     334        rc = rc2;
     335    }
     336
     337    LogFlowFuncLeaveRC(rc);
     338    return rc;
    135339}
    136340
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