VirtualBox

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

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

Main: change VirtualBox::createMachine() to accept arbitrary paths for the XML settings file; remove the override parameter

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.1 KB
Line 
1/* $Id: VBoxManageMisc.cpp 33451 2010-10-26 09:34:19Z 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#endif /* !VBOX_ONLY_DOCS */
33
34#include <iprt/asm.h>
35#include <iprt/buildconfig.h>
36#include <iprt/cidr.h>
37#include <iprt/ctype.h>
38#include <iprt/dir.h>
39#include <iprt/env.h>
40#include <VBox/err.h>
41#include <iprt/file.h>
42#include <iprt/initterm.h>
43#include <iprt/param.h>
44#include <iprt/path.h>
45#include <iprt/stream.h>
46#include <iprt/string.h>
47#include <iprt/stdarg.h>
48#include <iprt/thread.h>
49#include <iprt/uuid.h>
50#include <iprt/getopt.h>
51#include <iprt/ctype.h>
52#include <VBox/version.h>
53#include <VBox/log.h>
54
55#include "VBoxManage.h"
56
57using namespace com;
58
59
60
61int handleRegisterVM(HandlerArg *a)
62{
63 HRESULT rc;
64
65 if (a->argc != 1)
66 return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
67
68 ComPtr<IMachine> machine;
69 /** @todo Ugly hack to get both the API interpretation of relative paths
70 * and the client's interpretation of relative paths. Remove after the API
71 * has been redesigned. */
72 rc = a->virtualBox->OpenMachine(Bstr(a->argv[0]).raw(),
73 machine.asOutParam());
74 if (rc == VBOX_E_FILE_ERROR)
75 {
76 char szVMFileAbs[RTPATH_MAX] = "";
77 int vrc = RTPathAbs(a->argv[0], szVMFileAbs, sizeof(szVMFileAbs));
78 if (RT_FAILURE(vrc))
79 {
80 RTMsgError("Cannot convert filename \"%s\" to absolute path", a->argv[0]);
81 return 1;
82 }
83 CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(szVMFileAbs).raw(),
84 machine.asOutParam()));
85 }
86 else if (FAILED(rc))
87 CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]).raw(),
88 machine.asOutParam()));
89 if (SUCCEEDED(rc))
90 {
91 ASSERT(machine);
92 CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
93 }
94 return SUCCEEDED(rc) ? 0 : 1;
95}
96
97static const RTGETOPTDEF g_aUnregisterVMOptions[] =
98{
99 { "--delete", 'd', RTGETOPT_REQ_NOTHING },
100 { "-delete", 'd', RTGETOPT_REQ_NOTHING }, // deprecated
101};
102
103int handleUnregisterVM(HandlerArg *a)
104{
105 HRESULT rc;
106 const char *VMName = NULL;
107 bool fDelete = false;
108
109 int c;
110 RTGETOPTUNION ValueUnion;
111 RTGETOPTSTATE GetState;
112 // start at 0 because main() has hacked both the argc and argv given to us
113 RTGetOptInit(&GetState, a->argc, a->argv, g_aUnregisterVMOptions, RT_ELEMENTS(g_aUnregisterVMOptions),
114 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
115 while ((c = RTGetOpt(&GetState, &ValueUnion)))
116 {
117 switch (c)
118 {
119 case 'd': // --delete
120 fDelete = true;
121 break;
122
123 case VINF_GETOPT_NOT_OPTION:
124 if (!VMName)
125 VMName = ValueUnion.psz;
126 else
127 return errorSyntax(USAGE_UNREGISTERVM, "Invalid parameter '%s'", ValueUnion.psz);
128 break;
129
130 default:
131 if (c > 0)
132 {
133 if (RT_C_IS_PRINT(c))
134 return errorSyntax(USAGE_UNREGISTERVM, "Invalid option -%c", c);
135 else
136 return errorSyntax(USAGE_UNREGISTERVM, "Invalid option case %i", c);
137 }
138 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
139 return errorSyntax(USAGE_UNREGISTERVM, "unknown option: %s\n", ValueUnion.psz);
140 else if (ValueUnion.pDef)
141 return errorSyntax(USAGE_UNREGISTERVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
142 else
143 return errorSyntax(USAGE_UNREGISTERVM, "error: %Rrs", c);
144 }
145 }
146
147 /* check for required options */
148 if (!VMName)
149 return errorSyntax(USAGE_UNREGISTERVM, "VM name required");
150
151 ComPtr<IMachine> machine;
152 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName).raw(),
153 machine.asOutParam()));
154 if (machine)
155 {
156 SafeIfaceArray<IMedium> aMedia;
157 CleanupMode_T cleanupMode = CleanupMode_DetachAllReturnNone;
158 if (fDelete)
159 cleanupMode = CleanupMode_DetachAllReturnHardDisksOnly;
160 CHECK_ERROR(machine, Unregister(cleanupMode,
161 ComSafeArrayAsOutParam(aMedia)));
162 if (SUCCEEDED(rc))
163 {
164 if (fDelete)
165 {
166 ComPtr<IProgress> pProgress;
167 CHECK_ERROR(machine, Delete(ComSafeArrayAsInParam(aMedia), pProgress.asOutParam()));
168 CHECK_ERROR(pProgress, WaitForCompletion(-1));
169 }
170 }
171 }
172 return SUCCEEDED(rc) ? 0 : 1;
173}
174
175int handleCreateVM(HandlerArg *a)
176{
177 HRESULT rc;
178 Bstr baseFolder;
179 Bstr name;
180 Bstr osTypeId;
181 RTUUID id;
182 bool fRegister = false;
183
184 RTUuidClear(&id);
185 for (int i = 0; i < a->argc; i++)
186 {
187 if ( !strcmp(a->argv[i], "--basefolder")
188 || !strcmp(a->argv[i], "-basefolder"))
189 {
190 if (a->argc <= i + 1)
191 return errorArgument("Missing argument to '%s'", a->argv[i]);
192 i++;
193 baseFolder = a->argv[i];
194 }
195 else if ( !strcmp(a->argv[i], "--name")
196 || !strcmp(a->argv[i], "-name"))
197 {
198 if (a->argc <= i + 1)
199 return errorArgument("Missing argument to '%s'", a->argv[i]);
200 i++;
201 name = a->argv[i];
202 }
203 else if ( !strcmp(a->argv[i], "--ostype")
204 || !strcmp(a->argv[i], "-ostype"))
205 {
206 if (a->argc <= i + 1)
207 return errorArgument("Missing argument to '%s'", a->argv[i]);
208 i++;
209 osTypeId = a->argv[i];
210 }
211 else if ( !strcmp(a->argv[i], "--uuid")
212 || !strcmp(a->argv[i], "-uuid"))
213 {
214 if (a->argc <= i + 1)
215 return errorArgument("Missing argument to '%s'", a->argv[i]);
216 i++;
217 if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
218 return errorArgument("Invalid UUID format %s\n", a->argv[i]);
219 }
220 else if ( !strcmp(a->argv[i], "--register")
221 || !strcmp(a->argv[i], "-register"))
222 {
223 fRegister = true;
224 }
225 else
226 return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str());
227 }
228
229 /* check for required options */
230 if (name.isEmpty())
231 return errorSyntax(USAGE_CREATEVM, "Parameter --name is required");
232
233 do
234 {
235 Bstr bstrSettingsFile;
236 CHECK_ERROR_BREAK(a->virtualBox,
237 ComposeMachineFilename(name.raw(),
238 baseFolder.raw(),
239 bstrSettingsFile.asOutParam()));
240 ComPtr<IMachine> machine;
241 CHECK_ERROR_BREAK(a->virtualBox,
242 CreateMachine(bstrSettingsFile.raw(),
243 name.raw(),
244 osTypeId.raw(),
245 Guid(id).toUtf16().raw(),
246 machine.asOutParam()));
247
248 CHECK_ERROR_BREAK(machine, SaveSettings());
249 if (fRegister)
250 {
251 CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
252 }
253 Bstr uuid;
254 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
255 Bstr settingsFile;
256 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
257 RTPrintf("Virtual machine '%ls' is created%s.\n"
258 "UUID: %s\n"
259 "Settings file: '%ls'\n",
260 name.raw(), fRegister ? " and registered" : "",
261 Utf8Str(uuid).c_str(), settingsFile.raw());
262 }
263 while (0);
264
265 return SUCCEEDED(rc) ? 0 : 1;
266}
267
268int handleStartVM(HandlerArg *a)
269{
270 HRESULT rc;
271 const char *VMName = NULL;
272 Bstr sessionType = "gui";
273
274 static const RTGETOPTDEF s_aStartVMOptions[] =
275 {
276 { "--type", 't', RTGETOPT_REQ_STRING },
277 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
278 };
279 int c;
280 RTGETOPTUNION ValueUnion;
281 RTGETOPTSTATE GetState;
282 // start at 0 because main() has hacked both the argc and argv given to us
283 RTGetOptInit(&GetState, a->argc, a->argv, s_aStartVMOptions, RT_ELEMENTS(s_aStartVMOptions),
284 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
285 while ((c = RTGetOpt(&GetState, &ValueUnion)))
286 {
287 switch (c)
288 {
289 case 't': // --type
290 if (!RTStrICmp(ValueUnion.psz, "gui"))
291 {
292 sessionType = "gui";
293 }
294#ifdef VBOX_WITH_VBOXSDL
295 else if (!RTStrICmp(ValueUnion.psz, "sdl"))
296 {
297 sessionType = "sdl";
298 }
299#endif
300#ifdef VBOX_WITH_HEADLESS
301 else if (!RTStrICmp(ValueUnion.psz, "capture"))
302 {
303 sessionType = "capture";
304 }
305 else if (!RTStrICmp(ValueUnion.psz, "headless"))
306 {
307 sessionType = "headless";
308 }
309#endif
310 else
311 return errorArgument("Invalid session type '%s'", ValueUnion.psz);
312 break;
313
314 case VINF_GETOPT_NOT_OPTION:
315 if (!VMName)
316 VMName = ValueUnion.psz;
317 else
318 return errorSyntax(USAGE_STARTVM, "Invalid parameter '%s'", ValueUnion.psz);
319 break;
320
321 default:
322 if (c > 0)
323 {
324 if (RT_C_IS_PRINT(c))
325 return errorSyntax(USAGE_STARTVM, "Invalid option -%c", c);
326 else
327 return errorSyntax(USAGE_STARTVM, "Invalid option case %i", c);
328 }
329 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
330 return errorSyntax(USAGE_STARTVM, "unknown option: %s\n", ValueUnion.psz);
331 else if (ValueUnion.pDef)
332 return errorSyntax(USAGE_STARTVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
333 else
334 return errorSyntax(USAGE_STARTVM, "error: %Rrs", c);
335 }
336 }
337
338 /* check for required options */
339 if (!VMName)
340 return errorSyntax(USAGE_STARTVM, "VM name required");
341
342 ComPtr<IMachine> machine;
343 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName).raw(),
344 machine.asOutParam()));
345 if (machine)
346 {
347 Bstr env;
348#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
349 /* make sure the VM process will start on the same display as VBoxManage */
350 Utf8Str str;
351 const char *pszDisplay = RTEnvGet("DISPLAY");
352 if (pszDisplay)
353 str = Utf8StrFmt("DISPLAY=%s\n", pszDisplay);
354 const char *pszXAuth = RTEnvGet("XAUTHORITY");
355 if (pszXAuth)
356 str.append(Utf8StrFmt("XAUTHORITY=%s\n", pszXAuth));
357 env = str;
358#endif
359 ComPtr<IProgress> progress;
360 CHECK_ERROR_RET(machine, LaunchVMProcess(a->session, sessionType.raw(),
361 env.raw(), progress.asOutParam()), rc);
362 RTPrintf("Waiting for the VM to power on...\n");
363 CHECK_ERROR_RET(progress, WaitForCompletion(-1), 1);
364
365 BOOL completed;
366 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
367 ASSERT(completed);
368
369 LONG iRc;
370 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
371 if (FAILED(iRc))
372 {
373 ComPtr<IVirtualBoxErrorInfo> errorInfo;
374 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
375 ErrorInfo info(errorInfo, COM_IIDOF(IVirtualBoxErrorInfo));
376 com::GluePrintErrorInfo(info);
377 }
378 else
379 {
380 RTPrintf("VM has been successfully started.\n");
381 }
382 }
383
384 /* it's important to always close sessions */
385 a->session->UnlockMachine();
386
387 return SUCCEEDED(rc) ? 0 : 1;
388}
389
390int handleDiscardState(HandlerArg *a)
391{
392 HRESULT rc;
393
394 if (a->argc != 1)
395 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
396
397 ComPtr<IMachine> machine;
398 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
399 machine.asOutParam()));
400 if (machine)
401 {
402 do
403 {
404 /* we have to open a session for this task */
405 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
406 do
407 {
408 ComPtr<IConsole> console;
409 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
410 CHECK_ERROR_BREAK(console, DiscardSavedState(true /* fDeleteFile */));
411 } while (0);
412 CHECK_ERROR_BREAK(a->session, UnlockMachine());
413 } while (0);
414 }
415
416 return SUCCEEDED(rc) ? 0 : 1;
417}
418
419int handleAdoptState(HandlerArg *a)
420{
421 HRESULT rc;
422
423 if (a->argc != 2)
424 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
425
426 ComPtr<IMachine> machine;
427 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
428 machine.asOutParam()));
429 if (machine)
430 {
431 do
432 {
433 /* we have to open a session for this task */
434 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
435 do
436 {
437 ComPtr<IConsole> console;
438 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
439 CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(a->argv[1]).raw()));
440 } while (0);
441 CHECK_ERROR_BREAK(a->session, UnlockMachine());
442 } while (0);
443 }
444
445 return SUCCEEDED(rc) ? 0 : 1;
446}
447
448int handleGetExtraData(HandlerArg *a)
449{
450 HRESULT rc = S_OK;
451
452 if (a->argc != 2)
453 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
454
455 /* global data? */
456 if (!strcmp(a->argv[0], "global"))
457 {
458 /* enumeration? */
459 if (!strcmp(a->argv[1], "enumerate"))
460 {
461 SafeArray<BSTR> aKeys;
462 CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
463
464 for (size_t i = 0;
465 i < aKeys.size();
466 ++i)
467 {
468 Bstr bstrKey(aKeys[i]);
469 Bstr bstrValue;
470 CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey.raw(),
471 bstrValue.asOutParam()));
472
473 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
474 }
475 }
476 else
477 {
478 Bstr value;
479 CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]).raw(),
480 value.asOutParam()));
481 if (!value.isEmpty())
482 RTPrintf("Value: %lS\n", value.raw());
483 else
484 RTPrintf("No value set!\n");
485 }
486 }
487 else
488 {
489 ComPtr<IMachine> machine;
490 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
491 machine.asOutParam()));
492 if (machine)
493 {
494 /* enumeration? */
495 if (!strcmp(a->argv[1], "enumerate"))
496 {
497 SafeArray<BSTR> aKeys;
498 CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
499
500 for (size_t i = 0;
501 i < aKeys.size();
502 ++i)
503 {
504 Bstr bstrKey(aKeys[i]);
505 Bstr bstrValue;
506 CHECK_ERROR(machine, GetExtraData(bstrKey.raw(),
507 bstrValue.asOutParam()));
508
509 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
510 }
511 }
512 else
513 {
514 Bstr value;
515 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]).raw(),
516 value.asOutParam()));
517 if (!value.isEmpty())
518 RTPrintf("Value: %lS\n", value.raw());
519 else
520 RTPrintf("No value set!\n");
521 }
522 }
523 }
524 return SUCCEEDED(rc) ? 0 : 1;
525}
526
527int handleSetExtraData(HandlerArg *a)
528{
529 HRESULT rc = S_OK;
530
531 if (a->argc < 2)
532 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
533
534 /* global data? */
535 if (!strcmp(a->argv[0], "global"))
536 {
537 /** @todo passing NULL is deprecated */
538 if (a->argc < 3)
539 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]).raw(),
540 NULL));
541 else if (a->argc == 3)
542 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]).raw(),
543 Bstr(a->argv[2]).raw()));
544 else
545 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
546 }
547 else
548 {
549 ComPtr<IMachine> machine;
550 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
551 machine.asOutParam()));
552 if (machine)
553 {
554 /** @todo passing NULL is deprecated */
555 if (a->argc < 3)
556 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]).raw(),
557 NULL));
558 else if (a->argc == 3)
559 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]).raw(),
560 Bstr(a->argv[2]).raw()));
561 else
562 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
563 }
564 }
565 return SUCCEEDED(rc) ? 0 : 1;
566}
567
568int handleSetProperty(HandlerArg *a)
569{
570 HRESULT rc;
571
572 /* there must be two arguments: property name and value */
573 if (a->argc != 2)
574 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
575
576 ComPtr<ISystemProperties> systemProperties;
577 a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
578
579 if (!strcmp(a->argv[0], "machinefolder"))
580 {
581 /* reset to default? */
582 if (!strcmp(a->argv[1], "default"))
583 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
584 else
585 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1]).raw()));
586 }
587 else if ( !strcmp(a->argv[0], "vrdeauthlibrary")
588 || !strcmp(a->argv[0], "vrdpauthlibrary"))
589 {
590 if (!strcmp(a->argv[0], "vrdpauthlibrary"))
591 RTStrmPrintf(g_pStdErr, "Warning: 'vrdpauthlibrary' is deprecated. Use 'vrdeauthlibrary'.\n");
592
593 /* reset to default? */
594 if (!strcmp(a->argv[1], "default"))
595 CHECK_ERROR(systemProperties, COMSETTER(VRDEAuthLibrary)(NULL));
596 else
597 CHECK_ERROR(systemProperties, COMSETTER(VRDEAuthLibrary)(Bstr(a->argv[1]).raw()));
598 }
599 else if (!strcmp(a->argv[0], "websrvauthlibrary"))
600 {
601 /* reset to default? */
602 if (!strcmp(a->argv[1], "default"))
603 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
604 else
605 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1]).raw()));
606 }
607 else if (!strcmp(a->argv[0], "vrdelibrary"))
608 {
609 /* disable? */
610 if (!strcmp(a->argv[1], "null"))
611 CHECK_ERROR(systemProperties, COMSETTER(DefaultVRDELibrary)(NULL));
612 else
613 CHECK_ERROR(systemProperties, COMSETTER(DefaultVRDELibrary)(Bstr(a->argv[1]).raw()));
614 }
615 else if (!strcmp(a->argv[0], "loghistorycount"))
616 {
617 uint32_t uVal;
618 int vrc;
619 vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
620 if (vrc != VINF_SUCCESS)
621 return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
622 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
623 }
624 else
625 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
626
627 return SUCCEEDED(rc) ? 0 : 1;
628}
629
630int handleSharedFolder(HandlerArg *a)
631{
632 HRESULT rc;
633
634 /* we need at least a command and target */
635 if (a->argc < 2)
636 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
637
638 ComPtr<IMachine> machine;
639 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]).raw(),
640 machine.asOutParam()));
641 if (!machine)
642 return 1;
643
644 if (!strcmp(a->argv[0], "add"))
645 {
646 /* we need at least four more parameters */
647 if (a->argc < 5)
648 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
649
650 char *name = NULL;
651 char *hostpath = NULL;
652 bool fTransient = false;
653 bool fWritable = true;
654 bool fAutoMount = false;
655
656 for (int i = 2; i < a->argc; i++)
657 {
658 if ( !strcmp(a->argv[i], "--name")
659 || !strcmp(a->argv[i], "-name"))
660 {
661 if (a->argc <= i + 1 || !*a->argv[i+1])
662 return errorArgument("Missing argument to '%s'", a->argv[i]);
663 i++;
664 name = a->argv[i];
665 }
666 else if ( !strcmp(a->argv[i], "--hostpath")
667 || !strcmp(a->argv[i], "-hostpath"))
668 {
669 if (a->argc <= i + 1 || !*a->argv[i+1])
670 return errorArgument("Missing argument to '%s'", a->argv[i]);
671 i++;
672 hostpath = a->argv[i];
673 }
674 else if ( !strcmp(a->argv[i], "--readonly")
675 || !strcmp(a->argv[i], "-readonly"))
676 {
677 fWritable = false;
678 }
679 else if ( !strcmp(a->argv[i], "--transient")
680 || !strcmp(a->argv[i], "-transient"))
681 {
682 fTransient = true;
683 }
684 else if ( !strcmp(a->argv[i], "--automount")
685 || !strcmp(a->argv[i], "-automount"))
686 {
687 fAutoMount = true;
688 }
689 else
690 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str());
691 }
692
693 if (NULL != strstr(name, " "))
694 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
695
696 /* required arguments */
697 if (!name || !hostpath)
698 {
699 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters --name and --hostpath are required");
700 }
701
702 if (fTransient)
703 {
704 ComPtr <IConsole> console;
705
706 /* open an existing session for the VM */
707 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
708 /* get the session machine */
709 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
710 /* get the session console */
711 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
712
713 CHECK_ERROR(console, CreateSharedFolder(Bstr(name).raw(),
714 Bstr(hostpath).raw(),
715 fWritable, fAutoMount));
716 if (console)
717 a->session->UnlockMachine();
718 }
719 else
720 {
721 /* open a session for the VM */
722 SessionType_T st;
723 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
724
725 /* get the mutable session machine */
726 a->session->COMGETTER(Machine)(machine.asOutParam());
727
728 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name).raw(),
729 Bstr(hostpath).raw(),
730 fWritable, fAutoMount));
731 if (SUCCEEDED(rc))
732 CHECK_ERROR(machine, SaveSettings());
733
734 a->session->UnlockMachine();
735 }
736 }
737 else if (!strcmp(a->argv[0], "remove"))
738 {
739 /* we need at least two more parameters */
740 if (a->argc < 3)
741 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
742
743 char *name = NULL;
744 bool fTransient = false;
745
746 for (int i = 2; i < a->argc; i++)
747 {
748 if ( !strcmp(a->argv[i], "--name")
749 || !strcmp(a->argv[i], "-name"))
750 {
751 if (a->argc <= i + 1 || !*a->argv[i+1])
752 return errorArgument("Missing argument to '%s'", a->argv[i]);
753 i++;
754 name = a->argv[i];
755 }
756 else if ( !strcmp(a->argv[i], "--transient")
757 || !strcmp(a->argv[i], "-transient"))
758 {
759 fTransient = true;
760 }
761 else
762 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str());
763 }
764
765 /* required arguments */
766 if (!name)
767 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter --name is required");
768
769 if (fTransient)
770 {
771 ComPtr <IConsole> console;
772
773 /* open an existing session for the VM */
774 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
775 /* get the session machine */
776 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
777 /* get the session console */
778 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
779
780 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name).raw()));
781
782 if (console)
783 a->session->UnlockMachine();
784 }
785 else
786 {
787 /* open a session for the VM */
788 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
789
790 /* get the mutable session machine */
791 a->session->COMGETTER(Machine)(machine.asOutParam());
792
793 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name).raw()));
794
795 /* commit and close the session */
796 CHECK_ERROR(machine, SaveSettings());
797 a->session->UnlockMachine();
798 }
799 }
800 else
801 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).c_str());
802
803 return 0;
804}
805
806int handleVMStatistics(HandlerArg *a)
807{
808 HRESULT rc;
809
810 /* at least one option: the UUID or name of the VM */
811 if (a->argc < 1)
812 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
813
814 /* try to find the given machine */
815 ComPtr<IMachine> machine;
816 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
817 machine.asOutParam()));
818 if (FAILED(rc))
819 return 1;
820
821 /* parse arguments. */
822 bool fReset = false;
823 bool fWithDescriptions = false;
824 const char *pszPattern = NULL; /* all */
825 for (int i = 1; i < a->argc; i++)
826 {
827 if ( !strcmp(a->argv[i], "--pattern")
828 || !strcmp(a->argv[i], "-pattern"))
829 {
830 if (pszPattern)
831 return errorSyntax(USAGE_VM_STATISTICS, "Multiple --patterns options is not permitted");
832 if (i + 1 >= a->argc)
833 return errorArgument("Missing argument to '%s'", a->argv[i]);
834 pszPattern = a->argv[++i];
835 }
836 else if ( !strcmp(a->argv[i], "--descriptions")
837 || !strcmp(a->argv[i], "-descriptions"))
838 fWithDescriptions = true;
839 /* add: --file <filename> and --formatted */
840 else if ( !strcmp(a->argv[i], "--reset")
841 || !strcmp(a->argv[i], "-reset"))
842 fReset = true;
843 else
844 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
845 }
846 if (fReset && fWithDescriptions)
847 return errorSyntax(USAGE_VM_STATISTICS, "The --reset and --descriptions options does not mix");
848
849
850 /* open an existing session for the VM. */
851 CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared));
852 if (SUCCEEDED(rc))
853 {
854 /* get the session console. */
855 ComPtr <IConsole> console;
856 CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
857 if (SUCCEEDED(rc))
858 {
859 /* get the machine debugger. */
860 ComPtr <IMachineDebugger> debugger;
861 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
862 if (SUCCEEDED(rc))
863 {
864 if (fReset)
865 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern).raw()));
866 else
867 {
868 Bstr stats;
869 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern).raw(),
870 fWithDescriptions,
871 stats.asOutParam()));
872 if (SUCCEEDED(rc))
873 {
874 /* if (fFormatted)
875 { big mess }
876 else
877 */
878 RTPrintf("%ls\n", stats.raw());
879 }
880 }
881 }
882 a->session->UnlockMachine();
883 }
884 }
885
886 return SUCCEEDED(rc) ? 0 : 1;
887}
888
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