VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageUpdateCheck.cpp@ 94595

Last change on this file since 94595 was 94438, checked in by vboxsync, 3 years ago

Main/HostUpdate+VBoxManage/UpdateCheck: Simple tidy-up of some breakage
from previous code improvements: ensure m_updateURL is set after parsing
the HTTP server's response and print out the URL response in 'VBoxManage
updatecheck perform' when --machine-readable isn't supplied. Also for
VBoxManage disable the progress display and informational messages when
--machine-readable is specified. bugref:7983

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: VBoxManageUpdateCheck.cpp 94438 2022-04-01 13:46:16Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'updatecheck' command.
4 */
5
6/*
7 * Copyright (C) 2020-2022 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 <VBox/com/com.h>
23#include <VBox/com/ErrorInfo.h>
24#include <VBox/com/errorprint.h>
25#include <VBox/com/VirtualBox.h>
26#include <VBox/com/array.h>
27
28#include <iprt/buildconfig.h>
29#include <VBox/version.h>
30
31#include <VBox/log.h>
32#include <iprt/getopt.h>
33#include <iprt/stream.h>
34#include <iprt/ctype.h>
35#include <iprt/message.h>
36
37#include "VBoxManage.h"
38
39DECLARE_TRANSLATION_CONTEXT(UpdateCheck);
40
41using namespace com; // SafeArray
42
43/**
44 * updatecheck getsettings
45 */
46static RTEXITCODE doVBoxUpdateGetSettings(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox)
47{
48 /*
49 * Parse options.
50 */
51 static const RTGETOPTDEF s_aOptions[] =
52 {
53 { "--machine-readable", 'm', RTGETOPT_REQ_NOTHING }
54 };
55 RTGETOPTSTATE GetState;
56 int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0);
57 AssertRCReturn(vrc, RTEXITCODE_INIT);
58
59 bool fMachineReadable = false;
60
61 int c;
62 RTGETOPTUNION ValueUnion;
63 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
64 {
65 switch (c)
66 {
67 case 'm':
68 fMachineReadable = true;
69 break;
70
71 default:
72 return errorGetOpt(c, &ValueUnion);
73 }
74 }
75
76 /*
77 * Do the work.
78 */
79 ComPtr<ISystemProperties> pSystemProperties;
80 CHECK_ERROR2I_RET(aVirtualBox, COMGETTER(SystemProperties)(pSystemProperties.asOutParam()), RTEXITCODE_FAILURE);
81
82 BOOL fVBoxUpdateEnabled;
83 CHECK_ERROR2I_RET(pSystemProperties, COMGETTER(VBoxUpdateEnabled)(&fVBoxUpdateEnabled), RTEXITCODE_FAILURE);
84 if (fMachineReadable)
85 outputMachineReadableBool("enabled", &fVBoxUpdateEnabled);
86 else
87 RTPrintf(UpdateCheck::tr("Enabled: %s\n"),
88 fVBoxUpdateEnabled ? UpdateCheck::tr("yes") : UpdateCheck::tr("no"));
89
90 ULONG cVBoxUpdateCount;
91 CHECK_ERROR2I_RET(pSystemProperties, COMGETTER(VBoxUpdateCount)(&cVBoxUpdateCount), RTEXITCODE_FAILURE);
92 if (fMachineReadable)
93 outputMachineReadableULong("count", &cVBoxUpdateCount);
94 else
95 RTPrintf(UpdateCheck::tr("Count: %u\n"), cVBoxUpdateCount);
96
97 ULONG cDaysFrequencey;
98 CHECK_ERROR2I_RET(pSystemProperties, COMGETTER(VBoxUpdateFrequency)(&cDaysFrequencey), RTEXITCODE_FAILURE);
99 if (fMachineReadable)
100 outputMachineReadableULong("frequency", &cDaysFrequencey);
101 else if (cDaysFrequencey == 0)
102 RTPrintf(UpdateCheck::tr("Frequency: never\n")); /** @todo r=bird: Two inconsistencies here. HostUpdateImpl.cpp code will indicate the need for updating if no last-check-date. modifysettings cannot set it to zero (I added the error message, you just skipped setting it originally). */
103 else if (cDaysFrequencey == 1)
104 RTPrintf(UpdateCheck::tr("Frequency: every day\n"));
105 else
106 RTPrintf(UpdateCheck::tr("Frequency: every %u days\n"), cDaysFrequencey);
107
108 VBoxUpdateTarget_T enmVBoxUpdateTarget;
109 CHECK_ERROR2I_RET(pSystemProperties, COMGETTER(VBoxUpdateTarget)(&enmVBoxUpdateTarget), RTEXITCODE_FAILURE);
110 const char *psz;
111 const char *pszMachine;
112 switch (enmVBoxUpdateTarget)
113 {
114 case VBoxUpdateTarget_Stable:
115 psz = UpdateCheck::tr("Stable - new minor and maintenance releases");
116 pszMachine = "stable";
117 break;
118 case VBoxUpdateTarget_AllReleases:
119 psz = UpdateCheck::tr("All releases - new minor, maintenance, and major releases");
120 pszMachine = "all-releases";
121 break;
122 case VBoxUpdateTarget_WithBetas:
123 psz = UpdateCheck::tr("With Betas - new minor, maintenance, major, and beta releases");
124 pszMachine = "with-betas";
125 break;
126 default:
127 AssertFailed();
128 psz = UpdateCheck::tr("Unset");
129 pszMachine = "invalid";
130 break;
131 }
132 if (fMachineReadable)
133 outputMachineReadableString("target", pszMachine);
134 else
135 RTPrintf(UpdateCheck::tr("Target: %s\n"), psz);
136
137 Bstr bstrLastCheckDate;
138 CHECK_ERROR2I_RET(pSystemProperties, COMGETTER(VBoxUpdateLastCheckDate)(bstrLastCheckDate.asOutParam()),
139 RTEXITCODE_FAILURE);
140 if (fMachineReadable)
141 outputMachineReadableString("last-check-date", &bstrLastCheckDate);
142 else if (bstrLastCheckDate.isNotEmpty())
143 RTPrintf(UpdateCheck::tr("Last Check Date: %ls\n"), bstrLastCheckDate.raw());
144
145 return RTEXITCODE_SUCCESS;
146}
147
148/**
149 * updatecheck modifysettings
150 */
151static RTEXITCODE doVBoxUpdateModifySettings(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox)
152{
153 /*
154 * Parse options.
155 */
156 static const RTGETOPTDEF s_aOptions[] =
157 {
158 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
159 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
160 { "--target", 't', RTGETOPT_REQ_STRING },
161 { "--frequency", 'f', RTGETOPT_REQ_UINT32 },
162 };
163
164 RTGETOPTSTATE GetState;
165 int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0);
166 AssertRCReturn(vrc, RTEXITCODE_INIT);
167
168 int fEnabled = -1; /* tristate: -1 (not modified), false, true */
169 VBoxUpdateTarget_T const enmVBoxUpdateTargetNil = (VBoxUpdateTarget_T)-999;
170 VBoxUpdateTarget_T enmVBoxUpdateTarget = enmVBoxUpdateTargetNil;
171 uint32_t cDaysUpdateFrequency = 0;
172
173 int c;
174 RTGETOPTUNION ValueUnion;
175 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
176 {
177 switch (c)
178 {
179 case 'e':
180 fEnabled = true;
181 break;
182
183 case 'd':
184 fEnabled = false;
185 break;
186
187 case 't':
188 if (!RTStrICmp(ValueUnion.psz, "stable"))
189 enmVBoxUpdateTarget = VBoxUpdateTarget_Stable;
190 else if (!RTStrICmp(ValueUnion.psz, "withbetas"))
191 enmVBoxUpdateTarget = VBoxUpdateTarget_WithBetas;
192 else if (!RTStrICmp(ValueUnion.psz, "allreleases"))
193 enmVBoxUpdateTarget = VBoxUpdateTarget_AllReleases;
194 else
195 return errorArgument(UpdateCheck::tr("Unknown target specified: '%s'"), ValueUnion.psz);
196 break;
197
198 case 'f':
199 cDaysUpdateFrequency = ValueUnion.u32;
200 if (cDaysUpdateFrequency == 0)
201 return errorArgument(UpdateCheck::tr("The update frequency cannot be zero"));
202 break;
203
204 default:
205 return errorGetOpt(c, &ValueUnion);
206 }
207 }
208
209 if ( fEnabled == -1
210 && enmVBoxUpdateTarget != enmVBoxUpdateTargetNil
211 && cDaysUpdateFrequency == 0)
212 return errorSyntax(UpdateCheck::tr("No change requested"));
213
214 /*
215 * Make the changes.
216 */
217 ComPtr<ISystemProperties> pSystemProperties;
218 CHECK_ERROR2I_RET(aVirtualBox, COMGETTER(SystemProperties)(pSystemProperties.asOutParam()), RTEXITCODE_FAILURE);
219
220 if (enmVBoxUpdateTarget != enmVBoxUpdateTargetNil)
221 {
222 CHECK_ERROR2I_RET(pSystemProperties, COMSETTER(VBoxUpdateTarget)(enmVBoxUpdateTarget), RTEXITCODE_FAILURE);
223 }
224
225 if (fEnabled != -1)
226 {
227 CHECK_ERROR2I_RET(pSystemProperties, COMSETTER(VBoxUpdateEnabled)((BOOL)fEnabled), RTEXITCODE_FAILURE);
228 }
229
230 if (cDaysUpdateFrequency)
231 {
232 CHECK_ERROR2I_RET(pSystemProperties, COMSETTER(VBoxUpdateFrequency)(cDaysUpdateFrequency), RTEXITCODE_FAILURE);
233 }
234
235 return RTEXITCODE_SUCCESS;
236}
237
238/**
239 * updatecheck perform
240 */
241static RTEXITCODE doVBoxUpdate(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox)
242{
243 /*
244 * Parse arguments.
245 */
246 static const RTGETOPTDEF s_aOptions[] =
247 {
248 { "--machine-readable", 'm', RTGETOPT_REQ_NOTHING }
249 };
250 RTGETOPTSTATE GetState;
251 int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0);
252 AssertRCReturn(vrc, RTEXITCODE_INIT);
253
254 bool fMachineReadable = false;
255
256 int c;
257 RTGETOPTUNION ValueUnion;
258 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
259 {
260 switch (c)
261 {
262 case 'm':
263 fMachineReadable = true;
264 break;
265
266 default:
267 return errorGetOpt(c, &ValueUnion);
268 }
269 }
270
271 /*
272 * Do the work.
273 */
274 ComPtr<IHost> pHost;
275 CHECK_ERROR2I_RET(aVirtualBox, COMGETTER(Host)(pHost.asOutParam()), RTEXITCODE_FAILURE);
276
277 ComPtr<IHostUpdate> pHostUpdate;
278 CHECK_ERROR2I_RET(pHost, COMGETTER(Update)(pHostUpdate.asOutParam()), RTEXITCODE_FAILURE);
279
280 UpdateCheckType_T updateCheckType = UpdateCheckType_VirtualBox;
281 ComPtr<IProgress> ptrProgress;
282
283 if (!fMachineReadable)
284 RTPrintf(UpdateCheck::tr("Checking for a new VirtualBox version...\n"));
285
286 // we don't call CHECK_ERROR2I_RET(pHostUpdate, VBoxUpdate(updateCheckType, ...); here so we can check for a specific
287 // return value indicating update checks are disabled.
288 HRESULT rc = pHostUpdate->UpdateCheck(updateCheckType, ptrProgress.asOutParam());
289 if (FAILED(rc))
290 {
291/** @todo r=bird: WTF? This makes no sense. I've commented upon this in the
292 * HostUpdateImpl.cpp code too. */
293 if (rc == E_NOTIMPL)
294 {
295 RTPrintf(UpdateCheck::tr("VirtualBox update checking has been disabled.\n"));
296 return RTEXITCODE_SUCCESS;
297 }
298
299 if (ptrProgress.isNull())
300 RTStrmPrintf(g_pStdErr, UpdateCheck::tr("Failed to create ptrProgress object: %Rhrc\n"), rc);
301 else
302 com::GlueHandleComError(pHostUpdate, "VBoxUpdate(updateCheckType, ptrProgress.asOutParam())",
303 rc, __FILE__, __LINE__);
304 return RTEXITCODE_FAILURE;
305 }
306
307 /* HRESULT hrc = */ showProgress(ptrProgress, fMachineReadable ? SHOW_PROGRESS_NONE : SHOW_PROGRESS);
308 CHECK_PROGRESS_ERROR_RET(ptrProgress, (UpdateCheck::tr("Check for update failed.")), RTEXITCODE_FAILURE);
309
310 BOOL fUpdateNeeded = FALSE;
311 CHECK_ERROR2I_RET(pHostUpdate, COMGETTER(UpdateResponse)(&fUpdateNeeded), RTEXITCODE_FAILURE);
312
313 if (fMachineReadable)
314 outputMachineReadableBool("update-needed", &fUpdateNeeded);
315
316 if (fUpdateNeeded)
317 {
318 Bstr bstrUpdateVersion;
319 CHECK_ERROR2I_RET(pHostUpdate, COMGETTER(UpdateVersion)(bstrUpdateVersion.asOutParam()), RTEXITCODE_FAILURE);
320 Bstr bstrUpdateURL;
321 CHECK_ERROR2I_RET(pHostUpdate, COMGETTER(UpdateURL)(bstrUpdateURL.asOutParam()), RTEXITCODE_FAILURE);
322
323 if (!fMachineReadable)
324 RTPrintf(UpdateCheck::tr(
325 "A new version of VirtualBox has been released! Version %ls is available at virtualbox.org.\n"
326 "You can download this version here: %ls\n"),
327 bstrUpdateVersion.raw(), bstrUpdateURL.raw());
328 else
329 {
330 outputMachineReadableString("update-version", &bstrUpdateVersion);
331 outputMachineReadableString("update-url", &bstrUpdateURL);
332 }
333 }
334 else if (!fMachineReadable)
335 RTPrintf(UpdateCheck::tr("You are already running the most recent version of VirtualBox.\n"));
336
337 return RTEXITCODE_SUCCESS;
338}
339
340/**
341 * Handles the 'updatecheck' command.
342 *
343 * @returns Appropriate exit code.
344 * @param a Handler argument.
345 */
346RTEXITCODE handleUpdateCheck(HandlerArg *a)
347{
348 if (a->argc < 1)
349 return errorNoSubcommand();
350 if (!strcmp(a->argv[0], "perform"))
351 {
352 setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_PERFORM);
353 return doVBoxUpdate(a->argc - 1, &a->argv[1], a->virtualBox);
354 }
355 if (!strcmp(a->argv[0], "getsettings"))
356 {
357 setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_GETSETTINGS);
358 return doVBoxUpdateGetSettings(a->argc - 1, &a->argv[1], a->virtualBox);
359 }
360 if (!strcmp(a->argv[0], "modifysettings"))
361 {
362 setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_MODIFYSETTINGS);
363 return doVBoxUpdateModifySettings(a->argc - 1, &a->argv[1], a->virtualBox);
364 }
365 return errorUnknownSubcommand(a->argv[0]);
366}
367
368/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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