VirtualBox

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

Last change on this file since 94740 was 94685, checked in by vboxsync, 3 years ago

Main/Update check: Settings fixes, added @todos. ​​bugref:7983

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: VBoxManageUpdateCheck.cpp 94685 2022-04-22 10:16:24Z 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
43static RTEXITCODE doUpdateList(int argc, char **argv, ComPtr<IUpdateAgent> pUpdateAgent)
44{
45 /*
46 * Parse options.
47 */
48 static const RTGETOPTDEF s_aOptions[] =
49 {
50 { "--machine-readable", 'm', RTGETOPT_REQ_NOTHING }
51 };
52 RTGETOPTSTATE GetState;
53 int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0);
54 AssertRCReturn(vrc, RTEXITCODE_INIT);
55
56 bool fMachineReadable = false;
57
58 int c;
59 RTGETOPTUNION ValueUnion;
60 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
61 {
62 switch (c)
63 {
64 case 'm':
65 fMachineReadable = true;
66 break;
67
68 default:
69 return errorGetOpt(c, &ValueUnion);
70 }
71 }
72
73 /*
74 * Do the work.
75 */
76 BOOL fEnabled;
77 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Enabled)(&fEnabled), RTEXITCODE_FAILURE);
78 if (fMachineReadable)
79 outputMachineReadableBool("enabled", &fEnabled);
80 else
81 RTPrintf(UpdateCheck::tr("Enabled: %s\n"),
82 fEnabled ? UpdateCheck::tr("yes") : UpdateCheck::tr("no"));
83
84 ULONG cCheckCount;
85 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(CheckCount)(&cCheckCount), RTEXITCODE_FAILURE);
86 if (fMachineReadable)
87 outputMachineReadableULong("count", &cCheckCount);
88 else
89 RTPrintf(UpdateCheck::tr("Count: %u\n"), cCheckCount);
90
91 ULONG uCheckFreqSeconds;
92 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(CheckFrequency)(&uCheckFreqSeconds), RTEXITCODE_FAILURE);
93
94 ULONG const uCheckFreqDays = uCheckFreqSeconds / RT_SEC_1DAY;
95
96 if (fMachineReadable)
97 outputMachineReadableULong("frequency", &uCheckFreqSeconds);
98 else if (uCheckFreqDays == 0)
99 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). */
100 else if (uCheckFreqDays == 1)
101 RTPrintf(UpdateCheck::tr("Frequency: every day\n"));
102 else
103 RTPrintf(UpdateCheck::tr("Frequency: every %u days\n"), uCheckFreqDays);
104
105 UpdateChannel_T enmUpdateChannel;
106 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Channel)(&enmUpdateChannel), RTEXITCODE_FAILURE);
107 const char *psz;
108 const char *pszMachine;
109 switch (enmUpdateChannel)
110 {
111 case UpdateChannel_Stable:
112 psz = UpdateCheck::tr("Stable - new minor and maintenance releases");
113 pszMachine = "stable";
114 break;
115 case UpdateChannel_All:
116 psz = UpdateCheck::tr("All releases - new minor, maintenance, and major releases");
117 pszMachine = "all-releases";
118 break;
119 case UpdateChannel_WithBetas:
120 psz = UpdateCheck::tr("With Betas - new minor, maintenance, major, and beta releases");
121 pszMachine = "with-betas";
122 break;
123 default:
124 AssertFailed();
125 psz = UpdateCheck::tr("Unset");
126 pszMachine = "invalid";
127 break;
128 }
129 if (fMachineReadable)
130 outputMachineReadableString("channel", pszMachine);
131 else
132 RTPrintf(UpdateCheck::tr("Channel: %s\n"), psz);
133
134 Bstr bstrLastCheckDate;
135 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(LastCheckDate)(bstrLastCheckDate.asOutParam()),
136 RTEXITCODE_FAILURE);
137 if (fMachineReadable)
138 outputMachineReadableString("last-check-date", &bstrLastCheckDate);
139 else if (bstrLastCheckDate.isNotEmpty())
140 RTPrintf(UpdateCheck::tr("Last Check Date: %ls\n"), bstrLastCheckDate.raw());
141
142 return RTEXITCODE_SUCCESS;
143}
144
145static RTEXITCODE doUpdateModify(int argc, char **argv, ComPtr<IUpdateAgent> pUpdateAgent)
146{
147 /*
148 * Parse options.
149 */
150 static const RTGETOPTDEF s_aOptions[] =
151 {
152 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
153 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
154 { "--channel", 'c', RTGETOPT_REQ_STRING },
155 { "--frequency", 'f', RTGETOPT_REQ_UINT32 },
156 };
157
158 RTGETOPTSTATE GetState;
159 int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0);
160 AssertRCReturn(vrc, RTEXITCODE_INIT);
161
162 int fEnabled = -1; /* tristate: -1 (not modified), false, true */
163 UpdateChannel_T const enmChannelNil = (UpdateChannel_T)-999;
164 UpdateChannel_T enmChannel = enmChannelNil;
165 uint32_t cFrequencyDays = 0;
166
167 int c;
168 RTGETOPTUNION ValueUnion;
169 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
170 {
171 switch (c)
172 {
173 case 'e':
174 fEnabled = true;
175 break;
176
177 case 'd':
178 fEnabled = false;
179 break;
180
181 case 'c':
182 if (!RTStrICmp(ValueUnion.psz, "stable"))
183 enmChannel = UpdateChannel_Stable;
184 else if (!RTStrICmp(ValueUnion.psz, "withbetas"))
185 enmChannel = UpdateChannel_WithBetas;
186 /** @todo UpdateChannel_WithTesting once supported. */
187 else if (!RTStrICmp(ValueUnion.psz, "all"))
188 enmChannel = UpdateChannel_All;
189 else
190 return errorArgument(UpdateCheck::tr("Unknown channel specified: '%s'"), ValueUnion.psz);
191 break;
192
193 case 'f':
194 cFrequencyDays = ValueUnion.u32;
195 if (cFrequencyDays == 0)
196 return errorArgument(UpdateCheck::tr("The update frequency cannot be zero"));
197 break;
198
199 /** @todo Add more options like proxy + repo handling etc. */
200
201 default:
202 return errorGetOpt(c, &ValueUnion);
203 }
204 }
205
206 if ( fEnabled == -1
207 && enmChannel == enmChannelNil
208 && cFrequencyDays == 0)
209 return errorSyntax(UpdateCheck::tr("No change requested"));
210
211 /*
212 * Make the changes.
213 */
214 if (enmChannel != enmChannelNil)
215 {
216 CHECK_ERROR2I_RET(pUpdateAgent, COMSETTER(Channel)(enmChannel), RTEXITCODE_FAILURE);
217 }
218 if (fEnabled != -1)
219 {
220 CHECK_ERROR2I_RET(pUpdateAgent, COMSETTER(Enabled)((BOOL)fEnabled), RTEXITCODE_FAILURE);
221 }
222 if (cFrequencyDays)
223 {
224 CHECK_ERROR2I_RET(pUpdateAgent, COMSETTER(CheckFrequency)(cFrequencyDays * RT_SEC_1DAY), RTEXITCODE_FAILURE);
225 }
226 return RTEXITCODE_SUCCESS;
227}
228
229static RTEXITCODE doUpdateCheck(int argc, char **argv, ComPtr<IUpdateAgent> pUpdateAgent)
230{
231 /*
232 * Parse arguments.
233 */
234 static const RTGETOPTDEF s_aOptions[] =
235 {
236 { "--machine-readable", 'm', RTGETOPT_REQ_NOTHING }
237 };
238 RTGETOPTSTATE GetState;
239 int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0);
240 AssertRCReturn(vrc, RTEXITCODE_INIT);
241
242 bool fMachineReadable = false;
243
244 int c;
245 RTGETOPTUNION ValueUnion;
246 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
247 {
248 switch (c)
249 {
250 case 'm':
251 fMachineReadable = true;
252 break;
253
254 default:
255 return errorGetOpt(c, &ValueUnion);
256 }
257 }
258
259 /*
260 * Do the work.
261 */
262 Bstr bstrName;
263 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Name)(bstrName.asOutParam()), RTEXITCODE_FAILURE);
264
265 if (!fMachineReadable)
266 RTPrintf(UpdateCheck::tr("Checking for a new %ls version...\n"), bstrName.raw());
267
268 /*
269 * We don't call CHECK_ERROR2I_RET(pHostUpdate, VBoxUpdate(updateCheckType, ...); here so we can check for a specific
270 * return value indicating update checks are disabled.
271 */
272 ComPtr<IProgress> pProgress;
273 HRESULT rc = pUpdateAgent->CheckFor(pProgress.asOutParam());
274 if (FAILED(rc))
275 {
276 if (pProgress.isNull())
277 RTStrmPrintf(g_pStdErr, UpdateCheck::tr("Failed to create update progress object: %Rhrc\n"), rc);
278 else
279 com::GlueHandleComError(pUpdateAgent, "HostUpdate(UpdateChannel_Stable, pProgress.asOutParam())",
280 rc, __FILE__, __LINE__);
281 return RTEXITCODE_FAILURE;
282 }
283
284 /* HRESULT hrc = */ showProgress(pProgress, fMachineReadable ? SHOW_PROGRESS_NONE : SHOW_PROGRESS);
285 CHECK_PROGRESS_ERROR_RET(pProgress, (UpdateCheck::tr("Checking for update failed.")), RTEXITCODE_FAILURE);
286
287 UpdateState_T updateState;
288 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(State)(&updateState), RTEXITCODE_FAILURE);
289
290 BOOL const fUpdateNeeded = updateState == UpdateState_Available;
291 if (fMachineReadable)
292 outputMachineReadableBool("update-needed", &fUpdateNeeded);
293
294 switch (updateState)
295 {
296 case UpdateState_Available:
297 {
298 Bstr bstrUpdateVersion;
299 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Version)(bstrUpdateVersion.asOutParam()), RTEXITCODE_FAILURE);
300 Bstr bstrUpdateURL;
301 CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(DownloadUrl)(bstrUpdateURL.asOutParam()), RTEXITCODE_FAILURE);
302
303 if (!fMachineReadable)
304 RTPrintf(UpdateCheck::tr(
305 "A new version of %ls has been released! Version %ls is available at virtualbox.org.\n"
306 "You can download this version here: %ls\n"),
307 bstrName.raw(), bstrUpdateVersion.raw(), bstrUpdateURL.raw());
308 else
309 {
310 outputMachineReadableString("update-version", &bstrUpdateVersion);
311 outputMachineReadableString("update-url", &bstrUpdateURL);
312 }
313
314 break;
315 }
316
317 case UpdateState_NotAvailable:
318 {
319 if (!fMachineReadable)
320 RTPrintf(UpdateCheck::tr("You are already running the most recent version of %ls.\n"), bstrName.raw());
321 break;
322 }
323
324 case UpdateState_Canceled:
325 break;
326
327 case UpdateState_Error:
328 RT_FALL_THROUGH();
329 default:
330 {
331 if (!fMachineReadable)
332 RTPrintf(UpdateCheck::tr("Something went wrong while checking for updates!\n"
333 "Please check network connection and try again later.\n"));
334 break;
335 }
336 }
337
338 return RTEXITCODE_SUCCESS;
339}
340
341/**
342 * Handles the 'updatecheck' command.
343 *
344 * @returns Appropriate exit code.
345 * @param a Handler argument.
346 */
347RTEXITCODE handleUpdateCheck(HandlerArg *a)
348{
349 ComPtr<IHost> pHost;
350 CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(pHost.asOutParam()), RTEXITCODE_FAILURE);
351
352 ComPtr<IUpdateAgent> pUpdate;
353 CHECK_ERROR2I_RET(pHost, COMGETTER(UpdateHost)(pUpdate.asOutParam()), RTEXITCODE_FAILURE);
354 /** @todo Add other update agents here. */
355
356 if (a->argc < 1)
357 return errorNoSubcommand();
358 if (!RTStrICmp(a->argv[0], "perform"))
359 {
360 setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_PERFORM);
361 return doUpdateCheck(a->argc - 1, &a->argv[1], pUpdate);
362 }
363 if (!RTStrICmp(a->argv[0], "list"))
364 {
365 setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_LIST);
366 return doUpdateList(a->argc - 1, &a->argv[1], pUpdate);
367 }
368 if (!RTStrICmp(a->argv[0], "modify"))
369 {
370 setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_MODIFY);
371 return doUpdateModify(a->argc - 1, &a->argv[1], pUpdate);
372 }
373 return errorUnknownSubcommand(a->argv[0]);
374}
375
376/* 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