VirtualBox

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

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