VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp@ 31713

Last change on this file since 31713 was 31539, checked in by vboxsync, 14 years ago

Main: use settings struct for machine user data; remove iprt::MiniString::raw() and change all occurences to c_str()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: VBoxManage.cpp 31539 2010-08-10 15:40:18Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#ifndef VBOX_ONLY_DOCS
23# include <VBox/com/com.h>
24# include <VBox/com/string.h>
25# include <VBox/com/Guid.h>
26# include <VBox/com/array.h>
27# include <VBox/com/ErrorInfo.h>
28# include <VBox/com/errorprint.h>
29# include <VBox/com/EventQueue.h>
30
31# include <VBox/com/VirtualBox.h>
32
33# include <vector>
34# include <list>
35#endif /* !VBOX_ONLY_DOCS */
36
37#include <VBox/err.h>
38#include <VBox/version.h>
39
40#include <iprt/asm.h>
41#include <iprt/buildconfig.h>
42#include <iprt/initterm.h>
43#include <iprt/stream.h>
44#include <iprt/string.h>
45
46#include <signal.h>
47
48#include "VBoxManage.h"
49
50
51/*******************************************************************************
52* Global Variables *
53*******************************************************************************/
54/*extern*/ bool g_fDetailedProgress = false;
55
56#ifndef VBOX_ONLY_DOCS
57/** Set by the signal handler. */
58static volatile bool g_fCanceled = false;
59
60
61/**
62 * Signal handler that sets g_fCanceled.
63 *
64 * This can be executed on any thread in the process, on Windows it may even be
65 * a thread dedicated to delivering this signal. Do not doing anything
66 * unnecessary here.
67 */
68static void showProgressSignalHandler(int iSignal)
69{
70 NOREF(iSignal);
71 ASMAtomicWriteBool(&g_fCanceled, true);
72}
73
74
75/**
76 * Print out progress on the console
77 */
78HRESULT showProgress(ComPtr<IProgress> progress)
79{
80 using namespace com;
81
82 BOOL fCompleted;
83 ULONG ulCurrentPercent;
84 ULONG ulLastPercent = 0;
85
86 ULONG ulCurrentOperationPercent;
87 ULONG ulLastOperationPercent = (ULONG)-1;
88
89 ULONG ulLastOperation = (ULONG)-1;
90 Bstr bstrOperationDescription;
91
92 ULONG cOperations;
93 progress->COMGETTER(OperationCount)(&cOperations);
94
95 if (!g_fDetailedProgress)
96 {
97 RTPrintf("0%%...");
98 RTStrmFlush(g_pStdOut);
99 }
100
101 /* setup signal handling if cancelable */
102 bool fCanceledAlready = false;
103 BOOL fCancelable;
104 HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable);
105 if (FAILED(hrc))
106 fCancelable = FALSE;
107 if (fCancelable)
108 {
109 signal(SIGINT, showProgressSignalHandler);
110#ifdef SIGBREAK
111 signal(SIGBREAK, showProgressSignalHandler);
112#endif
113 }
114
115 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
116 {
117 ULONG ulOperation;
118 progress->COMGETTER(Operation)(&ulOperation);
119
120 progress->COMGETTER(Percent(&ulCurrentPercent));
121 progress->COMGETTER(OperationPercent(&ulCurrentOperationPercent));
122
123 if (g_fDetailedProgress)
124 {
125 if (ulLastOperation != ulOperation)
126 {
127 progress->COMGETTER(OperationDescription(bstrOperationDescription.asOutParam()));
128 ulLastPercent = (ULONG)-1; // force print
129 ulLastOperation = ulOperation;
130 }
131
132 if ( ulCurrentPercent != ulLastPercent
133 || ulCurrentOperationPercent != ulLastOperationPercent
134 )
135 {
136 LONG lSecsRem;
137 progress->COMGETTER(TimeRemaining)(&lSecsRem);
138
139 RTPrintf("(%ld/%ld) %ls %ld%% => %ld%% (%d s remaining)\n", ulOperation + 1, cOperations, bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent, lSecsRem);
140 ulLastPercent = ulCurrentPercent;
141 ulLastOperationPercent = ulCurrentOperationPercent;
142 }
143 }
144 else
145 {
146 /* did we cross a 10% mark? */
147 if (ulCurrentPercent / 10 > ulLastPercent / 10)
148 {
149 /* make sure to also print out missed steps */
150 for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10)
151 {
152 if (curVal < 100)
153 {
154 RTPrintf("%ld%%...", curVal);
155 RTStrmFlush(g_pStdOut);
156 }
157 }
158 ulLastPercent = (ulCurrentPercent / 10) * 10;
159 }
160 }
161 if (fCompleted)
162 break;
163
164 /* process async cancelation */
165 if (g_fCanceled && !fCanceledAlready)
166 {
167 hrc = progress->Cancel();
168 if (SUCCEEDED(hrc))
169 fCanceledAlready = true;
170 else
171 g_fCanceled = false;
172 }
173
174 /* make sure the loop is not too tight */
175 progress->WaitForCompletion(100);
176 }
177
178 /* undo signal handling */
179 if (fCancelable)
180 {
181 signal(SIGINT, SIG_DFL);
182#ifdef SIGBREAK
183 signal(SIGBREAK, SIG_DFL);
184#endif
185 }
186
187 /* complete the line. */
188 LONG iRc = E_FAIL;
189 if (SUCCEEDED(progress->COMGETTER(ResultCode)(&iRc)))
190 {
191 if (SUCCEEDED(iRc))
192 RTPrintf("100%%\n");
193 else if (g_fCanceled)
194 RTPrintf("CANCELED\n");
195 else
196 RTPrintf("FAILED\n");
197 }
198 else
199 RTPrintf("\n");
200 RTStrmFlush(g_pStdOut);
201 return iRc;
202}
203
204#endif /* !VBOX_ONLY_DOCS */
205
206int main(int argc, char *argv[])
207{
208 /*
209 * Before we do anything, init the runtime without loading
210 * the support driver.
211 */
212 RTR3Init();
213
214 bool fShowLogo = true;
215 int iCmd = 1;
216 int iCmdArg;
217
218 /* global options */
219 for (int i = 1; i < argc || argc <= iCmd; i++)
220 {
221 if ( argc <= iCmd
222 || !strcmp(argv[i], "help")
223 || !strcmp(argv[i], "-?")
224 || !strcmp(argv[i], "-h")
225 || !strcmp(argv[i], "-help")
226 || !strcmp(argv[i], "--help"))
227 {
228 showLogo();
229 printUsage(USAGE_ALL);
230 return 0;
231 }
232
233 if ( !strcmp(argv[i], "-v")
234 || !strcmp(argv[i], "-version")
235 || !strcmp(argv[i], "-Version")
236 || !strcmp(argv[i], "--version"))
237 {
238 /* Print version number, and do nothing else. */
239 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
240 return 0;
241 }
242
243 if ( !strcmp(argv[i], "--dumpopts")
244 || !strcmp(argv[i], "-dumpopts"))
245 {
246 /* Special option to dump really all commands,
247 * even the ones not understood on this platform. */
248 printUsage(USAGE_DUMPOPTS);
249 return 0;
250 }
251
252 if ( !strcmp(argv[i], "--nologo")
253 || !strcmp(argv[i], "-nologo")
254 || !strcmp(argv[i], "-q"))
255 {
256 /* suppress the logo */
257 fShowLogo = false;
258 iCmd++;
259 }
260 else
261 {
262 break;
263 }
264 }
265
266 iCmdArg = iCmd + 1;
267
268 if (fShowLogo)
269 showLogo();
270
271
272#ifdef VBOX_ONLY_DOCS
273 int rc = 0;
274#else /* !VBOX_ONLY_DOCS */
275 using namespace com;
276 HRESULT rc = 0;
277
278 rc = com::Initialize();
279 if (FAILED(rc))
280 {
281 RTPrintf("ERROR: failed to initialize COM!\n");
282 return rc;
283 }
284
285 /*
286 * The input is in the host OS'es codepage (NT guarantees ACP).
287 * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
288 * For simplicity, just convert the argv[] array here.
289 */
290 for (int i = iCmdArg; i < argc; i++)
291 {
292 char *converted;
293 RTStrCurrentCPToUtf8(&converted, argv[i]);
294 argv[i] = converted;
295 }
296
297 do
298 {
299 // scopes all the stuff till shutdown
300 ////////////////////////////////////////////////////////////////////////////
301
302 /* convertfromraw: does not need a VirtualBox instantiation. */
303 if (argc >= iCmdArg && ( !strcmp(argv[iCmd], "convertfromraw")
304 || !strcmp(argv[iCmd], "convertdd")))
305 {
306 rc = handleConvertFromRaw(argc - iCmdArg, argv + iCmdArg);
307 break;
308 }
309
310 ComPtr<IVirtualBox> virtualBox;
311 ComPtr<ISession> session;
312
313 rc = virtualBox.createLocalObject(CLSID_VirtualBox);
314 if (FAILED(rc))
315 RTPrintf("ERROR: failed to create the VirtualBox object!\n");
316 else
317 {
318 rc = session.createInprocObject(CLSID_Session);
319 if (FAILED(rc))
320 RTPrintf("ERROR: failed to create a session object!\n");
321 }
322
323 if (FAILED(rc))
324 {
325 com::ErrorInfo info;
326 if (!info.isFullAvailable() && !info.isBasicAvailable())
327 {
328 com::GluePrintRCMessage(rc);
329 RTPrintf("Most likely, the VirtualBox COM server is not running or failed to start.\n");
330 }
331 else
332 com::GluePrintErrorInfo(info);
333 break;
334 }
335
336 HandlerArg handlerArg = { 0, NULL, virtualBox, session };
337
338 /*
339 * All registered command handlers
340 */
341 static const struct
342 {
343 const char *command;
344 int (*handler)(HandlerArg *a);
345 } s_commandHandlers[] =
346 {
347 { "internalcommands", handleInternalCommands },
348 { "list", handleList },
349 { "showvminfo", handleShowVMInfo },
350 { "registervm", handleRegisterVM },
351 { "unregistervm", handleUnregisterVM },
352 { "createhd", handleCreateHardDisk },
353 { "createvdi", handleCreateHardDisk }, /* backward compatiblity */
354 { "modifyhd", handleModifyHardDisk },
355 { "modifyvdi", handleModifyHardDisk }, /* backward compatiblity */
356 { "clonehd", handleCloneHardDisk },
357 { "clonevdi", handleCloneHardDisk }, /* backward compatiblity */
358 { "addiscsidisk", handleAddiSCSIDisk },
359 { "createvm", handleCreateVM },
360 { "modifyvm", handleModifyVM },
361 { "startvm", handleStartVM },
362 { "controlvm", handleControlVM },
363 { "discardstate", handleDiscardState },
364 { "adoptstate", handleAdoptState },
365 { "snapshot", handleSnapshot },
366 { "openmedium", handleOpenMedium },
367 { "registerimage", handleOpenMedium }, /* backward compatiblity */
368 { "closemedium", handleCloseMedium },
369 { "unregisterimage", handleCloseMedium }, /* backward compatiblity */
370 { "storageattach", handleStorageAttach },
371 { "storagectl", handleStorageController },
372 { "showhdinfo", handleShowHardDiskInfo },
373 { "showvdiinfo", handleShowHardDiskInfo }, /* backward compatiblity */
374 { "getextradata", handleGetExtraData },
375 { "setextradata", handleSetExtraData },
376 { "setproperty", handleSetProperty },
377 { "usbfilter", handleUSBFilter },
378 { "sharedfolder", handleSharedFolder },
379 { "vmstatistics", handleVMStatistics },
380#ifdef VBOX_WITH_GUEST_PROPS
381 { "guestproperty", handleGuestProperty },
382#endif
383#ifdef VBOX_WITH_GUEST_CONTROL
384 { "guestcontrol", handleGuestControl },
385#endif
386 { "metrics", handleMetrics },
387 { "import", handleImportAppliance },
388 { "export", handleExportAppliance },
389#ifdef VBOX_WITH_NETFLT
390 { "hostonlyif", handleHostonlyIf },
391#endif
392 { "dhcpserver", handleDHCPServer},
393 { NULL, NULL }
394 };
395
396 int commandIndex;
397 for (commandIndex = 0; s_commandHandlers[commandIndex].command != NULL; commandIndex++)
398 {
399 if (!strcmp(s_commandHandlers[commandIndex].command, argv[iCmd]))
400 {
401 handlerArg.argc = argc - iCmdArg;
402 handlerArg.argv = &argv[iCmdArg];
403
404 rc = s_commandHandlers[commandIndex].handler(&handlerArg);
405 break;
406 }
407 }
408 if (!s_commandHandlers[commandIndex].command)
409 rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).c_str());
410
411 /* Although all handlers should always close the session if they open it,
412 * we do it here just in case if some of the handlers contains a bug --
413 * leaving the direct session not closed will turn the machine state to
414 * Aborted which may have unwanted side effects like killing the saved
415 * state file (if the machine was in the Saved state before). */
416 session->UnlockMachine();
417
418 EventQueue::getMainEventQueue()->processEventQueue(0);
419 // end "all-stuff" scope
420 ////////////////////////////////////////////////////////////////////////////
421 } while (0);
422
423 com::Shutdown();
424#endif /* !VBOX_ONLY_DOCS */
425
426 /*
427 * Free converted argument vector
428 */
429 for (int i = iCmdArg; i < argc; i++)
430 RTStrFree(argv[i]);
431
432 return rc != 0;
433}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette