VirtualBox

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

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

Main: new VirtualBox::ComposeMachineFilename() API; remove the 'default hard disk folder' concept and related APIs; GUI wizards need fixing

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

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