VirtualBox

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

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

Main: COM header cleanup (remove obscure and unused templates), second try

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