Changeset 97395 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Nov 4, 2022 11:17:21 AM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 154395
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r97304 r97395 1418 1418 } 1419 1419 1420 /** 1421 * Converts a PathStyle_T to a human-readable string. 1422 * 1423 * @returns Human-readable string of PathStyle_T. 1424 * @param enmPathStyle PathStyle_T to convert. 1425 */ 1426 /* static */ 1427 const char *GuestBase::pathStyleToStr(PathStyle_T enmPathStyle) 1428 { 1429 switch (enmPathStyle) 1430 { 1431 case PathStyle_DOS: return "DOS"; 1432 case PathStyle_UNIX: return "UNIX"; 1433 case PathStyle_Unknown: return "Unknown"; 1434 default: break; 1435 } 1436 1437 return "<invalid>"; 1438 } 1439 1420 1440 GuestObject::GuestObject(void) 1421 1441 : mSession(NULL), … … 1690 1710 1691 1711 /** 1712 * Builds a (final) destination path from a given source + destination path. 1713 * 1714 * This does not utilize any file system access whatsoever. Used for guest and host paths. 1715 * 1716 * @returns VBox status code. 1717 * @param strSrcPath Source path to build destination path for. 1718 * @param enmSrcPathStyle Path style the source path is in. 1719 * @param strDstPath Destination path to use for building the (final) destination path. 1720 * @param enmDstPathStyle Path style the destination path is in. 1721 * 1722 * @note See rules within the function. 1723 */ 1724 /* static */ 1725 int GuestPath::BuildDestinationPath(const Utf8Str &strSrcPath, PathStyle_T enmSrcPathStyle, Utf8Str &strDstPath, PathStyle_T enmDstPathStyle) 1726 { 1727 /** 1728 * Rules: 1729 * 1730 * # source dest final dest remarks 1731 * 1732 * 1 /gst/dir1/ /dst/dir2/ /dst/dir2/<contents of dir1> Just copies contents of <contents>, not the directory itself. 1733 * 2 /gst/dir1 /dst/dir2/ /dst/dir2/dir1 Copies dir1 into dir2. 1734 * 3 /gst/dir1 /dst/dir2 /dst/dir2 Overwrites stuff from dir2 with stuff from dir1. 1735 */ 1736 const char *pszSrcName = RTPathFilenameEx(strSrcPath.c_str(), 1737 enmSrcPathStyle == PathStyle_DOS 1738 ? RTPATH_STR_F_STYLE_DOS : RTPATH_STR_F_STYLE_UNIX); 1739 1740 const char *pszDstName = RTPathFilenameEx(strDstPath.c_str(), 1741 enmDstPathStyle == PathStyle_DOS 1742 ? RTPATH_STR_F_STYLE_DOS : RTPATH_STR_F_STYLE_UNIX); 1743 1744 if ( (!pszSrcName && !pszDstName) /* #1 */ 1745 || ( pszSrcName && pszDstName)) /* #3 */ 1746 { 1747 /* Note: Must have DirectoryFlag_CopyIntoExisting + FileFlag_NoReplace *not* set. */ 1748 } 1749 else if (pszSrcName && !pszDstName) /* #2 */ 1750 { 1751 strDstPath += RTPATH_SLASH_STR; 1752 strDstPath += pszSrcName; 1753 } 1754 1755 return VINF_SUCCESS; 1756 } 1757 1758 /** 1692 1759 * Translates a path from a specific path style into another. 1693 1760 * … … 1710 1777 AssertReturn(RTStrIsValidEncoding(strPath.c_str()), VERR_INVALID_PARAMETER); 1711 1778 1712 #ifdef DEBUG1713 Utf8Str const strPathOrg = strPath; /* Make a backup so that we later can log stuff properly. */1714 #endif1715 1716 1779 int vrc = VINF_SUCCESS; 1717 1780 … … 1722 1785 || (fForce && enmDstPathStyle == PathStyle_UNIX)) 1723 1786 { 1724 strTranslated = RTPathChangeToUnixSlashes(strPath.mutableRaw(), true /* fForce */); 1787 strTranslated = strPath; 1788 RTPathChangeToUnixSlashes(strTranslated.mutableRaw(), true /* fForce */); 1725 1789 } 1726 1790 else if (enmDstPathStyle == PathStyle_DOS) … … 1729 1793 && fForce) 1730 1794 { 1731 strTranslated = RTPathChangeToDosSlashes(strPath.mutableRaw(), true /* fForce */); 1795 strTranslated = strPath; 1796 RTPathChangeToDosSlashes(strTranslated.mutableRaw(), true /* fForce */); 1732 1797 } 1733 1798 else if (enmSrcPathStyle == PathStyle_UNIX) … … 1778 1843 1779 1844 if (RT_FAILURE(vrc)) 1845 { 1846 LogRel2(("Guest Control: Translating path '%s' -> '%s' failed, vrc=%Rrc\n", strPath.c_str(), strTranslated.c_str(), vrc)); 1780 1847 return vrc; 1848 } 1781 1849 1782 1850 /* Cleanup. */ … … 1808 1876 strTranslated.jolt(); 1809 1877 1878 LogRel2(("Guest Control: Translating '%s' (%s) -> '%s' (%s)\n", 1879 strPath.c_str(), GuestBase::pathStyleToStr(enmSrcPathStyle), 1880 strTranslated.c_str(), GuestBase::pathStyleToStr(enmDstPathStyle), vrc)); 1881 1810 1882 if (RT_SUCCESS(vrc)) 1811 1883 strPath = strTranslated; 1812 1884 1813 #ifdef DEBUG1814 LogRel2(("Guest Control: Mapping '%s' -> '%s', vrc=%Rrc\n", strPathOrg.c_str(), strPath.c_str(), vrc));1815 #endif1816 1885 return vrc; 1817 1886 } -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r97305 r97395 887 887 * @return COM status, error set on failure 888 888 * @param strFlags String to extract flags from. 889 * @param fStrict Whether to set an error when an unknown / invalid flag is detected. 889 890 * @param pfFlags Where to store the extracted (and validated) flags. 890 891 */ 891 HRESULT GuestSession::i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, DirectoryCopyFlag_T *pfFlags)892 HRESULT GuestSession::i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, bool fStrict, DirectoryCopyFlag_T *pfFlags) 892 893 { 893 894 unsigned fFlags = DirectoryCopyFlag_None; … … 918 919 else if (MATCH_KEYWORD("FollowLinks")) 919 920 fFlags |= (unsigned)DirectoryCopyFlag_FollowLinks; 920 else 921 else if (fStrict) 921 922 return setError(E_INVALIDARG, tr("Invalid directory copy flag: %.*s"), (int)cchKeyword, pszNext); 922 923 #undef MATCH_KEYWORD … … 1458 1459 * @return COM status, error set on failure 1459 1460 * @param strFlags String to extract flags from. 1461 * @param fStrict Whether to set an error when an unknown / invalid flag is detected. 1460 1462 * @param pfFlags Where to store the extracted (and validated) flags. 1461 1463 */ 1462 HRESULT GuestSession::i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, FileCopyFlag_T *pfFlags)1464 HRESULT GuestSession::i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, bool fStrict, FileCopyFlag_T *pfFlags) 1463 1465 { 1464 1466 unsigned fFlags = (unsigned)FileCopyFlag_None; … … 1489 1491 else if (MATCH_KEYWORD("Update")) 1490 1492 fFlags |= (unsigned)FileCopyFlag_Update; 1491 else 1493 else if (fStrict) 1492 1494 return setError(E_INVALIDARG, tr("Invalid file copy flag: %.*s"), (int)cchKeyword, pszNext); 1493 1495 #undef MATCH_KEYWORD … … 3461 3463 3462 3464 GuestSessionFsSourceSpec source; 3463 source.strSource = aSource; 3464 source.enmType = FsObjType_File; 3465 source.enmPathStyle = i_getGuestPathStyle(); 3466 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3467 source.Type.File.fCopyFlags = (FileCopyFlag_T)fFlags; 3465 source.strSource = aSource; 3466 source.enmType = FsObjType_File; 3467 source.enmPathStyle = i_getGuestPathStyle(); 3468 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3469 source.fDirCopyFlags = DirectoryCopyFlag_None; 3470 source.fFileCopyFlags = (FileCopyFlag_T)fFlags; 3468 3471 3469 3472 SourceSet.push_back(source); … … 3489 3492 3490 3493 GuestSessionFsSourceSpec source; 3491 source.strSource = aSource; 3492 source.enmType = FsObjType_File; 3493 source.enmPathStyle = GuestSession::i_getHostPathStyle(); 3494 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3495 source.Type.File.fCopyFlags = (FileCopyFlag_T)fFlags; 3494 source.strSource = aSource; 3495 source.enmType = FsObjType_File; 3496 source.enmPathStyle = GuestSession::i_getHostPathStyle(); 3497 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3498 source.fDirCopyFlags = DirectoryCopyFlag_None; 3499 source.fFileCopyFlags = (FileCopyFlag_T)fFlags; 3496 3500 3497 3501 SourceSet.push_back(source); … … 3558 3562 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3559 3563 3560 HRESULT hrc; 3561 if (source.enmType == FsObjType_Directory) 3562 { 3563 hrc = GuestSession::i_directoryCopyFlagFromStr(strFlags, &source.Type.Dir.fCopyFlags); 3564 } 3565 else if (source.enmType == FsObjType_File) 3566 hrc = GuestSession::i_fileCopyFlagFromStr(strFlags, &source.Type.File.fCopyFlags); 3567 else 3568 return setError(E_INVALIDARG, tr("Source type %#x invalid / not supported"), source.enmType); 3569 if (FAILED(hrc)) 3570 return hrc; 3564 /* Check both flag groups here, as copying a directory also could mean to explicitly 3565 * *not* replacing any existing files (or just copy files which are newer, for instance). */ 3566 GuestSession::i_directoryCopyFlagFromStr(strFlags, false /* fStrict */, &source.fDirCopyFlags); 3567 GuestSession::i_fileCopyFlagFromStr(strFlags, false /* fStrict */, &source.fFileCopyFlags); 3571 3568 3572 3569 SourceSet.push_back(source); … … 3628 3625 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3629 3626 3630 HRESULT hrc; 3631 if (source.enmType == FsObjType_Directory) 3632 hrc = GuestSession::i_directoryCopyFlagFromStr(strFlags, &source.Type.Dir.fCopyFlags); 3633 else if (source.enmType == FsObjType_File) 3634 hrc = GuestSession::i_fileCopyFlagFromStr(strFlags, &source.Type.File.fCopyFlags); 3635 else 3636 return setError(E_INVALIDARG, tr("Source type %#x invalid / not supported"), source.enmType); 3637 if (FAILED(hrc)) 3638 return hrc; 3627 GuestSession::i_directoryCopyFlagFromStr(strFlags, false /* fStrict */, &source.fDirCopyFlags); 3628 GuestSession::i_fileCopyFlagFromStr(strFlags, false /* fStrict */, &source.fFileCopyFlags); 3639 3629 3640 3630 SourceSet.push_back(source); … … 3679 3669 3680 3670 GuestSessionFsSourceSpec source; 3681 source.strSource = aSource; 3682 source.enmType = FsObjType_Directory; 3683 source.enmPathStyle = i_getGuestPathStyle(); 3684 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3685 source.Type.Dir.fCopyFlags = (DirectoryCopyFlag_T)fFlags; 3671 source.strSource = aSource; 3672 source.enmType = FsObjType_Directory; 3673 source.enmPathStyle = i_getGuestPathStyle(); 3674 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3675 source.fDirCopyFlags = (DirectoryCopyFlag_T)fFlags; 3676 source.fFileCopyFlags = FileCopyFlag_None; /* Overwrite existing files. */ 3686 3677 3687 3678 SourceSet.push_back(source); … … 3708 3699 3709 3700 GuestSessionFsSourceSpec source; 3710 source.strSource = aSource; 3711 source.enmType = FsObjType_Directory; 3712 source.enmPathStyle = GuestSession::i_getHostPathStyle(); 3713 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3714 source.Type.Dir.fCopyFlags = (DirectoryCopyFlag_T)fFlags; 3701 source.strSource = aSource; 3702 source.enmType = FsObjType_Directory; 3703 source.enmPathStyle = GuestSession::i_getHostPathStyle(); 3704 source.fDryRun = false; /** @todo Implement support for a dry run. */ 3705 source.fDirCopyFlags = (DirectoryCopyFlag_T)fFlags; 3706 source.fFileCopyFlags = FileCopyFlag_None; /* Overwrite existing files. */ 3715 3707 3716 3708 SourceSet.push_back(source); -
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r97344 r97395 288 288 * VWRN_ALREADY_EXISTS if directory on the guest already exists but must not exist (\a fCanExist is \c false). 289 289 * @param strPath Absolute path to directory on the guest (guest style path) to create. 290 * @param fMode Directory mode to use for creation. 290 291 * @param enmDirectoryCreateFlags Directory creation flags. 291 * @param fMode Directory mode to use for creation.292 292 * @param fFollowSymlinks Whether to follow symlinks on the guest or not. 293 293 * @param fCanExist Whether the directory to create is allowed to exist already. 294 294 */ 295 295 int GuestSessionTask::directoryCreateOnGuest(const com::Utf8Str &strPath, 296 DirectoryCreateFlag_T enmDirectoryCreateFlags, uint32_t fMode,296 uint32_t fMode, DirectoryCreateFlag_T enmDirectoryCreateFlags, 297 297 bool fFollowSymlinks, bool fCanExist) 298 298 { … … 355 355 * @return VBox status code. VERR_ALREADY_EXISTS if directory on the guest already exists. 356 356 * @param strPath Absolute path to directory on the host (host style path) to create. 357 * @param fMode Directory mode to use for creation. 357 358 * @param fCreate Directory creation flags. 358 * @param fMode Directory mode to use for creation.359 359 * @param fCanExist Whether the directory to create is allowed to exist already. 360 360 */ 361 int GuestSessionTask::directoryCreateOnHost(const com::Utf8Str &strPath, uint32_t fCreate, uint32_t fMode, bool fCanExist) 362 { 363 LogFlowFunc(("strPath=%s, fCreate=0x%x, fMode=%RU32, fCanExist=%RTbool\n", strPath.c_str(), fCreate, fMode, fCanExist)); 361 int GuestSessionTask::directoryCreateOnHost(const com::Utf8Str &strPath, uint32_t fMode, uint32_t fCreate, bool fCanExist) 362 { 363 LogFlowFunc(("strPath=%s, fMode=%RU32, fCreate=0x%x, fCanExist=%RTbool\n", strPath.c_str(), fMode, fCreate, fCanExist)); 364 365 LogRel2(("Guest Control: Creating host directory '%s' ...\n", strPath.c_str())); 364 366 365 367 int vrc = RTDirCreate(strPath.c_str(), fMode, fCreate); … … 502 504 * Copies a file from the guest to the host. 503 505 * 504 * @return VBox status code. VINF_NO_CHANGE if file was skipped.505 506 * @param strSrc Full path of source file on the guest to copy. 506 507 * @param strDst Full destination path and file name (host style) to copy file to. … … 619 620 } 620 621 621 char *pszDstFile = NULL;622 623 622 if (RT_SUCCESS(vrc)) 624 623 { … … 627 626 if (fFileCopyFlags & FileCopyFlag_NoReplace) 628 627 { 629 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 630 Utf8StrFmt(tr("Host file \"%s\" already exists"), strDst.c_str())); 628 setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(tr("Host file \"%s\" already exists"), strDst.c_str())); 631 629 vrc = VERR_ALREADY_EXISTS; 632 630 } 633 else634 pszDstFile = RTStrDup(strDst.c_str());635 631 } 636 632 else if (RTFS_IS_DIRECTORY(dstObjInfo.Attr.fMode)) 637 633 { 638 /* Build the final file name with destination path (on the host). */ 639 char szDstPath[RTPATH_MAX]; 640 vrc = RTStrCopy(szDstPath, sizeof(szDstPath), strDst.c_str()); 641 if (RT_SUCCESS(vrc)) 642 { 643 vrc = RTPathAppend(szDstPath, sizeof(szDstPath), RTPathFilename(strSrc.c_str())); 644 if (RT_SUCCESS(vrc)) 645 pszDstFile = RTStrDup(szDstPath); 646 } 634 setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(tr("Host destination \"%s\" is a directory"), strDst.c_str())); 635 vrc = VERR_IS_A_DIRECTORY; 647 636 } 648 637 else if (RTFS_IS_SYMLINK(dstObjInfo.Attr.fMode)) … … 650 639 if (!(fFileCopyFlags & FileCopyFlag_FollowLinks)) 651 640 { 652 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 653 Utf8StrFmt(tr("Host file \"%s\" is a symbolic link"), 654 strDst.c_str())); 641 setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(tr("Host destination \"%s\" is a symbolic link"), strDst.c_str())); 655 642 vrc = VERR_IS_A_SYMLINK; 656 643 } 657 else658 pszDstFile = RTStrDup(strDst.c_str());659 644 } 660 645 else 661 646 { 662 LogFlowThisFunc(("Object type %RU32 not implemented yet\n", dstObjInfo.Attr.fMode)); 663 vrc = VERR_NOT_IMPLEMENTED; 664 } 665 } 666 else if (vrc == VERR_FILE_NOT_FOUND) 667 pszDstFile = RTStrDup(strDst.c_str()); 647 LogFlowThisFunc(("Host file system type %#x not supported\n", dstObjInfo.Attr.fMode & RTFS_TYPE_MASK)); 648 vrc = VERR_NOT_SUPPORTED; 649 } 650 } 651 652 LogRel2(("Guest Control: Copying file '%s' from guest to '%s' on host ...\n", strSrc.c_str(), strDst.c_str())); 653 654 LogFlowFunc(("vrc=%Rrc, dstFsType=%#x, pszDstFile=%s\n", vrc, dstObjInfo.Attr.fMode & RTFS_TYPE_MASK, strDst.c_str())); 668 655 669 656 if ( RT_SUCCESS(vrc) 670 657 || vrc == VERR_FILE_NOT_FOUND) 671 658 { 672 if (!pszDstFile) 673 { 674 setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(tr("No memory to allocate host file path"))); 675 vrc = VERR_NO_MEMORY; 659 660 RTFILE hDstFile; 661 vrc = RTFileOpen(&hDstFile, strDst.c_str(), 662 RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */ 663 if (RT_SUCCESS(vrc)) 664 { 665 LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", 666 strSrc.c_str(), strDst.c_str(), srcObjData.mObjectSize)); 667 668 vrc = fileCopyFromGuestInner(strSrc, srcFile, strDst, &hDstFile, fFileCopyFlags, 669 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize); 670 671 int vrc2 = RTFileClose(hDstFile); 672 AssertRC(vrc2); 676 673 } 677 674 else 678 { 679 RTFILE hDstFile; 680 vrc = RTFileOpen(&hDstFile, pszDstFile, 681 RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */ 682 if (RT_SUCCESS(vrc)) 683 { 684 LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", 685 strSrc.c_str(), pszDstFile, srcObjData.mObjectSize)); 686 687 vrc = fileCopyFromGuestInner(strSrc, srcFile, pszDstFile, &hDstFile, fFileCopyFlags, 688 0 /* Offset, unused */, (uint64_t)srcObjData.mObjectSize); 689 690 int vrc2 = RTFileClose(hDstFile); 691 AssertRC(vrc2); 692 } 693 else 694 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 695 Utf8StrFmt(tr("Opening/creating host file \"%s\" failed: %Rrc"), 696 pszDstFile, vrc)); 697 } 698 } 699 700 RTStrFree(pszDstFile); 675 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 676 Utf8StrFmt(tr("Opening/creating host file \"%s\" failed: %Rrc"), strDst.c_str(), vrc)); 677 } 701 678 702 679 int vrc2 = srcFile->i_closeFile(&vrcGuest); … … 819 796 * Copies a file from the guest to the host. 820 797 * 821 * @return VBox status code. VINF_NO_CHANGE if file was skipped.822 798 * @param strSrc Full path of source file on the host to copy. 823 799 * @param strDst Full destination path and file name (guest style) to copy file to. … … 828 804 LogFlowThisFunc(("strSource=%s, strDst=%s, fFileCopyFlags=0x%x\n", strSrc.c_str(), strDst.c_str(), fFileCopyFlags)); 829 805 830 Utf8Str strDstFinal = strDst;831 832 806 GuestFileOpenInfo dstOpenInfo; 833 dstOpenInfo.mFilename = strDst Final;807 dstOpenInfo.mFilename = strDst; 834 808 if (fFileCopyFlags & FileCopyFlag_NoReplace) 835 809 dstOpenInfo.mOpenAction = FileOpenAction_CreateNew; … … 877 851 { 878 852 GuestFsObjData dstObjData; 879 vrc = mSession->i_fileQueryInfo(strDst Final, RT_BOOL(fFileCopyFlags & FileCopyFlag_FollowLinks), dstObjData,853 vrc = mSession->i_fileQueryInfo(strDst, RT_BOOL(fFileCopyFlags & FileCopyFlag_FollowLinks), dstObjData, 880 854 &vrcGuest); 881 855 if (RT_SUCCESS(vrc)) … … 886 860 { 887 861 LogRel2(("Guest Control: Guest file \"%s\" has same or newer modification date, skipping", 888 strDst Final.c_str()));862 strDst.c_str())); 889 863 fSkip = true; 890 864 } … … 903 877 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 904 878 Utf8StrFmt(tr("Guest error while determining object data for guest file \"%s\": %Rrc"), 905 strDstFinal.c_str(), vrcGuest));879 strDst.c_str(), vrcGuest)); 906 880 break; 907 881 } … … 910 884 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 911 885 Utf8StrFmt(tr("Host error while determining object data for guest file \"%s\": %Rrc"), 912 strDst Final.c_str(), vrc));886 strDst.c_str(), vrc)); 913 887 } 914 888 } … … 932 906 if (RT_SUCCESS(vrc)) 933 907 { 908 LogRel2(("Guest Control: Copying file '%s' from host to '%s' on guest ...\n", strSrc.c_str(), strDst.c_str())); 909 934 910 RTVFSFILE hSrcFile; 935 911 vrc = RTVfsFileOpenNormal(szSrcReal, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, &hSrcFile); … … 937 913 { 938 914 LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", 939 szSrcReal, strDst Final.c_str(), srcObjInfo.cbObject));940 941 vrc = fileCopyToGuestInner(szSrcReal, hSrcFile, strDst Final, dstFile,915 szSrcReal, strDst.c_str(), srcObjInfo.cbObject)); 916 917 vrc = fileCopyToGuestInner(szSrcReal, hSrcFile, strDst, dstFile, 942 918 fFileCopyFlags, 0 /* Offset, unused */, srcObjInfo.cbObject); 943 919 … … 1003 979 { 1004 980 pEntry = new FsEntry(); 1005 pEntry->fMode = pcObjInfo->Attr.fMode & RTFS_TYPE_MASK;981 pEntry->fMode = pcObjInfo->Attr.fMode; 1006 982 pEntry->strPath = strFile; 1007 983 … … 1046 1022 * will be done directly when working on those. See @bugref{10139}. */ 1047 1023 1048 LogFlowFunc(("mSrcRootAbs=%s, mDstRootAbs=%s, f CopyFlags=%#x\n",1049 mSrcRootAbs.c_str(), mDstRootAbs.c_str(), mSourceSpec. Type.Dir.fCopyFlags));1024 LogFlowFunc(("mSrcRootAbs=%s, mDstRootAbs=%s, fDirCopyFlags=%#x, fFileCopyFlags=%#x\n", 1025 mSrcRootAbs.c_str(), mDstRootAbs.c_str(), mSourceSpec.fDirCopyFlags, mSourceSpec.fFileCopyFlags)); 1050 1026 1051 1027 return VINF_SUCCESS; … … 1072 1048 LogFlowFuncLeave(); 1073 1049 } 1050 1051 #ifdef DEBUG 1052 /** 1053 * Dumps a FsList to the debug log. 1054 */ 1055 void FsList::DumpToLog(void) 1056 { 1057 LogFlowFunc(("strSrcRootAbs=%s, strDstRootAbs=%s\n", mSrcRootAbs.c_str(), mDstRootAbs.c_str())); 1058 1059 FsEntries::iterator itEntry = mVecEntries.begin(); 1060 while (itEntry != mVecEntries.end()) 1061 { 1062 FsEntry *pEntry = *itEntry; 1063 LogFlowFunc(("\tstrPath=%s (fMode %#x)\n", pEntry->strPath.c_str(), pEntry->fMode)); 1064 ++itEntry; 1065 } 1066 1067 LogFlowFuncLeave(); 1068 } 1069 #endif /* DEBUG */ 1074 1070 1075 1071 /** … … 1162 1158 LogRel2(("Guest Control: Directory '%s'\n", strEntry.c_str())); 1163 1159 1164 if (!(mSourceSpec. Type.Dir.fCopyFlags & DirectoryCopyFlag_Recursive))1160 if (!(mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_Recursive)) 1165 1161 break; 1166 1162 … … 1171 1167 case FsObjType_Symlink: 1172 1168 { 1173 if (mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_FollowLinks) 1169 if ( mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_FollowLinks 1170 || mSourceSpec.fFileCopyFlags & FileCopyFlag_FollowLinks) 1174 1171 { 1175 1172 /** @todo Symlink handling from guest is not implemented yet. … … 1276 1273 LogRel2(("Guest Control: Directory '%s'\n", strEntry.c_str())); 1277 1274 1278 if (!(mSourceSpec. Type.Dir.fCopyFlags & DirectoryCopyFlag_Recursive))1275 if (!(mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_Recursive)) 1279 1276 break; 1280 1277 … … 1293 1290 case RTFS_TYPE_SYMLINK: 1294 1291 { 1295 if (mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_FollowLinks) 1292 Utf8Str strEntryAbs = strPathAbs + (const char *)pDirEntry->szName; 1293 1294 vrc = RTPathReal(strEntryAbs.c_str(), pszPathReal, cbPathReal); 1295 if (RT_SUCCESS(vrc)) 1296 1296 { 1297 Utf8Str strEntryAbs = strPathAbs + (const char *)pDirEntry->szName; 1298 1299 vrc = RTPathReal(strEntryAbs.c_str(), pszPathReal, cbPathReal); 1297 vrc = RTPathQueryInfo(pszPathReal, &objInfo, RTFSOBJATTRADD_NOTHING); 1300 1298 if (RT_SUCCESS(vrc)) 1301 1299 { 1302 vrc = RTPathQueryInfo(pszPathReal, &objInfo, RTFSOBJATTRADD_NOTHING); 1303 if (RT_SUCCESS(vrc)) 1300 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) 1304 1301 { 1305 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) 1306 { 1307 LogRel2(("Guest Control: Symbolic link '%s' -> '%s' (directory)\n", 1308 strEntryAbs.c_str(), pszPathReal)); 1302 LogRel2(("Guest Control: Symbolic link '%s' -> '%s' (directory)\n", 1303 strEntryAbs.c_str(), pszPathReal)); 1304 if (mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_FollowLinks) 1309 1305 vrc = AddDirFromHost(strPath, strEntry, pszPathReal, cbPathReal, pDirEntry); 1310 } 1311 else if (RTFS_IS_FILE(objInfo.Attr.fMode)) 1312 { 1313 LogRel2(("Guest Control: Symbolic link '%s' -> '%s' (file)\n", 1314 strEntryAbs.c_str(), pszPathReal)); 1306 } 1307 else if (RTFS_IS_FILE(objInfo.Attr.fMode)) 1308 { 1309 LogRel2(("Guest Control: Symbolic link '%s' -> '%s' (file)\n", 1310 strEntryAbs.c_str(), pszPathReal)); 1311 if (mSourceSpec.fFileCopyFlags & DirectoryCopyFlag_FollowLinks) 1315 1312 vrc = AddEntryFromHost(strEntry, &objInfo); 1316 }1317 else1318 vrc = VERR_NOT_SUPPORTED;1319 1313 } 1320 1321 if (RT_FAILURE(vrc)) 1322 LogRel2(("Guest Control: Unable to query symbolic link info for '%s', rc=%Rrc\n", 1323 pszPathReal, vrc)); 1314 else 1315 vrc = VERR_NOT_SUPPORTED; 1324 1316 } 1325 else 1326 { 1327 LogRel2(("Guest Control: Unable to resolve symlink for '%s', rc=%Rrc\n", strPathAbs.c_str(), vrc)); 1328 if (vrc == VERR_FILE_NOT_FOUND) /* Broken symlink, skip. */ 1329 vrc = VINF_SUCCESS; 1330 } 1317 1318 if (RT_FAILURE(vrc)) 1319 LogRel2(("Guest Control: Unable to query symbolic link info for '%s', rc=%Rrc\n", 1320 pszPathReal, vrc)); 1331 1321 } 1332 1322 else 1333 LogRel2(("Guest Control: Symbolic link '%s' (skipped)\n", strEntry.c_str())); 1323 { 1324 LogRel2(("Guest Control: Unable to resolve symlink for '%s', rc=%Rrc\n", strPathAbs.c_str(), vrc)); 1325 if (vrc == VERR_FILE_NOT_FOUND) /* Broken symlink, skip. */ 1326 vrc = VINF_SUCCESS; 1327 } 1334 1328 break; 1335 1329 } … … 1475 1469 if (itSrc->enmType == FsObjType_Directory) 1476 1470 { 1477 /* If the source does not end with a slash, copy over the entire directory 1478 * (and not just its contents). */ 1479 if (!strSrc.endsWith(mstrGuestPathStyle)) 1480 { 1481 if (!RTPATH_IS_SLASH(strDst[strDst.length() - 1])) 1482 strDst += RTPATH_SLASH_STR; 1483 1484 strDst += Utf8Str(RTPathFilename(strSrc.c_str())); 1485 } 1486 1487 fFollowSymlinks = itSrc->Type.Dir.fCopyFlags & DirectoryCopyFlag_FollowLinks; 1471 fFollowSymlinks = itSrc->fDirCopyFlags & DirectoryCopyFlag_FollowLinks; 1488 1472 } 1489 1473 else 1490 1474 { 1491 fFollowSymlinks = RT_BOOL(itSrc->Type.File.fCopyFlags & FileCopyFlag_FollowLinks); 1492 } 1493 1494 LogFlowFunc(("strSrc=%s, strDst=%s, fFollowSymlinks=%RTbool\n", strSrc.c_str(), strDst.c_str(), fFollowSymlinks)); 1475 fFollowSymlinks = RT_BOOL(itSrc->fFileCopyFlags & FileCopyFlag_FollowLinks); 1476 } 1477 1478 LogFlowFunc(("strSrc=%s (path style is %s), strDst=%s, fFollowSymlinks=%RTbool\n", 1479 strSrc.c_str(), GuestBase::pathStyleToStr(itSrc->enmPathStyle), strDst.c_str(), fFollowSymlinks)); 1495 1480 1496 1481 GuestFsObjData srcObjData; … … 1500 1485 { 1501 1486 if (vrc == VERR_GSTCTL_GUEST_ERROR) 1502 strErrorInfo = GuestBase::getErrorAsString(tr("Guest file lookup failed"),1487 strErrorInfo = GuestBase::getErrorAsString(tr("Guest source lookup failed"), 1503 1488 GuestErrorInfo(GuestErrorInfo::Type_ToolStat, vrcGuest, strSrc.c_str())); 1504 1489 else 1505 strErrorInfo.printf(tr("Guest file lookup for \"%s\" failed: %Rrc"),1490 strErrorInfo.printf(tr("Guest source lookup for \"%s\" failed: %Rrc"), 1506 1491 strSrc.c_str(), vrc); 1507 1492 break; … … 1534 1519 if (RT_SUCCESS(vrc)) 1535 1520 { 1536 if (itSrc->enmType == FsObjType_Directory) 1537 vrc = pFsList->AddDirFromGuest(strSrc); 1538 else 1539 vrc = pFsList->AddEntryFromGuest(RTPathFilename(strSrc.c_str()), srcObjData); 1521 switch (itSrc->enmType) 1522 { 1523 case FsObjType_Directory: 1524 { 1525 vrc = pFsList->AddDirFromGuest(strSrc); 1526 break; 1527 } 1528 1529 case FsObjType_File: 1530 /* The file name is already part of the actual list's source root (strSrc). */ 1531 break; 1532 1533 default: 1534 LogRel2(("Guest Control: Warning: Unknown guest file system type %#x for source \"%s\", skipping\n", 1535 itSrc->enmType, strSrc.c_str())); 1536 break; 1537 } 1540 1538 } 1541 1539 … … 1547 1545 break; 1548 1546 } 1549 1547 #ifdef DEBUG 1548 pFsList->DumpToLog(); 1549 #endif 1550 1550 mVecLists.push_back(pFsList); 1551 1551 } … … 1608 1608 Utf8Str strDstRootAbs = pList->mDstRootAbs; 1609 1609 1610 const bool fCopyIntoExisting = pList->mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting; 1611 const bool fFollowSymlinks = true; /** @todo */ 1612 const uint32_t fDirMode = 0700; /** @todo Play safe by default; implement ACLs. */ 1613 uint32_t fDirCreate = 0; 1614 1615 if (!fFollowSymlinks) 1616 fDirCreate |= RTDIRCREATE_FLAGS_NO_SYMLINKS; 1610 GuestPath::BuildDestinationPath(strSrcRootAbs, mSession->i_getGuestPathStyle(), 1611 strDstRootAbs, PATH_STYLE_NATIVE); 1612 1613 bool fCopyIntoExisting; 1614 bool fFollowSymlinks; 1615 1616 if (pList->mSourceSpec.enmType == FsObjType_Directory) 1617 { 1618 fCopyIntoExisting = RT_BOOL(pList->mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_CopyIntoExisting); 1619 fFollowSymlinks = RT_BOOL(pList->mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_FollowLinks); 1620 } 1621 else if (pList->mSourceSpec.enmType == FsObjType_File) 1622 { 1623 fCopyIntoExisting = !RT_BOOL(pList->mSourceSpec.fFileCopyFlags & FileCopyFlag_NoReplace); 1624 fFollowSymlinks = RT_BOOL(pList->mSourceSpec.fFileCopyFlags & FileCopyFlag_FollowLinks); 1625 } 1626 else 1627 AssertFailedBreakStmt(vrc = VERR_NOT_IMPLEMENTED); 1628 1629 uint32_t const fDirMode = 0700; /** @todo Play safe by default; implement ACLs. */ 1630 uint32_t fDirCreate = 0; 1631 1632 bool fDstExists = true; 1617 1633 1618 1634 RTFSOBJINFO ObjInfo; 1619 1635 RT_ZERO(ObjInfo); 1620 vrc = RTPathQueryInfo(strDstRootAbs.c_str(), &ObjInfo, RTFSOBJATTRADD_NOTHING); 1621 if ( RT_FAILURE(vrc) 1622 && vrc != VERR_FILE_NOT_FOUND 1623 && vrc != VERR_PATH_NOT_FOUND) 1624 { 1625 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1626 Utf8StrFmt(tr("Host path lookup for \"%s\" failed: %Rrc"), strDstRootAbs.c_str(), vrc)); 1627 break; 1628 } 1629 else 1630 vrc = VINF_SUCCESS; /* Reset rc. */ 1631 1632 bool const fDstIsDir = RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode); 1633 bool const fDstDirMustExist = strDstRootAbs.endsWith(PATH_STYLE_SEP_STR(PATH_STYLE_NATIVE)); /* Copy into existing dir? */ 1634 1635 /* Copy source(s) into an existing directory on the host (path ends with a slash)? */ 1636 if (fDstDirMustExist) 1637 { 1638 if ( !RTDirExists(strDstRootAbs.c_str()) 1639 || !fDstIsDir) 1636 vrc = RTPathQueryInfoEx(strDstRootAbs.c_str(), &ObjInfo, RTFSOBJATTRADD_NOTHING, 1637 fFollowSymlinks ? RTPATH_F_FOLLOW_LINK : RTPATH_F_ON_LINK /* fFlags */); 1638 if (RT_FAILURE(vrc)) 1639 { 1640 if ( vrc == VERR_FILE_NOT_FOUND 1641 || vrc == VERR_PATH_NOT_FOUND) 1642 { 1643 fDstExists = false; 1644 vrc = VINF_SUCCESS; 1645 } 1646 else 1640 1647 { 1641 1648 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1642 Utf8StrFmt(tr("Host directory \"%s\" does not exist"), strDstRootAbs.c_str())); 1643 vrc = VERR_PATH_NOT_FOUND; 1649 Utf8StrFmt(tr("Host path lookup for \"%s\" failed: %Rrc"), strDstRootAbs.c_str(), vrc)); 1644 1650 break; 1645 1651 } 1646 1652 } 1647 /* else Copy source(s) into a file on the host. */ 1648 1649 /* Create the destination directory if required. */ 1650 if ( pList->mSourceSpec.enmType == FsObjType_Directory 1651 && pList->mSourceSpec.fDryRun == false) 1652 { 1653 vrc = directoryCreateOnHost(strDstRootAbs, fDirCreate, fDirMode, fCopyIntoExisting); 1653 1654 /* Create the root directory. */ 1655 if (pList->mSourceSpec.enmType == FsObjType_Directory) 1656 { 1657 LogFlowFunc(("Directory: fDirCopyFlags=%#x, fCopyIntoExisting=%RTbool, fFollowSymlinks=%RTbool\n", 1658 pList->mSourceSpec.fDirCopyFlags, fCopyIntoExisting, fFollowSymlinks)); 1659 1660 if (fDstExists) 1661 { 1662 switch (ObjInfo.Attr.fMode & RTFS_TYPE_MASK) 1663 { 1664 case RTFS_TYPE_DIRECTORY: 1665 { 1666 if (!fCopyIntoExisting) 1667 { 1668 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1669 Utf8StrFmt(tr("Host root directory \"%s\" already exists"), strDstRootAbs.c_str())); 1670 vrc = VERR_ALREADY_EXISTS; 1671 break; 1672 } 1673 break; 1674 } 1675 1676 case RTFS_TYPE_FILE: 1677 { 1678 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1679 Utf8StrFmt(tr("Destination \"%s\" on the host already exists and is a file"), strDstRootAbs.c_str())); 1680 vrc = VERR_IS_A_FILE; 1681 break; 1682 } 1683 1684 default: 1685 { 1686 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1687 Utf8StrFmt(tr("Unknown object type (%#x) on host for \"%s\""), 1688 ObjInfo.Attr.fMode & RTFS_TYPE_MASK, strDstRootAbs.c_str())); 1689 vrc = VERR_NOT_SUPPORTED; 1690 break; 1691 } 1692 } 1693 } 1694 1654 1695 if (RT_FAILURE(vrc)) 1655 1696 break; 1656 } 1657 1658 FsEntries::const_iterator itEntry = pList->mVecEntries.begin(); 1659 while (itEntry != pList->mVecEntries.end()) 1660 { 1661 FsEntry *pEntry = *itEntry; 1662 AssertPtr(pEntry); 1663 1664 Utf8Str strSrcAbs = strSrcRootAbs; 1665 Utf8Str strDstAbs = strDstRootAbs; 1666 1667 if (pList->mSourceSpec.enmType == FsObjType_Directory) 1668 { 1697 1698 /* Clean up the final host destination root path (for cleaning up mixed path separators). */ 1699 vrc = GuestPath::Translate(strDstRootAbs, 1700 PATH_STYLE_NATIVE /* Source */, PATH_STYLE_NATIVE /* Dest */, true /* fForce */); 1701 if (RT_FAILURE(vrc)) 1702 { 1703 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1704 Utf8StrFmt(tr("Translating host destination root path '%s' failed: %Rrc"), 1705 strDstRootAbs.c_str(), vrc)); 1706 break; 1707 } 1708 1709 /* Make sure the destination root directory exists. */ 1710 if (pList->mSourceSpec.fDryRun == false) 1711 { 1712 vrc = directoryCreateOnHost(strDstRootAbs, fDirMode, 0 /* fCreate */, true /* fCanExist */); 1713 if (RT_FAILURE(vrc)) 1714 break; 1715 } 1716 1717 AssertBreakStmt(pList->mSourceSpec.enmType == FsObjType_Directory, vrc = VERR_NOT_SUPPORTED); 1718 1719 /* Walk the entries. */ 1720 FsEntries::const_iterator itEntry = pList->mVecEntries.begin(); 1721 while (itEntry != pList->mVecEntries.end()) 1722 { 1723 FsEntry *pEntry = *itEntry; 1724 AssertPtr(pEntry); 1725 1726 Utf8Str strSrcAbs = strSrcRootAbs; 1727 Utf8Str strDstAbs = strDstRootAbs; 1728 1669 1729 strSrcAbs += PATH_STYLE_SEP_STR(pList->mSourceSpec.enmPathStyle); 1670 1730 strSrcAbs += pEntry->strPath; 1671 } 1672 1673 if (fDstIsDir) 1674 { 1731 1675 1732 strDstAbs += PATH_STYLE_SEP_STR(PATH_STYLE_NATIVE); 1676 1733 strDstAbs += pEntry->strPath; 1677 } 1678 1679 /* Translate the final guest source path (for cleaning up mixed path separators). */ 1680 vrc = GuestPath::Translate(strSrcAbs, pList->mSourceSpec.enmPathStyle /* Source */, pList->mSourceSpec.enmPathStyle /* Dest */, 1681 true /* fForce */); 1682 if (RT_FAILURE(vrc)) 1683 break; 1684 1685 /* Translate the final host destination path (for cleaning up mixed path separators). */ 1686 vrc = GuestPath::Translate(strDstAbs, PATH_STYLE_NATIVE, PATH_STYLE_NATIVE /* Dest */, true /* fForce */); 1687 if (RT_FAILURE(vrc)) 1688 break; 1689 1690 mProgress->SetNextOperation(Bstr(strSrcAbs).raw(), 1); 1691 1692 LogRel2(("Guest Control: Copying '%s' from guest to '%s' on host ...\n", strSrcAbs.c_str(), strDstAbs.c_str())); 1693 1694 switch (pEntry->fMode & RTFS_TYPE_MASK) 1695 { 1696 case RTFS_TYPE_DIRECTORY: 1697 LogRel2(("Guest Control: Copying directory '%s' from guest to '%s' on host ...\n", strSrcAbs.c_str(), strDstAbs.c_str())); 1698 if (!pList->mSourceSpec.fDryRun) 1699 vrc = directoryCreateOnHost(strDstAbs, fDirCreate, fDirMode, fCopyIntoExisting); 1734 1735 /* Clean up the final guest source path (for cleaning up mixed path separators). */ 1736 vrc = GuestPath::Translate(strSrcAbs, pList->mSourceSpec.enmPathStyle /* Source */, pList->mSourceSpec.enmPathStyle /* Dest */, 1737 true /* fForce */); 1738 if (RT_FAILURE(vrc)) 1739 { 1740 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1741 Utf8StrFmt(tr("Translating guest source path '%s' from %s to %s failed: %Rrc"), 1742 strSrcAbs.c_str(), 1743 GuestBase::pathStyleToStr(pList->mSourceSpec.enmPathStyle), 1744 GuestBase::pathStyleToStr(pList->mSourceSpec.enmPathStyle), vrc)); 1700 1745 break; 1701 1702 case RTFS_TYPE_FILE: 1703 RT_FALL_THROUGH(); 1704 case RTFS_TYPE_SYMLINK: 1705 LogRel2(("Guest Control: Copying %s '%s' from guest to '%s' on host ...\n", 1706 (pEntry->fMode & RTFS_TYPE_MASK) == RTFS_TYPE_SYMLINK ? "symlink" : "file", strSrcAbs.c_str(), strDstAbs.c_str())); 1707 if (!pList->mSourceSpec.fDryRun) 1708 vrc = fileCopyFromGuest(strSrcAbs, strDstAbs, FileCopyFlag_None); 1746 } 1747 1748 /* Translate the final host destination path. */ 1749 vrc = GuestPath::Translate(strDstAbs, pList->mSourceSpec.enmPathStyle, PATH_STYLE_NATIVE /* Source */, true /* fForce */); 1750 if (RT_FAILURE(vrc)) 1751 { 1752 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1753 Utf8StrFmt(tr("Translating host destination path '%s' from %s to %s failed: %Rrc"), 1754 strDstAbs.c_str(), 1755 GuestBase::pathStyleToStr(pList->mSourceSpec.enmPathStyle), 1756 GuestBase::pathStyleToStr(PATH_STYLE_NATIVE), vrc)); 1709 1757 break; 1710 1711 default: 1712 LogFlowFunc(("Warning: Type %d for '%s' is not supported\n", 1713 pEntry->fMode & RTFS_TYPE_MASK, strSrcAbs.c_str())); 1758 } 1759 1760 mProgress->SetNextOperation(Bstr(strSrcAbs).raw(), 1); 1761 1762 switch (pEntry->fMode & RTFS_TYPE_MASK) 1763 { 1764 case RTFS_TYPE_DIRECTORY: 1765 if (!pList->mSourceSpec.fDryRun) 1766 vrc = directoryCreateOnHost(strDstAbs, fDirMode, fDirCreate, fCopyIntoExisting); 1767 break; 1768 1769 case RTFS_TYPE_FILE: 1770 RT_FALL_THROUGH(); 1771 case RTFS_TYPE_SYMLINK: 1772 if (!pList->mSourceSpec.fDryRun) 1773 vrc = fileCopyFromGuest(strSrcAbs, strDstAbs, pList->mSourceSpec.fFileCopyFlags); 1774 break; 1775 1776 default: 1777 AssertFailed(); /* Should never happen (we already have a filtered list). */ 1778 break; 1779 } 1780 1781 if (RT_FAILURE(vrc)) 1714 1782 break; 1715 } 1716 1717 if (RT_FAILURE(vrc)) 1718 break; 1719 1720 ++itEntry; 1721 } 1783 1784 ++itEntry; 1785 } 1786 } 1787 else if (pList->mSourceSpec.enmType == FsObjType_File) 1788 { 1789 LogFlowFunc(("File: fFileCopyFlags=%#x, fCopyIntoExisting=%RTbool, fFollowSymlinks=%RTbool\n", 1790 pList->mSourceSpec.fFileCopyFlags, fCopyIntoExisting, fFollowSymlinks)); 1791 1792 if (fDstExists) 1793 { 1794 switch (ObjInfo.Attr.fMode & RTFS_TYPE_MASK) 1795 { 1796 case RTFS_TYPE_DIRECTORY: 1797 { 1798 if (!fCopyIntoExisting) 1799 { 1800 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1801 Utf8StrFmt(tr("Destination \"%s\" on the host already exists and is a directory"), 1802 strDstRootAbs.c_str())); 1803 vrc = VERR_IS_A_DIRECTORY; 1804 break; 1805 } 1806 break; 1807 } 1808 1809 case RTFS_TYPE_FILE: 1810 { 1811 if (!fCopyIntoExisting) 1812 { 1813 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1814 Utf8StrFmt(tr("Host file \"%s\" already exists"), strDstRootAbs.c_str())); 1815 vrc = VERR_ALREADY_EXISTS; 1816 } 1817 break; 1818 } 1819 1820 default: 1821 { 1822 /** @ŧodo Resolve symlinks? */ 1823 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1824 Utf8StrFmt(tr("Unknown object type (%#x) on host for \"%s\""), 1825 ObjInfo.Attr.fMode & RTFS_TYPE_MASK, strDstRootAbs.c_str())); 1826 vrc = VERR_NOT_SUPPORTED; 1827 break; 1828 } 1829 } 1830 } 1831 1832 if (!pList->mSourceSpec.fDryRun) 1833 vrc = fileCopyFromGuest(strSrcRootAbs, strDstRootAbs, pList->mSourceSpec.fFileCopyFlags); 1834 } 1835 else 1836 AssertFailedStmt(vrc = VERR_NOT_SUPPORTED); 1722 1837 1723 1838 if (RT_FAILURE(vrc)) … … 1793 1908 Utf8Str strDst = mDest; 1794 1909 1795 LogFlowFunc(("strSrc=%s, strDst=%s\n", strSrc.c_str(), strDst.c_str()));1910 bool fFollowSymlinks; 1796 1911 1797 1912 if (strSrc.isEmpty()) … … 1802 1917 } 1803 1918 1919 if (itSrc->enmType == FsObjType_Directory) 1920 { 1921 fFollowSymlinks = itSrc->fDirCopyFlags & DirectoryCopyFlag_FollowLinks; 1922 } 1923 else 1924 { 1925 fFollowSymlinks = RT_BOOL(itSrc->fFileCopyFlags & FileCopyFlag_FollowLinks); 1926 } 1927 1928 LogFlowFunc(("strSrc=%s (path style is %s), strDst=%s\n", 1929 strSrc.c_str(), GuestBase::pathStyleToStr(itSrc->enmPathStyle), strDst.c_str())); 1930 1804 1931 RTFSOBJINFO srcFsObjInfo; 1805 vrc = RTPathQueryInfo(strSrc.c_str(), &srcFsObjInfo, RTFSOBJATTRADD_NOTHING); 1932 vrc = RTPathQueryInfoEx(strSrc.c_str(), &srcFsObjInfo, RTFSOBJATTRADD_NOTHING, 1933 fFollowSymlinks ? RTPATH_F_FOLLOW_LINK : RTPATH_F_ON_LINK /* fFlags */); 1806 1934 if (RT_FAILURE(vrc)) 1807 1935 { … … 1836 1964 if (RT_SUCCESS(vrc)) 1837 1965 { 1838 if (itSrc->enmType == FsObjType_Directory)1966 switch (itSrc->enmType) 1839 1967 { 1840 char szPathReal[RTPATH_MAX]; 1841 RTDIRENTRYEX DirEntry; 1842 vrc = pFsList->AddDirFromHost(strSrc /* strPath */, "" /* strSubDir */, 1843 szPathReal, sizeof(szPathReal), &DirEntry); 1968 case FsObjType_Directory: 1969 { 1970 char szPathReal[RTPATH_MAX]; 1971 RTDIRENTRYEX DirEntry; 1972 vrc = pFsList->AddDirFromHost(strSrc /* strPath */, "" /* strSubDir */, 1973 szPathReal, sizeof(szPathReal), &DirEntry); 1974 } 1975 1976 case FsObjType_File: 1977 /* The file name is already part of the actual list's source root (strSrc). */ 1978 break; 1979 1980 default: 1981 LogRel2(("Guest Control: Warning: Unknown guest host system type %#x for source \"%s\", skipping\n", 1982 itSrc->enmType, strSrc.c_str())); 1983 break; 1844 1984 } 1845 else1846 vrc = pFsList->AddEntryFromHost(RTPathFilename(strSrc.c_str()), &srcFsObjInfo);1847 1985 } 1848 1986 … … 1854 1992 break; 1855 1993 } 1856 1994 #ifdef DEBUG 1995 pFsList->DumpToLog(); 1996 #endif 1857 1997 mVecLists.push_back(pFsList); 1858 1998 } … … 1915 2055 Utf8Str strDstRootAbs = pList->mDstRootAbs; 1916 2056 1917 /* Translate the destination path from the host to a path compatible with the guest. */ 1918 vrc = GuestPath::Translate(strDstRootAbs, PATH_STYLE_NATIVE /* Source */, mSession->i_getGuestPathStyle() /* Dest */); 2057 GuestPath::BuildDestinationPath(strSrcRootAbs, PATH_STYLE_NATIVE, 2058 strDstRootAbs, mSession->i_getGuestPathStyle()); 2059 2060 /* Translate the destination path from the host to a path compatible with the guest. 2061 * strDstRootAbs already is in the destination path style, so just do a path cleanup. */ 2062 vrc = GuestPath::Translate(strDstRootAbs, 2063 mSession->i_getGuestPathStyle() /* Source */, mSession->i_getGuestPathStyle() /* Dest */, 2064 true /* fForce */); 1919 2065 if (RT_FAILURE(vrc)) 2066 { 2067 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2068 Utf8StrFmt(tr("Translating guest destination path '%s' from %s to %s failed: %Rrc"), 2069 strDstRootAbs.c_str(), 2070 GuestBase::pathStyleToStr(PATH_STYLE_NATIVE), 2071 GuestBase::pathStyleToStr(mSession->i_getGuestPathStyle()), vrc)); 1920 2072 break; 1921 1922 bool fCopyIntoExisting = false; 1923 bool fFollowSymlinks = false; 1924 uint32_t fDirMode = 0700; /** @todo Play safe by default; implement ACLs. */ 2073 } 2074 2075 bool fCopyIntoExisting; 2076 bool fFollowSymlinks; 2077 2078 if (pList->mSourceSpec.enmType == FsObjType_Directory) 2079 { 2080 fCopyIntoExisting = RT_BOOL(pList->mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_CopyIntoExisting); 2081 fFollowSymlinks = RT_BOOL(pList->mSourceSpec.fDirCopyFlags & DirectoryCopyFlag_FollowLinks); 2082 } 2083 else if (pList->mSourceSpec.enmType == FsObjType_File) 2084 { 2085 fCopyIntoExisting = !RT_BOOL(pList->mSourceSpec.fFileCopyFlags & FileCopyFlag_NoReplace); 2086 fFollowSymlinks = RT_BOOL(pList->mSourceSpec.fFileCopyFlags & FileCopyFlag_FollowLinks); 2087 } 2088 else 2089 AssertFailedBreakStmt(vrc = VERR_NOT_IMPLEMENTED); 2090 2091 uint32_t const fDirMode = 0700; /** @todo Play safe by default; implement ACLs. */ 2092 2093 bool fDstExists = true; 1925 2094 1926 2095 GuestFsObjData dstObjData; 1927 2096 int vrcGuest; 1928 vrc = mSession->i_fsQueryInfo(strDstRootAbs, pList->mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_FollowLinks, 1929 dstObjData, &vrcGuest); 2097 vrc = mSession->i_fsQueryInfo(strDstRootAbs, fFollowSymlinks, dstObjData, &vrcGuest); 1930 2098 if (RT_FAILURE(vrc)) 1931 2099 { … … 1937 2105 RT_FALL_THROUGH(); 1938 2106 case VERR_FILE_NOT_FOUND: 1939 /* We will deal with this down below. */ 1940 vrc = VINF_SUCCESS; 2107 { 2108 fDstExists = false; 2109 vrc = VINF_SUCCESS; 1941 2110 break; 2111 } 1942 2112 default: 1943 2113 setProgressErrorMsg(VBOX_E_IPRT_ERROR, … … 1956 2126 } 1957 2127 1958 LogFlowFunc(("List inital: rc=%Rrc, srcRootAbs=%s, dstRootAbs=%s\n",1959 vrc, strSrcRootAbs.c_str(), strDstRootAbs.c_str()));1960 1961 /* Calculated file copy flags for the current source spec. */1962 FileCopyFlag_T fFileCopyFlags = FileCopyFlag_None;1963 1964 /* Create the root directory. */1965 2128 if (pList->mSourceSpec.enmType == FsObjType_Directory) 1966 2129 { 1967 fCopyIntoExisting = RT_BOOL(pList->mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting);1968 fFollowSymlinks = RT_BOOL(pList->mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_FollowLinks);1969 1970 2130 LogFlowFunc(("Directory: fDirCopyFlags=%#x, fCopyIntoExisting=%RTbool, fFollowSymlinks=%RTbool\n", 1971 pList->mSourceSpec.Type.Dir.fCopyFlags, fCopyIntoExisting, fFollowSymlinks)); 1972 1973 /* If the directory on the guest already exists, append the name of the root source directory to it. */ 1974 switch (dstObjData.mType) 1975 { 1976 case FsObjType_Directory: 1977 { 1978 if (fCopyIntoExisting) 2131 pList->mSourceSpec.fDirCopyFlags, fCopyIntoExisting, fFollowSymlinks)); 2132 2133 if (fDstExists) 2134 { 2135 switch (dstObjData.mType) 2136 { 2137 case FsObjType_Directory: 1979 2138 { 1980 /* Build the destination path on the guest. */ 1981 strDstRootAbs += PATH_STYLE_SEP_STR(mSession->i_getGuestPathStyle()) + Utf8Str(RTPathFilename(strSrcRootAbs.c_str())); 2139 if (!fCopyIntoExisting) 2140 { 2141 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2142 Utf8StrFmt(tr("Guest root directory \"%s\" already exists"), 2143 strDstRootAbs.c_str())); 2144 vrc = VERR_ALREADY_EXISTS; 2145 } 2146 break; 1982 2147 } 1983 else 2148 2149 case FsObjType_File: 1984 2150 { 1985 2151 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 1986 Utf8StrFmt(tr(" Guest directory \"%s\" already exists"),2152 Utf8StrFmt(tr("Destination \"%s\" on guest already exists and is a file"), 1987 2153 strDstRootAbs.c_str())); 1988 vrc = VERR_ ALREADY_EXISTS;2154 vrc = VERR_IS_A_FILE; 1989 2155 } 2156 2157 case FsObjType_Symlink: 2158 /** @ŧodo Resolve symlinks? */ 2159 break; 2160 2161 default: 2162 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2163 Utf8StrFmt(tr("Unknown object type (%#x) on guest for \"%s\""), 2164 dstObjData.mType, strDstRootAbs.c_str())); 2165 vrc = VERR_NOT_SUPPORTED; 2166 break; 2167 } 2168 } 2169 2170 if (RT_FAILURE(vrc)) 2171 break; 2172 2173 /* Clean up the final guest destination root path (for cleaning up mixed path separators). */ 2174 vrc = GuestPath::Translate(strDstRootAbs, 2175 mSession->i_getGuestPathStyle() /* Source */, mSession->i_getGuestPathStyle() /* Dest */, 2176 true /* fForce */); 2177 if (RT_FAILURE(vrc)) 2178 { 2179 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2180 Utf8StrFmt(tr("Translating guest destination root path '%s' failed: %Rrc"), 2181 strDstRootAbs.c_str(), vrc)); 2182 break; 2183 } 2184 2185 /* Make sure the destination root directory exists. */ 2186 if (pList->mSourceSpec.fDryRun == false) 2187 { 2188 vrc = directoryCreateOnGuest(strDstRootAbs, fDirMode, DirectoryCreateFlag_None, 2189 fFollowSymlinks, fCopyIntoExisting); 2190 if (RT_FAILURE(vrc)) 1990 2191 break; 1991 } 1992 1993 case FsObjType_File: 1994 RT_FALL_THROUGH(); 1995 case FsObjType_Symlink: 1996 /* Nothing to do. */ 2192 } 2193 2194 /* Walk the entries. */ 2195 FsEntries::const_iterator itEntry = pList->mVecEntries.begin(); 2196 while ( RT_SUCCESS(vrc) 2197 && itEntry != pList->mVecEntries.end()) 2198 { 2199 FsEntry *pEntry = *itEntry; 2200 AssertPtr(pEntry); 2201 2202 Utf8Str strSrcAbs = strSrcRootAbs; 2203 Utf8Str strDstAbs = strDstRootAbs; 2204 2205 strSrcAbs += PATH_STYLE_SEP_STR(PATH_STYLE_NATIVE); 2206 strSrcAbs += pEntry->strPath; 2207 2208 strDstAbs += PATH_STYLE_SEP_STR(mSession->i_getGuestPathStyle()); 2209 strDstAbs += pEntry->strPath; 2210 2211 /* Clean up the final host source path (for cleaning up mixed path separators). */ 2212 vrc = GuestPath::Translate(strSrcAbs, 2213 PATH_STYLE_NATIVE /* Source */, PATH_STYLE_NATIVE /* Dest */, 2214 true /* fForce */); 2215 if (RT_FAILURE(vrc)) 2216 { 2217 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2218 Utf8StrFmt(tr("Translating host source path '%s' from %s to %s failed: %Rrc"), 2219 strSrcAbs.c_str(), 2220 GuestBase::pathStyleToStr(PATH_STYLE_NATIVE), 2221 GuestBase::pathStyleToStr(PATH_STYLE_NATIVE), vrc)); 1997 2222 break; 1998 1999 default: 2223 } 2224 2225 /* Translate the final guest destination path. */ 2226 vrc = GuestPath::Translate(strDstAbs, 2227 mSession->i_getGuestPathStyle() /* Source */, mSession->i_getGuestPathStyle() /* Dest */, 2228 true /* fForce */); 2229 if (RT_FAILURE(vrc)) 2230 { 2000 2231 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2001 Utf8StrFmt(tr("Unknown object type (%#x) on guest for \"%s\""), 2002 dstObjData.mType, strDstRootAbs.c_str())); 2003 vrc = VERR_NOT_SUPPORTED; 2232 Utf8StrFmt(tr("Translating guest destination path '%s' from %s to %s failed: %Rrc"), 2233 strDstAbs.c_str(), 2234 GuestBase::pathStyleToStr(PATH_STYLE_NATIVE), 2235 GuestBase::pathStyleToStr(mSession->i_getGuestPathStyle()), vrc)); 2004 2236 break; 2005 } 2006 2007 /* Make sure the destination root directory exists. */ 2008 if ( RT_SUCCESS(vrc) 2009 && pList->mSourceSpec.fDryRun == false) 2010 { 2011 vrc = directoryCreateOnGuest(strDstRootAbs, DirectoryCreateFlag_None, fDirMode, 2012 fFollowSymlinks, true /* fCanExist */); 2013 } 2014 2015 /* No tweaking of fFileCopyFlags needed here. */ 2237 } 2238 2239 mProgress->SetNextOperation(Bstr(strSrcAbs).raw(), 1); 2240 2241 switch (pEntry->fMode & RTFS_TYPE_MASK) 2242 { 2243 case RTFS_TYPE_DIRECTORY: 2244 { 2245 LogRel2(("Guest Control: Copying directory '%s' from host to '%s' on guest ...\n", strSrcAbs.c_str(), strDstAbs.c_str())); 2246 if (!pList->mSourceSpec.fDryRun) 2247 vrc = directoryCreateOnGuest(strDstAbs, fDirMode, DirectoryCreateFlag_None, 2248 fFollowSymlinks, fCopyIntoExisting); 2249 break; 2250 } 2251 2252 case RTFS_TYPE_FILE: 2253 { 2254 if (!pList->mSourceSpec.fDryRun) 2255 vrc = fileCopyToGuest(strSrcAbs, strDstAbs, pList->mSourceSpec.fFileCopyFlags); 2256 break; 2257 } 2258 2259 default: 2260 LogRel2(("Guest Control: Warning: Host file system type 0x%x for '%s' is not supported, skipping\n", 2261 pEntry->fMode & RTFS_TYPE_MASK, strSrcAbs.c_str())); 2262 break; 2263 } 2264 2265 if (RT_FAILURE(vrc)) 2266 break; 2267 2268 ++itEntry; 2269 } 2016 2270 } 2017 2271 else if (pList->mSourceSpec.enmType == FsObjType_File) 2018 2272 { 2019 fCopyIntoExisting = !(pList->mSourceSpec.Type.File.fCopyFlags & FileCopyFlag_NoReplace);2020 fFollowSymlinks = RT_BOOL(pList->mSourceSpec.Type.File.fCopyFlags & FileCopyFlag_FollowLinks);2021 2022 2273 LogFlowFunc(("File: fFileCopyFlags=%#x, fCopyIntoExisting=%RTbool, fFollowSymlinks=%RTbool\n", 2023 pList->mSourceSpec.Type.File.fCopyFlags, fCopyIntoExisting, fFollowSymlinks)); 2024 2025 fFileCopyFlags = pList->mSourceSpec.Type.File.fCopyFlags; /* Just use the flags directly from the spec. */ 2274 pList->mSourceSpec.fFileCopyFlags, fCopyIntoExisting, fFollowSymlinks)); 2275 2276 if (fDstExists) 2277 { 2278 switch (dstObjData.mType) 2279 { 2280 case FsObjType_Directory: 2281 { 2282 if (!fCopyIntoExisting) 2283 { 2284 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2285 Utf8StrFmt(tr("Destination \"%s\" on the guest already exists and is a directory"), 2286 strDstRootAbs.c_str())); 2287 vrc = VERR_IS_A_DIRECTORY; 2288 break; 2289 } 2290 2291 /* Append the actual file name to the destination. */ 2292 strDstRootAbs += PATH_STYLE_SEP_STR(mSession->i_getGuestPathStyle()); 2293 strDstRootAbs += RTPathFilename(strSrcRootAbs.c_str()); 2294 break; 2295 } 2296 2297 case FsObjType_File: 2298 { 2299 if (!fCopyIntoExisting) 2300 { 2301 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2302 Utf8StrFmt(tr("Guest file \"%s\" already exists"), strDstRootAbs.c_str())); 2303 vrc = VERR_ALREADY_EXISTS; 2304 } 2305 break; 2306 } 2307 2308 default: 2309 { 2310 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2311 Utf8StrFmt(tr("Unsupported guest file system type (%#x) for \"%s\""), 2312 dstObjData.mType, strDstRootAbs.c_str())); 2313 vrc = VERR_NOT_SUPPORTED; 2314 break; 2315 } 2316 } 2317 } 2318 2319 /* Cleanup the destination path. */ 2320 vrc = GuestPath::Translate(strDstRootAbs, mSession->i_getGuestPathStyle() /* Source */, 2321 mSession->i_getGuestPathStyle() /* Dest */, true /* fForce */); 2322 if (RT_FAILURE(vrc)) 2323 { 2324 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 2325 Utf8StrFmt(tr("Translating guest destination path '%s' from %s to %s failed: %Rrc"), 2326 strDstRootAbs.c_str(), vrc)); 2327 break; 2328 } 2329 2330 if (!pList->mSourceSpec.fDryRun) 2331 vrc = fileCopyToGuest(strSrcRootAbs, strDstRootAbs, pList->mSourceSpec.fFileCopyFlags); 2026 2332 } 2027 2333 else 2028 2334 AssertFailedStmt(vrc = VERR_NOT_SUPPORTED); 2029 2030 LogFlowFunc(("List final: rc=%Rrc, srcRootAbs=%s, dstRootAbs=%s, fFileCopyFlags=%#x\n",2031 vrc, strSrcRootAbs.c_str(), strDstRootAbs.c_str(), fFileCopyFlags));2032 2033 LogRel2(("Guest Control: Copying '%s' from host to '%s' on guest ...\n", strSrcRootAbs.c_str(), strDstRootAbs.c_str()));2034 2035 if (RT_FAILURE(vrc))2036 break;2037 2038 FsEntries::const_iterator itEntry = pList->mVecEntries.begin();2039 while ( RT_SUCCESS(vrc)2040 && itEntry != pList->mVecEntries.end())2041 {2042 FsEntry *pEntry = *itEntry;2043 AssertPtr(pEntry);2044 2045 Utf8Str strSrcAbs = strSrcRootAbs;2046 Utf8Str strDstAbs = strDstRootAbs;2047 2048 if (pList->mSourceSpec.enmType == FsObjType_Directory)2049 {2050 strSrcAbs += PATH_STYLE_SEP_STR(PATH_STYLE_NATIVE);2051 strSrcAbs += pEntry->strPath;2052 }2053 2054 /** @todo Handle stuff like "C:" for destination, where the destination will be the CWD for drive C. */2055 if (dstObjData.mType == FsObjType_Directory)2056 {2057 strDstAbs += PATH_STYLE_SEP_STR(mSession->i_getGuestPathStyle());2058 strDstAbs += pEntry->strPath;2059 }2060 2061 /* Translate the final source host path (for cleaning up mixed path separators). */2062 vrc = GuestPath::Translate(strSrcAbs, PATH_STYLE_NATIVE /* Source */, PATH_STYLE_NATIVE /* Dest */, true /* fForce */);2063 if (RT_FAILURE(vrc))2064 break;2065 2066 /* Translate the final destination path from the host to a path compatible with the guest. */2067 vrc = GuestPath::Translate(strDstAbs, PATH_STYLE_NATIVE /* Source */, mSession->i_getGuestPathStyle() /* Dest */);2068 if (RT_FAILURE(vrc))2069 break;2070 2071 mProgress->SetNextOperation(Bstr(strSrcAbs).raw(), 1);2072 2073 switch (pEntry->fMode & RTFS_TYPE_MASK)2074 {2075 case RTFS_TYPE_DIRECTORY:2076 {2077 LogRel2(("Guest Control: Copying directory '%s' from host to '%s' on guest ...\n", strSrcAbs.c_str(), strDstAbs.c_str()));2078 if (!pList->mSourceSpec.fDryRun)2079 vrc = directoryCreateOnGuest(strDstAbs, DirectoryCreateFlag_None, fDirMode,2080 fFollowSymlinks, fCopyIntoExisting);2081 break;2082 }2083 2084 case RTFS_TYPE_FILE:2085 {2086 LogRel2(("Guest Control: Copying file '%s' from host to '%s' on guest ...\n", strSrcAbs.c_str(), strDstAbs.c_str()));2087 if (!pList->mSourceSpec.fDryRun)2088 vrc = fileCopyToGuest(strSrcAbs, strDstAbs, fFileCopyFlags);2089 break;2090 }2091 2092 default:2093 LogRel2(("Guest Control: Warning: Type 0x%x for '%s' is not supported, skipping\n",2094 pEntry->fMode & RTFS_TYPE_MASK, strSrcAbs.c_str()));2095 break;2096 }2097 2098 if (RT_FAILURE(vrc))2099 break;2100 2101 ++itEntry;2102 }2103 2335 2104 2336 if (RT_FAILURE(vrc))
Note:
See TracChangeset
for help on using the changeset viewer.