VirtualBox

source: vbox/trunk/src/VBox/ImageMounter/vboximg-mount/vboximgMedia.cpp@ 95144

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

Frontends + Main: Adjust to the new rules wrt. to rc -> hrc,vrc usage. This also fixes quite a few bugs wrt shadow variables, wrong return values and output error translations / exit codes. Also see @todos added [build fix, cleanup for VBoxImgMount mess] ​bugref:10223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/* $Id: vboximgMedia.cpp 95144 2022-05-31 10:14:03Z vboxsync $ $Revision: 95144 $ */
2/** @file
3 * vboximgMedia.cpp - Disk Image Flattening FUSE Program.
4 */
5
6/*
7 * Copyright (C) 2009-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#include <VirtualBox_XPCOM.h>
19#include <VBox/com/VirtualBox.h>
20#include <VBox/vd.h>
21#include <VBox/vd-ifs.h>
22#include <VBox/log.h>
23#include <iprt/errcore.h>
24#include <VBox/com/ErrorInfo.h>
25#include <VBox/com/NativeEventQueue.h>
26#include <VBox/com/com.h>
27#include <VBox/com/string.h>
28#include <VBox/com/Guid.h>
29#include <VBox/com/array.h>
30#include <VBox/com/errorprint.h>
31#include <VBox/vd-plugin.h>
32#include <iprt/initterm.h>
33#include <iprt/assert.h>
34#include <iprt/message.h>
35#include <iprt/critsect.h>
36#include <iprt/asm.h>
37#include <iprt/mem.h>
38#include <iprt/string.h>
39#include <iprt/initterm.h>
40#include <iprt/stream.h>
41#include <iprt/types.h>
42#include <iprt/path.h>
43#include <iprt/utf16.h>
44#include <math.h>
45#include "vboximgOpts.h"
46
47using namespace com;
48
49extern VBOXIMGOPTS g_vboximgOpts;
50
51#define SAFENULL(strPtr) (strPtr ? strPtr : "") /** Makes null harmless to print */
52#define CSTR(arg) Utf8Str(arg).c_str() /** Converts XPCOM string type to C string type */
53#define MAX_UUID_LEN 256 /** Max length of a UUID */
54#define VM_MAX_NAME 32 /** Max length of VM name we handle */
55
56typedef struct MEDIUMINFO
57{
58 char *pszName;
59 char *pszUuid;
60 char *pszBaseUuid;
61 char *pszPath;
62 char *pszDescription;
63 char *pszState;
64 char *pszType;
65 char *pszFormat;
66 bool fSnapshot;
67 PRInt64 cbSize;
68 MediumType_T type;
69 MediumState_T state;
70 ~MEDIUMINFO()
71 {
72 RTMemFree(pszName);
73 RTMemFree(pszUuid);
74 RTMemFree(pszPath);
75 RTMemFree(pszDescription);
76 RTMemFree(pszFormat);
77 }
78} MEDIUMINFO;
79
80
81char *vboximgScaledSize(size_t size)
82{
83 uint64_t exp = 0;
84 if (size > 0)
85 exp = log2((double)size);
86 char scaledMagnitude = ((char []){ ' ', 'K', 'M', 'G', 'T', 'P' })[exp / 10];
87 /* This workaround is because IPRT RT*Printf* funcs don't handle floating point format specifiers */
88 double cbScaled = (double)size / pow(2, (double)(((uint64_t)(exp / 10)) * 10));
89 uint64_t intPart = cbScaled;
90 uint64_t fracPart = (cbScaled - (double)intPart) * 10;
91 char tmp[256];
92 RTStrPrintf(tmp, sizeof (tmp), "%d.%d%c", intPart, fracPart, scaledMagnitude);
93 return RTStrDup(tmp);
94}
95
96static int getMediumInfo(IMachine *pMachine, IMedium *pMedium, MEDIUMINFO **ppMediumInfo)
97{
98 RT_NOREF(pMachine);
99
100 MEDIUMINFO *info = new MEDIUMINFO();
101 *ppMediumInfo = info;
102
103 Bstr name;
104 Bstr uuid;
105 Bstr baseUuid;
106 Bstr path;
107 Bstr description;
108 Bstr format;
109 PRInt64 *pSize = &info->cbSize;
110 ComPtr<IMedium> pBase;
111 MediumType_T *pType = &info->type;
112 MediumState_T *pState = &info->state;
113
114 *pState = MediumState_NotCreated;
115
116 HRESULT hrc;
117
118 CHECK_ERROR(pMedium, RefreshState(pState));
119 CHECK_ERROR(pMedium, COMGETTER(Id)(uuid.asOutParam()));
120 CHECK_ERROR(pMedium, COMGETTER(Base)(pBase.asOutParam()));
121 CHECK_ERROR(pBase, COMGETTER(Id)(baseUuid.asOutParam()));
122
123 CHECK_ERROR(pMedium, COMGETTER(State)(pState));
124
125 CHECK_ERROR(pMedium, COMGETTER(Location)(path.asOutParam()));
126 CHECK_ERROR(pMedium, COMGETTER(Format)(format.asOutParam()));
127 CHECK_ERROR(pMedium, COMGETTER(Type)(pType));
128 CHECK_ERROR(pMedium, COMGETTER(Size)(pSize));
129
130 info->pszUuid = RTStrDup((char *)CSTR(uuid));
131 info->pszBaseUuid = RTStrDup((char *)CSTR(baseUuid));
132 info->pszPath = RTStrDup((char *)CSTR(path));
133 info->pszFormat = RTStrDup((char *)CSTR(format));
134 info->fSnapshot = RTStrCmp(CSTR(uuid), CSTR(baseUuid)) != 0;
135
136 if (info->fSnapshot)
137 {
138 /** @todo Determine the VM snapshot this and set name and description
139 * to the snapshot name/description
140 */
141 CHECK_ERROR(pMedium, COMGETTER(Name)(name.asOutParam()));
142 CHECK_ERROR(pMedium, COMGETTER(Description)(description.asOutParam()));
143 }
144 else
145 {
146 CHECK_ERROR(pMedium, COMGETTER(Name)(name.asOutParam()));
147 CHECK_ERROR(pMedium, COMGETTER(Description)(description.asOutParam()));
148 }
149
150 info->pszName = RTStrDup((char *)CSTR(name));
151 info->pszDescription = RTStrDup((char *)CSTR(description));
152
153 switch(*pType)
154 {
155 case MediumType_Normal:
156 info->pszType = (char *)"normal";
157 break;
158 case MediumType_Immutable:
159 info->pszType = (char *)"immutable";
160 break;
161 case MediumType_Writethrough:
162 info->pszType = (char *)"writethrough";
163 break;
164 case MediumType_Shareable:
165 info->pszType = (char *)"shareable";
166 break;
167 case MediumType_Readonly:
168 info->pszType = (char *)"readonly";
169 break;
170 case MediumType_MultiAttach:
171 info->pszType = (char *)"multiattach";
172 break;
173 default:
174 info->pszType = (char *)"?";
175 }
176
177 switch(*pState)
178 {
179 case MediumState_NotCreated:
180 info->pszState = (char *)"uncreated";
181 break;
182 case MediumState_Created:
183 info->pszState = (char *)"created";
184 break;
185 case MediumState_LockedRead:
186 info->pszState = (char *)"rlock";
187 break;
188 case MediumState_LockedWrite:
189 info->pszState = (char *)"wlock";
190 break;
191 case MediumState_Inaccessible:
192 info->pszState = (char *)"no access";
193 break;
194 case MediumState_Creating:
195 info->pszState = (char *)"creating";
196 break;
197 case MediumState_Deleting:
198 info->pszState = (char *)"deleting";
199 break;
200 default:
201 info->pszState = (char *)"?";
202 }
203 return VINF_SUCCESS;
204}
205
206static void displayMediumInfo(MEDIUMINFO *pInfo, int nestLevel, bool fLast)
207{
208 char *pszSzScaled = vboximgScaledSize(pInfo->cbSize);
209 int cPad = nestLevel * 2;
210 if (g_vboximgOpts.fWide && !g_vboximgOpts.fVerbose)
211 {
212 RTPrintf("%3s %-*s %7s %-9s %9s %-*s %s\n",
213 !fLast ? (pInfo->fSnapshot ? " | " : " +-") : (pInfo->fSnapshot ? " " : " +-"),
214 VM_MAX_NAME, pInfo->fSnapshot ? "+- <snapshot>" : pInfo->pszName,
215 pszSzScaled,
216 pInfo->pszFormat,
217 pInfo->pszState,
218 cPad, "", pInfo->pszUuid);
219 }
220 else
221 {
222 if (!pInfo->fSnapshot)
223 {
224 RTPrintf(" Image: %s\n", pInfo->pszName);
225 if (pInfo->pszDescription && RTStrNLen(pInfo->pszDescription, 256) > 0)
226 RTPrintf("Desc: %s\n", pInfo->pszDescription);
227 RTPrintf(" UUID: %s\n", pInfo->pszUuid);
228 if (g_vboximgOpts.fVerbose)
229 {
230 RTPrintf(" Path: %s\n", pInfo->pszPath);
231 RTPrintf(" Format: %s\n", pInfo->pszFormat);
232 RTPrintf(" Size: %s\n", pszSzScaled);
233 RTPrintf(" State: %s\n", pInfo->pszState);
234 RTPrintf(" Type: %s\n", pInfo->pszType);
235 }
236 RTPrintf("\n");
237 }
238 else
239 {
240 RTPrintf(" Snapshot: %s\n", pInfo->pszUuid);
241 if (g_vboximgOpts.fVerbose)
242 {
243 RTPrintf(" Name: %s\n", pInfo->pszName);
244 RTPrintf(" Desc: %s\n", pInfo->pszDescription);
245 }
246 RTPrintf(" Size: %s\n", pszSzScaled);
247 if (g_vboximgOpts.fVerbose)
248 RTPrintf(" Path: %s\n", pInfo->pszPath);
249 RTPrintf("\n");
250 }
251 }
252 RTMemFree(pszSzScaled);
253}
254
255static int vboximgListBranch(IMachine *pMachine, IMedium *pMedium, uint8_t nestLevel, bool fLast)
256{
257 MEDIUMINFO *pMediumInfo;
258 int vrc = getMediumInfo(pMachine, pMedium, &pMediumInfo);
259 if (RT_FAILURE(vrc))
260 return vrc;
261
262 displayMediumInfo(pMediumInfo, nestLevel, fLast);
263
264 HRESULT hrc;
265 com::SafeIfaceArray<IMedium> pChildren;
266 CHECK_ERROR_RET(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(pChildren)), VERR_NOT_FOUND); /** @todo r=andy Find a better rc. */
267
268 for (size_t i = 0; i < pChildren.size(); i++)
269 vboximgListBranch(pMachine, pChildren[i], nestLevel + 1, fLast);
270
271 delete pMediumInfo;
272
273 return VINF_SUCCESS;
274}
275
276static int listMedia(IVirtualBox *pVirtualBox, IMachine *pMachine, char *vmName, char *vmUuid)
277{
278 RT_NOREF(pVirtualBox);
279 RT_NOREF(vmName);
280 RT_NOREF(vmUuid);
281
282 int vrc = VINF_SUCCESS;
283
284 com::SafeIfaceArray<IMediumAttachment> pMediumAttachments;
285
286 HRESULT hrc;
287 CHECK_ERROR(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(pMediumAttachments)));
288
289 for (size_t i = 0; i < pMediumAttachments.size(); i++)
290 {
291 bool fLast = (i == pMediumAttachments.size() - 1);
292 DeviceType_T deviceType;
293
294 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Type)(&deviceType));
295 if (deviceType != DeviceType_HardDisk)
296 continue;
297
298 ComPtr<IMedium> pMedium;
299 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Medium)(pMedium.asOutParam()));
300
301 ComPtr<IMedium> pBase;
302 CHECK_ERROR(pMedium, COMGETTER(Base)(pBase.asOutParam()));
303 if (g_vboximgOpts.fWide && !g_vboximgOpts.fVerbose)
304 RTPrintf(" |\n");
305 else
306 RTPrintf("\n");
307
308 vrc = vboximgListBranch(pMachine, pBase, 0, fLast);
309 if (RT_FAILURE(vrc))
310 {
311 RTPrintf("vboximgListBranch failed with %Rrc\n", vrc);
312 break;
313 }
314 }
315
316 return vrc;
317}
318/**
319 * Display all registered VMs on the screen with some information about each
320 *
321 * @param virtualBox VirtualBox instance object.
322 */
323int vboximgListVMs(IVirtualBox *pVirtualBox)
324{
325 HRESULT hrc;
326 com::SafeIfaceArray<IMachine> pMachines;
327 CHECK_ERROR(pVirtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam(pMachines)));
328
329 if (g_vboximgOpts.fWide)
330 {
331 RTPrintf("\n");
332 RTPrintf("VM Image Size Type State UUID (hierarchy)\n");
333 }
334
335 int vrc = VINF_SUCCESS;
336
337 for (size_t i = 0; i < pMachines.size(); ++i)
338 {
339 ComPtr<IMachine> pMachine = pMachines[i];
340 if (pMachine)
341 {
342 BOOL fAccessible;
343 CHECK_ERROR(pMachines[i], COMGETTER(Accessible)(&fAccessible));
344 if (fAccessible)
345 {
346 Bstr machineName;
347 Bstr machineUuid;
348 Bstr description;
349 Bstr machineLocation;
350
351 CHECK_ERROR(pMachine, COMGETTER(Name)(machineName.asOutParam()));
352 CHECK_ERROR(pMachine, COMGETTER(Id)(machineUuid.asOutParam()));
353 CHECK_ERROR(pMachine, COMGETTER(Description)(description.asOutParam()));
354 CHECK_ERROR(pMachine, COMGETTER(SettingsFilePath)(machineLocation.asOutParam()));
355
356
357 if ( g_vboximgOpts.pszVm == NULL
358 || RTStrNCmp(CSTR(machineUuid), g_vboximgOpts.pszVm, MAX_UUID_LEN) == 0
359 || RTStrNCmp((const char *)machineName.raw(), g_vboximgOpts.pszVm, MAX_UUID_LEN) == 0)
360 {
361 if (g_vboximgOpts.fVerbose)
362 {
363 RTPrintf("-----------------------------------------------------------------\n");
364 RTPrintf("VM Name: \"%s\"\n", CSTR(machineName));
365 RTPrintf("UUID: %s\n", CSTR(machineUuid));
366 if (*description.raw() != '\0')
367 RTPrintf("Desc: %s\n", CSTR(description));
368 RTPrintf("Path: %s\n", CSTR(machineLocation));
369 }
370 else
371 {
372 if (g_vboximgOpts.fWide & !g_vboximgOpts.fVerbose)
373 {
374 RTPrintf("----------------------------------------------------------------- "
375 "------------------------------------\n");
376 RTPrintf("%-*s %*s %s\n", VM_MAX_NAME, CSTR(machineName), 33, "", CSTR(machineUuid));
377 }
378 else
379 {
380 RTPrintf("-----------------------------------------------------------------\n");
381 RTPrintf("VM: %s\n", CSTR(machineName));
382 RTPrintf("UUID: %s\n", CSTR(machineUuid));
383 }
384 }
385
386 int vrc2 = listMedia(pVirtualBox, pMachine,
387 RTStrDup(CSTR(machineName)), RTStrDup(CSTR(machineUuid)));
388 if (RT_SUCCESS(vrc))
389 vrc = vrc2;
390
391 RTPrintf("\n");
392 }
393 }
394 }
395 }
396
397 return vrc;
398}
399
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