Changeset 36609 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Apr 7, 2011 9:20:29 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 71056
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r36227 r36609 108 108 GETOPTDEF_EXEC_WAITFORSTDOUT, 109 109 GETOPTDEF_EXEC_WAITFORSTDERR 110 }; 111 112 enum GETOPTDEF_COPYTO 113 { 114 GETOPTDEF_COPYTO_DRYRUN = 1000, 115 GETOPTDEF_COPYTO_FOLLOW, 116 GETOPTDEF_COPYTO_PASSWORD, 117 GETOPTDEF_COPYTO_TARGETDIR, 118 GETOPTDEF_COPYTO_USERNAME 110 119 }; 111 120 … … 488 497 case VINF_GETOPT_NOT_OPTION: 489 498 { 490 #if 0 /** @todo r=bird: enable this when the argv[0] issue has been addressed. */491 499 if (args.size() == 0 && Utf8Cmd.isEmpty()) 492 500 Utf8Cmd = ValueUnion.psz; 493 501 args.push_back(Bstr(ValueUnion.psz).raw()); 494 #else495 if (Utf8Cmd.isEmpty())496 {497 Utf8Cmd = ValueUnion.psz;498 if (Utf8Cmd.isEmpty())499 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The first argument cannot be empty yet, wait for 4.1.0");500 }501 else502 args.push_back(Bstr(ValueUnion.psz).raw());503 #endif504 502 break; 505 503 } … … 1006 1004 if (RT_SUCCESS(rc)) 1007 1005 { 1008 RTListInit(pList);1009 1006 rc = ctrlDirectoryEntryAppend(pszSourceAbs, pszDestAbs, pList); 1010 1007 *pcObjects = 1; … … 1067 1064 if (RT_SUCCESS(rc)) 1068 1065 { 1069 RTListInit(pList);1070 1066 rc = ctrlCopyDirectoryRead(pszSourceAbsRoot, NULL /* Sub directory */, 1071 1067 pszFilter, pszDestAbs, … … 1140 1136 * wildcard expansion by a unix shell. The best solution here would be 1141 1137 * two different variant, one windowsy (xcopy) and one unixy (gnu cp). */ 1142 /** @todo r=bird: Why isn't IGuest::CopyToGuest powerful enough to do 1143 * all this recursive copying? */ 1138 1139 /* 1140 * IGuest::CopyToGuest is kept as simple as possible to let the developer choose 1141 * what and how to implement the file enumeration/recursive lookup, like VBoxManage 1142 * does in here. 1143 */ 1144 1144 1145 1145 static const RTGETOPTDEF s_aOptions[] = 1146 1146 { 1147 { "--dryrun", 'd', RTGETOPT_REQ_NOTHING }, /**< @todo r=bird: '-d' incompatible with GNU cp. */ 1148 { "--follow", 'F', RTGETOPT_REQ_NOTHING }, /**< @todo r=bird: This isn't a GNU cp option. This is instead spread over several options. */ 1149 { "--password", 'p', RTGETOPT_REQ_STRING }, /**< @todo r=bird: Just drop these short options since (BSD, GNU, ++) cp uses '-p' to indicate that ownership, timestamp and other stuff should be preserved. Other file commands probably use '-p' as well. */ 1150 { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, /**< @todo r=bird: Most cp implementations treats '-r' as an alias for '-R'. */ 1151 { "--username", 'u', RTGETOPT_REQ_STRING }, /**< @todo r=bird: Just drop these short options since GNU cp uses '-u' to indicate update-only (as does 4nt). Other file commands probably uses '-u' as well. */ 1152 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 1147 { "--dryrun", GETOPTDEF_COPYTO_DRYRUN, RTGETOPT_REQ_NOTHING }, 1148 { "--follow", GETOPTDEF_COPYTO_FOLLOW, RTGETOPT_REQ_NOTHING }, 1149 { "--password", GETOPTDEF_COPYTO_PASSWORD, RTGETOPT_REQ_STRING }, 1150 { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, 1151 { "--target-directory", GETOPTDEF_COPYTO_TARGETDIR, RTGETOPT_REQ_STRING }, 1152 { "--username", GETOPTDEF_COPYTO_USERNAME, RTGETOPT_REQ_STRING }, 1153 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 1153 1154 }; 1154 1155 … … 1156 1157 RTGETOPTUNION ValueUnion; 1157 1158 RTGETOPTSTATE GetState; 1158 RTGetOptInit(&GetState, pArg->argc, pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); 1159 RTGetOptInit(&GetState, pArg->argc, pArg->argv, 1160 s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST); 1159 1161 1160 1162 Utf8Str Utf8Source; … … 1167 1169 bool fDryRun = false; 1168 1170 1171 RTLISTNODE listSources; 1172 uint32_t cSources = 0; 1173 RTListInit(&listSources); 1174 1169 1175 int vrc = VINF_SUCCESS; 1170 uint32_t idxNonOption = 0;1171 1176 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 1172 1177 { … … 1174 1179 switch (ch) 1175 1180 { 1176 case 'd': /* Dry run */1181 case GETOPTDEF_COPYTO_DRYRUN: 1177 1182 fDryRun = true; 1178 1183 break; 1179 1184 1180 case 'F': /* Follow symlinks */1185 case GETOPTDEF_COPYTO_FOLLOW: 1181 1186 fFlags |= CopyFileFlag_FollowLinks; 1182 1187 break; 1183 1188 1184 case 'p': /* Password */1189 case GETOPTDEF_COPYTO_PASSWORD: 1185 1190 Utf8Password = ValueUnion.psz; 1186 1191 break; … … 1190 1195 break; 1191 1196 1192 case 'u': /* User name */ 1197 case GETOPTDEF_COPYTO_TARGETDIR: 1198 Utf8Dest = ValueUnion.psz; 1199 break; 1200 1201 case GETOPTDEF_COPYTO_USERNAME: 1193 1202 Utf8UserName = ValueUnion.psz; 1194 1203 break; … … 1200 1209 case VINF_GETOPT_NOT_OPTION: 1201 1210 { 1202 /* Get the actual source + destination. */ 1203 switch (idxNonOption) 1211 /* Last argument and no destination specified with 1212 * --target-directory yet? Then use the current argument 1213 * as destination. */ 1214 if ( pArg->argc == GetState.iNext 1215 && Utf8Dest.isEmpty()) 1204 1216 { 1205 case 0: 1206 Utf8Source = ValueUnion.psz; 1207 break; 1208 1209 case 1: 1210 Utf8Dest = ValueUnion.psz; 1211 break; 1212 1213 /* @todo r=bird: VBoxManage guestcontrol execute <VMName> copyto hostfile.1 hostfile.2 hostfile.3 guestdir/ 1214 * A better way to implement this would be to tell RTGetOptInit to sort the argument, so 1215 * that when VINF_GETOPT_NOT_OPTION is returned, the remainder of pArg->argv are all arguments. */ 1216 1217 default: 1218 return errorSyntax(USAGE_GUESTCONTROL, "Too many parameters specified, only source and destination allowed!"); 1217 Utf8Dest = ValueUnion.psz; 1219 1218 } 1220 idxNonOption++; 1221 if (idxNonOption == UINT32_MAX) 1222 return errorSyntax(USAGE_GUESTCONTROL, "Too many files specified!"); 1219 else 1220 { 1221 int vrc = ctrlDirectoryEntryAppend(ValueUnion.psz, /* Source */ 1222 NULL, /* No destination given */ 1223 &listSources); 1224 if (RT_SUCCESS(vrc)) 1225 { 1226 cSources++; 1227 if (cSources == UINT32_MAX) 1228 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many sources specified! Aborting."); 1229 } 1230 else 1231 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Failed to append source: %Rrc", vrc); 1232 } 1223 1233 break; 1224 1234 } … … 1229 1239 } 1230 1240 1231 if ( Utf8Source.isEmpty())1241 if (!cSources) 1232 1242 return errorSyntax(USAGE_GUESTCONTROL, 1233 "No source specified!");1243 "No source(s) specified!"); 1234 1244 1235 1245 if (Utf8Dest.isEmpty()) … … 1253 1263 1254 1264 RTLISTNODE listToCopy; 1255 uint32_t cObjects = 0; 1256 vrc = ctrlCopyInit(Utf8Source.c_str(), Utf8Dest.c_str(), fFlags, 1257 &cObjects, &listToCopy); 1258 if (RT_FAILURE(vrc)) 1259 { 1260 switch (vrc) 1261 { 1262 case VERR_NOT_FOUND: 1263 RTMsgError("No files to copy found!\n"); 1264 break; 1265 1266 case VERR_FILE_NOT_FOUND: 1267 RTMsgError("Source path \"%s\" not found!\n", Utf8Source.c_str()); 1268 break; 1269 1270 default: 1271 RTMsgError("Failed to initialize, rc=%Rrc\n", vrc); 1272 break; 1273 } 1274 } 1275 else 1265 RTListInit(&listToCopy); 1266 uint32_t cTotalObjects = 0; 1267 1268 PDIRECTORYENTRY pNodeSource; 1269 RTListForEach(&listSources, pNodeSource, DIRECTORYENTRY, Node) 1270 { 1271 uint32_t cObjects = 0; 1272 vrc = ctrlCopyInit(pNodeSource->pszSourcePath, Utf8Dest.c_str(), fFlags, 1273 &cObjects, &listToCopy); 1274 if (RT_FAILURE(vrc)) 1275 { 1276 switch (vrc) 1277 { 1278 case VERR_NOT_FOUND: 1279 /* Not fatal, just continue to the next source entry (if available). */ 1280 continue; 1281 1282 case VERR_FILE_NOT_FOUND: 1283 RTMsgError("Source path \"%s\" not found!\n", Utf8Source.c_str()); 1284 break; 1285 1286 default: 1287 RTMsgError("Failed to initialize, rc=%Rrc\n", vrc); 1288 break; 1289 } 1290 } 1291 else if (fVerbose) 1292 { 1293 RTPrintf("Source \"%s\" has %ld elements to copy\n", 1294 pNodeSource->pszSourcePath, cObjects); 1295 } 1296 cTotalObjects += cObjects; 1297 } 1298 1299 if (fVerbose && cTotalObjects) 1300 RTPrintf("Total %ld elements to copy to \"%s\"\n", 1301 cTotalObjects, Utf8Dest.c_str()); 1302 1303 if (cTotalObjects) 1276 1304 { 1277 1305 PDIRECTORYENTRY pNode; 1278 if (RT_SUCCESS(vrc)) 1306 uint32_t uCurObject = 1; 1307 1308 RTListForEach(&listToCopy, pNode, DIRECTORYENTRY, Node) 1279 1309 { 1280 1310 if (fVerbose) 1281 { 1282 if (fCopyRecursive) 1283 RTPrintf("Recursively copying \"%s\" to \"%s\" (%u file(s)) ...\n", 1284 Utf8Source.c_str(), Utf8Dest.c_str(), cObjects); 1285 else 1286 RTPrintf("Copying \"%s\" to \"%s\" (%u file(s)) ...\n", 1287 Utf8Source.c_str(), Utf8Dest.c_str(), cObjects); 1288 } 1289 1290 uint32_t iObject = 1; 1291 RTListForEach(&listToCopy, pNode, DIRECTORYENTRY, Node) 1292 { 1293 if (!fDryRun) 1294 { 1295 if (fVerbose) 1296 RTPrintf("Copying \"%s\" to \"%s\" (%u/%u) ...\n", 1297 pNode->pszSourcePath, pNode->pszDestPath, iObject, cObjects); 1298 /* Finally copy the desired file (if no dry run selected). */ 1299 if (!fDryRun) 1300 vrc = ctrlCopyFileToGuest(guest, fVerbose, pNode->pszSourcePath, pNode->pszDestPath, 1301 Utf8UserName.c_str(), Utf8Password.c_str(), fFlags); 1302 } 1303 if (RT_FAILURE(vrc)) 1304 break; 1305 iObject++; 1306 } 1307 if (RT_SUCCESS(vrc) && fVerbose) 1308 RTPrintf("Copy operation successful!\n"); 1309 } 1310 ctrlDirectoryListDestroy(&listToCopy); 1311 } 1311 RTPrintf("Copying \"%s\" to \"%s\" (%u/%u) ...\n", 1312 pNode->pszSourcePath, pNode->pszDestPath, uCurObject, cTotalObjects); 1313 /* Finally copy the desired file (if no dry run selected). */ 1314 if (!fDryRun) 1315 vrc = ctrlCopyFileToGuest(guest, fVerbose, pNode->pszSourcePath, pNode->pszDestPath, 1316 Utf8UserName.c_str(), Utf8Password.c_str(), fFlags); 1317 if (RT_FAILURE(vrc)) 1318 break; 1319 uCurObject++; 1320 } 1321 Assert(cTotalObjects == uCurObject - 1); 1322 1323 if (RT_SUCCESS(vrc) && fVerbose) 1324 RTPrintf("Copy operation successful!\n"); 1325 } 1326 1327 ctrlDirectoryListDestroy(&listToCopy); 1328 ctrlDirectoryListDestroy(&listSources); 1312 1329 1313 1330 if (RT_FAILURE(vrc)) … … 1338 1355 RTGETOPTUNION ValueUnion; 1339 1356 RTGETOPTSTATE GetState; 1340 RTGetOptInit(&GetState, pArg->argc, pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); 1357 RTGetOptInit(&GetState, pArg->argc, pArg->argv, 1358 s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST); 1341 1359 1342 1360 Utf8Str Utf8UserName; 1343 1361 Utf8Str Utf8Password; 1344 1362 uint32_t fFlags = CreateDirectoryFlag_None; 1345 uint32_t fDirMode = 0; /* 0 == default mode, right?*/1363 uint32_t fDirMode = 0; /* Default mode. */ 1346 1364 bool fVerbose = false; 1347 1365 … … 1379 1397 case VINF_GETOPT_NOT_OPTION: 1380 1398 { 1381 /** @todo r=bird: Simplify by letting RTGetOptInit sort the argv, just like1382 * for cp. */1383 1399 int vrc = ctrlDirectoryEntryAppend(NULL, /* No source given */ 1384 1400 ValueUnion.psz, /* Destination */
Note:
See TracChangeset
for help on using the changeset viewer.