Changeset 71796 in vbox
- Timestamp:
- Apr 9, 2018 7:26:50 PM (6 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
-
include/GuestSessionImplTasks.h (modified) (1 diff)
-
src-client/GuestSessionImplTasks.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/GuestSessionImplTasks.h
r71657 r71796 79 79 /** @name File handling primitives. 80 80 * @{ */ 81 int fileCopyFromEx( const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags,82 PRTFILE pFile,uint64_t cbOffset, uint64_t cbSize);81 int fileCopyFromEx(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T enmFileCopyFlags, 82 uint64_t cbOffset, uint64_t cbSize); 83 83 int fileCopyFrom(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags); 84 84 int fileCopyToEx(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags, PRTFILE pFile, -
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r71667 r71796 266 266 * 267 267 * @return VBox status code. 268 * @param strSource Full path of source file on the guest to copy. 269 * @param strDest Full destination path and file name (host style) to copy file to. 270 * @param enmFileCopyFlags File copy flags. Currently not used. 271 * @param pFile Destination file handle to use for accessing the host file. 272 * The caller is responsible of opening / closing the file accordingly. 273 * @param cbOffset Offset (in bytes) where to start copying the source file. 274 * Currently unused, must be 0. 275 * @param cbSize Size (in bytes) to copy from the source file. 276 * Currently unused, must be 0. 268 * @param srcFile Guest file (source) to copy to the host. Must be in opened and ready state already. 269 * @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. 272 * @param cbSize Size (in bytes) to copy from the source file. 277 273 */ 278 int GuestSessionTask::fileCopyFromEx(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T enmFileCopyFlags, 279 PRTFILE pFile, uint64_t cbOffset, uint64_t cbSize) 280 { 281 RT_NOREF(enmFileCopyFlags, cbOffset, cbSize); 282 283 AssertReturn(cbOffset == 0, VERR_NOT_IMPLEMENTED); 284 AssertReturn(cbSize == 0, VERR_NOT_IMPLEMENTED); 285 286 RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */ 287 288 LogFlowFunc(("strSource=%s, strDest=%s, fCopyFlags=0x%x, cbOff=%RU64, cbSize=%RU64\n", 289 strSource.c_str(), strDest.c_str(), enmFileCopyFlags, cbOffset, cbSize)); 290 291 /* 292 * Note: There will be races between querying file size + reading the guest file's 293 * content because we currently *do not* lock down the guest file when doing the 294 * actual operations. 295 ** @todo Use the IGuestFile API for locking down the file on the guest! 296 */ 297 GuestFsObjData objData; 298 int rcGuest = VERR_IPE_UNINITIALIZED_STATUS; 299 int rc = mSession->i_fileQueryInfo(strSource, false /*fFollowSymlinks*/, objData, &rcGuest); 300 if (RT_FAILURE(rc)) 301 { 302 switch (rc) 303 { 304 case VERR_GSTCTL_GUEST_ERROR: 305 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest)); 306 break; 307 308 default: 309 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 310 Utf8StrFmt(GuestSession::tr("Querying guest file information for \"%s\" failed: %Rrc"), 311 strSource.c_str(), rc)); 312 break; 313 } 314 } 315 else if (objData.mType != FsObjType_File) /* Only single files are supported at the moment. */ 316 { 317 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 318 Utf8StrFmt(GuestSession::tr("Object \"%s\" on the guest is not a file"), strSource.c_str())); 319 rc = VERR_NOT_A_FILE; 274 int GuestSessionTask::fileCopyFromEx(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T enmFileCopyFlags, 275 uint64_t uOffset, uint64_t cbSize) 276 { 277 RT_NOREF(enmFileCopyFlags); 278 279 BOOL fCanceled = FALSE; 280 uint64_t cbWrittenTotal = 0; 281 uint64_t cbToRead = cbSize; 282 283 uint32_t uTimeoutMs = 30 * 1000; /* 30s timeout. */ 284 285 int rc = VINF_SUCCESS; 286 287 if (uOffset) 288 { 289 uint64_t puOffset; 290 rc = srcFile->i_seekAt(uOffset, GUEST_FILE_SEEKTYPE_BEGIN, uTimeoutMs, &puOffset); 291 if (RT_FAILURE(rc)) 292 { 293 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 294 Utf8StrFmt(GuestSession::tr("Seeking to offset %RU64) failed: %Rrc"), uOffset, rc)); 295 return rc; 296 } 297 } 298 299 BYTE byBuf[_64K]; 300 while (cbToRead) 301 { 302 uint32_t cbRead; 303 const uint32_t cbChunk = RT_MIN(cbToRead, sizeof(byBuf)); 304 rc = srcFile->i_readData(cbChunk, uTimeoutMs, byBuf, sizeof(byBuf), &cbRead); 305 if (RT_FAILURE(rc)) 306 { 307 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 308 Utf8StrFmt(GuestSession::tr("Reading %RU32 bytes @ %RU64, failed: %Rrc"), cbChunk, cbWrittenTotal, rc)); 309 break; 310 } 311 312 rc = RTFileWrite(*phDstFile, byBuf, cbRead, NULL /* No partial writes */); 313 if (RT_FAILURE(rc)) 314 { 315 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 316 Utf8StrFmt(GuestSession::tr("Writing to %RU32 bytes to file failed: %Rrc"), cbRead, rc)); 317 break; 318 } 319 320 Assert(cbToRead >= cbRead); 321 cbToRead -= cbRead; 322 323 /* Update total bytes written to the guest. */ 324 cbWrittenTotal += cbRead; 325 Assert(cbWrittenTotal <= cbSize); 326 327 /* Did the user cancel the operation above? */ 328 if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled))) 329 && fCanceled) 330 break; 331 332 rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)cbSize / 100.0))); 333 if (RT_FAILURE(rc)) 334 break; 320 335 } 321 336 … … 323 338 return rc; 324 339 325 GuestProcessStartupInfo procInfo;326 procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),327 strSource.c_str(), strDest.c_str(), objData.mObjectSize);328 procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_CAT);329 procInfo.mFlags = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;330 331 /* Set arguments.*/332 procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */333 procInfo.mArguments.push_back(strSource); /* Which file to output? */334 335 /* Startup process. */336 ComObjPtr<GuestProcess> pProcess;337 rc = mSession->i_processCreateEx(procInfo, pProcess);338 if (RT_SUCCESS(rc))339 rc = pProcess->i_startProcess(msTimeout, &rcGuest);340 341 if (RT_FAILURE(rc))342 {343 switch (rc)344 {345 case VERR_GSTCTL_GUEST_ERROR:346 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest));347 break;348 349 default:350 setProgressErrorMsg(VBOX_E_IPRT_ERROR,351 Utf8StrFmt(GuestSession::tr(352 "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),353 strSource.c_str(), rc));354 break;355 }356 357 return rc;358 }359 360 ProcessWaitResult_T waitRes;361 BYTE byBuf[_64K];362 363 BOOL fCanceled = FALSE;364 uint64_t cbWrittenTotal = 0;365 uint64_t cbToRead = objData.mObjectSize;366 367 for (;;)368 {369 rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut, msTimeout, waitRes, &rcGuest);370 if (RT_FAILURE(rc))371 {372 switch (rc)373 {374 case VERR_GSTCTL_GUEST_ERROR:375 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest));376 break;377 378 default:379 setProgressErrorMsg(VBOX_E_IPRT_ERROR,380 Utf8StrFmt(GuestSession::tr("Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),381 strSource.c_str(), rc));382 break;383 }384 385 break;386 }387 388 if ( waitRes == ProcessWaitResult_StdOut389 || waitRes == ProcessWaitResult_WaitFlagNotSupported)390 {391 /* If the guest does not support waiting for stdin, we now yield in392 * order to reduce the CPU load due to busy waiting. */393 if (waitRes == ProcessWaitResult_WaitFlagNotSupported)394 RTThreadYield(); /* Optional, don't check rc. */395 396 uint32_t cbRead = 0; /* readData can return with VWRN_GSTCTL_OBJECTSTATE_CHANGED. */397 rc = pProcess->i_readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),398 msTimeout, byBuf, sizeof(byBuf),399 &cbRead, &rcGuest);400 if (RT_FAILURE(rc))401 {402 switch (rc)403 {404 case VERR_GSTCTL_GUEST_ERROR:405 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(rcGuest));406 break;407 408 default:409 setProgressErrorMsg(VBOX_E_IPRT_ERROR,410 Utf8StrFmt(GuestSession::tr("Reading from guest file \"%s\" (offset %RU64) failed: %Rrc"),411 strSource.c_str(), cbWrittenTotal, rc));412 break;413 }414 415 break;416 }417 418 if (cbRead)419 {420 rc = RTFileWrite(*pFile, byBuf, cbRead, NULL /* No partial writes */);421 if (RT_FAILURE(rc))422 {423 setProgressErrorMsg(VBOX_E_IPRT_ERROR,424 Utf8StrFmt(GuestSession::tr("Writing to host file \"%s\" (%RU64 bytes left) failed: %Rrc"),425 strDest.c_str(), cbToRead, rc));426 break;427 }428 429 /* Only subtract bytes reported written by the guest. */430 Assert(cbToRead >= cbRead);431 cbToRead -= cbRead;432 433 /* Update total bytes written to the guest. */434 cbWrittenTotal += cbRead;435 Assert(cbWrittenTotal <= (uint64_t)objData.mObjectSize);436 437 /* Did the user cancel the operation above? */438 if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))439 && fCanceled)440 break;441 442 rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)objData.mObjectSize / 100.0)));443 if (RT_FAILURE(rc))444 break;445 }446 }447 else448 break;449 450 } /* for */451 452 LogFlowThisFunc(("rc=%Rrc, rcGuest=%Rrc, waitRes=%ld, cbWrittenTotal=%RU64, cbSize=%RI64, cbToRead=%RU64\n",453 rc, rcGuest, waitRes, cbWrittenTotal, objData.mObjectSize, cbToRead));454 455 /*456 * Wait on termination of guest process until it completed all operations.457 */458 if ( !fCanceled459 || RT_SUCCESS(rc))460 {461 rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &rcGuest);462 if ( RT_FAILURE(rc)463 || waitRes != ProcessWaitResult_Terminate)464 {465 if (RT_FAILURE(rc))466 setProgressErrorMsg(VBOX_E_IPRT_ERROR,467 Utf8StrFmt(468 GuestSession::tr("Waiting on termination for copying file \"%s\" from guest failed: %Rrc"),469 strSource.c_str(), rc));470 else471 {472 setProgressErrorMsg(VBOX_E_IPRT_ERROR,473 Utf8StrFmt(GuestSession::tr(474 "Waiting on termination for copying file \"%s\" from guest failed with wait result %ld"),475 strSource.c_str(), waitRes));476 rc = VERR_GENERAL_FAILURE; /* Fudge. */477 }478 }479 }480 481 if (RT_FAILURE(rc))482 return rc;483 484 /** @todo this code sequence is duplicated in CopyTo */485 ProcessStatus_T procStatus = ProcessStatus_TerminatedAbnormally;486 HRESULT hrc = pProcess->COMGETTER(Status(&procStatus));487 if (!SUCCEEDED(hrc))488 procStatus = ProcessStatus_TerminatedAbnormally;489 490 LONG exitCode = 42424242;491 hrc = pProcess->COMGETTER(ExitCode(&exitCode));492 if (!SUCCEEDED(hrc))493 exitCode = 42424242;494 495 if ( procStatus != ProcessStatus_TerminatedNormally496 || exitCode != 0)497 {498 LogFlowThisFunc(("procStatus=%d, exitCode=%d\n", procStatus, exitCode));499 if (procStatus == ProcessStatus_TerminatedNormally)500 rc = GuestProcessTool::exitCodeToRc(procInfo, exitCode);501 else502 rc = VERR_GENERAL_FAILURE;503 setProgressErrorMsg(VBOX_E_IPRT_ERROR,504 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to host failed: %Rrc"),505 strSource.c_str(), rc));506 }507 340 /* 508 341 * Even if we succeeded until here make sure to check whether we really transfered 509 342 * everything. 510 343 */ 511 else if ( objData.mObjectSize > 0512 && cbWrittenTotal == 0)344 if ( cbSize > 0 345 && cbWrittenTotal == 0) 513 346 { 514 347 /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write 515 348 * to the destination -> access denied. */ 516 349 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 517 Utf8StrFmt(GuestSession::tr("Writing guest file \"%s\" to host to \"%s\" failed: Access denied"), 518 strSource.c_str(), strDest.c_str())); 350 Utf8StrFmt(GuestSession::tr("Writing guest file to host failed: Access denied"))); 519 351 rc = VERR_ACCESS_DENIED; 520 352 } 521 else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)353 else if (cbWrittenTotal < cbSize) 522 354 { 523 355 /* If we did not copy all let the user know. */ 524 356 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 525 Utf8StrFmt(GuestSession::tr("Copying guest file \"%s\" to host to \"%s\" failed (%RU64/%RI64 bytes transfered)"),526 strSource.c_str(), strDest.c_str(), cbWrittenTotal, objData.mObjectSize));357 Utf8StrFmt(GuestSession::tr("Copying guest file to host to failed (%RU64/%RU64 bytes transfered)"), 358 cbWrittenTotal, cbSize)); 527 359 rc = VERR_INTERRUPTED; 528 360 } … … 535 367 * Copies a file from the guest to the host. 536 368 * 537 * @return VBox status code. 369 * @return VBox status code. VINF_NO_CHANGE if file was skipped. 538 370 * @param strSource Full path of source file on the guest to copy. 539 371 * @param strDest Full destination path and file name (host style) to copy file to. … … 544 376 LogFlowThisFunc(("strSource=%s, strDest=%s, enmFileCopyFlags=0x%x\n", strSource.c_str(), strDest.c_str(), enmFileCopyFlags)); 545 377 378 GuestFileOpenInfo srcOpenInfo; 379 RT_ZERO(srcOpenInfo); 380 srcOpenInfo.mFileName = strSource; 381 srcOpenInfo.mOpenAction = FileOpenAction_OpenExisting; 382 srcOpenInfo.mAccessMode = FileAccessMode_ReadOnly; 383 srcOpenInfo.mSharingMode = FileSharingMode_All; /** @todo Use _Read when implemented. */ 384 385 ComObjPtr<GuestFile> srcFile; 386 387 GuestFsObjData srcObjData; 388 RT_ZERO(srcObjData); 389 390 int rcGuest = VERR_IPE_UNINITIALIZED_STATUS; 391 int rc = mSession->i_fsQueryInfo(strSource.c_str(), TRUE /* fFollowSymlinks */, srcObjData, &rcGuest); 392 if (RT_FAILURE(rc)) 393 { 394 switch (rc) 395 { 396 case VERR_GSTCTL_GUEST_ERROR: 397 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(rcGuest)); 398 break; 399 400 default: 401 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 402 Utf8StrFmt(GuestSession::tr("Source file lookup for \"%s\" failed: %Rrc"), 403 strSource.c_str(), rc)); 404 break; 405 } 406 } 407 else 408 { 409 switch (srcObjData.mType) 410 { 411 case FsObjType_File: 412 break; 413 414 case FsObjType_Symlink: 415 if (!(enmFileCopyFlags & FileCopyFlag_FollowLinks)) 416 { 417 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 418 Utf8StrFmt(GuestSession::tr("Source file \"%s\" is a symbolic link"), 419 strSource.c_str(), rc)); 420 rc = VERR_IS_A_SYMLINK; 421 } 422 break; 423 424 default: 425 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 426 Utf8StrFmt(GuestSession::tr("Source element \"%s\" is not a file"), strSource.c_str())); 427 rc = VERR_NOT_A_FILE; 428 break; 429 } 430 } 431 432 if (RT_FAILURE(rc)) 433 return rc; 434 435 rc = mSession->i_fileOpen(srcOpenInfo, srcFile, &rcGuest); 436 if (RT_FAILURE(rc)) 437 { 438 switch (rc) 439 { 440 case VERR_GSTCTL_GUEST_ERROR: 441 setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(rcGuest)); 442 break; 443 444 default: 445 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 446 Utf8StrFmt(GuestSession::tr("Source file \"%s\" could not be opened: %Rrc"), 447 strSource.c_str(), rc)); 448 break; 449 } 450 } 451 452 if (RT_FAILURE(rc)) 453 return rc; 454 546 455 char *pszDstFile = NULL; 547 548 RTFSOBJINFO objInfo; 549 int rc = RTPathQueryInfo(strDest.c_str(), &objInfo, RTFSOBJATTRADD_NOTHING); 456 RTFSOBJINFO dstObjInfo; 457 RT_ZERO(dstObjInfo); 458 459 bool fSkip = false; /* Whether to skip handling the file. */ 460 550 461 if (RT_SUCCESS(rc)) 551 462 { 552 if (RTFS_IS_FILE(objInfo.Attr.fMode)) 463 rc = RTPathQueryInfo(strDest.c_str(), &dstObjInfo, RTFSOBJATTRADD_NOTHING); 464 if (RT_SUCCESS(rc)) 553 465 { 554 466 if (enmFileCopyFlags & FileCopyFlag_NoReplace) 555 467 { 556 468 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 557 Utf8StrFmt(GuestSession::tr("Destination file \"%s\" on host already exists"), 469 Utf8StrFmt(GuestSession::tr("Destination file \"%s\" already exists"), strDest.c_str())); 470 rc = VERR_ALREADY_EXISTS; 471 } 472 473 if (enmFileCopyFlags & FileCopyFlag_Update) 474 { 475 RTTIMESPEC srcModificationTimeTS; 476 RTTimeSpecSetSeconds(&srcModificationTimeTS, srcObjData.mModificationTime); 477 if (RTTimeSpecCompare(&srcModificationTimeTS, &dstObjInfo.ModificationTime) <= 0) 478 { 479 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 480 Utf8StrFmt(GuestSession::tr("Destination file \"%s\" has same or newer modification date"), 481 strDest.c_str())); 482 fSkip = true; 483 } 484 } 485 } 486 else 487 { 488 if (rc != VERR_FILE_NOT_FOUND) /* Destination file does not exist (yet)? */ 489 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 490 Utf8StrFmt(GuestSession::tr("Destination file lookup for \"%s\" failed: %Rrc"), 558 491 strDest.c_str(), rc)); 559 return VERR_ALREADY_EXISTS; 560 } 561 562 pszDstFile = RTStrDup(strDest.c_str()); 563 } 564 else if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) 492 } 493 } 494 495 if (fSkip) 496 { 497 int rc2 = srcFile->i_closeFile(&rcGuest); 498 AssertRC(rc2); 499 return VINF_SUCCESS; 500 } 501 502 if (RT_SUCCESS(rc)) 503 { 504 if (RTFS_IS_FILE(dstObjInfo.Attr.fMode)) 505 { 506 if (enmFileCopyFlags & FileCopyFlag_NoReplace) 507 { 508 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 509 Utf8StrFmt(GuestSession::tr("Destination file \"%s\" already exists"), 510 strDest.c_str(), rc)); 511 rc = VERR_ALREADY_EXISTS; 512 } 513 else 514 pszDstFile = RTStrDup(strDest.c_str()); 515 } 516 else if (RTFS_IS_DIRECTORY(dstObjInfo.Attr.fMode)) 565 517 { 566 518 if ( strDest.endsWith("\\") … … 578 530 { 579 531 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 580 Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" on hostalready exists"),532 Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" already exists"), 581 533 strDest.c_str(), rc)); 582 r eturnVERR_ALREADY_EXISTS;583 } 584 } 585 else if (RTFS_IS_SYMLINK( objInfo.Attr.fMode))534 rc = VERR_ALREADY_EXISTS; 535 } 536 } 537 else if (RTFS_IS_SYMLINK(dstObjInfo.Attr.fMode)) 586 538 { 587 539 if (!(enmFileCopyFlags & FileCopyFlag_FollowLinks)) 588 540 { 589 541 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 590 Utf8StrFmt(GuestSession::tr("Destination file \"%s\" on the hostis a symbolic link"),542 Utf8StrFmt(GuestSession::tr("Destination file \"%s\" is a symbolic link"), 591 543 strDest.c_str(), rc)); 592 return VERR_IS_A_SYMLINK; 593 } 594 595 pszDstFile = RTStrDup(strDest.c_str()); 596 } 597 } 598 else 544 rc = VERR_IS_A_SYMLINK; 545 } 546 else 547 pszDstFile = RTStrDup(strDest.c_str()); 548 } 549 else 550 { 551 LogFlowThisFunc(("Object type %RU32 not implemented yet\n", dstObjInfo.Attr.fMode)); 552 rc = VERR_NOT_IMPLEMENTED; 553 } 554 } 555 else if (rc == VERR_FILE_NOT_FOUND) 599 556 pszDstFile = RTStrDup(strDest.c_str()); 600 557 601 if (!pszDstFile) 602 { 603 setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("No memory to allocate destination file path"))); 604 return VERR_NO_MEMORY; 605 } 606 607 RTFILE hFile; 608 rc = RTFileOpen(&hFile, pszDstFile, 609 RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */ 610 if (RT_FAILURE(rc)) 611 { 612 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 613 Utf8StrFmt(GuestSession::tr("Opening/creating destination file on host \"%s\" failed: %Rrc"), 614 pszDstFile, rc)); 615 return rc; 616 } 617 618 rc = fileCopyFromEx(strSource, pszDstFile, enmFileCopyFlags, &hFile, 0 /* Offset, unused */, 0 /* Size, unused */); 619 620 int rc2 = RTFileClose(hFile); 558 if ( RT_SUCCESS(rc) 559 || rc == VERR_FILE_NOT_FOUND) 560 { 561 if (!pszDstFile) 562 { 563 setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("No memory to allocate destination file path"))); 564 rc = VERR_NO_MEMORY; 565 } 566 else 567 { 568 RTFILE hDstFile; 569 rc = RTFileOpen(&hDstFile, pszDstFile, 570 RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */ 571 if (RT_SUCCESS(rc)) 572 { 573 LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", strSource.c_str(), pszDstFile, srcObjData.mObjectSize)); 574 575 rc = fileCopyFromEx(srcFile, &hDstFile, enmFileCopyFlags, 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize); 576 577 int rc2 = RTFileClose(hDstFile); 578 AssertRC(rc2); 579 } 580 else 581 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 582 Utf8StrFmt(GuestSession::tr("Opening/creating destination file \"%s\" failed: %Rrc"), 583 pszDstFile, rc)); 584 } 585 } 586 587 RTStrFree(pszDstFile); 588 589 int rc2 = srcFile->i_closeFile(&rcGuest); 621 590 AssertRC(rc2); 622 623 if (pszDstFile)624 RTStrFree(pszDstFile);625 591 626 592 LogFlowFuncLeaveRC(rc);
Note:
See TracChangeset
for help on using the changeset viewer.

