VirtualBox

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

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

Main: rename ISession::close() to ISession::unlockMachine(); API documentation

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