Changeset 36973 in vbox
- Timestamp:
- May 5, 2011 4:44:10 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r36887 r36973 44 44 #include <iprt/thread.h> 45 45 46 #include <map> 47 #include <vector> 48 46 49 #ifdef USE_XPCOM_QUEUE 47 50 # include <sys/select.h> … … 66 69 static volatile bool g_fGuestCtrlCanceled = false; 67 70 68 /* 69 * Structure holding a directory entry. 70 */ 71 typedef struct DIRECTORYENTRY 72 { 73 char *pszSourcePath; 74 char *pszDestPath; 75 RTLISTNODE Node; 76 } DIRECTORYENTRY, *PDIRECTORYENTRY; 71 typedef struct SOURCEFILEENTRY 72 { 73 SOURCEFILEENTRY(const char *pszSource, const char *pszFilter) 74 : mSource(pszSource), 75 mFilter(pszFilter) {} 76 SOURCEFILEENTRY(const char *pszSource) 77 : mSource(pszSource) 78 { 79 if ( !RTFileExists(pszSource) 80 && !RTDirExists(pszSource)) 81 { 82 /* No file and no directory -- maybe a filter? */ 83 if (NULL != strpbrk(RTPathFilename(pszSource), "*?")) 84 { 85 /* Yep, get the actual filter part. */ 86 mFilter = RTPathFilename(pszSource); 87 /* Remove the filter from actual sourcec directory name. */ 88 RTPathStripFilename(mSource.mutableRaw()); 89 mSource.jolt(); 90 } 91 } 92 } 93 Utf8Str mSource; 94 Utf8Str mFilter; 95 } SOURCEFILEENTRY, *PSOURCEFILEENTRY; 96 typedef std::vector<SOURCEFILEENTRY> SOURCEVEC, *PSOURCEVEC; 97 98 typedef struct DESTFILEENTRY 99 { 100 DESTFILEENTRY(Utf8Str strFileName) : mFileName(strFileName) {} 101 Utf8Str mFileName; 102 } DESTFILEENTRY, *PDESTFILEENTRY; 103 typedef std::map< Utf8Str, std::vector<DESTFILEENTRY> > DESTDIRMAP, *PDESTDIRMAP; 104 typedef std::map< Utf8Str, std::vector<DESTFILEENTRY> >::iterator DESTDIRMAPITER, *PDESTDIRMAPITER; 77 105 78 106 /** … … 491 519 492 520 case GETOPTDEF_EXEC_WAITFORSTDERR: 493 fWaitForExit = (fOutputFlags |= ProcessOutputFlag_StdErr) ;521 fWaitForExit = (fOutputFlags |= ProcessOutputFlag_StdErr) ? true : false; 494 522 break; 495 523 … … 735 763 736 764 /** 737 * Appends a new file/directory entry to a given list.738 *739 * @return IPRT status code.740 * @param pszFileSource Full qualified source path of file to copy (optional).741 * @param pszFileDest Full qualified destination path (optional).742 * @param pList Copy list used for insertion.743 *744 * @todo r=bird: Since everyone is maintaining an entry count, it would make745 * sense to abstract the list. To simplify cleanup work, it would be746 * preferable to use a standard C++ container template class.747 */748 static int ctrlDirectoryEntryAppend(const char *pszFileSource, const char *pszFileDest,749 PRTLISTNODE pList)750 {751 AssertPtrReturn(pList, VERR_INVALID_POINTER);752 AssertReturn(pszFileSource || pszFileDest, VERR_INVALID_PARAMETER);753 754 PDIRECTORYENTRY pNode = (PDIRECTORYENTRY)RTMemAlloc(sizeof(DIRECTORYENTRY));755 if (pNode == NULL)756 return VERR_NO_MEMORY;757 758 pNode->pszSourcePath = NULL;759 pNode->pszDestPath = NULL;760 761 if (pszFileSource)762 {763 pNode->pszSourcePath = RTStrDup(pszFileSource);764 AssertPtrReturn(pNode->pszSourcePath, VERR_NO_MEMORY);765 }766 if (pszFileDest)767 {768 pNode->pszDestPath = RTStrDup(pszFileDest);769 AssertPtrReturn(pNode->pszDestPath, VERR_NO_MEMORY);770 }771 772 pNode->Node.pPrev = NULL;773 pNode->Node.pNext = NULL;774 RTListAppend(pList, &pNode->Node);775 return VINF_SUCCESS;776 }777 778 /**779 * Destroys a directory list.780 *781 * @param pList Pointer to list to destroy.782 */783 static void ctrlDirectoryListDestroy(PRTLISTNODE pList)784 {785 AssertPtr(pList);786 787 /* Destroy file list. */788 PDIRECTORYENTRY pNode = RTListGetFirst(pList, DIRECTORYENTRY, Node);789 while (pNode)790 {791 PDIRECTORYENTRY pNext = RTListNodeGetNext(&pNode->Node, DIRECTORYENTRY, Node);792 bool fLast = RTListNodeIsLast(pList, &pNode->Node);793 794 if (pNode->pszSourcePath)795 RTStrFree(pNode->pszSourcePath);796 if (pNode->pszDestPath)797 RTStrFree(pNode->pszDestPath);798 RTListNodeRemove(&pNode->Node);799 RTMemFree(pNode);800 801 if (fLast)802 break;803 804 pNode = pNext;805 }806 }807 808 809 /**810 765 * Reads a specified directory (recursively) based on the copy flags 811 766 * and appends all matching entries to the supplied list. … … 821 776 * @param pcObjects Where to store the overall objects to 822 777 * copy found. 823 * @param pList Pointer to the object list to use. 778 * @param dirMap Reference to destination directory map to store found 779 * directories (primary key) + files (secondary key, vector). 824 780 */ 825 781 static int ctrlCopyDirectoryRead(const char *pszRootDir, const char *pszSubDir, 826 782 const char *pszFilter, const char *pszDest, 827 uint32_t fFlags, uint32_t *pcObjects, PRTLISTNODE pList)783 uint32_t fFlags, uint32_t *pcObjects, DESTDIRMAP &dirMap) 828 784 { 829 785 AssertPtrReturn(pszRootDir, VERR_INVALID_POINTER); … … 832 788 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 833 789 AssertPtrReturn(pcObjects, VERR_INVALID_POINTER); 834 AssertPtrReturn(pList, VERR_INVALID_POINTER);835 790 836 791 /* … … 880 835 char *pszNewSub = NULL; 881 836 if (pszSubDir) 882 RTStrAPrintf(&pszNewSub, "%s %s/", pszSubDir, DirEntry.szName);837 RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, DirEntry.szName); 883 838 else 884 RTStrAPrintf(&pszNewSub, "%s /", DirEntry.szName);839 RTStrAPrintf(&pszNewSub, "%s", DirEntry.szName); 885 840 886 841 if (pszNewSub) 887 842 { 843 dirMap[pszNewSub]; 844 888 845 rc = ctrlCopyDirectoryRead(pszRootDir, pszNewSub, 889 846 pszFilter, pszDest, 890 fFlags, pcObjects, pList);847 fFlags, pcObjects, dirMap); 891 848 RTStrFree(pszNewSub); 892 849 } … … 910 867 || RTStrSimplePatternMatch(pszFilter, DirEntry.szName)) 911 868 { 912 char *pszFileSource = NULL; 913 char *pszFileDest = NULL; 914 if (RTStrAPrintf(&pszFileSource, "%s%s%s", 915 pszRootDir, pszSubDir ? pszSubDir : "", 916 DirEntry.szName) >= 0) 917 { 918 if (RTStrAPrintf(&pszFileDest, "%s%s%s", 919 pszDest, pszSubDir ? pszSubDir : "", 920 DirEntry.szName) <= 0) 921 { 922 rc = VERR_NO_MEMORY; 923 } 924 } 925 else 926 rc = VERR_NO_MEMORY; 927 928 if (RT_SUCCESS(rc)) 929 { 930 rc = ctrlDirectoryEntryAppend(pszFileSource, pszFileDest, pList); 931 if (RT_SUCCESS(rc)) 932 *pcObjects += 1; 933 } 934 935 if (pszFileSource) 936 RTStrFree(pszFileSource); 937 if (pszFileDest) 938 RTStrFree(pszFileDest); 869 dirMap[pszSubDir].push_back(DESTFILEENTRY(Utf8Str(DirEntry.szName))); 870 *pcObjects += 1; 939 871 } 940 872 } … … 954 886 955 887 /** 956 * Initializes the copy process and builds up an object list 957 * with all required information to start the actual copy process. 888 * Constructs a destinations map from a source entry and a destination root. 958 889 * 959 890 * @return IPRT status code. 960 * @param pszSource Source path on host to use. 961 * @param pszDest Destination path on guest to use. 962 * @param fFlags Copy flags. 963 * @param pcObjects Where to store the count of objects to be copied. 964 * @param pList Where to store the object list. 965 */ 966 static int ctrlCopyInit(const char *pszSource, const char *pszDest, uint32_t fFlags, 967 uint32_t *pcObjects, PRTLISTNODE pList) 968 { 969 AssertPtrReturn(pszSource, VERR_INVALID_PARAMETER); 970 AssertPtrReturn(pszDest, VERR_INVALID_PARAMETER); 971 AssertPtrReturn(pcObjects, VERR_INVALID_PARAMETER); 972 AssertPtrReturn(pList, VERR_INVALID_PARAMETER); 973 891 * @param sourceEntry Reference to a specified source entry to use. 892 * @param fFlags Copy file flags. Needed for recursive directory parsing. 893 * @param pszDestRoot Pointer to destination root. This can be used to add one or 894 * more directories to the actual destination path. 895 * @param mapDest Reference to the destination map for storing the actual result. 896 * @param pcObjects Pointer to a total object (file) count to copy. 897 */ 898 static int ctrlCopyConstructDestinations(SOURCEFILEENTRY &sourceEntry, uint32_t fFlags, const char *pszDestRoot, 899 DESTDIRMAP &mapDest, uint32_t *pcObjects) 900 { 974 901 int rc = VINF_SUCCESS; 975 char *pszSourceAbs = RTPathAbsDup(pszSource); 976 if (pszSourceAbs) 977 { 978 if ( RTPathFilename(pszSourceAbs) 979 && RTFileExists(pszSourceAbs)) /* We have a single file ... */ 980 { 981 char *pszDestAbs = RTStrDup(pszDest); 982 if (pszDestAbs) 983 { 984 /* Do we have a trailing slash for the destination? 985 * Then this is a directory ... */ 986 size_t cch = strlen(pszDestAbs); 987 if ( cch > 1 988 && ( RTPATH_IS_SLASH(pszDestAbs[cch - 1]) 989 || RTPATH_IS_SLASH(pszDestAbs[cch - 2]) 990 ) 991 ) 992 { 993 rc = RTStrAAppend(&pszDestAbs, RTPathFilename(pszSourceAbs)); 994 } 995 else 996 { 997 /* Since the desetination seems not to be a directory, 998 * we assume that this is the absolute path to the destination 999 * file -> nothing to do here ... */ 1000 } 1001 1002 if (RT_SUCCESS(rc)) 1003 { 1004 rc = ctrlDirectoryEntryAppend(pszSourceAbs, pszDestAbs, pList); 1005 *pcObjects = 1; 1006 } 1007 RTStrFree(pszDestAbs); 1008 } 1009 else 1010 rc = VERR_NO_MEMORY; 1011 } 1012 else /* ... or a directory. */ 1013 { 1014 /* Append trailing slash to absolute directory. */ 1015 if (RTDirExists(pszSourceAbs)) 1016 RTStrAAppend(&pszSourceAbs, RTPATH_SLASH_STR); 1017 1018 /* Extract directory filter (e.g. "*.exe"). */ 1019 char *pszFilter = RTPathFilename(pszSourceAbs); 1020 char *pszSourceAbsRoot = RTStrDup(pszSourceAbs); 1021 char *pszDestAbs = RTStrDup(pszDest); 1022 if ( pszSourceAbsRoot 1023 && pszDestAbs) 1024 { 1025 if (pszFilter) 1026 { 1027 RTPathStripFilename(pszSourceAbsRoot); 1028 rc = RTStrAAppend(&pszSourceAbsRoot, RTPATH_SLASH_STR); 1029 } 1030 else 1031 { 1032 /* 1033 * If we have more than one file to copy, make sure that we have 1034 * a trailing slash so that we can construct a full path name 1035 * (e.g. "foo.txt" -> "c:/foo/temp.txt") as destination. 1036 */ 1037 size_t cch = strlen(pszSourceAbsRoot); 1038 if ( cch > 1 1039 && !RTPATH_IS_SLASH(pszSourceAbsRoot[cch - 1]) 1040 && !RTPATH_IS_SLASH(pszSourceAbsRoot[cch - 2])) 1041 { 1042 rc = RTStrAAppend(&pszSourceAbsRoot, RTPATH_SLASH_STR); 1043 } 1044 } 1045 1046 if (RT_SUCCESS(rc)) 1047 { 1048 /* 1049 * Make sure we have a valid destination path. All we can do 1050 * here is to check whether we have a trailing slash -- the rest 1051 * (i.e. path creation, rights etc.) needs to be done inside the guest. 1052 */ 1053 size_t cch = strlen(pszDestAbs); 1054 if ( cch > 1 1055 && !RTPATH_IS_SLASH(pszDestAbs[cch - 1]) 1056 && !RTPATH_IS_SLASH(pszDestAbs[cch - 2])) 1057 { 1058 rc = RTStrAAppend(&pszDestAbs, RTPATH_SLASH_STR); 1059 } 1060 } 1061 1062 if (RT_SUCCESS(rc)) 1063 { 1064 rc = ctrlCopyDirectoryRead(pszSourceAbsRoot, NULL /* Sub directory */, 1065 pszFilter, pszDestAbs, 1066 fFlags, pcObjects, pList); 1067 if (RT_SUCCESS(rc) && *pcObjects == 0) 1068 rc = VERR_NOT_FOUND; 1069 } 1070 1071 if (pszDestAbs) 1072 RTStrFree(pszDestAbs); 1073 if (pszSourceAbsRoot) 1074 RTStrFree(pszSourceAbsRoot); 1075 } 1076 else 1077 rc = VERR_NO_MEMORY; 1078 } 1079 RTStrFree(pszSourceAbs); 902 const char *pszSource = sourceEntry.mSource.c_str(); 903 if ( RTPathFilename(pszSource) 904 && RTFileExists(pszSource)) 905 { 906 /* Source is a single file. */ 907 char *pszFileName = RTPathFilename(pszSource); 908 mapDest[Utf8Str(pszDestRoot)].push_back(DESTFILEENTRY(pszFileName)); 909 910 *pcObjects++; 1080 911 } 1081 912 else 1082 rc = VERR_NO_MEMORY; 913 { 914 /* Source is either a directory or a filter (e.g. *.dll). */ 915 rc = ctrlCopyDirectoryRead(pszSource, 916 NULL /* pszSubDir */, 917 sourceEntry.mFilter.isEmpty() ? NULL : sourceEntry.mFilter.c_str(), 918 pszDestRoot, fFlags, pcObjects, mapDest); 919 } 920 return rc; 921 } 922 923 /** 924 * Determines the destination root for a specified source entry. 925 * 926 * @return IPRT status code. 927 * @param ppszDestRoot Receives pointer of allocated destination root. 928 * @param sourceEntry Source entry to determine the destination root for. 929 * @param pszDest Original destination string to use. 930 */ 931 static int ctrlCopyGetDestinationRoot(char **ppszDestRoot, SOURCEFILEENTRY &sourceEntry, const char *pszDest) 932 { 933 AssertPtrReturn(ppszDestRoot, VERR_INVALID_POINTER); 934 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 935 936 int rc = VINF_SUCCESS; 937 938 /* 939 * If a source filter is set (e.g. *.dll) use the original 940 * destination as our final root, because we want to copy all filtered 941 * files directly into the original root (and its sub directories if apply). 942 */ 943 char *pszDestRoot; 944 if (!sourceEntry.mFilter.isEmpty()) 945 pszDestRoot = RTStrDup(pszDest); 946 else 947 { 948 /* 949 * However, if no source filter is set we want to also copy the original 950 * source directory to our destination so that source "c:\foo", dest "c:\temp" 951 * becomes "c:\temp\foo". 952 */ 953 int iLen = RTStrAPrintf(&pszDestRoot, "%s/%s", 954 pszDest, RTPathFilename(sourceEntry.mSource.c_str())); 955 if (!iLen) 956 rc = VERR_NO_MEMORY; 957 } 958 959 if (RT_SUCCESS(rc)) 960 *ppszDestRoot = pszDestRoot; 961 return rc; 962 } 963 964 /** 965 * Prepares the destination directory hirarchy on the guest side by creating the directories 966 * and sets the appropriate access rights. 967 * 968 * @return IPRT status code. 969 * @param pGuest IGuest interface pointer. 970 * @param itDest Destination map iterator to process. 971 * @param pszDestRoot Destination root to use. 972 * @param pszUsername Username to use. 973 * @param pszPassword Password to use. 974 */ 975 static int ctrlCopyPrepareDestDirectory(IGuest *pGuest, DESTDIRMAPITER itDest, const char *pszDestRoot, 976 const char *pszUsername, const char *pszPassword) 977 { 978 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 979 AssertPtrReturn(pszDestRoot, VERR_INVALID_POINTER); 980 AssertPtrReturn(pszUsername, VERR_INVALID_POINTER); 981 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 982 983 ComPtr<IProgress> progress; 984 char *pszDestFinal = NULL; 985 int rc = VINF_SUCCESS; 986 987 /* Create root directory (= empty name) and skip the rest for 988 * this round. */ 989 if (itDest->first.isEmpty()) 990 { 991 pszDestFinal = RTStrDup(pszDestRoot); 992 if (!pszDestFinal) 993 rc = VERR_NO_MEMORY; 994 } 995 /* @todo Skip creating empty directories (or directories where a file filter (e.g. *.dll) 996 * did not find any files to copy. Make this configurable later! */ 997 else if (itDest->second.size()) 998 { 999 if (!RTStrAPrintf(&pszDestFinal, "%s/%s", pszDestRoot, itDest->first.c_str())) 1000 rc = VERR_NO_MEMORY; 1001 } 1002 1003 if (RT_SUCCESS(rc) && pszDestFinal) 1004 { 1005 HRESULT hrc = pGuest->CreateDirectory(Bstr(pszDestFinal).raw(), 1006 Bstr(pszUsername).raw(), Bstr(pszPassword).raw(), 1007 700, CreateDirectoryFlag_Parents, progress.asOutParam()); 1008 if (FAILED(hrc)) 1009 rc = ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 1010 RTStrFree(pszDestFinal); 1011 } 1083 1012 return rc; 1084 1013 } … … 1088 1017 * 1089 1018 * @return IPRT status code. 1090 * @param pGuest IGuest interface pointer. 1091 * @param fVerbose Verbose flag. 1092 * @param pszSource Source path of existing host file to copy. 1093 * @param pszDest Destination path on guest to copy the file to. 1094 * @param pszUserName User name on guest to use for the copy operation. 1095 * @param pszPassword Password of user account. 1096 * @param fFlags Copy flags. 1097 */ 1098 static int ctrlCopyFileToGuest(IGuest *pGuest, bool fVerbose, const char *pszSource, const char *pszDest, 1019 * @param pGuest IGuest interface pointer. 1020 * @param pszSource Source path of existing host file to copy. 1021 * @param pszDest Destination path on guest to copy the file to. 1022 * @param pszUserName User name on guest to use for the copy operation. 1023 * @param pszPassword Password of user account. 1024 * @param fFlags Copy flags. 1025 */ 1026 static int ctrlCopyFileToGuest(IGuest *pGuest, const char *pszSource, const char *pszDest, 1099 1027 const char *pszUserName, const char *pszPassword, 1100 1028 uint32_t fFlags) 1101 1029 { 1102 AssertPtrReturn(pGuest, VERR_INVALID_P ARAMETER);1103 AssertPtrReturn(pszSource, VERR_INVALID_P ARAMETER);1104 AssertPtrReturn(pszDest, VERR_INVALID_P ARAMETER);1105 AssertPtrReturn(pszUserName, VERR_INVALID_P ARAMETER);1106 AssertPtrReturn(pszPassword, VERR_INVALID_P ARAMETER);1030 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 1031 AssertPtrReturn(pszSource, VERR_INVALID_POINTER); 1032 AssertPtrReturn(pszDest, VERR_INVALID_POINTER); 1033 AssertPtrReturn(pszUserName, VERR_INVALID_POINTER); 1034 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 1107 1035 1108 1036 int vrc = VINF_SUCCESS; … … 1122 1050 } 1123 1051 1052 1053 static int ctrlCopyToDestDirectory(IGuest *pGuest, bool fVerbose, DESTDIRMAPITER itDest, const char *pszDestRoot, 1054 SOURCEFILEENTRY &sourceEntry, uint32_t uFlags, const char *pszUsername, const char *pszPassword) 1055 { 1056 AssertPtrReturn(pGuest, VERR_INVALID_POINTER); 1057 AssertPtrReturn(pszDestRoot, VERR_INVALID_POINTER); 1058 AssertPtrReturn(pszUsername, VERR_INVALID_POINTER); 1059 AssertPtrReturn(pszPassword, VERR_INVALID_POINTER); 1060 1061 int rc = VINF_SUCCESS; 1062 for (unsigned long l = 0; l < itDest->second.size(); l++) 1063 { 1064 int iLen; 1065 char *pszSource; 1066 if (itDest->first.isEmpty()) 1067 iLen = RTStrAPrintf(&pszSource, "%s/%s", sourceEntry.mSource.c_str(), 1068 itDest->second[l].mFileName.c_str()); 1069 else 1070 iLen = RTStrAPrintf(&pszSource, "%s/%s/%s", sourceEntry.mSource.c_str(), 1071 itDest->first.c_str(), itDest->second[l].mFileName.c_str()); 1072 if (!iLen) 1073 { 1074 rc = VERR_NO_MEMORY; 1075 break; 1076 } 1077 1078 char *pszDest; 1079 if (itDest->first.isEmpty()) 1080 iLen = RTStrAPrintf(&pszDest, "%s/%s", pszDestRoot, 1081 itDest->second[l].mFileName.c_str()); 1082 else 1083 iLen = RTStrAPrintf(&pszDest, "%s/%s/%s", pszDestRoot, itDest->first.c_str(), 1084 itDest->second[l].mFileName.c_str()); 1085 if (!iLen) 1086 { 1087 rc = VERR_NO_MEMORY; 1088 RTStrFree(pszSource); 1089 break; 1090 } 1091 1092 if (fVerbose) 1093 RTPrintf("\"%s\" -> \"%s\"\n", pszSource, pszDest); 1094 1095 /* Finally copy the desired file (if no dry run selected). */ 1096 rc = ctrlCopyFileToGuest(pGuest, pszSource, pszDest, 1097 pszUsername, pszPassword, uFlags); 1098 RTStrFree(pszSource); 1099 RTStrFree(pszDest); 1100 } 1101 return rc; 1102 } 1103 1124 1104 static int handleCtrlCopyTo(ComPtr<IGuest> guest, HandlerArg *pArg) 1125 1105 { … … 1167 1147 bool fDryRun = false; 1168 1148 1169 RTLISTNODE listSources; 1170 uint32_t cSources = 0; 1171 RTListInit(&listSources); 1149 SOURCEVEC vecSources; 1172 1150 1173 1151 int vrc = VINF_SUCCESS; … … 1217 1195 else 1218 1196 { 1219 vrc = ctrlDirectoryEntryAppend(ValueUnion.psz, /* Source */ 1220 NULL, /* No destination given */ 1221 &listSources); 1222 if (RT_SUCCESS(vrc)) 1223 { 1224 cSources++; 1225 if (cSources == UINT32_MAX) 1226 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many sources specified! Aborting."); 1227 } 1228 else 1229 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Failed to append source: %Rrc", vrc); 1197 /* Save the source directory. */ 1198 vecSources.push_back(SOURCEFILEENTRY(ValueUnion.psz)); 1230 1199 } 1231 1200 break; … … 1237 1206 } 1238 1207 1239 if (! cSources)1208 if (!vecSources.size()) 1240 1209 return errorSyntax(USAGE_GUESTCONTROL, 1241 1210 "No source(s) specified!"); … … 1250 1219 1251 1220 /* 1252 * Done parsing arguments, do s tuff.1221 * Done parsing arguments, do some more preparations. 1253 1222 */ 1254 HRESULT rc = S_OK;1255 1223 if (fVerbose) 1256 1224 { 1257 1225 if (fDryRun) 1258 1226 RTPrintf("Dry run - no files copied!\n"); 1259 RTPrintf("Gathering file information ...\n"); 1260 } 1261 1262 RTLISTNODE listToCopy; 1263 RTListInit(&listToCopy); 1264 uint32_t cTotalObjects = 0; 1265 1266 PDIRECTORYENTRY pNodeSource; 1267 RTListForEach(&listSources, pNodeSource, DIRECTORYENTRY, Node) 1227 } 1228 1229 /* Strip traling slash from destination path. */ 1230 RTPathStripTrailingSlash(Utf8Dest.mutableRaw()); 1231 Utf8Dest.jolt(); 1232 1233 /* 1234 * Here starts the actual fun! 1235 */ 1236 for (unsigned long s = 0; s < vecSources.size(); s++) 1268 1237 { 1269 1238 uint32_t cObjects = 0; 1270 vrc = ctrlCopyInit(pNodeSource->pszSourcePath, Utf8Dest.c_str(), fFlags, 1271 &cObjects, &listToCopy); 1272 if (RT_FAILURE(vrc)) 1273 { 1274 switch (vrc) 1239 DESTDIRMAP mapDest; 1240 1241 char *pszDestRoot; 1242 vrc = ctrlCopyGetDestinationRoot(&pszDestRoot, vecSources[s], Utf8Dest.c_str()); 1243 if (RT_SUCCESS(vrc)) 1244 { 1245 vrc = ctrlCopyConstructDestinations(vecSources[s], fFlags, pszDestRoot, 1246 mapDest, &cObjects); 1247 if (RT_FAILURE(vrc)) 1275 1248 { 1276 case VERR_NOT_FOUND: 1277 /* Not fatal, just continue to the next source entry (if available). */ 1278 continue; 1279 1280 case VERR_FILE_NOT_FOUND: 1281 RTMsgError("Source path \"%s\" not found!\n", Utf8Source.c_str()); 1282 break; 1283 1284 default: 1285 RTMsgError("Failed to initialize, rc=%Rrc\n", vrc); 1286 break; 1249 if ( fVerbose 1250 && vrc == VERR_FILE_NOT_FOUND) 1251 { 1252 RTPrintf("Warning: Source \"\%s\" does not exist, skipping!\n", 1253 vecSources[s].mSource.c_str()); 1254 } 1287 1255 } 1288 } 1289 else if (fVerbose) 1290 { 1291 RTPrintf("Source \"%s\" has %ld elements to copy\n", 1292 pNodeSource->pszSourcePath, cObjects); 1293 } 1294 cTotalObjects += cObjects; 1295 } 1296 1297 if (fVerbose && cTotalObjects) 1298 RTPrintf("Total %ld elements to copy to \"%s\"\n", 1299 cTotalObjects, Utf8Dest.c_str()); 1300 1301 if (cTotalObjects) 1302 { 1303 PDIRECTORYENTRY pNode; 1304 uint32_t uCurObject = 1; 1305 1306 RTListForEach(&listToCopy, pNode, DIRECTORYENTRY, Node) 1307 { 1308 if (fVerbose) 1309 RTPrintf("Copying \"%s\" to \"%s\" (%u/%u) ...\n", 1310 pNode->pszSourcePath, pNode->pszDestPath, uCurObject, cTotalObjects); 1311 /* Finally copy the desired file (if no dry run selected). */ 1312 if (!fDryRun) 1313 vrc = ctrlCopyFileToGuest(guest, fVerbose, pNode->pszSourcePath, pNode->pszDestPath, 1314 Utf8UserName.c_str(), Utf8Password.c_str(), fFlags); 1315 if (RT_FAILURE(vrc)) 1316 break; 1317 uCurObject++; 1318 } 1319 1320 Assert(cTotalObjects >= uCurObject - 1); 1321 if (cTotalObjects != uCurObject - 1) 1322 RTPrintf("Warning: %u elements instead of %ld were copied!\n", 1323 uCurObject - 1, cTotalObjects); 1324 else if (RT_SUCCESS(vrc) && fVerbose) 1325 RTPrintf("Copy operation successful!\n"); 1326 } 1327 1328 ctrlDirectoryListDestroy(&listToCopy); 1329 ctrlDirectoryListDestroy(&listSources); 1330 1331 if (RT_FAILURE(vrc)) 1332 rc = VBOX_E_IPRT_ERROR; 1333 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 1256 else 1257 { 1258 /* 1259 * Prepare directory structure of each destination directory. 1260 */ 1261 DESTDIRMAPITER itDest; 1262 ComPtr<IProgress> progress; 1263 for (itDest = mapDest.begin(); itDest != mapDest.end(); itDest++) 1264 { 1265 if (!fDryRun) 1266 vrc = ctrlCopyPrepareDestDirectory(guest, itDest, pszDestRoot, 1267 Utf8UserName.c_str(), Utf8Password.c_str()); 1268 if (RT_FAILURE(vrc)) 1269 break; 1270 } 1271 1272 if (fVerbose) 1273 { 1274 if (!cObjects) 1275 RTPrintf("Warning: Source \"%s\" has no (matching) files to copy, skipping!\n", 1276 vecSources[s].mSource.c_str()); 1277 else 1278 RTPrintf("Copying \"%s\" (%u files) ...\n", 1279 vecSources[s].mSource.c_str(), cObjects); 1280 } 1281 1282 /* 1283 * Copy files of each destination root directory to the guest. 1284 */ 1285 for (itDest = mapDest.begin(); itDest != mapDest.end(); itDest++) 1286 { 1287 if (fVerbose && itDest->second.size()) 1288 { 1289 if (itDest->first.isEmpty()) 1290 RTPrintf("Copying %u files ...\n", itDest->second.size()); 1291 else 1292 RTPrintf("Copying directory \"%s\" (%u files) ...\n", 1293 itDest->first.c_str(), itDest->second.size()); 1294 } 1295 1296 if (!fDryRun) 1297 vrc = ctrlCopyToDestDirectory(guest, fVerbose, itDest, pszDestRoot, 1298 vecSources[s], fFlags, Utf8UserName.c_str(), Utf8Password.c_str()); 1299 if (RT_FAILURE(vrc)) 1300 break; 1301 } 1302 } 1303 RTStrFree(pszDestRoot); 1304 } 1305 } 1306 1307 return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 1334 1308 } 1335 1309 … … 1365 1339 bool fVerbose = false; 1366 1340 1367 RTLISTNODE listDirs; 1368 uint32_t cDirs = 0; 1369 RTListInit(&listDirs); 1341 DESTDIRMAP mapDirs; 1370 1342 1371 1343 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; … … 1398 1370 case VINF_GETOPT_NOT_OPTION: 1399 1371 { 1400 int vrc = ctrlDirectoryEntryAppend(NULL, /* No source given */ 1401 ValueUnion.psz, /* Destination */ 1402 &listDirs); 1403 if (RT_SUCCESS(vrc)) 1404 { 1405 cDirs++; 1406 if (cDirs == UINT32_MAX) 1407 rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many directories specified! Aborting."); 1408 } 1409 else 1410 rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "Failed to append directory: %Rrc", vrc); 1372 mapDirs[ValueUnion.psz]; /* Add destination directory to map. */ 1411 1373 break; 1412 1374 } … … 1418 1380 } 1419 1381 1382 uint32_t cDirs = mapDirs.size(); 1420 1383 if (rcExit == RTEXITCODE_SUCCESS && !cDirs) 1421 1384 rcExit = errorSyntax(USAGE_GUESTCONTROL, "No directory to create specified!"); … … 1430 1393 */ 1431 1394 HRESULT hrc = S_OK; 1432 if (fVerbose && cDirs > 1)1395 if (fVerbose && cDirs) 1433 1396 RTPrintf("Creating %u directories ...\n", cDirs); 1434 1397 1435 PDIRECTORYENTRY pNode;1436 RTListForEach(&listDirs, pNode, DIRECTORYENTRY, Node)1398 DESTDIRMAPITER it = mapDirs.begin(); 1399 while (it != mapDirs.end()) 1437 1400 { 1438 1401 if (fVerbose) 1439 RTPrintf("Creating directory \"%s\" ...\n", pNode->pszDestPath);1402 RTPrintf("Creating directory \"%s\" ...\n", it->first.c_str()); 1440 1403 1441 1404 ComPtr<IProgress> progress; 1442 hrc = guest->CreateDirectory(Bstr( pNode->pszDestPath).raw(),1405 hrc = guest->CreateDirectory(Bstr(it->first).raw(), 1443 1406 Bstr(Utf8UserName).raw(), Bstr(Utf8Password).raw(), 1444 1407 fDirMode, fFlags, progress.asOutParam()); 1445 1408 if (FAILED(hrc)) 1446 1409 { 1447 ctrlPrintError(guest, COM_IIDOF(IGuest)); /* (return code ignored, save original rc)*/1410 ctrlPrintError(guest, COM_IIDOF(IGuest)); /* Return code ignored, save original rc. */ 1448 1411 break; 1449 1412 } 1450 } 1413 1414 it++; 1415 } 1416 1451 1417 if (FAILED(hrc)) 1452 1418 rcExit = RTEXITCODE_FAILURE; 1453 1419 } 1454 1455 /*1456 * Clean up and return.1457 */1458 ctrlDirectoryListDestroy(&listDirs);1459 1420 1460 1421 return rcExit;
Note:
See TracChangeset
for help on using the changeset viewer.