Changeset 71817 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Apr 11, 2018 10:48:34 AM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 121938
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r71796 r71817 263 263 264 264 /** 265 * Copies a file from the guest to the host, extended version.265 * Main function for copying a file from guest to the host. 266 266 * 267 267 * @return VBox status code. 268 268 * @param srcFile Guest file (source) to copy to the host. Must be in opened and ready state already. 269 269 * @param phDstFile Pointer to host file handle (destination) to copy to. Must be in opened and ready state already. 270 * @param enmFileCopyFlagsFile copy flags.271 * @param uOffsetOffset (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. 272 272 * @param cbSize Size (in bytes) to copy from the source file. 273 273 */ 274 int GuestSessionTask::fileCopyFrom Ex(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T enmFileCopyFlags,275 uint64_t uOffset, uint64_t cbSize)276 { 277 RT_NOREF( enmFileCopyFlags);274 int GuestSessionTask::fileCopyFromGuestInner(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T fFileCopyFlags, 275 uint64_t offCopy, uint64_t cbSize) 276 { 277 RT_NOREF(fFileCopyFlags); 278 278 279 279 BOOL fCanceled = FALSE; … … 285 285 int rc = VINF_SUCCESS; 286 286 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); 291 291 if (RT_FAILURE(rc)) 292 292 { 293 293 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)); 295 295 return rc; 296 296 } … … 370 370 * @param strSource Full path of source file on the guest to copy. 371 371 * @param strDest Full destination path and file name (host style) to copy file to. 372 * @param enmFileCopyFlagsFile copy flags.372 * @param fFileCopyFlags File copy flags. 373 373 */ 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));374 int 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)); 377 377 378 378 GuestFileOpenInfo srcOpenInfo; … … 389 389 390 390 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); 392 392 if (RT_FAILURE(rc)) 393 393 { … … 413 413 414 414 case FsObjType_Symlink: 415 if (!( enmFileCopyFlags & FileCopyFlag_FollowLinks))415 if (!(fFileCopyFlags & FileCopyFlag_FollowLinks)) 416 416 { 417 417 setProgressErrorMsg(VBOX_E_IPRT_ERROR, … … 464 464 if (RT_SUCCESS(rc)) 465 465 { 466 if ( enmFileCopyFlags & FileCopyFlag_NoReplace)466 if (fFileCopyFlags & FileCopyFlag_NoReplace) 467 467 { 468 468 setProgressErrorMsg(VBOX_E_IPRT_ERROR, … … 471 471 } 472 472 473 if ( enmFileCopyFlags & FileCopyFlag_Update)473 if (fFileCopyFlags & FileCopyFlag_Update) 474 474 { 475 475 RTTIMESPEC srcModificationTimeTS; … … 504 504 if (RTFS_IS_FILE(dstObjInfo.Attr.fMode)) 505 505 { 506 if ( enmFileCopyFlags & FileCopyFlag_NoReplace)506 if (fFileCopyFlags & FileCopyFlag_NoReplace) 507 507 { 508 508 setProgressErrorMsg(VBOX_E_IPRT_ERROR, … … 537 537 else if (RTFS_IS_SYMLINK(dstObjInfo.Attr.fMode)) 538 538 { 539 if (!( enmFileCopyFlags & FileCopyFlag_FollowLinks))539 if (!(fFileCopyFlags & FileCopyFlag_FollowLinks)) 540 540 { 541 541 setProgressErrorMsg(VBOX_E_IPRT_ERROR, … … 573 573 LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", strSource.c_str(), pszDstFile, srcObjData.mObjectSize)); 574 574 575 rc = fileCopyFrom Ex(srcFile, &hDstFile, enmFileCopyFlags, 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize);575 rc = fileCopyFromGuestInner(srcFile, &hDstFile, fFileCopyFlags, 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize); 576 576 577 577 int rc2 = RTFileClose(hDstFile); … … 595 595 596 596 /** 597 * Copies a file from the host to the guest, extended version.597 * Main function for copying a file from host to the guest. 598 598 * 599 599 * @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 */ 606 int 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. 600 702 * @param strSource Full path of source file on the host to copy. 601 703 * @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. 607 705 */ 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); 706 int 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); 637 714 638 715 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); 644 717 if (RT_FAILURE(rc)) 645 718 { … … 647 720 { 648 721 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)); 650 728 break; 651 729 652 730 default: 653 731 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)) 658 793 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) 699 841 { 700 842 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; 807 862 } 808 863 809 864 if (RT_SUCCESS(rc)) 810 865 { 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 834 880 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 835 Utf8StrFmt(GuestSession::tr(" Copying file \"%s\" to guestfailed: %Rrc"),881 Utf8StrFmt(GuestSession::tr("Opening source file \"%s\" failed: %Rrc"), 836 882 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); 913 889 return rc; 914 890 } … … 964 940 965 941 SessionTaskCopyDirFrom::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) 972 944 { 973 945 m_strTaskName = "gctlCpyDirFrm"; 946 947 mSource = strSource; 948 mDest = strDest; 949 mFilter = strFilter; 950 951 u.Dir.fCopyFlags = fDirCopyFlags; 974 952 } 975 953 976 954 SessionTaskCopyDirFrom::~SessionTaskCopyDirFrom(void) 977 955 { 978 979 956 } 980 957 … … 1115 1092 Utf8Str strSrcFile = strSrcDir + strSrcSubDir + strName; 1116 1093 Utf8Str strDstFile = strDstDir + strSrcSubDir + strName; 1117 rc = fileCopyFrom (strSrcFile, strDstFile, FileCopyFlag_None);1094 rc = fileCopyFromGuest(strSrcFile, strDstFile, FileCopyFlag_None); 1118 1095 } 1119 1096 break; … … 1147 1124 int rc = VINF_SUCCESS; 1148 1125 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 1149 1139 /* 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()); 1152 1142 if ( fExists 1153 && !( mDirCopyFlags & DirectoryCopyFlag_CopyIntoExisting))1143 && !(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting)) 1154 1144 { 1155 1145 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())); 1157 1147 rc = VERR_ALREADY_EXISTS; 1158 1148 } 1159 1149 else if (!fExists) 1160 1150 { 1161 rc = RTDirCreate( mDest.c_str(), fDirMode, 0);1151 rc = RTDirCreate(strDstDir.c_str(), fDirMode, 0); 1162 1152 if (RT_FAILURE(rc)) 1163 1153 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1164 1154 Utf8StrFmt(GuestSession::tr("Error creating destination directory \"%s\", rc=%Rrc"), 1165 mDest.c_str(), rc));1155 strDstDir.c_str(), rc)); 1166 1156 } 1167 1157 … … 1170 1160 1171 1161 RTDIR hDir; 1172 rc = RTDirOpen(&hDir, mDest.c_str());1162 rc = RTDirOpen(&hDir, strDstDir.c_str()); 1173 1163 if (RT_FAILURE(rc)) 1174 1164 { 1175 1165 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1176 1166 Utf8StrFmt(GuestSession::tr("Error opening destination directory \"%s\", rc=%Rrc"), 1177 mDest.c_str(), rc));1167 strDstDir.c_str(), rc)); 1178 1168 return rc; 1179 1169 } … … 1181 1171 /* At this point the directory on the host was created and (hopefully) is ready 1182 1172 * to receive further content. */ 1183 rc = directoryCopyToHost( mSource, mFilter, mDest, fRecursive, fFollowSymlinks,1173 rc = directoryCopyToHost(strSrcDir, mFilter, strDstDir, fRecursive, fFollowSymlinks, 1184 1174 "" /* strSubDir; for recursion */); 1185 1175 if (RT_SUCCESS(rc)) … … 1194 1184 SessionTaskCopyDirTo::SessionTaskCopyDirTo(GuestSession *pSession, 1195 1185 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) 1202 1188 { 1203 1189 m_strTaskName = "gctlCpyDirTo"; 1190 1191 mSource = strSource; 1192 mDest = strDest; 1193 mFilter = strFilter; 1194 1195 u.Dir.fCopyFlags = fDirCopyFlags; 1204 1196 } 1205 1197 … … 1324 1316 Utf8Str strSrcFile = strSrcDir + strSrcSubDir + Utf8Str(pDirEntry->szName); 1325 1317 Utf8Str strDstFile = strDstDir + strSrcSubDir + Utf8Str(pDirEntry->szName); 1326 rc = fileCopyTo (strSrcFile, strDstFile, FileCopyFlag_None);1318 rc = fileCopyToGuest(strSrcFile, strDstFile, FileCopyFlag_None); 1327 1319 } 1328 1320 break; … … 1355 1347 const uint32_t uDirMode = 0700; /* Play safe by default. */ 1356 1348 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 1357 1362 /* 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); 1360 1365 if ( rc == VWRN_ALREADY_EXISTS 1361 && !( mDirCopyFlags & DirectoryCopyFlag_CopyIntoExisting))1366 && !(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting)) 1362 1367 { 1363 1368 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())); 1365 1370 } 1366 1371 … … 1370 1375 /* At this point the directory on the guest was created and (hopefully) is ready 1371 1376 * to receive further content. */ 1372 rc = directoryCopyToGuest( mSource, mFilter, mDest, fRecursive, fFollowSymlinks,1377 rc = directoryCopyToGuest(strSrcDir, mFilter, strDstDir, fRecursive, fFollowSymlinks, 1373 1378 "" /* strSubDir; for recursion */); 1374 1379 if (RT_SUCCESS(rc)) … … 1380 1385 1381 1386 SessionTaskCopyFileTo::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) 1390 1389 { 1391 1390 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; 1405 1396 } 1406 1397 … … 1417 1408 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1418 1409 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); 1502 1411 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(); 1517 1413 1518 1414 LogFlowFuncLeaveRC(rc); … … 1521 1417 1522 1418 SessionTaskCopyFileFrom::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) 1528 1421 { 1529 1422 m_strTaskName = "gctlCpyFileFrm"; 1423 1424 mSource = strSource; 1425 mDest = strDest; 1426 1427 u.File.fCopyFlags = fFileCopyFlags; 1530 1428 } 1531 1429 … … 1542 1440 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1543 1441 1544 int rc = fileCopyFrom (mSource, mDest, mFileCopyFlags);1442 int rc = fileCopyFromGuest(mSource, mDest, u.File.fCopyFlags); 1545 1443 if (RT_SUCCESS(rc)) 1546 1444 rc = setProgressSuccess(); … … 1553 1451 const Utf8Str &strSource, 1554 1452 const ProcessArguments &aArguments, 1555 uint32_t uFlags)1453 uint32_t fFlags) 1556 1454 : GuestSessionTask(pSession) 1557 1455 { 1558 mSource = strSource; 1456 m_strTaskName = "gctlUpGA"; 1457 1458 mSource = strSource; 1559 1459 mArguments = aArguments; 1560 mFlags = uFlags; 1561 m_strTaskName = "gctlUpGA"; 1460 mFlags = fFlags; 1562 1461 } 1563 1462 … … 1607 1506 int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO, 1608 1507 Utf8Str const &strFileSource, const Utf8Str &strFileDest, 1609 bool fOptional , uint32_t *pcbSize)1508 bool fOptional) 1610 1509 { 1611 1510 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 1612 1511 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); 1619 1517 if (RT_FAILURE(rc)) 1620 1518 { … … 1625 1523 } 1626 1524 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); 1633 1528 if (RT_SUCCESS(rc)) 1634 1529 { … … 1636 1531 strFileSource.c_str(), strFileDest.c_str())); 1637 1532 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 } 1724 1556 } 1725 1557 else 1726 1558 { 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; 1755 1567 } 1756 1568 … … 2185 1997 if (itFiles->fFlags & ISOFILE_FLAG_OPTIONAL) 2186 1998 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); 2189 2000 if (RT_FAILURE(rc)) 2190 2001 {
Note:
See TracChangeset
for help on using the changeset viewer.