Changeset 97343 in vbox
- Timestamp:
- Oct 31, 2022 9:47:06 AM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 154341
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r97308 r97343 1686 1686 HRESULT hrc = S_OK; 1687 1687 1688 bool fDstIsDir = false; 1689 1690 if (!fHostToGuest) 1691 { 1692 RTFSOBJINFO ObjInfo; 1693 vrc = RTPathQueryInfo(szAbsDst, &ObjInfo, RTFSOBJATTRADD_NOTHING); 1694 if (RT_SUCCESS(vrc)) 1695 { 1696 fDstIsDir = RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode); 1697 } 1698 else if ( RT_FAILURE(vrc) 1699 && vrc != VERR_FILE_NOT_FOUND) /* Destination file on the host might not exist yet, which is fine. */ 1700 return RTMsgErrorExitFailure(GuestCtrl::tr("RTPathQueryInfo failed on '%s': %Rrc"), szAbsDst, vrc); 1701 } 1702 else 1703 { 1704 BOOL fDirExists = FALSE; 1705 hrc = pCtx->pGuestSession->DirectoryExists(Bstr(pszDst).raw(), TRUE /* fFollowSymlinks */, &fDirExists); 1706 if (SUCCEEDED(hrc)) 1707 fDstIsDir = RT_BOOL(fDirExists); 1708 } 1709 1710 /* If multiple sources are specified, the destination must be a directory. */ 1711 fDstMustBeDir = cSources > 1; 1712 1713 /* If destination must be a directory, check this first before everything else. */ 1714 if ( fDstMustBeDir 1715 && !fDstIsDir) 1716 { 1717 return RTMsgErrorExitFailure(GuestCtrl::tr("Destination must be a directory!")); 1718 } 1719 1720 for (size_t iSrc = 0; iSrc < cSources; iSrc++) 1721 { 1722 /* 1723 * Note: Having a dedicated progress object on every single source being copied can be very slow. 1724 * We implement IGuestSession::Copy[From|To]Guest() since quite a while which does most of the below 1725 * under the hood in Main using a multi-staged progress object. However, leave this like it is for now 1726 * to (also) have a different method of API testing. 1727 */ 1728 ComPtr<IProgress> pProgress; 1729 const char *pszSource = papszSources[iSrc]; 1730 1731 /* Note: Wildcards have to be processed by the calling process (i.e. via globbing, if available). */ 1732 1688 com::SafeArray<IN_BSTR> aSources; 1689 com::SafeArray<IN_BSTR> aFilters; /** @todo Populate those? For now we use caller-based globbing. */ 1690 com::SafeArray<IN_BSTR> aCopyFlags; 1691 1692 size_t iSrc = 0; 1693 for (; iSrc < cSources; iSrc++) 1694 { 1695 aSources.push_back(Bstr(papszSources[iSrc]).raw()); 1696 aFilters.push_back(Bstr("").raw()); /* Empty for now. See @todo above. */ 1697 1698 /* Compile the comma-separated list of flags. 1699 * Certain flags are only available for specific file system objects, e.g. directories. */ 1700 bool fIsDir = false; 1733 1701 if (fHostToGuest) 1734 1702 { 1735 /* 1736 * Source is host, destination guest. 1737 */ 1738 char szAbsSrc[RTPATH_MAX]; 1739 vrc = RTPathAbs(pszSource, szAbsSrc, sizeof(szAbsSrc)); 1703 RTFSOBJINFO ObjInfo; 1704 vrc = RTPathQueryInfo(papszSources[iSrc], &ObjInfo, RTFSOBJATTRADD_NOTHING); 1740 1705 if (RT_SUCCESS(vrc)) 1741 { 1742 RTFSOBJINFO ObjInfo; 1743 vrc = RTPathQueryInfo(szAbsSrc, &ObjInfo, RTFSOBJATTRADD_NOTHING); 1744 if (RT_SUCCESS(vrc)) 1745 { 1746 if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) 1747 { 1748 if (pCtx->cVerbose) 1749 RTPrintf(GuestCtrl::tr("File '%s' -> '%s'\n"), szAbsSrc, pszDst); 1750 1751 SafeArray<FileCopyFlag_T> aCopyFlags; 1752 hrc = pCtx->pGuestSession->FileCopyToGuest(Bstr(szAbsSrc).raw(), Bstr(pszDst).raw(), 1753 ComSafeArrayAsInParam(aCopyFlags), pProgress.asOutParam()); 1754 } 1755 else if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) 1756 { 1757 if (pCtx->cVerbose) 1758 RTPrintf(GuestCtrl::tr("Directory '%s' -> '%s'\n"), szAbsSrc, pszDst); 1759 1760 SafeArray<DirectoryCopyFlag_T> aCopyFlags; 1761 aCopyFlags.push_back(DirectoryCopyFlag_CopyIntoExisting); 1762 if (fRecursive) 1763 aCopyFlags.push_back(DirectoryCopyFlag_Recursive); 1764 if (fFollow) 1765 aCopyFlags.push_back(DirectoryCopyFlag_FollowLinks); 1766 hrc = pCtx->pGuestSession->DirectoryCopyToGuest(Bstr(szAbsSrc).raw(), Bstr(pszDst).raw(), 1767 ComSafeArrayAsInParam(aCopyFlags), pProgress.asOutParam()); 1768 } 1769 else 1770 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("Not a file or directory: %s\n"), szAbsSrc); 1771 } 1772 else 1773 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("RTPathQueryInfo failed on '%s': %Rrc"), szAbsSrc, vrc); 1774 } 1775 else 1776 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("RTPathAbs failed on '%s': %Rrc"), pszSource, vrc); 1777 } 1778 else 1779 { 1780 /* 1781 * Source guest, destination host. 1782 */ 1783 /* We need to query the source type on the guest first in order to know which copy flavor we need. */ 1706 fIsDir = RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode); 1707 1708 if (RT_FAILURE(vrc)) 1709 break; 1710 } 1711 else /* Guest to host. */ 1712 { 1784 1713 ComPtr<IGuestFsObjInfo> pFsObjInfo; 1785 hrc = pCtx->pGuestSession->FsObjQueryInfo(Bstr(pszSource).raw(), TRUE /* fFollowSymlinks */, pFsObjInfo.asOutParam()); 1714 hrc = pCtx->pGuestSession->FsObjQueryInfo(Bstr(papszSources[iSrc]).raw(), RT_BOOL(fFollow) /* fFollowSymlinks */, 1715 pFsObjInfo.asOutParam()); 1786 1716 if (SUCCEEDED(hrc)) 1787 1717 { … … 1791 1721 { 1792 1722 /* Take action according to source file. */ 1793 if (enmObjType == FsObjType_Directory) 1794 { 1795 if (pCtx->cVerbose) 1796 RTPrintf(GuestCtrl::tr("Directory '%s' -> '%s'\n"), pszSource, pszDst); 1797 1798 SafeArray<DirectoryCopyFlag_T> aCopyFlags; 1799 aCopyFlags.push_back(DirectoryCopyFlag_CopyIntoExisting); 1800 if (fRecursive) 1801 aCopyFlags.push_back(DirectoryCopyFlag_Recursive); 1802 if (fFollow) 1803 aCopyFlags.push_back(DirectoryCopyFlag_FollowLinks); 1804 hrc = pCtx->pGuestSession->DirectoryCopyFromGuest(Bstr(pszSource).raw(), Bstr(pszDst).raw(), 1805 ComSafeArrayAsInParam(aCopyFlags), pProgress.asOutParam()); 1806 } 1807 else if (enmObjType == FsObjType_File) 1808 { 1809 if (pCtx->cVerbose) 1810 RTPrintf(GuestCtrl::tr("File '%s' -> '%s'\n"), pszSource, pszDst); 1811 1812 SafeArray<FileCopyFlag_T> aCopyFlags; 1813 if (fFollow) 1814 aCopyFlags.push_back(FileCopyFlag_FollowLinks); 1815 hrc = pCtx->pGuestSession->FileCopyFromGuest(Bstr(pszSource).raw(), Bstr(pszDst).raw(), 1816 ComSafeArrayAsInParam(aCopyFlags), pProgress.asOutParam()); 1817 } 1818 else 1819 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("Not a file or directory: %s\n"), pszSource); 1723 fIsDir = enmObjType == FsObjType_Directory; 1820 1724 } 1821 else1822 rcExit = RTEXITCODE_FAILURE;1823 1725 } 1824 else 1825 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("FsObjQueryInfo failed on '%s': %Rhrc"), pszSource, hrc); 1826 } 1827 1828 if (FAILED(hrc)) 1829 { 1830 vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1831 } 1832 else if (pProgress.isNotNull()) 1833 { 1834 if (pCtx->cVerbose) 1835 hrc = showProgress(pProgress); 1836 else 1837 hrc = pProgress->WaitForCompletion(-1 /* No timeout */); 1838 if (SUCCEEDED(hrc)) 1839 CHECK_PROGRESS_ERROR(pProgress, (GuestCtrl::tr("File copy failed"))); 1840 vrc = gctlPrintProgressError(pProgress); 1841 } 1842 1843 /* Keep going. */ 1726 1727 if (FAILED(hrc)) 1728 { 1729 vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1730 break; 1731 } 1732 } 1733 1734 if (pCtx->cVerbose) 1735 RTPrintf(GuestCtrl::tr("Source '%s' is a %s\n"), papszSources[iSrc], fIsDir ? "directory" : "file"); 1736 1737 Utf8Str strCopyFlags; 1738 if (fRecursive && fIsDir) /* Only available for directories. Just ignore otherwise. */ 1739 strCopyFlags += "Recursive,"; 1740 if (fIsDir) 1741 strCopyFlags += "CopyIntoExisting,"; /* Implicit. */ 1742 if (fFollow) 1743 strCopyFlags += "FollowLinks,"; 1744 aCopyFlags.push_back(Bstr(strCopyFlags).raw()); 1745 } 1746 1747 if (RT_FAILURE(vrc)) 1748 return RTMsgErrorExitFailure(GuestCtrl::tr("Error looking file system information for source '%s', rc=%Rrc"), 1749 papszSources[iSrc], vrc); 1750 1751 ComPtr<IProgress> pProgress; 1752 if (fHostToGuest) 1753 { 1754 hrc = pCtx->pGuestSession->CopyToGuest(ComSafeArrayAsInParam(aSources), 1755 ComSafeArrayAsInParam(aFilters), ComSafeArrayAsInParam(aCopyFlags), 1756 Bstr(pszDst).raw(), pProgress.asOutParam()); 1757 } 1758 else /* Guest to host. */ 1759 { 1760 hrc = pCtx->pGuestSession->CopyFromGuest(ComSafeArrayAsInParam(aSources), 1761 ComSafeArrayAsInParam(aFilters), ComSafeArrayAsInParam(aCopyFlags), 1762 Bstr(pszDst).raw(), pProgress.asOutParam()); 1763 } 1764 1765 if (FAILED(hrc)) 1766 { 1767 vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1768 } 1769 else if (pProgress.isNotNull()) 1770 { 1771 if (pCtx->cVerbose) 1772 hrc = showProgress(pProgress); 1773 else 1774 hrc = pProgress->WaitForCompletion(-1 /* No timeout */); 1775 if (SUCCEEDED(hrc)) 1776 CHECK_PROGRESS_ERROR(pProgress, (GuestCtrl::tr("File copy failed"))); 1777 vrc = gctlPrintProgressError(pProgress); 1844 1778 } 1845 1779
Note:
See TracChangeset
for help on using the changeset viewer.