Changeset 92859 in vbox
- Timestamp:
- Dec 10, 2021 11:30:41 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r92822 r92859 261 261 RTStrmPrintf(pStrm, 262 262 " copyfrom [common-options]\n" 263 " [- -follow] [-R|--recursive]\n"263 " [-L|--dereference] [-R|--recursive]\n" 264 264 " <guest-src0> [guest-src1 [...]] <host-dst>\n" 265 265 "\n" 266 266 " copyfrom [common-options]\n" 267 " [- -follow] [-R|--recursive]\n"268 " [- -target-directory <host-dst-dir>]\n"267 " [-L|--dereference] [-R|--recursive]\n" 268 " [-t|--target-directory <host-dst-dir>]\n" 269 269 " <guest-src0> [guest-src1 [...]]\n" 270 270 "\n"); … … 272 272 RTStrmPrintf(pStrm, 273 273 " copyto [common-options]\n" 274 " [- -follow] [-R|--recursive]\n"274 " [-L|--dereference] [-R|--recursive]\n" 275 275 " <host-src0> [host-src1 [...]] <guest-dst>\n" 276 276 "\n" 277 277 " copyto [common-options]\n" 278 " [- -follow] [-R|--recursive]\n"279 " [- -target-directory <guest-dst>]\n"278 " [-L|--dereference] [-R|--recursive]\n" 279 " [-t|--target-directory <guest-dst>]\n" 280 280 " <host-src0> [host-src1 [...]]\n" 281 281 "\n"); … … 1724 1724 AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); 1725 1725 1726 /** @todo r=bird: This command isn't very unix friendly in general. mkdir1727 * is much better (partly because it is much simpler of course). The main1728 * arguments against this is that (1) all but two options conflicts with1729 * what 'man cp' tells me on a GNU/Linux system, (2) wildchar matching is1730 * done windows CMD style (though not in a 100% compatible way), and (3)1731 * that only one source is allowed - efficiently sabotaging default1732 * wildcard expansion by a unix shell. The best solution here would be1733 * two different variant, one windowsy (xcopy) and one unixy (gnu cp). */1734 1735 1726 /* 1736 1727 * IGuest::CopyToGuest is kept as simple as possible to let the developer choose … … 1738 1729 * does in here. 1739 1730 */ 1740 enum GETOPTDEF_COPY1741 {1742 GETOPTDEF_COPY_FOLLOW = 1000,1743 GETOPTDEF_COPY_TARGETDIR1744 };1745 1731 static const RTGETOPTDEF s_aOptions[] = 1746 1732 { 1747 1733 GCTLCMD_COMMON_OPTION_DEFS() 1748 { "--follow", GETOPTDEF_COPY_FOLLOW, RTGETOPT_REQ_NOTHING }, 1749 { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, 1750 { "--target-directory", GETOPTDEF_COPY_TARGETDIR, RTGETOPT_REQ_STRING } 1734 { "--follow", 'L', RTGETOPT_REQ_NOTHING }, /* Kept for backwards-compatibility (VBox < 7.0). */ 1735 { "--dereference", 'L', RTGETOPT_REQ_NOTHING }, 1736 { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, 1737 { "--target-directory", 't', RTGETOPT_REQ_STRING } 1751 1738 }; 1752 1739 … … 1771 1758 GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); 1772 1759 1773 case GETOPTDEF_COPY_FOLLOW: 1760 case 'L': 1761 if (!RTStrICmp(ValueUnion.pDef->pszLong, "--follow")) 1762 RTMsgWarning("--follow is deprecated; use --dereference instead."); 1774 1763 fFollow = true; 1775 1764 break; 1776 1765 1777 case 'R': /* Recursive processing */1766 case 'R': 1778 1767 fRecursive = true; 1779 1768 break; 1780 1769 1781 case GETOPTDEF_COPY_TARGETDIR:1770 case 't': 1782 1771 pszDst = ValueUnion.psz; 1783 1772 fDstMustBeDir = true; … … 1828 1817 } 1829 1818 1830 HRESULT rc = S_OK; 1831 ComPtr<IProgress> pProgress; 1832 /** @todo r=bird: This codes does nothing to handle the case where there are 1833 * multiple sources. You need to do serveral thing before thats handled 1834 * correctly. For starters the progress object handling needs to be moved 1835 * inside the loop. Next you need to check what the destination is, because you 1836 * can only copy multiple source files/directories to another directory. You 1837 * actually need to check whether the target exists and is a directory 1838 * regardless of you have 1 or 10 source files/dirs. 1839 * 1840 * Btw. the original approach to error handling here was APPALING. If some file 1841 * couldn't be stat'ed or if it was a file/directory, you only spat out messages 1842 * in verbose mode and never set the status code. 1843 * 1844 * The handling of the wildcard filtering expressions in sources was also just 1845 * skipped. I've corrected this, but you still need to make up your mind wrt 1846 * wildcards or not. 1847 * 1848 * Update: I've kicked out the whole SourceFileEntry/vecSources stuff as we can 1849 * use argv directly without any unnecessary copying. You just have to 1850 * look for the wildcards inside this loop instead. 1851 */ 1852 NOREF(fDstMustBeDir); 1853 if (cSources != 1) 1854 return RTMsgErrorExitFailure(GuestCtrl::tr("Only one source file or directory at the moment.")); 1819 HRESULT rc = S_OK; 1820 1821 bool fDstIsDir = false; 1822 1823 if (!fHostToGuest) 1824 { 1825 RTFSOBJINFO ObjInfo; 1826 vrc = RTPathQueryInfo(szAbsDst, &ObjInfo, RTFSOBJATTRADD_NOTHING); 1827 if (RT_FAILURE(vrc)) 1828 return RTMsgErrorExitFailure(GuestCtrl::tr("RTPathQueryInfo failed on '%s': %Rrc"), szAbsDst, vrc); 1829 fDstIsDir = RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode); 1830 } 1831 else 1832 { 1833 BOOL fDirExists = FALSE; 1834 rc = pCtx->pGuestSession->DirectoryExists(Bstr(pszDst).raw(), TRUE /* fFollowSymlinks */, &fDirExists); 1835 if (SUCCEEDED(rc)) 1836 fDstIsDir = RT_BOOL(fDirExists); 1837 } 1838 1839 /* If multiple sources are specified, the destination must be a directory. */ 1840 fDstMustBeDir = cSources > 1; 1841 1842 /* If destination must be a directory, check this first before everything else. */ 1843 if ( fDstMustBeDir 1844 && !fDstIsDir) 1845 { 1846 return RTMsgErrorExitFailure(GuestCtrl::tr("Destination must be a directory!")); 1847 } 1848 1855 1849 for (size_t iSrc = 0; iSrc < cSources; iSrc++) 1856 1850 { 1857 const char *pszSource = papszSources[iSrc]; 1858 1859 /* Check if the source contains any wilecards in the last component, if so we 1860 don't know how to deal with it yet and refuse. */ 1861 const char *pszSrcFinalComp = RTPathFilename(pszSource); 1862 if (pszSrcFinalComp && strpbrk(pszSrcFinalComp, "*?")) 1863 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("Skipping '%s' because wildcard expansion isn't implemented yet\n"), 1864 pszSource); 1865 else if (fHostToGuest) 1851 /* 1852 * Note: Having a dedicated progress object on every single source being copied can be very slow. 1853 * We implement IGuestSession::Copy[From|To]Guest() since quite a while which does most of the below 1854 * under the hood in Main using a multi-staged progress object. However, leave this like it is for now 1855 * to (also) have a different method of API testing. 1856 */ 1857 ComPtr<IProgress> pProgress; 1858 const char *pszSource = papszSources[iSrc]; 1859 1860 /* Note: Wildcards have to be processed by the calling process (i.e. via globbing, if available). */ 1861 1862 if (fHostToGuest) 1866 1863 { 1867 1864 /* … … 1881 1878 RTPrintf(GuestCtrl::tr("File '%s' -> '%s'\n"), szAbsSrc, pszDst); 1882 1879 1883 SafeArray<FileCopyFlag_T> copyFlags;1880 SafeArray<FileCopyFlag_T> aCopyFlags; 1884 1881 rc = pCtx->pGuestSession->FileCopyToGuest(Bstr(szAbsSrc).raw(), Bstr(pszDst).raw(), 1885 ComSafeArrayAsInParam( copyFlags), pProgress.asOutParam());1882 ComSafeArrayAsInParam(aCopyFlags), pProgress.asOutParam()); 1886 1883 } 1887 1884 else if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) … … 1957 1954 rcExit = RTMsgErrorExitFailure(GuestCtrl::tr("FsObjQueryInfo failed on '%s': %Rhrc"), pszSource, rc); 1958 1955 } 1959 } 1960 1961 if (FAILED(rc)) 1962 { 1963 vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1964 } 1965 else if (pProgress.isNotNull()) 1966 { 1967 if (pCtx->cVerbose) 1968 rc = showProgress(pProgress); 1969 else 1970 rc = pProgress->WaitForCompletion(-1 /* No timeout */); 1971 if (SUCCEEDED(rc)) 1972 CHECK_PROGRESS_ERROR(pProgress, (GuestCtrl::tr("File copy failed"))); 1973 vrc = gctlPrintProgressError(pProgress); 1974 } 1956 1957 if (FAILED(rc)) 1958 { 1959 vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1960 } 1961 else if (pProgress.isNotNull()) 1962 { 1963 if (pCtx->cVerbose) 1964 rc = showProgress(pProgress); 1965 else 1966 rc = pProgress->WaitForCompletion(-1 /* No timeout */); 1967 if (SUCCEEDED(rc)) 1968 CHECK_PROGRESS_ERROR(pProgress, (GuestCtrl::tr("File copy failed"))); 1969 vrc = gctlPrintProgressError(pProgress); 1970 } 1971 1972 /* Keep going. */ 1973 } 1974 1975 1975 if (RT_FAILURE(vrc)) 1976 1976 rcExit = RTEXITCODE_FAILURE;
Note:
See TracChangeset
for help on using the changeset viewer.