VirtualBox

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

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

forgotten file

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

© 2023 Oracle
ContactPrivacy policyTerms of Use