VirtualBox

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

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

VRDE: API changes for the VRDP server separation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.8 KB
Line 
1/* $Id: VBoxManageMisc.cpp 33386 2010-10-24 15:57:55Z 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 ComPtr<IMachine> machine;
236
237 CHECK_ERROR_BREAK(a->virtualBox,
238 CreateMachine(name.raw(),
239 osTypeId.raw(),
240 baseFolder.raw(),
241 Guid(id).toUtf16().raw(),
242 FALSE,
243 machine.asOutParam()));
244
245 CHECK_ERROR_BREAK(machine, SaveSettings());
246 if (fRegister)
247 {
248 CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
249 }
250 Bstr uuid;
251 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
252 Bstr settingsFile;
253 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
254 RTPrintf("Virtual machine '%ls' is created%s.\n"
255 "UUID: %s\n"
256 "Settings file: '%ls'\n",
257 name.raw(), fRegister ? " and registered" : "",
258 Utf8Str(uuid).c_str(), settingsFile.raw());
259 }
260 while (0);
261
262 return SUCCEEDED(rc) ? 0 : 1;
263}
264
265int handleStartVM(HandlerArg *a)
266{
267 HRESULT rc;
268 const char *VMName = NULL;
269 Bstr sessionType = "gui";
270
271 static const RTGETOPTDEF s_aStartVMOptions[] =
272 {
273 { "--type", 't', RTGETOPT_REQ_STRING },
274 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
275 };
276 int c;
277 RTGETOPTUNION ValueUnion;
278 RTGETOPTSTATE GetState;
279 // start at 0 because main() has hacked both the argc and argv given to us
280 RTGetOptInit(&GetState, a->argc, a->argv, s_aStartVMOptions, RT_ELEMENTS(s_aStartVMOptions),
281 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
282 while ((c = RTGetOpt(&GetState, &ValueUnion)))
283 {
284 switch (c)
285 {
286 case 't': // --type
287 if (!RTStrICmp(ValueUnion.psz, "gui"))
288 {
289 sessionType = "gui";
290 }
291#ifdef VBOX_WITH_VBOXSDL
292 else if (!RTStrICmp(ValueUnion.psz, "sdl"))
293 {
294 sessionType = "sdl";
295 }
296#endif
297#ifdef VBOX_WITH_HEADLESS
298 else if (!RTStrICmp(ValueUnion.psz, "capture"))
299 {
300 sessionType = "capture";
301 }
302 else if (!RTStrICmp(ValueUnion.psz, "headless"))
303 {
304 sessionType = "headless";
305 }
306#endif
307 else
308 return errorArgument("Invalid session type '%s'", ValueUnion.psz);
309 break;
310
311 case VINF_GETOPT_NOT_OPTION:
312 if (!VMName)
313 VMName = ValueUnion.psz;
314 else
315 return errorSyntax(USAGE_STARTVM, "Invalid parameter '%s'", ValueUnion.psz);
316 break;
317
318 default:
319 if (c > 0)
320 {
321 if (RT_C_IS_PRINT(c))
322 return errorSyntax(USAGE_STARTVM, "Invalid option -%c", c);
323 else
324 return errorSyntax(USAGE_STARTVM, "Invalid option case %i", c);
325 }
326 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
327 return errorSyntax(USAGE_STARTVM, "unknown option: %s\n", ValueUnion.psz);
328 else if (ValueUnion.pDef)
329 return errorSyntax(USAGE_STARTVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
330 else
331 return errorSyntax(USAGE_STARTVM, "error: %Rrs", c);
332 }
333 }
334
335 /* check for required options */
336 if (!VMName)
337 return errorSyntax(USAGE_STARTVM, "VM name required");
338
339 ComPtr<IMachine> machine;
340 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName).raw(),
341 machine.asOutParam()));
342 if (machine)
343 {
344 Bstr env;
345#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
346 /* make sure the VM process will start on the same display as VBoxManage */
347 Utf8Str str;
348 const char *pszDisplay = RTEnvGet("DISPLAY");
349 if (pszDisplay)
350 str = Utf8StrFmt("DISPLAY=%s\n", pszDisplay);
351 const char *pszXAuth = RTEnvGet("XAUTHORITY");
352 if (pszXAuth)
353 str.append(Utf8StrFmt("XAUTHORITY=%s\n", pszXAuth));
354 env = str;
355#endif
356 ComPtr<IProgress> progress;
357 CHECK_ERROR_RET(machine, LaunchVMProcess(a->session, sessionType.raw(),
358 env.raw(), progress.asOutParam()), rc);
359 RTPrintf("Waiting for the VM to power on...\n");
360 CHECK_ERROR_RET(progress, WaitForCompletion(-1), 1);
361
362 BOOL completed;
363 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
364 ASSERT(completed);
365
366 LONG iRc;
367 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
368 if (FAILED(iRc))
369 {
370 ComPtr<IVirtualBoxErrorInfo> errorInfo;
371 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
372 ErrorInfo info(errorInfo, COM_IIDOF(IVirtualBoxErrorInfo));
373 com::GluePrintErrorInfo(info);
374 }
375 else
376 {
377 RTPrintf("VM has been successfully started.\n");
378 }
379 }
380
381 /* it's important to always close sessions */
382 a->session->UnlockMachine();
383
384 return SUCCEEDED(rc) ? 0 : 1;
385}
386
387int handleDiscardState(HandlerArg *a)
388{
389 HRESULT rc;
390
391 if (a->argc != 1)
392 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
393
394 ComPtr<IMachine> machine;
395 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
396 machine.asOutParam()));
397 if (machine)
398 {
399 do
400 {
401 /* we have to open a session for this task */
402 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
403 do
404 {
405 ComPtr<IConsole> console;
406 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
407 CHECK_ERROR_BREAK(console, DiscardSavedState(true /* fDeleteFile */));
408 } while (0);
409 CHECK_ERROR_BREAK(a->session, UnlockMachine());
410 } while (0);
411 }
412
413 return SUCCEEDED(rc) ? 0 : 1;
414}
415
416int handleAdoptState(HandlerArg *a)
417{
418 HRESULT rc;
419
420 if (a->argc != 2)
421 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
422
423 ComPtr<IMachine> machine;
424 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
425 machine.asOutParam()));
426 if (machine)
427 {
428 do
429 {
430 /* we have to open a session for this task */
431 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
432 do
433 {
434 ComPtr<IConsole> console;
435 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
436 CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(a->argv[1]).raw()));
437 } while (0);
438 CHECK_ERROR_BREAK(a->session, UnlockMachine());
439 } while (0);
440 }
441
442 return SUCCEEDED(rc) ? 0 : 1;
443}
444
445int handleGetExtraData(HandlerArg *a)
446{
447 HRESULT rc = S_OK;
448
449 if (a->argc != 2)
450 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
451
452 /* global data? */
453 if (!strcmp(a->argv[0], "global"))
454 {
455 /* enumeration? */
456 if (!strcmp(a->argv[1], "enumerate"))
457 {
458 SafeArray<BSTR> aKeys;
459 CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
460
461 for (size_t i = 0;
462 i < aKeys.size();
463 ++i)
464 {
465 Bstr bstrKey(aKeys[i]);
466 Bstr bstrValue;
467 CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey.raw(),
468 bstrValue.asOutParam()));
469
470 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
471 }
472 }
473 else
474 {
475 Bstr value;
476 CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]).raw(),
477 value.asOutParam()));
478 if (!value.isEmpty())
479 RTPrintf("Value: %lS\n", value.raw());
480 else
481 RTPrintf("No value set!\n");
482 }
483 }
484 else
485 {
486 ComPtr<IMachine> machine;
487 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
488 machine.asOutParam()));
489 if (machine)
490 {
491 /* enumeration? */
492 if (!strcmp(a->argv[1], "enumerate"))
493 {
494 SafeArray<BSTR> aKeys;
495 CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
496
497 for (size_t i = 0;
498 i < aKeys.size();
499 ++i)
500 {
501 Bstr bstrKey(aKeys[i]);
502 Bstr bstrValue;
503 CHECK_ERROR(machine, GetExtraData(bstrKey.raw(),
504 bstrValue.asOutParam()));
505
506 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
507 }
508 }
509 else
510 {
511 Bstr value;
512 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]).raw(),
513 value.asOutParam()));
514 if (!value.isEmpty())
515 RTPrintf("Value: %lS\n", value.raw());
516 else
517 RTPrintf("No value set!\n");
518 }
519 }
520 }
521 return SUCCEEDED(rc) ? 0 : 1;
522}
523
524int handleSetExtraData(HandlerArg *a)
525{
526 HRESULT rc = S_OK;
527
528 if (a->argc < 2)
529 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
530
531 /* global data? */
532 if (!strcmp(a->argv[0], "global"))
533 {
534 /** @todo passing NULL is deprecated */
535 if (a->argc < 3)
536 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]).raw(),
537 NULL));
538 else if (a->argc == 3)
539 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]).raw(),
540 Bstr(a->argv[2]).raw()));
541 else
542 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
543 }
544 else
545 {
546 ComPtr<IMachine> machine;
547 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
548 machine.asOutParam()));
549 if (machine)
550 {
551 /** @todo passing NULL is deprecated */
552 if (a->argc < 3)
553 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]).raw(),
554 NULL));
555 else if (a->argc == 3)
556 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]).raw(),
557 Bstr(a->argv[2]).raw()));
558 else
559 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
560 }
561 }
562 return SUCCEEDED(rc) ? 0 : 1;
563}
564
565int handleSetProperty(HandlerArg *a)
566{
567 HRESULT rc;
568
569 /* there must be two arguments: property name and value */
570 if (a->argc != 2)
571 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
572
573 ComPtr<ISystemProperties> systemProperties;
574 a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
575
576 if (!strcmp(a->argv[0], "machinefolder"))
577 {
578 /* reset to default? */
579 if (!strcmp(a->argv[1], "default"))
580 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
581 else
582 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1]).raw()));
583 }
584 else if ( !strcmp(a->argv[0], "vrdeauthlibrary")
585 || !strcmp(a->argv[0], "vrdpauthlibrary"))
586 {
587 if (!strcmp(a->argv[0], "vrdpauthlibrary"))
588 RTStrmPrintf(g_pStdErr, "Warning: 'vrdpauthlibrary' is deprecated. Use 'vrdeauthlibrary'.\n");
589
590 /* reset to default? */
591 if (!strcmp(a->argv[1], "default"))
592 CHECK_ERROR(systemProperties, COMSETTER(VRDEAuthLibrary)(NULL));
593 else
594 CHECK_ERROR(systemProperties, COMSETTER(VRDEAuthLibrary)(Bstr(a->argv[1]).raw()));
595 }
596 else if (!strcmp(a->argv[0], "websrvauthlibrary"))
597 {
598 /* reset to default? */
599 if (!strcmp(a->argv[1], "default"))
600 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
601 else
602 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1]).raw()));
603 }
604 else if (!strcmp(a->argv[0], "vrdelibrary"))
605 {
606 /* disable? */
607 if (!strcmp(a->argv[1], "null"))
608 CHECK_ERROR(systemProperties, COMSETTER(DefaultVRDELibrary)(NULL));
609 else
610 CHECK_ERROR(systemProperties, COMSETTER(DefaultVRDELibrary)(Bstr(a->argv[1]).raw()));
611 }
612 else if (!strcmp(a->argv[0], "loghistorycount"))
613 {
614 uint32_t uVal;
615 int vrc;
616 vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
617 if (vrc != VINF_SUCCESS)
618 return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
619 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
620 }
621 else
622 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
623
624 return SUCCEEDED(rc) ? 0 : 1;
625}
626
627int handleSharedFolder(HandlerArg *a)
628{
629 HRESULT rc;
630
631 /* we need at least a command and target */
632 if (a->argc < 2)
633 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
634
635 ComPtr<IMachine> machine;
636 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]).raw(),
637 machine.asOutParam()));
638 if (!machine)
639 return 1;
640
641 if (!strcmp(a->argv[0], "add"))
642 {
643 /* we need at least four more parameters */
644 if (a->argc < 5)
645 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
646
647 char *name = NULL;
648 char *hostpath = NULL;
649 bool fTransient = false;
650 bool fWritable = true;
651 bool fAutoMount = false;
652
653 for (int i = 2; i < a->argc; i++)
654 {
655 if ( !strcmp(a->argv[i], "--name")
656 || !strcmp(a->argv[i], "-name"))
657 {
658 if (a->argc <= i + 1 || !*a->argv[i+1])
659 return errorArgument("Missing argument to '%s'", a->argv[i]);
660 i++;
661 name = a->argv[i];
662 }
663 else if ( !strcmp(a->argv[i], "--hostpath")
664 || !strcmp(a->argv[i], "-hostpath"))
665 {
666 if (a->argc <= i + 1 || !*a->argv[i+1])
667 return errorArgument("Missing argument to '%s'", a->argv[i]);
668 i++;
669 hostpath = a->argv[i];
670 }
671 else if ( !strcmp(a->argv[i], "--readonly")
672 || !strcmp(a->argv[i], "-readonly"))
673 {
674 fWritable = false;
675 }
676 else if ( !strcmp(a->argv[i], "--transient")
677 || !strcmp(a->argv[i], "-transient"))
678 {
679 fTransient = true;
680 }
681 else if ( !strcmp(a->argv[i], "--automount")
682 || !strcmp(a->argv[i], "-automount"))
683 {
684 fAutoMount = true;
685 }
686 else
687 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str());
688 }
689
690 if (NULL != strstr(name, " "))
691 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
692
693 /* required arguments */
694 if (!name || !hostpath)
695 {
696 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters --name and --hostpath are required");
697 }
698
699 if (fTransient)
700 {
701 ComPtr <IConsole> console;
702
703 /* open an existing session for the VM */
704 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
705 /* get the session machine */
706 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
707 /* get the session console */
708 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
709
710 CHECK_ERROR(console, CreateSharedFolder(Bstr(name).raw(),
711 Bstr(hostpath).raw(),
712 fWritable, fAutoMount));
713 if (console)
714 a->session->UnlockMachine();
715 }
716 else
717 {
718 /* open a session for the VM */
719 SessionType_T st;
720 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
721
722 /* get the mutable session machine */
723 a->session->COMGETTER(Machine)(machine.asOutParam());
724
725 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name).raw(),
726 Bstr(hostpath).raw(),
727 fWritable, fAutoMount));
728 if (SUCCEEDED(rc))
729 CHECK_ERROR(machine, SaveSettings());
730
731 a->session->UnlockMachine();
732 }
733 }
734 else if (!strcmp(a->argv[0], "remove"))
735 {
736 /* we need at least two more parameters */
737 if (a->argc < 3)
738 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
739
740 char *name = NULL;
741 bool fTransient = false;
742
743 for (int i = 2; i < a->argc; i++)
744 {
745 if ( !strcmp(a->argv[i], "--name")
746 || !strcmp(a->argv[i], "-name"))
747 {
748 if (a->argc <= i + 1 || !*a->argv[i+1])
749 return errorArgument("Missing argument to '%s'", a->argv[i]);
750 i++;
751 name = a->argv[i];
752 }
753 else if ( !strcmp(a->argv[i], "--transient")
754 || !strcmp(a->argv[i], "-transient"))
755 {
756 fTransient = true;
757 }
758 else
759 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str());
760 }
761
762 /* required arguments */
763 if (!name)
764 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter --name is required");
765
766 if (fTransient)
767 {
768 ComPtr <IConsole> console;
769
770 /* open an existing session for the VM */
771 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
772 /* get the session machine */
773 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
774 /* get the session console */
775 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
776
777 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name).raw()));
778
779 if (console)
780 a->session->UnlockMachine();
781 }
782 else
783 {
784 /* open a session for the VM */
785 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
786
787 /* get the mutable session machine */
788 a->session->COMGETTER(Machine)(machine.asOutParam());
789
790 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name).raw()));
791
792 /* commit and close the session */
793 CHECK_ERROR(machine, SaveSettings());
794 a->session->UnlockMachine();
795 }
796 }
797 else
798 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).c_str());
799
800 return 0;
801}
802
803int handleVMStatistics(HandlerArg *a)
804{
805 HRESULT rc;
806
807 /* at least one option: the UUID or name of the VM */
808 if (a->argc < 1)
809 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
810
811 /* try to find the given machine */
812 ComPtr<IMachine> machine;
813 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
814 machine.asOutParam()));
815 if (FAILED(rc))
816 return 1;
817
818 /* parse arguments. */
819 bool fReset = false;
820 bool fWithDescriptions = false;
821 const char *pszPattern = NULL; /* all */
822 for (int i = 1; i < a->argc; i++)
823 {
824 if ( !strcmp(a->argv[i], "--pattern")
825 || !strcmp(a->argv[i], "-pattern"))
826 {
827 if (pszPattern)
828 return errorSyntax(USAGE_VM_STATISTICS, "Multiple --patterns options is not permitted");
829 if (i + 1 >= a->argc)
830 return errorArgument("Missing argument to '%s'", a->argv[i]);
831 pszPattern = a->argv[++i];
832 }
833 else if ( !strcmp(a->argv[i], "--descriptions")
834 || !strcmp(a->argv[i], "-descriptions"))
835 fWithDescriptions = true;
836 /* add: --file <filename> and --formatted */
837 else if ( !strcmp(a->argv[i], "--reset")
838 || !strcmp(a->argv[i], "-reset"))
839 fReset = true;
840 else
841 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
842 }
843 if (fReset && fWithDescriptions)
844 return errorSyntax(USAGE_VM_STATISTICS, "The --reset and --descriptions options does not mix");
845
846
847 /* open an existing session for the VM. */
848 CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared));
849 if (SUCCEEDED(rc))
850 {
851 /* get the session console. */
852 ComPtr <IConsole> console;
853 CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
854 if (SUCCEEDED(rc))
855 {
856 /* get the machine debugger. */
857 ComPtr <IMachineDebugger> debugger;
858 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
859 if (SUCCEEDED(rc))
860 {
861 if (fReset)
862 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern).raw()));
863 else
864 {
865 Bstr stats;
866 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern).raw(),
867 fWithDescriptions,
868 stats.asOutParam()));
869 if (SUCCEEDED(rc))
870 {
871 /* if (fFormatted)
872 { big mess }
873 else
874 */
875 RTPrintf("%ls\n", stats.raw());
876 }
877 }
878 }
879 a->session->UnlockMachine();
880 }
881 }
882
883 return SUCCEEDED(rc) ? 0 : 1;
884}
885
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