VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostDriveImpl.cpp@ 88956

Last change on this file since 88956 was 86241, checked in by vboxsync, 4 years ago

Main: bugref:9224: Fixed the error when obtain the disk info in block mode in the MacOS

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: HostDriveImpl.cpp 86241 2020-09-23 14:31:55Z vboxsync $ */
2/** @file
3 * VirtualBox Main - IHostDrive implementation, VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2013-2019 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#define LOG_GROUP LOG_GROUP_MAIN_HOSTDRIVE
19#include "Global.h"
20#include "HostDriveImpl.h"
21#include "HostDrivePartitionImpl.h"
22#include "LoggingNew.h"
23#include "VirtualBoxImpl.h"
24
25#include <iprt/dvm.h>
26#include <iprt/err.h>
27#include <iprt/file.h>
28#include <iprt/path.h>
29#include <iprt/vfs.h>
30#include <VBox/com/Guid.h>
31
32
33/*
34 * HostDrive implementation.
35 */
36DEFINE_EMPTY_CTOR_DTOR(HostDrive)
37
38HRESULT HostDrive::FinalConstruct()
39{
40 return BaseFinalConstruct();
41}
42
43void HostDrive::FinalRelease()
44{
45 uninit();
46
47 BaseFinalRelease();
48}
49
50/**
51 * Initializes the instance.
52 */
53HRESULT HostDrive::initFromPathAndModel(const com::Utf8Str &drivePath, const com::Utf8Str &driveModel)
54{
55 LogFlowThisFunc(("\n"));
56
57 AssertReturn(!drivePath.isEmpty(), E_INVALIDARG);
58
59 /* Enclose the state transition NotReady->InInit->Ready */
60 AutoInitSpan autoInitSpan(this);
61 AssertReturn(autoInitSpan.isOk(), E_FAIL);
62
63 m.partitioningType = PartitioningType_MBR;
64 m.drivePath = drivePath;
65 m.model = driveModel;
66 m.partitions.clear();
67
68 /*
69 * Try open the drive so we can extract futher details,
70 * like the size, sector size and partitions.
71 */
72 HRESULT hrc = E_FAIL;
73 RTFILE hRawFile = NIL_RTFILE;
74 int vrc = RTFileOpen(&hRawFile, drivePath.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
75 if (RT_SUCCESS(vrc))
76 {
77 vrc = RTFileQuerySize(hRawFile, &m.cbDisk);
78 int vrc2 = RTFileQuerySectorSize(hRawFile, &m.cbSector);
79 if (RT_FAILURE(vrc2))
80 vrc = vrc2;
81 if (RT_SUCCESS(vrc))
82 {
83 /*
84 * Hand it to DVM.
85 */
86 RTVFSFILE hVfsFile = NIL_RTVFSFILE;
87 vrc = RTVfsFileFromRTFile(hRawFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE /*fOpen*/,
88 true /*fLeaveOpen*/, &hVfsFile);
89 if (RT_SUCCESS(vrc))
90 {
91 RTDVM hVolMgr = NIL_RTDVM;
92 vrc = RTDvmCreate(&hVolMgr, hVfsFile, m.cbSector, 0 /*fFlags*/);
93 if (RT_SUCCESS(vrc))
94 {
95 vrc = RTDvmMapOpen(hVolMgr);
96 if (RT_SUCCESS(vrc))
97 {
98 hrc = S_OK;
99
100 /*
101 * Get details.
102 */
103 switch (RTDvmMapGetFormatType(hVolMgr))
104 {
105 case RTDVMFORMATTYPE_GPT:
106 m.partitioningType = PartitioningType_GPT;
107 break;
108 case RTDVMFORMATTYPE_MBR:
109 m.partitioningType = PartitioningType_MBR;
110 break;
111 case RTDVMFORMATTYPE_BSD_LABEL:
112 AssertMsgFailed(("TODO\n"));
113 break;
114 default:
115 AssertFailed();
116 }
117
118 RTUUID Uuid = RTUUID_INITIALIZE_NULL;
119 if (RT_SUCCESS(RTDvmMapQueryDiskUuid(hVolMgr, &Uuid)))
120 m.uuid = Uuid;
121
122 /*
123 * Enumerate volumes and tuck them into the partitions list..
124 */
125 uint32_t const cVolumes = RTDvmMapGetValidVolumes(hVolMgr);
126 RTDVMVOLUME hVol = NIL_RTDVMVOLUME;
127 for (uint32_t i = 0; i < cVolumes; i++)
128 {
129 /* Enumeration cruft: */
130 RTDVMVOLUME hVolNext = NIL_RTDVMVOLUME;
131 if (i == 0)
132 vrc = RTDvmMapQueryFirstVolume(hVolMgr, &hVolNext);
133 else
134 vrc = RTDvmMapQueryNextVolume(hVolMgr, hVol, &hVolNext);
135 AssertRCBreakStmt(vrc, hrc = Global::vboxStatusCodeToCOM(vrc));
136
137 uint32_t cRefs = RTDvmVolumeRelease(hVol);
138 Assert(cRefs != UINT32_MAX); RT_NOREF(cRefs);
139 hVol = hVolNext;
140
141 /* Instantiate a new partition object and add it to the list: */
142 ComObjPtr<HostDrivePartition> ptrHostPartition;
143 hrc = ptrHostPartition.createObject();
144 if (SUCCEEDED(hrc))
145 hrc = ptrHostPartition->initFromDvmVol(hVol);
146 if (SUCCEEDED(hrc))
147 try
148 {
149 m.partitions.push_back(ptrHostPartition);
150 }
151 catch (std::bad_alloc &)
152 {
153 AssertFailedBreakStmt(hrc = E_OUTOFMEMORY);
154 }
155 }
156 RTDvmVolumeRelease(hVol);
157 }
158 else
159 hrc = Global::vboxStatusCodeToCOM(vrc);
160 RTDvmRelease(hVolMgr);
161 }
162 else
163 hrc = Global::vboxStatusCodeToCOM(vrc);
164 RTVfsFileRelease(hVfsFile);
165 }
166 else
167 hrc = Global::vboxStatusCodeToCOM(vrc);
168 }
169 else /* VERR_IO_NOT_READ / STATUS_NO_MEDIA_IN_DEVICE is likely for card readers on windows. */
170 hrc = Global::vboxStatusCodeToCOM(vrc);
171 RTFileClose(hRawFile);
172 }
173 else
174 {
175 /*
176 * We don't use the Global::vboxStatusCodeToCOM(vrc) here
177 * because RTFileOpen can return some error which causes
178 * the assertion and breaks original idea of returning
179 * the object in the limited state.
180 */
181 if ( vrc == VERR_RESOURCE_BUSY
182 || vrc == VERR_ACCESS_DENIED)
183 hrc = E_ACCESSDENIED;
184 else
185 hrc = VBOX_E_IPRT_ERROR;
186 }
187
188 /* Confirm a successful initialization */
189 if (SUCCEEDED(hrc))
190 autoInitSpan.setSucceeded();
191 else
192 autoInitSpan.setLimited(hrc);
193 return S_OK;
194}
195
196/**
197 * Uninitializes the instance.
198 * Called either from FinalRelease() or by the parent when it gets destroyed.
199 */
200void HostDrive::uninit()
201{
202 LogFlowThisFunc(("\n"));
203
204 /* Enclose the state transition Ready->InUninit->NotReady */
205 AutoUninitSpan autoUninitSpan(this);
206 if (autoUninitSpan.uninitDone())
207 return;
208
209 m.drivePath.setNull();
210 m.partitions.clear();
211}
212
213
214/*********************************************************************************************************************************
215* IHostDrive properties *
216*********************************************************************************************************************************/
217
218HRESULT HostDrive::getPartitioningType(PartitioningType_T *aPartitioningType)
219{
220 *aPartitioningType = m.partitioningType;
221 return S_OK;
222}
223
224HRESULT HostDrive::getDrivePath(com::Utf8Str &aDrivePath)
225{
226 aDrivePath = m.drivePath;
227 return S_OK;
228}
229
230HRESULT HostDrive::getUuid(com::Guid &aUuid)
231{
232 aUuid = m.uuid;
233 return S_OK;
234}
235
236HRESULT HostDrive::getSectorSize(ULONG *aSectorSize)
237{
238 *aSectorSize = m.cbSector;
239 return S_OK;
240}
241
242HRESULT HostDrive::getSize(LONG64 *aSize)
243{
244 *aSize = (LONG64)m.cbDisk;
245 if (*aSize < 0)
246 *aSize = INT64_MAX;
247 return S_OK;
248}
249
250HRESULT HostDrive::getModel(com::Utf8Str &aModel)
251{
252 return aModel.assignEx(m.model);
253}
254
255HRESULT HostDrive::getPartitions(std::vector<ComPtr<IHostDrivePartition> > &aPartitions)
256{
257 aPartitions = m.partitions;
258 return S_OK;
259}
260
261
262
263/* 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