VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp@ 30871

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

Main: event names now in past tense

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.1 KB
Line 
1/* $Id: VBoxManageGuestProp.cpp 30871 2010-07-16 10:07:21Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'guestproperty' command.
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#include "VBoxManage.h"
23
24#include <VBox/com/com.h>
25#include <VBox/com/string.h>
26#include <VBox/com/array.h>
27#include <VBox/com/ErrorInfo.h>
28#include <VBox/com/errorprint.h>
29
30#include <VBox/com/VirtualBox.h>
31#include <VBox/com/EventQueue.h>
32
33#include <VBox/log.h>
34#include <iprt/asm.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/time.h>
38#include <iprt/thread.h>
39
40#ifdef USE_XPCOM_QUEUE
41# include <sys/select.h>
42# include <errno.h>
43#endif
44
45#ifdef RT_OS_DARWIN
46# include <CoreFoundation/CFRunLoop.h>
47#endif
48
49using namespace com;
50
51void usageGuestProperty(void)
52{
53 RTPrintf("VBoxManage guestproperty get <vmname>|<uuid>\n"
54 " <property> [--verbose]\n"
55 "\n");
56 RTPrintf("VBoxManage guestproperty set <vmname>|<uuid>\n"
57 " <property> [<value> [--flags <flags>]]\n"
58 "\n");
59 RTPrintf("VBoxManage guestproperty enumerate <vmname>|<uuid>\n"
60 " [--patterns <patterns>]\n"
61 "\n");
62 RTPrintf("VBoxManage guestproperty wait <vmname>|<uuid> <patterns>\n"
63 " [--timeout <msec>] [--fail-on-timeout]\n"
64 "\n");
65}
66
67static int handleGetGuestProperty(HandlerArg *a)
68{
69 HRESULT rc = S_OK;
70
71 bool verbose = false;
72 if ( a->argc == 3
73 && ( !strcmp(a->argv[2], "--verbose")
74 || !strcmp(a->argv[2], "-verbose")))
75 verbose = true;
76 else if (a->argc != 2)
77 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
78
79 ComPtr<IMachine> machine;
80 /* assume it's a UUID */
81 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
82 if (FAILED(rc) || !machine)
83 {
84 /* must be a name */
85 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
86 }
87 if (machine)
88 {
89 Bstr uuid;
90 machine->COMGETTER(Id)(uuid.asOutParam());
91
92 /* open a session for the VM - new or existing */
93 if (FAILED (a->virtualBox->OpenSession(a->session, uuid)))
94 CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, uuid), 1);
95
96 /* get the mutable session machine */
97 a->session->COMGETTER(Machine)(machine.asOutParam());
98
99 Bstr value;
100 ULONG64 u64Timestamp;
101 Bstr flags;
102 CHECK_ERROR(machine, GetGuestProperty(Bstr(a->argv[1]), value.asOutParam(),
103 &u64Timestamp, flags.asOutParam()));
104 if (!value)
105 RTPrintf("No value set!\n");
106 if (value)
107 RTPrintf("Value: %lS\n", value.raw());
108 if (value && verbose)
109 {
110 RTPrintf("Timestamp: %lld\n", u64Timestamp);
111 RTPrintf("Flags: %lS\n", flags.raw());
112 }
113 }
114 return SUCCEEDED(rc) ? 0 : 1;
115}
116
117static int handleSetGuestProperty(HandlerArg *a)
118{
119 HRESULT rc = S_OK;
120
121 /*
122 * Check the syntax. We can deduce the correct syntax from the number of
123 * arguments.
124 */
125 bool usageOK = true;
126 const char *pszName = NULL;
127 const char *pszValue = NULL;
128 const char *pszFlags = NULL;
129 if (a->argc == 3)
130 pszValue = a->argv[2];
131 else if (a->argc == 4)
132 usageOK = false;
133 else if (a->argc == 5)
134 {
135 pszValue = a->argv[2];
136 if ( strcmp(a->argv[3], "--flags")
137 && strcmp(a->argv[3], "-flags"))
138 usageOK = false;
139 pszFlags = a->argv[4];
140 }
141 else if (a->argc != 2)
142 usageOK = false;
143 if (!usageOK)
144 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
145 /* This is always needed. */
146 pszName = a->argv[1];
147
148 ComPtr<IMachine> machine;
149 /* assume it's a UUID */
150 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
151 if (FAILED(rc) || !machine)
152 {
153 /* must be a name */
154 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
155 }
156 if (machine)
157 {
158 Bstr uuid;
159 machine->COMGETTER(Id)(uuid.asOutParam());
160
161 /* open a session for the VM - new or existing */
162 if (FAILED (a->virtualBox->OpenSession(a->session, uuid)))
163 CHECK_ERROR_RET (a->virtualBox, OpenExistingSession(a->session, uuid), 1);
164
165 /* get the mutable session machine */
166 a->session->COMGETTER(Machine)(machine.asOutParam());
167
168 if (!pszValue && !pszFlags)
169 CHECK_ERROR(machine, SetGuestPropertyValue(Bstr(pszName), Bstr("")));
170 else if (!pszFlags)
171 CHECK_ERROR(machine, SetGuestPropertyValue(Bstr(pszName), Bstr(pszValue)));
172 else
173 CHECK_ERROR(machine, SetGuestProperty(Bstr(pszName), Bstr(pszValue), Bstr(pszFlags)));
174
175 if (SUCCEEDED(rc))
176 CHECK_ERROR(machine, SaveSettings());
177
178 a->session->Close();
179 }
180 return SUCCEEDED(rc) ? 0 : 1;
181}
182
183/**
184 * Enumerates the properties in the guest property store.
185 *
186 * @returns 0 on success, 1 on failure
187 * @note see the command line API description for parameters
188 */
189static int handleEnumGuestProperty(HandlerArg *a)
190{
191 /*
192 * Check the syntax. We can deduce the correct syntax from the number of
193 * arguments.
194 */
195 if ( a->argc < 1
196 || a->argc == 2
197 || ( a->argc > 3
198 && strcmp(a->argv[1], "--patterns")
199 && strcmp(a->argv[1], "-patterns")))
200 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
201
202 /*
203 * Pack the patterns
204 */
205 Utf8Str Utf8Patterns(a->argc > 2 ? a->argv[2] : "");
206 for (int i = 3; i < a->argc; ++i)
207 Utf8Patterns = Utf8StrFmt ("%s,%s", Utf8Patterns.raw(), a->argv[i]);
208
209 /*
210 * Make the actual call to Main.
211 */
212 ComPtr<IMachine> machine;
213 /* assume it's a UUID */
214 HRESULT rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
215 if (FAILED(rc) || !machine)
216 {
217 /* must be a name */
218 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
219 }
220 if (machine)
221 {
222 Bstr uuid;
223 machine->COMGETTER(Id)(uuid.asOutParam());
224
225 /* open a session for the VM - new or existing */
226 if (FAILED(a->virtualBox->OpenSession(a->session, uuid)))
227 CHECK_ERROR_RET (a->virtualBox, OpenExistingSession(a->session, uuid), 1);
228
229 /* get the mutable session machine */
230 a->session->COMGETTER(Machine)(machine.asOutParam());
231
232 com::SafeArray <BSTR> names;
233 com::SafeArray <BSTR> values;
234 com::SafeArray <ULONG64> timestamps;
235 com::SafeArray <BSTR> flags;
236 CHECK_ERROR(machine, EnumerateGuestProperties(Bstr(Utf8Patterns),
237 ComSafeArrayAsOutParam(names),
238 ComSafeArrayAsOutParam(values),
239 ComSafeArrayAsOutParam(timestamps),
240 ComSafeArrayAsOutParam(flags)));
241 if (SUCCEEDED(rc))
242 {
243 if (names.size() == 0)
244 RTPrintf("No properties found.\n");
245 for (unsigned i = 0; i < names.size(); ++i)
246 RTPrintf("Name: %lS, value: %lS, timestamp: %lld, flags: %lS\n",
247 names[i], values[i], timestamps[i], flags[i]);
248 }
249 }
250 return SUCCEEDED(rc) ? 0 : 1;
251}
252
253/**
254 * Enumerates the properties in the guest property store.
255 *
256 * @returns 0 on success, 1 on failure
257 * @note see the command line API description for parameters
258 */
259static int handleWaitGuestProperty(HandlerArg *a)
260{
261 /*
262 * Handle arguments
263 */
264 bool fFailOnTimeout = false;
265 const char *pszPatterns = NULL;
266 uint32_t cMsTimeout = RT_INDEFINITE_WAIT;
267 bool usageOK = true;
268 if (a->argc < 2)
269 usageOK = false;
270 else
271 pszPatterns = a->argv[1];
272 ComPtr<IMachine> machine;
273 /* assume it's a UUID */
274 HRESULT rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
275 if (FAILED(rc) || !machine)
276 {
277 /* must be a name */
278 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
279 }
280 if (!machine)
281 usageOK = false;
282 for (int i = 2; usageOK && i < a->argc; ++i)
283 {
284 if ( !strcmp(a->argv[i], "--timeout")
285 || !strcmp(a->argv[i], "-timeout"))
286 {
287 if ( i + 1 >= a->argc
288 || RTStrToUInt32Full(a->argv[i + 1], 10, &cMsTimeout) != VINF_SUCCESS)
289 usageOK = false;
290 else
291 ++i;
292 }
293 else if (!strcmp(a->argv[i], "--fail-on-timeout"))
294 fFailOnTimeout = true;
295 else
296 usageOK = false;
297 }
298 if (!usageOK)
299 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
300
301 /*
302 * Set up the event listener and wait until found match or timeout.
303 */
304 Bstr aMachStrGuid;
305 machine->COMGETTER(Id)(aMachStrGuid.asOutParam());
306 Guid aMachGuid(aMachStrGuid);
307 ComPtr<IEventSource> es;
308 CHECK_ERROR(a->virtualBox, COMGETTER(EventSource)(es.asOutParam()));
309 ComPtr<IEventListener> listener;
310 CHECK_ERROR(es, CreateListener(listener.asOutParam()));
311 com::SafeArray <VBoxEventType_T> eventTypes(1);
312 eventTypes.push_back(VBoxEventType_OnGuestPropertyChanged);
313 CHECK_ERROR(es, RegisterListener(listener, ComSafeArrayAsInParam(eventTypes), false));
314
315 uint64_t u64Started = RTTimeMilliTS();
316 bool fSignalled = false;
317 do
318 {
319 unsigned cMsWait;
320 if (cMsTimeout == RT_INDEFINITE_WAIT)
321 cMsWait = 1000;
322 else
323 {
324 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
325 if (cMsElapsed >= cMsTimeout)
326 break; /* timed out */
327 cMsWait = RT_MIN(1000, cMsTimeout - (uint32_t)cMsElapsed);
328 }
329
330 ComPtr<IEvent> ev;
331 rc = es->GetEvent(listener, cMsWait, ev.asOutParam());
332 if (ev)
333 {
334 VBoxEventType_T aType;
335 rc = ev->COMGETTER(Type)(&aType);
336 switch (aType)
337 {
338 case VBoxEventType_OnGuestPropertyChanged:
339 {
340 ComPtr<IGuestPropertyChangedEvent> gpcev = ev;
341 Assert(gpcev);
342 Bstr aNextStrGuid;
343 gpcev->COMGETTER(MachineId)(aNextStrGuid.asOutParam());
344 if (aMachGuid != Guid(aNextStrGuid))
345 continue;
346 Bstr aNextName;
347 gpcev->COMGETTER(Name)(aNextName.asOutParam());
348 if (RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
349 Utf8Str(aNextName).raw(), RTSTR_MAX, NULL))
350 {
351 Bstr aNextValue, aNextFlags;
352 gpcev->COMGETTER(Value)(aNextValue.asOutParam());
353 gpcev->COMGETTER(Flags)(aNextFlags.asOutParam());
354 RTPrintf("Name: %lS, value: %lS, flags: %lS\n",
355 aNextName.raw(), aNextValue.raw(), aNextFlags.raw());
356 fSignalled = true;
357 }
358 break;
359 }
360 default:
361 AssertFailed();
362 }
363 }
364 } while (!fSignalled);
365
366 es->UnregisterListener(listener);
367
368 int rcRet = 0;
369 if (!fSignalled)
370 {
371 RTPrintf("Time out or interruption while waiting for a notification.\n");
372 if (fFailOnTimeout)
373 rcRet = 2;
374 }
375 return rcRet;
376}
377
378/**
379 * Access the guest property store.
380 *
381 * @returns 0 on success, 1 on failure
382 * @note see the command line API description for parameters
383 */
384int handleGuestProperty(HandlerArg *a)
385{
386 HandlerArg arg = *a;
387 arg.argc = a->argc - 1;
388 arg.argv = a->argv + 1;
389
390 if (a->argc == 0)
391 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
392
393 /* switch (cmd) */
394 if (strcmp(a->argv[0], "get") == 0)
395 return handleGetGuestProperty(&arg);
396 if (strcmp(a->argv[0], "set") == 0)
397 return handleSetGuestProperty(&arg);
398 if (strcmp(a->argv[0], "enumerate") == 0)
399 return handleEnumGuestProperty(&arg);
400 if (strcmp(a->argv[0], "wait") == 0)
401 return handleWaitGuestProperty(&arg);
402
403 /* default: */
404 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
405}
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