VirtualBox

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

Last change on this file since 26956 was 26517, checked in by vboxsync, 15 years ago

*: RTGetOpt cleanup related to --help and --version (now standard option). Use RTGetOptPrintError.

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