Changeset 38085 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- Jul 21, 2011 7:29:54 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r37761 r38085 69 69 static volatile bool g_fGuestCtrlCanceled = false; 70 70 71 typedef struct COPYCONTEXT 72 { 73 IGuest *pGuest; 74 bool fVerbose; 75 bool fHostToGuest; 76 char *pszUsername; 77 char *pszPassword; 78 } COPYCONTEXT, *PCOPYCONTEXT; 79 71 80 /** 72 81 * An entry for a source element, including an optional filter. … … 100 109 101 110 /** 102 * An entry for an element which needs to be copied tothe guest.111 * An entry for an element which needs to be copied/created to/on the guest. 103 112 */ 104 113 typedef struct DESTFILEENTRY … … 187 196 " [--timeout <msec>] [--unix2dos] [--verbose]\n" 188 197 " [--wait-exit] [--wait-stdout] [--wait-stderr]\n" 189 //" [--output-format=<dos>|<unix>]\n"190 " [--output-type=<binary>|<text>]\n"191 198 " [-- [<argument1>] ... [<argumentN>]]\n" 192 199 /** @todo Add a "--" parameter (has to be last parameter) to directly execute 193 200 * stuff, e.g. "VBoxManage guestcontrol execute <VMName> --username <> ... -- /bin/rm -Rf /foo". */ 194 201 "\n" 195 #if 0196 202 " copyfrom\n" 197 203 " <source on guest> <destination on host>\n" … … 199 205 " [--dryrun] [--follow] [--recursive] [--verbose]\n" 200 206 "\n" 201 #endif202 207 " copyto|cp\n" 203 208 " <source on host> <destination on guest>\n" … … 206 211 "\n" 207 212 " createdir[ectory]|mkdir|md\n" 208 " <director yto create on guest>\n"213 " <director[y|ies] to create on guest>\n" 209 214 " --username <name> --password <password>\n" 210 215 " [--parents] [--mode <mode>] [--verbose]\n" 216 "\n" 217 " stat\n" 218 " <file element(s) to check on guest>\n" 219 " --username <name> --password <password>\n" 220 " [--verbose]\n" 211 221 "\n" 212 222 " updateadditions\n" … … 572 582 if (Utf8UserName.isEmpty()) 573 583 return errorSyntax(USAGE_GUESTCONTROL, "No user name specified!"); 584 585 /* Any output conversion not supported yet! */ 586 if (eOutputType != OUTPUTTYPE_UNDEFINED) 587 return errorSyntax(USAGE_GUESTCONTROL, "Output conversion not implemented yet!"); 574 588 575 589 /* … … 685 699 * generic problem and the new VFS APIs will handle it more 686 700 * transparently. (requires writing dos2unix/unix2dos filters ofc) */ 687 if (eOutputType != OUTPUTTYPE_UNDEFINED) 701 702 /* 703 * If aOutputData is text data from the guest process' stdout or stderr, 704 * it has a platform dependent line ending. So standardize on 705 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on 706 * Windows. Otherwise we end up with CR/CR/LF on Windows. 707 */ 708 ULONG cbOutputDataPrint = cbOutputData; 709 for (BYTE *s = aOutputData.raw(), *d = s; 710 s - aOutputData.raw() < (ssize_t)cbOutputData; 711 s++, d++) 688 712 { 689 /* 690 * If aOutputData is text data from the guest process' stdout or stderr, 691 * it has a platform dependent line ending. So standardize on 692 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on 693 * Windows. Otherwise we end up with CR/CR/LF on Windows. 694 */ 695 ULONG cbOutputDataPrint = cbOutputData; 696 for (BYTE *s = aOutputData.raw(), *d = s; 697 s - aOutputData.raw() < (ssize_t)cbOutputData; 698 s++, d++) 713 if (*s == '\r') 699 714 { 700 if (*s == '\r') 701 { 702 /* skip over CR, adjust destination */ 703 d--; 704 cbOutputDataPrint--; 705 } 706 else if (s != d) 707 *d = *s; 715 /* skip over CR, adjust destination */ 716 d--; 717 cbOutputDataPrint--; 708 718 } 709 RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputDataPrint); 719 else if (s != d) 720 *d = *s; 710 721 } 711 else /* Just dump all data as we got it ... */ 712 RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputData); 722 RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputDataPrint); 713 723 } 714 724 } … … 790 800 } 791 801 792 /** @todo Clean up too long parameter list -> move guest specific stuff into own struct etc! */ 793 static int ctrlCopyDirectoryReadGuest(IGuest *pGuest, 794 const char *pszUsername, const char *pszPassword, 795 const char *pszRootDir, const char *pszSubDir, 796 const char *pszFilter, const char *pszDest, 797 uint32_t fFlags, uint32_t *pcObjects, DESTDIRMAP &dirMap) 798 { 799 AssertPtrReturn(pszRootDir, VERR_INVALID_POINTER); 802 static int ctrlCopyContextCreate(IGuest *pGuest, bool fVerbose, bool fHostToGuest, 803 const char *pszUsername, const char *pszPassword, 804 PCOPYCONTEXT *ppContext) 805 { 806 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 807 AssertPtrReturn(pszUsername, VERR_INVALID_POINTER); 808 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 809 810 PCOPYCONTEXT pContext = (PCOPYCONTEXT)RTMemAlloc(sizeof(COPYCONTEXT)); 811 AssertPtrReturn(pContext, VERR_NO_MEMORY); 812 pContext->pGuest = pGuest; 813 pContext->fVerbose = fVerbose; 814 pContext->fHostToGuest = fHostToGuest; 815 816 pContext->pszUsername = RTStrDup(pszUsername); 817 if (!pContext->pszUsername) 818 { 819 RTMemFree(pContext); 820 return VERR_NO_MEMORY; 821 } 822 823 pContext->pszPassword = RTStrDup(pszPassword); 824 if (!pContext->pszPassword) 825 { 826 RTStrFree(pContext->pszUsername); 827 RTMemFree(pContext); 828 return VERR_NO_MEMORY; 829 } 830 831 *ppContext = pContext; 832 833 return VINF_SUCCESS; 834 } 835 836 static void ctrlCopyContextFree(PCOPYCONTEXT pContext) 837 { 838 if (pContext) 839 { 840 RTStrFree(pContext->pszUsername); 841 RTStrFree(pContext->pszPassword); 842 RTMemFree(pContext); 843 } 844 } 845 846 /* 847 * Source Dest Translated 848 * c:\foo.txt c:\from_host c:\from_host\foo.txt 849 * c:\asdf\foo c:\qwer c:\qwer\foo 850 * c:\bar\baz.txt d:\users\ d:\users\baz.txt 851 * c:\*.dll e:\baz e:\baz 852 */ 853 static int ctrlCopyTranslatePath(PCOPYCONTEXT pContext, 854 const char *pszSourceRoot, const char *pszSource, 855 const char *pszDest, char **ppszTranslated) 856 { 857 AssertPtrReturn(pContext, VERR_INVALID_POINTER); 858 AssertPtrReturn(pszSourceRoot, VERR_INVALID_POINTER); 859 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 860 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 861 AssertPtrReturn(ppszTranslated, VERR_INVALID_POINTER); 862 863 /* Source path must contain the source root! */ 864 if (!RTPathStartsWith(pszSource, pszSourceRoot)) 865 return VERR_INVALID_PARAMETER; 866 867 /* Construct the relative dest destination path by "subtracting" the 868 * source from the source root, e.g. 869 * 870 * source root path = "e:\foo\", source = "e:\foo\bar" 871 * dest = "d:\baz\" 872 * translated = "d:\baz\bar\" 873 */ 874 875 size_t lenRoot = strlen(pszSourceRoot); 876 AssertReturn(lenRoot, VERR_INVALID_PARAMETER); 877 char *pszTranslated = RTStrDup(pszDest); 878 AssertReturn(pszTranslated, VERR_NO_MEMORY); 879 int vrc = RTStrAAppend(&pszTranslated, &pszSource[lenRoot]); 880 if (RT_FAILURE(vrc)) 881 return vrc; 882 883 *ppszTranslated = pszTranslated; 884 885 #ifdef DEBUG 886 if (pContext->fVerbose) 887 RTPrintf("Translating root=%s, source=%s, dest=%s -> %s\n", 888 pszSourceRoot, pszSource, pszDest, *ppszTranslated); 889 #endif 890 891 return vrc; 892 } 893 894 static int ctrlCopyDirCreate(PCOPYCONTEXT pContext, const char *pszDir) 895 { 896 AssertPtrReturn(pContext, VERR_INVALID_POINTER); 897 AssertPtrReturn(pszDir, VERR_INVALID_POINTER); 898 899 int rc = VINF_SUCCESS; 900 if (pContext->fHostToGuest) /* We want to create directories on the guest. */ 901 { 902 HRESULT hrc = pContext->pGuest->DirectoryCreate(Bstr(pszDir).raw(), 903 Bstr(pContext->pszUsername).raw(), Bstr(pContext->pszPassword).raw(), 904 700, DirectoryCreateFlag_Parents); 905 if (FAILED(hrc)) 906 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 907 } 908 else /* ... or on the host. */ 909 { 910 rc = RTDirCreate(pszDir, 700); 911 if (rc == VERR_ALREADY_EXISTS) 912 rc = VINF_SUCCESS; 913 } 914 return rc; 915 } 916 917 static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest, 918 const char *pszDir, bool *fExists) 919 { 920 AssertPtrReturn(pContext, false); 921 AssertPtrReturn(pszDir, false); 922 AssertPtrReturn(fExists, false); 923 924 int rc = VINF_SUCCESS; 925 if (bGuest) 926 { 927 BOOL fDirExists = FALSE; 928 HRESULT hr = pContext->pGuest->FileExists(Bstr(pszDir).raw(), 929 Bstr(pContext->pszUsername).raw(), 930 Bstr(pContext->pszPassword).raw(), &fDirExists); 931 if (FAILED(hr)) 932 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 933 else 934 *fExists = fDirExists ? true : false; 935 } 936 else 937 *fExists = RTDirExists(pszDir); 938 return rc; 939 } 940 941 static int ctrlCopyDirExistsOnDest(PCOPYCONTEXT pContext, const char *pszDir, 942 bool *fExists) 943 { 944 return ctrlCopyDirExists(pContext, pContext->fHostToGuest, 945 pszDir, fExists); 946 } 947 948 static int ctrlCopyDirExistsOnSource(PCOPYCONTEXT pContext, const char *pszDir, 949 bool *fExists) 950 { 951 return ctrlCopyDirExists(pContext, !pContext->fHostToGuest, 952 pszDir, fExists); 953 } 954 955 static int ctrlCopyFileExists(PCOPYCONTEXT pContext, bool bOnGuest, 956 const char *pszFile, bool *fExists) 957 { 958 AssertPtrReturn(pContext, false); 959 AssertPtrReturn(pszFile, false); 960 AssertPtrReturn(fExists, false); 961 962 int rc = VINF_SUCCESS; 963 if (bOnGuest) 964 { 965 BOOL fFileExists = FALSE; 966 HRESULT hr = pContext->pGuest->FileExists(Bstr(pszFile).raw(), 967 Bstr(pContext->pszUsername).raw(), 968 Bstr(pContext->pszPassword).raw(), &fFileExists); 969 if (FAILED(hr)) 970 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 971 else 972 *fExists = fFileExists ? true : false; 973 } 974 else 975 *fExists = RTFileExists(pszFile); 976 return rc; 977 } 978 979 static int ctrlCopyFileExistsOnDest(PCOPYCONTEXT pContext, const char *pszFile, 980 bool *fExists) 981 { 982 return ctrlCopyFileExists(pContext, pContext->fHostToGuest, 983 pszFile, fExists); 984 } 985 986 static int ctrlCopyFileExistsOnSource(PCOPYCONTEXT pContext, const char *pszFile, 987 bool *fExists) 988 { 989 return ctrlCopyFileExists(pContext, !pContext->fHostToGuest, 990 pszFile, fExists); 991 } 992 993 static int ctrlCopyFileToTarget(PCOPYCONTEXT pContext, const char *pszFileSource, 994 const char *pszFileDest, uint32_t fFlags) 995 { 996 AssertPtrReturn(pContext, VERR_INVALID_POINTER); 997 AssertPtrReturn(pszFileSource, VERR_INVALID_POINTER); 998 AssertPtrReturn(pszFileDest, VERR_INVALID_POINTER); 999 1000 if (pContext->fVerbose) 1001 { 1002 RTPrintf("Copying \"%s\" to \"%s\" ...\n", 1003 pszFileSource, pszFileDest); 1004 } 1005 1006 int vrc = VINF_SUCCESS; 1007 ComPtr<IProgress> progress; 1008 HRESULT hr; 1009 if (pContext->fHostToGuest) 1010 { 1011 hr = pContext->pGuest->CopyToGuest(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(), 1012 Bstr(pContext->pszUsername).raw(), Bstr(pContext->pszPassword).raw(), 1013 fFlags, progress.asOutParam()); 1014 } 1015 else 1016 { 1017 hr = pContext->pGuest->CopyFromGuest(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(), 1018 Bstr(pContext->pszUsername).raw(), Bstr(pContext->pszPassword).raw(), 1019 fFlags, progress.asOutParam()); 1020 } 1021 1022 if (FAILED(hr)) 1023 vrc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 1024 else 1025 { 1026 hr = showProgress(progress); 1027 if (FAILED(hr)) 1028 vrc = ctrlPrintProgressError(progress); 1029 } 1030 1031 return vrc; 1032 } 1033 1034 static int ctrlCopyDirToGuest(PCOPYCONTEXT pContext, 1035 const char *pszSource, const char *pszFilter, 1036 const char *pszDest, uint32_t fFlags, 1037 const char *pszSubDir /* For recursion */) 1038 { 1039 AssertPtrReturn(pContext, VERR_INVALID_POINTER); 1040 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 1041 /* Filter is optional. */ 1042 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 800 1043 /* Sub directory is optional. */ 801 /* Filter directory is optional. */802 AssertPtrReturn(pszDest, VERR_INVALID_POINTER);803 AssertPtrReturn(pcObjects, VERR_INVALID_POINTER);804 1044 805 1045 /* … … 807 1047 */ 808 1048 char szCurDir[RTPATH_MAX]; 809 int rc = RTStrCopy(szCurDir, sizeof(szCurDir), psz RootDir);810 if (RT_SUCCESS(rc) && pszSubDir != NULL)1049 int rc = RTStrCopy(szCurDir, sizeof(szCurDir), pszSource); 1050 if (RT_SUCCESS(rc) && pszSubDir) 811 1051 rc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir); 812 1052 813 if (RT_SUCCESS(rc)) 814 { 815 ULONG uDirHandle; 816 HRESULT hr = pGuest->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(), fFlags, 817 Bstr(pszUsername).raw(), Bstr(pszPassword).raw(), &uDirHandle); 818 if (FAILED(hr)) 819 rc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 820 else 821 { 822 ComPtr <IGuestDirEntry> dirEntry; 823 while (SUCCEEDED(hr = pGuest->DirectoryRead(uDirHandle, dirEntry.asOutParam()))) 824 { 825 GuestDirEntryType_T enmType; 826 dirEntry->COMGETTER(Type)(&enmType); 827 828 Bstr strName; 829 dirEntry->COMGETTER(Name)(strName.asOutParam()); 830 831 switch (enmType) 832 { 833 case GuestDirEntryType_Directory: 834 { 835 /* Skip "." and ".." entries. */ 836 if ( !strName.compare(Bstr(".")) 837 || !strName.compare(Bstr(".."))) 838 break; 839 840 const char *pszName = Utf8Str(strName).c_str(); 841 if (fFlags & CopyFileFlag_Recursive) 842 { 843 char *pszNewSub = NULL; 844 if (pszSubDir) 845 RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, pszName); 846 else 847 RTStrAPrintf(&pszNewSub, "%s", pszName); 848 849 if (pszNewSub) 850 { 851 dirMap[pszNewSub]; 852 853 rc = ctrlCopyDirectoryReadGuest(pGuest, pszUsername, pszPassword, 854 pszRootDir, pszNewSub, 855 pszFilter, pszDest, 856 fFlags, pcObjects, dirMap); 857 RTStrFree(pszNewSub); 858 } 859 else 860 rc = VERR_NO_MEMORY; 861 } 862 break; 863 } 864 865 case GuestDirEntryType_Symlink: 866 if ( (fFlags & CopyFileFlag_Recursive) 867 && (fFlags & CopyFileFlag_FollowLinks)) 868 { 869 /* Fall through to next case is intentional. */ 870 } 871 else 872 break; 873 874 case GuestDirEntryType_File: 875 { 876 const char *pszName = Utf8Str(strName).c_str(); 877 if ( !pszFilter 878 || RTStrSimplePatternMatch(pszFilter, pszName)) 879 { 880 dirMap[pszSubDir].push_back(DESTFILEENTRY(pszName)); 881 *pcObjects += 1; 882 } 883 break; 884 } 885 886 default: 887 break; 888 } 889 } 890 891 hr = pGuest->DirectoryClose(uDirHandle); 892 if (FAILED(rc)) 893 rc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 894 } 895 } 896 return rc; 897 } 898 899 /** 900 * Reads a specified directory (recursively) based on the copy flags 901 * and appends all matching entries to the supplied list. 902 * 903 * @return IPRT status code. 904 * @param pszRootDir Directory to start with. Must end with 905 * a trailing slash and must be absolute. 906 * @param pszSubDir Sub directory part relative to the root 907 * directory; needed for recursion. 908 * @param pszFilter Search filter (e.g. *.pdf). 909 * @param pszDest Destination directory. 910 * @param fFlags Copy flags. 911 * @param pcObjects Where to store the overall objects to 912 * copy found. 913 * @param dirMap Reference to destination directory map to store found 914 * directories (primary key) + files (secondary key, vector). 915 */ 916 static int ctrlCopyDirectoryReadHost(const char *pszRootDir, const char *pszSubDir, 917 const char *pszFilter, const char *pszDest, 918 uint32_t fFlags, uint32_t *pcObjects, DESTDIRMAP &dirMap) 919 { 920 AssertPtrReturn(pszRootDir, VERR_INVALID_POINTER); 921 /* Sub directory is optional. */ 922 /* Filter directory is optional. */ 923 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 924 AssertPtrReturn(pcObjects, VERR_INVALID_POINTER); 925 926 /* 927 * Construct current path. 928 */ 929 char szCurDir[RTPATH_MAX]; 930 int rc = RTStrCopy(szCurDir, sizeof(szCurDir), pszRootDir); 931 if (RT_SUCCESS(rc) && pszSubDir != NULL) 932 rc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir); 1053 /* Flag indicating whether the current directory was created on the 1054 * target or not. */ 1055 bool fDirCreated = false; 933 1056 934 1057 /* … … 977 1100 if (pszNewSub) 978 1101 { 979 dirMap[pszNewSub]; 980 981 rc = ctrlCopyDirectoryReadHost(pszRootDir, pszNewSub, 982 pszFilter, pszDest, 983 fFlags, pcObjects, dirMap); 1102 rc = ctrlCopyDirToGuest(pContext, 1103 pszSource, pszFilter, 1104 pszDest, fFlags, pszNewSub); 984 1105 RTStrFree(pszNewSub); 985 1106 } … … 1004 1125 || RTStrSimplePatternMatch(pszFilter, DirEntry.szName)) 1005 1126 { 1006 dirMap[pszSubDir].push_back(DESTFILEENTRY(Utf8Str(DirEntry.szName))); 1007 *pcObjects += 1; 1127 if (!fDirCreated) 1128 { 1129 char *pszDestDir; 1130 rc = ctrlCopyTranslatePath(pContext, pszSource, szCurDir, 1131 pszDest, &pszDestDir); 1132 if (RT_SUCCESS(rc)) 1133 { 1134 rc = ctrlCopyDirCreate(pContext, pszDestDir); 1135 RTStrFree(pszDestDir); 1136 1137 fDirCreated = true; 1138 } 1139 } 1140 1141 if (RT_SUCCESS(rc)) 1142 { 1143 char *pszFileSource; 1144 if (RTStrAPrintf(&pszFileSource, "%s/%s", 1145 szCurDir, DirEntry.szName)) 1146 { 1147 char *pszFileDest; 1148 rc = ctrlCopyTranslatePath(pContext, pszSource, pszFileSource, 1149 pszDest, &pszFileDest); 1150 if (RT_SUCCESS(rc)) 1151 { 1152 rc = ctrlCopyFileToTarget(pContext, pszFileSource, 1153 pszFileDest, 0 /* Flags? */); 1154 RTStrFree(pszFileDest); 1155 } 1156 RTStrFree(pszFileSource); 1157 } 1158 } 1008 1159 } 1009 1160 break; … … 1022 1173 } 1023 1174 1024 /** 1025 * Constructs a destinations map from a source entry and a destination root. 1026 * 1027 * @return IPRT status code. 1028 * @param fHostToGuest 1029 * @param sourceEntry Reference to a specified source entry to use. 1030 * @param fFlags Copy file flags. Needed for recursive directory parsing. 1031 * @param pszDestRoot Pointer to destination root. This can be used to add one or 1032 * more directories to the actual destination path. 1033 * @param mapDest Reference to the destination map for storing the actual result. 1034 * @param pcObjects Pointer to a total object (file) count to copy. 1035 */ 1036 static int ctrlCopyConstructDestinationsForGuest(SOURCEFILEENTRY &sourceEntry, uint32_t fFlags, 1037 const char *pszDestRoot, DESTDIRMAP &mapDest, 1038 uint32_t *pcObjects) 1039 { 1040 int rc = VINF_SUCCESS; 1041 const char *pszSource = sourceEntry.mSource.c_str(); 1042 1043 if ( RTPathFilename(pszSource) 1044 && RTFileExists(pszSource)) 1045 { 1046 /* Source is a single file. */ 1047 char *pszFileName = RTPathFilename(pszSource); 1048 mapDest[Utf8Str("")].push_back(DESTFILEENTRY(pszFileName)); 1049 1050 *pcObjects += 1; 1051 } 1175 static int ctrlCopyDirToHost(PCOPYCONTEXT pContext, 1176 const char *pszSource, const char *pszFilter, 1177 const char *pszDest, uint32_t fFlags, 1178 const char *pszSubDir /* For recursion */) 1179 { 1180 AssertPtrReturn(pContext, VERR_INVALID_POINTER); 1181 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 1182 /* Filter is optional. */ 1183 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 1184 /* Sub directory is optional. */ 1185 1186 /* 1187 * Construct current path. 1188 */ 1189 char szCurDir[RTPATH_MAX]; 1190 int rc = RTStrCopy(szCurDir, sizeof(szCurDir), pszSource); 1191 if (RT_SUCCESS(rc) && pszSubDir) 1192 rc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir); 1193 1194 /* Flag indicating whether the current directory was created on the 1195 * target or not. */ 1196 bool fDirCreated = false; 1197 1198 ULONG uDirHandle; 1199 HRESULT hr = pContext->pGuest->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(), 1200 fFlags, 1201 Bstr(pContext->pszUsername).raw(), Bstr(pContext->pszPassword).raw(), 1202 &uDirHandle); 1203 if (FAILED(hr)) 1204 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 1052 1205 else 1053 1206 { 1054 /* Source is either a directory or a filter (e.g. *.dll). */ 1055 rc = ctrlCopyDirectoryReadHost(pszSource, 1056 NULL /* pszSubDir */, 1057 sourceEntry.mFilter.isEmpty() ? NULL : sourceEntry.mFilter.c_str(), 1058 pszDestRoot, fFlags, pcObjects, mapDest); 1059 } 1207 ComPtr <IGuestDirEntry> dirEntry; 1208 while (SUCCEEDED(hr = pContext->pGuest->DirectoryRead(uDirHandle, dirEntry.asOutParam()))) 1209 { 1210 GuestDirEntryType_T enmType; 1211 dirEntry->COMGETTER(Type)(&enmType); 1212 1213 Bstr strName; 1214 dirEntry->COMGETTER(Name)(strName.asOutParam()); 1215 1216 switch (enmType) 1217 { 1218 case GuestDirEntryType_Directory: 1219 { 1220 /* Skip "." and ".." entries. */ 1221 if ( !strName.compare(Bstr(".")) 1222 || !strName.compare(Bstr(".."))) 1223 break; 1224 1225 if (fFlags & CopyFileFlag_Recursive) 1226 { 1227 Utf8Str strDir(strName); 1228 char *pszNewSub = NULL; 1229 if (pszSubDir) 1230 RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, strDir.c_str()); 1231 else 1232 RTStrAPrintf(&pszNewSub, "%s", strDir.c_str()); 1233 1234 if (pszNewSub) 1235 { 1236 rc = ctrlCopyDirToHost(pContext, 1237 pszSource, pszFilter, 1238 pszDest, fFlags, pszNewSub); 1239 RTStrFree(pszNewSub); 1240 } 1241 else 1242 rc = VERR_NO_MEMORY; 1243 } 1244 break; 1245 } 1246 1247 case GuestDirEntryType_Symlink: 1248 if ( (fFlags & CopyFileFlag_Recursive) 1249 && (fFlags & CopyFileFlag_FollowLinks)) 1250 { 1251 /* Fall through to next case is intentional. */ 1252 } 1253 else 1254 break; 1255 1256 case GuestDirEntryType_File: 1257 { 1258 const char *pszName = Utf8Str(strName).c_str(); 1259 if ( !pszFilter 1260 || RTStrSimplePatternMatch(pszFilter, pszName)) 1261 { 1262 if (!fDirCreated) 1263 { 1264 char *pszDestDir; 1265 rc = ctrlCopyTranslatePath(pContext, pszSource, szCurDir, 1266 pszDest, &pszDestDir); 1267 if (RT_SUCCESS(rc)) 1268 { 1269 rc = ctrlCopyDirCreate(pContext, pszDestDir); 1270 RTStrFree(pszDestDir); 1271 1272 fDirCreated = true; 1273 } 1274 } 1275 1276 if (RT_SUCCESS(rc)) 1277 { 1278 Utf8Str strDir(strName); 1279 char *pszFileSource; 1280 if (RTStrAPrintf(&pszFileSource, "%s/%s", 1281 szCurDir, strDir.c_str())) 1282 { 1283 char *pszFileDest; 1284 rc = ctrlCopyTranslatePath(pContext, pszSource, pszFileSource, 1285 pszDest, &pszFileDest); 1286 if (RT_SUCCESS(rc)) 1287 { 1288 rc = ctrlCopyFileToTarget(pContext, pszFileSource, 1289 pszFileDest, 0 /* Flags? */); 1290 RTStrFree(pszFileDest); 1291 } 1292 RTStrFree(pszFileSource); 1293 } 1294 } 1295 } 1296 break; 1297 } 1298 1299 default: 1300 break; 1301 } 1302 } 1303 1304 hr = pContext->pGuest->DirectoryClose(uDirHandle); 1305 if (FAILED(rc)) 1306 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 1307 } 1308 1060 1309 return rc; 1061 1310 } 1062 1311 1063 static int ctrlCopyConstructDestinationsForHost(IGuest *pGuest, 1064 const char *pszUsername, const char *pszPassword, 1065 SOURCEFILEENTRY &sourceEntry, uint32_t fFlags, 1066 const char *pszDestRoot, DESTDIRMAP &mapDest, 1067 uint32_t *pcObjects) 1068 { 1069 int rc = VINF_SUCCESS; 1070 const char *pszSource = sourceEntry.mSource.c_str(); 1071 1072 BOOL fExists = FALSE; 1073 HRESULT hr = pGuest->FileExists(Bstr(pszSource).raw(), 1074 Bstr(pszUsername).raw(), Bstr(pszPassword).raw(), &fExists); 1075 if (FAILED(rc)) 1076 rc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 1312 static int ctrlCopyDirToTarget(PCOPYCONTEXT pContext, 1313 const char *pszSource, const char *pszFilter, 1314 const char *pszDest, uint32_t fFlags, 1315 const char *pszSubDir /* For recursion */) 1316 { 1317 if (pContext->fHostToGuest) 1318 return ctrlCopyDirToGuest(pContext, pszSource, pszFilter, 1319 pszDest, fFlags, pszSubDir); 1320 return ctrlCopyDirToHost(pContext, pszSource, pszFilter, 1321 pszDest, fFlags, pszSubDir); 1322 } 1323 1324 static int ctrlCopyCreateSourceRoot(const char *pszSource, char **ppszSourceRoot) 1325 { 1326 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 1327 AssertPtrReturn(ppszSourceRoot, VERR_INVALID_POINTER); 1328 1329 char *pszNewRoot = RTStrDup(pszSource); 1330 AssertPtrReturn(pszNewRoot, VERR_NO_MEMORY); 1331 1332 size_t lenRoot = strlen(pszNewRoot); 1333 if ( lenRoot 1334 && pszNewRoot[lenRoot - 1] == '/' 1335 && pszNewRoot[lenRoot - 1] == '\\' 1336 && lenRoot > 1 1337 && pszNewRoot[lenRoot - 2] == '/' 1338 && pszNewRoot[lenRoot - 2] == '\\') 1339 { 1340 *ppszSourceRoot = pszNewRoot; 1341 if (lenRoot > 1) 1342 *ppszSourceRoot[lenRoot - 2] = '\0'; 1343 *ppszSourceRoot[lenRoot - 1] = '\0'; 1344 } 1077 1345 else 1078 1346 { 1079 if (fExists) 1080 { 1081 /* Source is a single file. */ 1082 char *pszFileName = RTPathFilename(pszSource); 1083 mapDest[Utf8Str(pszDestRoot)].push_back(DESTFILEENTRY(pszFileName)); 1084 1085 *pcObjects++; 1086 } 1087 else 1088 { 1089 /* Source is either a directory or a filter (e.g. *.dll). */ 1090 rc = ctrlCopyDirectoryReadGuest(pGuest, pszUsername, pszPassword, 1091 pszSource, NULL /* pszSubDir */, 1092 sourceEntry.mFilter.isEmpty() ? NULL : sourceEntry.mFilter.c_str(), 1093 pszDestRoot, fFlags, pcObjects, mapDest); 1094 } 1095 } 1096 return rc; 1097 } 1098 1099 /** 1100 * Prepares the destination directory hirarchy on the guest side by creating the directories 1101 * and sets the appropriate access rights. 1102 * 1103 * @return IPRT status code. 1104 * @param pGuest IGuest interface pointer. 1105 * @param fHostToGuest 1106 * @param itDest Destination map iterator to process. 1107 * @param pszDestRoot Destination root to use. 1108 * @param pszUsername Username to use. 1109 * @param pszPassword Password to use. 1110 */ 1111 static int ctrlCopyPrepareDestDirectory(IGuest *pGuest, bool fHostToGuest, 1112 const char *pszDestRoot, const char *pszDestSub, 1113 const char *pszUsername, const char *pszPassword) 1114 { 1115 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 1116 AssertPtrReturn(pszDestRoot, VERR_INVALID_POINTER); 1117 AssertPtrReturn(pszDestSub, VERR_INVALID_POINTER); 1118 AssertPtrReturn(pszUsername, VERR_INVALID_POINTER); 1119 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 1120 1121 char *pszDestFinal = NULL; 1122 int rc = VINF_SUCCESS; 1123 1124 /* Create root directory (= empty name) and skip the rest for 1125 * this round. */ 1126 if (!strlen(pszDestSub)) 1127 { 1128 pszDestFinal = RTStrDup(pszDestRoot); 1129 if (!pszDestFinal) 1130 rc = VERR_NO_MEMORY; 1131 } 1132 else /* Create sub-directories, also empty ones. */ 1133 { 1134 if (!RTStrAPrintf(&pszDestFinal, "%s/%s", pszDestRoot, pszDestSub)) 1135 rc = VERR_NO_MEMORY; 1136 } 1137 1138 if (RT_SUCCESS(rc) && pszDestFinal) 1139 { 1140 if (fHostToGuest) /* We want to create directories on the guest. */ 1141 { 1142 HRESULT hrc = pGuest->DirectoryCreate(Bstr(pszDestFinal).raw(), 1143 Bstr(pszUsername).raw(), Bstr(pszPassword).raw(), 1144 700, DirectoryCreateFlag_Parents); 1145 if (FAILED(hrc)) 1146 rc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 1147 } 1148 else /* ... or on the host. */ 1149 { 1150 rc = RTDirCreate(pszDestFinal, 700); 1151 } 1152 RTStrFree(pszDestFinal); 1153 } 1154 return rc; 1155 } 1156 1157 /** 1158 * Copys a file from host to the guest. 1159 * 1160 * @return IPRT status code. 1161 * @param pGuest IGuest interface pointer. 1162 * @param pszSource Source path of existing host file to copy to the guest. 1163 * @param pszDest Destination path on guest to copy the file to. 1164 * @param pszUserName User name on guest to use for the copy operation. 1165 * @param pszPassword Password of user account. 1166 * @param fFlags Copy flags. 1167 */ 1168 static int ctrlCopyFileToGuest(IGuest *pGuest, const char *pszSource, const char *pszDest, 1169 const char *pszUserName, const char *pszPassword, 1170 uint32_t fFlags) 1171 { 1172 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 1173 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 1174 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 1175 AssertPtrReturn(pszUserName, VERR_INVALID_POINTER); 1176 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 1177 1178 int vrc = VINF_SUCCESS; 1179 ComPtr<IProgress> progress; 1180 HRESULT rc = pGuest->CopyToGuest(Bstr(pszSource).raw(), Bstr(pszDest).raw(), 1181 Bstr(pszUserName).raw(), Bstr(pszPassword).raw(), 1182 fFlags, progress.asOutParam()); 1183 if (FAILED(rc)) 1184 vrc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 1185 else 1186 { 1187 rc = showProgress(progress); 1188 if (FAILED(rc)) 1189 vrc = ctrlPrintProgressError(progress); 1190 } 1191 return vrc; 1192 } 1193 1194 /** 1195 * Copys a file from guest to the host. 1196 * 1197 * @return IPRT status code. 1198 * @param pGuest IGuest interface pointer. 1199 * @param pszSource Source path of existing guest file to copy to the host. 1200 * @param pszDest Destination path/file on host to copy the file to. 1201 * @param pszUserName User name on guest to use for the copy operation. 1202 * @param pszPassword Password of user account. 1203 * @param fFlags Copy flags. 1204 */ 1205 static int ctrlCopyFileToHost(IGuest *pGuest, const char *pszSource, const char *pszDest, 1206 const char *pszUserName, const char *pszPassword, 1207 uint32_t fFlags) 1208 { 1209 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 1210 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 1211 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 1212 AssertPtrReturn(pszUserName, VERR_INVALID_POINTER); 1213 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 1214 1215 int vrc = VINF_SUCCESS; 1216 ComPtr<IProgress> progress; 1217 HRESULT rc = pGuest->CopyFromGuest(Bstr(pszSource).raw(), Bstr(pszDest).raw(), 1218 Bstr(pszUserName).raw(), Bstr(pszPassword).raw(), 1219 fFlags, progress.asOutParam()); 1220 if (FAILED(rc)) 1221 vrc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 1222 else 1223 { 1224 rc = showProgress(progress); 1225 if (FAILED(rc)) 1226 vrc = ctrlPrintProgressError(progress); 1227 } 1228 return vrc; 1229 } 1230 1231 static int ctrlCopyToDestDirectory(IGuest *pGuest, bool fVerbose, bool fDryRun, bool fHostToGuest, 1232 const char *pszSourceDir, 1233 const char *pszDestRoot, const char *pszDestSub, const char *pszFileName, 1234 uint32_t uFlags, const char *pszUsername, const char *pszPassword) 1235 { 1236 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 1237 AssertPtrReturn(pszDestRoot, VERR_INVALID_POINTER); 1238 AssertPtrReturn(pszDestSub, VERR_INVALID_POINTER); 1239 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER); 1240 AssertPtrReturn(pszSourceDir, VERR_INVALID_POINTER); 1241 AssertPtrReturn(pszUsername, VERR_INVALID_POINTER); 1242 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 1243 1244 int iLen; 1245 char *pszSource; 1246 if (!strlen(pszDestSub)) 1247 iLen = RTStrAPrintf(&pszSource, "%s/%s", pszSourceDir, pszFileName); 1248 else 1249 iLen = RTStrAPrintf(&pszSource, "%s/%s/%s", 1250 pszSourceDir, pszDestSub, pszFileName); 1251 if (!iLen) 1252 return VERR_NO_MEMORY; 1253 1254 char *pszDest; 1255 if (!strlen(pszDestSub)) 1256 iLen = RTStrAPrintf(&pszDest, "%s/%s", pszDestRoot, pszFileName); 1257 else 1258 iLen = RTStrAPrintf(&pszDest, "%s/%s/%s", pszDestRoot, pszDestSub, 1259 pszFileName); 1260 if (!iLen) 1261 { 1262 RTStrFree(pszSource); 1263 return VERR_NO_MEMORY; 1264 } 1265 1266 if (fVerbose) 1267 RTPrintf("\"%s\" -> \"%s\"\n", pszSource, pszDest); 1268 1269 int rc = VINF_SUCCESS; 1270 1271 /* Finally copy the desired file (if no dry run selected). */ 1272 if (!fDryRun) 1273 { 1274 if (fHostToGuest) 1275 rc = ctrlCopyFileToGuest(pGuest, pszSource, pszDest, 1276 pszUsername, pszPassword, uFlags); 1277 else 1278 rc = ctrlCopyFileToHost(pGuest, pszSource, pszDest, 1279 pszUsername, pszPassword, uFlags); 1280 } 1281 RTStrFree(pszSource); 1282 RTStrFree(pszDest); 1283 1284 return rc; 1347 /* If there's anything (like a file name or a filter), 1348 * strip it! */ 1349 RTPathStripFilename(pszNewRoot); 1350 *ppszSourceRoot = pszNewRoot; 1351 } 1352 1353 return VINF_SUCCESS; 1354 } 1355 1356 static void ctrlCopyFreeSourceRoot(char *pszSourceRoot) 1357 { 1358 RTStrFree(pszSourceRoot); 1285 1359 } 1286 1360 … … 1415 1489 } 1416 1490 1417 /* Strip traling slash from destination path. */ 1418 RTPathStripTrailingSlash(Utf8Dest.mutableRaw()); 1419 Utf8Dest.jolt(); 1420 1421 /* 1422 * Here starts the actual fun! 1423 */ 1424 for (unsigned long s = 0; s < vecSources.size(); s++) 1425 { 1426 char *pszSourceDir; 1427 if (RTDirExists(vecSources[s].mSource.c_str())) 1428 pszSourceDir = RTStrDup(vecSources[s].mSource.c_str()); 1429 else 1430 { 1431 pszSourceDir = RTStrDup(vecSources[s].mSource.c_str()); 1432 RTPathStripFilename(pszSourceDir); 1433 } 1434 1435 uint32_t cObjects = 0; 1436 DESTDIRMAP mapDest; 1437 const char *pszDestRoot = Utf8Dest.c_str(); 1438 1439 if (fHostToGuest) 1440 vrc = ctrlCopyConstructDestinationsForGuest(vecSources[s], fFlags, pszDestRoot, 1441 mapDest, &cObjects); 1442 else 1443 vrc = ctrlCopyConstructDestinationsForHost(guest, Utf8UserName.c_str(), Utf8Password.c_str(), 1444 vecSources[s], fFlags, pszDestRoot, 1445 mapDest, &cObjects); 1446 if (RT_FAILURE(vrc)) 1447 { 1448 if ( fVerbose 1449 && vrc == VERR_FILE_NOT_FOUND) 1450 { 1451 RTPrintf("Warning: Source \"%s\" does not exist, skipping!\n", 1452 vecSources[s].mSource.c_str()); 1453 } 1454 } 1455 else 1456 { 1457 /* 1458 * Prepare directory structure of each destination directory. 1459 */ 1460 DESTDIRMAPITER itDest; 1461 for (itDest = mapDest.begin(); itDest != mapDest.end(); itDest++) 1462 { 1463 if (fVerbose) 1491 /* Create the copy context -- it contains all information 1492 * the routines need to know when handling the actual copying. */ 1493 PCOPYCONTEXT pContext; 1494 vrc = ctrlCopyContextCreate(guest, fVerbose, fHostToGuest, 1495 Utf8UserName.c_str(), Utf8Password.c_str(), 1496 &pContext); 1497 if (RT_FAILURE(vrc)) 1498 { 1499 RTMsgError("Unable to create copy context, rc=%Rrc\n", vrc); 1500 return RTEXITCODE_FAILURE; 1501 } 1502 1503 /* If the destination is a path, (try to) create it. */ 1504 const char *pszDest = Utf8Dest.c_str(); 1505 AssertPtr(pszDest); 1506 size_t lenDest = strlen(pszDest); 1507 if ( lenDest 1508 ||pszDest[lenDest - 1] == '/' 1509 || pszDest[lenDest - 1] == '\\') 1510 { 1511 vrc = ctrlCopyDirCreate(pContext, pszDest); 1512 } 1513 1514 if (RT_SUCCESS(vrc)) 1515 { 1516 /* 1517 * Here starts the actual fun! 1518 * Handle all given sources one by one. 1519 */ 1520 for (unsigned long s = 0; s < vecSources.size(); s++) 1521 { 1522 const char *pszSource = vecSources[s].mSource.c_str(); 1523 const char *pszFilter = vecSources[s].mFilter.c_str(); 1524 1525 char *pszSourceRoot; 1526 vrc = ctrlCopyCreateSourceRoot(pszSource, &pszSourceRoot); 1527 if (RT_FAILURE(vrc)) 1528 { 1529 RTMsgError("Unable to create source root, rc=%Rrc\n", vrc); 1530 break; 1531 } 1532 1533 if (fVerbose) 1534 RTPrintf("Source: %s\n", pszSource); 1535 1536 /* @todo Files with filter?? */ 1537 bool fExists; 1538 vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fExists); 1539 if (RT_SUCCESS(vrc)) 1540 { 1541 if (fExists) 1464 1542 { 1465 const char *pszSubDir = itDest->first.c_str(); 1466 AssertPtr(pszSubDir); 1467 if (!strlen(pszSubDir)) 1468 RTPrintf("Preparing directory \"%s\" ...\n", pszDestRoot); 1543 /* Single file. */ 1544 char *pszDest; 1545 vrc = ctrlCopyTranslatePath(pContext, pszSourceRoot, pszSource, 1546 Utf8Dest.c_str(), &pszDest); 1547 if (RT_SUCCESS(vrc)) 1548 { 1549 vrc = ctrlCopyFileToTarget(pContext, pszSource, 1550 pszDest, fFlags); 1551 RTStrFree(pszDest); 1552 } 1469 1553 else 1470 RTPrintf("Preparing directory \"%s/%s\" ...\n", pszDestRoot, 1471 itDest->first.c_str()); 1554 { 1555 RTMsgError("Unable to translate path for \"%s\", rc=%Rrc\n", 1556 pszSource, vrc); 1557 } 1472 1558 } 1473 if (!fDryRun) 1474 vrc = ctrlCopyPrepareDestDirectory(guest, fHostToGuest, 1475 pszDestRoot, itDest->first.c_str(), 1476 Utf8UserName.c_str(), Utf8Password.c_str()); 1477 if (RT_FAILURE(vrc)) 1478 break; 1559 else 1560 { 1561 if ( (RT_SUCCESS(ctrlCopyDirExistsOnSource(pContext, pszSource, &fExists)) 1562 && fExists) 1563 || ( RT_SUCCESS(ctrlCopyDirExistsOnSource(pContext, pszSourceRoot, &fExists)) 1564 && fExists 1565 && pszFilter) 1566 ) 1567 { 1568 /* Directory (with filter?). */ 1569 vrc = ctrlCopyDirToTarget(pContext, pszSource, pszFilter, 1570 Utf8Dest.c_str(), fFlags, NULL /* Subdir */); 1571 } 1572 } 1573 } 1574 1575 ctrlCopyFreeSourceRoot(pszSourceRoot); 1576 1577 if ( RT_SUCCESS(vrc) 1578 && !fExists) 1579 { 1580 RTMsgError("Warning: Source \"%s\" does not exist, skipping!\n", 1581 pszSource); 1582 continue; 1479 1583 } 1480 1584 1481 1585 if (RT_FAILURE(vrc)) 1482 break; 1483 1484 if (fVerbose) 1485 { 1486 if (!cObjects) 1487 RTPrintf("Warning: Source \"%s\" has no (matching) files to copy, skipping!\n", 1488 vecSources[s].mSource.c_str()); 1489 else 1490 RTPrintf("Copying \"%s\" (%u files) ...\n", 1491 vecSources[s].mSource.c_str(), cObjects); 1492 } 1493 1494 /* 1495 * Copy files of each destination root directory to the guest. 1496 */ 1497 for (itDest = mapDest.begin(); itDest != mapDest.end(); itDest++) 1498 { 1499 if (fVerbose && itDest->second.size()) 1500 { 1501 if (itDest->first.isEmpty()) 1502 RTPrintf("Copying %u files ...\n", itDest->second.size()); 1503 else 1504 RTPrintf("Copying directory \"%s\" (%u files) ...\n", 1505 itDest->first.c_str(), itDest->second.size()); 1506 } 1507 1508 for (unsigned long l = 0; l < itDest->second.size(); l++) 1509 { 1510 vrc = ctrlCopyToDestDirectory(guest, fVerbose, fDryRun, fHostToGuest, 1511 pszSourceDir, 1512 pszDestRoot, itDest->first.c_str() /* Sub directory */, 1513 itDest->second[l].mFileName.c_str() /* Filename */, 1514 fFlags, Utf8UserName.c_str(), Utf8Password.c_str()); 1515 if (RT_FAILURE(vrc)) 1516 break; 1517 } 1518 1519 if (RT_FAILURE(vrc)) 1520 break; 1521 } 1522 1523 if (RT_FAILURE(vrc)) 1524 break; 1525 } 1526 1527 RTStrFree(pszSourceDir); 1528 } 1586 { 1587 RTMsgError("Error processing \"%s\", rc=%Rrc\n", 1588 pszSource, vrc); 1589 break; 1590 } 1591 } 1592 } 1593 1594 ctrlCopyContextFree(pContext); 1529 1595 1530 1596 return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; … … 1632 1698 ctrlPrintError(guest, COM_IIDOF(IGuest)); /* Return code ignored, save original rc. */ 1633 1699 break; 1700 } 1701 1702 it++; 1703 } 1704 1705 if (FAILED(hrc)) 1706 rcExit = RTEXITCODE_FAILURE; 1707 } 1708 1709 return rcExit; 1710 } 1711 1712 static int handleCtrlStat(ComPtr<IGuest> guest, HandlerArg *pArg) 1713 { 1714 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER); 1715 1716 /* 1717 * Parse arguments. 1718 * 1719 * Note! No direct returns here, everyone must go thru the cleanup at the 1720 * end of this function. 1721 */ 1722 static const RTGETOPTDEF s_aOptions[] = 1723 { 1724 /** @todo Implement "--dereference/-L", and "--file-system/-f" later! */ 1725 { "--password", 'p', RTGETOPT_REQ_STRING }, 1726 { "--username", 'u', RTGETOPT_REQ_STRING }, 1727 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 1728 }; 1729 1730 int ch; 1731 RTGETOPTUNION ValueUnion; 1732 RTGETOPTSTATE GetState; 1733 RTGetOptInit(&GetState, pArg->argc, pArg->argv, 1734 s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST); 1735 1736 Utf8Str Utf8UserName; 1737 Utf8Str Utf8Password; 1738 1739 bool fVerbose = false; 1740 DESTDIRMAP mapDirs; 1741 1742 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 1743 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) 1744 && rcExit == RTEXITCODE_SUCCESS) 1745 { 1746 /* For options that require an argument, ValueUnion has received the value. */ 1747 switch (ch) 1748 { 1749 case 'p': /* Password */ 1750 Utf8Password = ValueUnion.psz; 1751 break; 1752 1753 case 'u': /* User name */ 1754 Utf8UserName = ValueUnion.psz; 1755 break; 1756 1757 case 'v': /* Verbose */ 1758 fVerbose = true; 1759 break; 1760 1761 case VINF_GETOPT_NOT_OPTION: 1762 { 1763 mapDirs[ValueUnion.psz]; /* Add element to check to map. */ 1764 break; 1765 } 1766 1767 default: 1768 rcExit = RTGetOptPrintError(ch, &ValueUnion); 1769 break; 1770 } 1771 } 1772 1773 uint32_t cDirs = mapDirs.size(); 1774 if (rcExit == RTEXITCODE_SUCCESS && !cDirs) 1775 rcExit = errorSyntax(USAGE_GUESTCONTROL, "No element to check specified!"); 1776 1777 if (rcExit == RTEXITCODE_SUCCESS && Utf8UserName.isEmpty()) 1778 rcExit = errorSyntax(USAGE_GUESTCONTROL, "No user name specified!"); 1779 1780 if (rcExit == RTEXITCODE_SUCCESS) 1781 { 1782 /* 1783 * Create the directories. 1784 */ 1785 HRESULT hrc = S_OK; 1786 1787 DESTDIRMAPITER it = mapDirs.begin(); 1788 while (it != mapDirs.end()) 1789 { 1790 if (fVerbose) 1791 RTPrintf("Checking for element \"%s\" ...\n", it->first.c_str()); 1792 1793 BOOL fExists; 1794 hrc = guest->FileExists(Bstr(it->first).raw(), 1795 Bstr(Utf8UserName).raw(), Bstr(Utf8Password).raw(), 1796 &fExists); 1797 if (FAILED(hrc)) 1798 { 1799 ctrlPrintError(guest, COM_IIDOF(IGuest)); /* Return code ignored, save original rc. */ 1800 break; 1801 } 1802 else 1803 { 1804 /** @todo: Output vbox_stat's stdout output to get more information about 1805 * what happened. */ 1806 1807 /* If there's at least one element which does not exist on the guest, 1808 * drop out with exitcode 1. */ 1809 if (!fExists) 1810 { 1811 RTPrintf("Cannot stat for element \"%s\": No such file or directory.\n", 1812 it->first.c_str()); 1813 rcExit = RTEXITCODE_FAILURE; 1814 } 1634 1815 } 1635 1816 … … 1772 1953 rcExit = handleCtrlExecProgram(guest, &arg); 1773 1954 } 1774 #if 01775 1955 else if (!strcmp(pArg->argv[1], "copyfrom")) 1776 1956 { … … 1778 1958 false /* Guest to host */); 1779 1959 } 1780 #endif1781 1960 else if ( !strcmp(pArg->argv[1], "copyto") 1782 1961 || !strcmp(pArg->argv[1], "cp")) … … 1792 1971 rcExit = handleCtrlCreateDirectory(guest, &arg); 1793 1972 } 1973 else if ( !strcmp(pArg->argv[1], "stat")) 1974 { 1975 rcExit = handleCtrlStat(guest, &arg); 1976 } 1794 1977 else if ( !strcmp(pArg->argv[1], "updateadditions") 1795 1978 || !strcmp(pArg->argv[1], "updateadds"))
Note:
See TracChangeset
for help on using the changeset viewer.