VirtualBox

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

Last change on this file since 86123 was 85929, checked in by vboxsync, 4 years ago

Main: bugref:9224: Main+VBoxManageDisk+doc part

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: HostDriveImpl.cpp 85929 2020-08-28 14:40: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 const char *pszDrivePath = drivePath.c_str();
69
70#ifdef RT_OS_DARWIN
71 /*
72 * Ensure the path specified for the drive in raw mode, i.e. drive name begins with 'r'
73 * Otherwise, the RTFileOpen will always return the error about 'busy resource'
74 */
75 /** @todo r=bird: Shouldn't we make iokit.cpp just return the /dev/rdiskX*
76 * paths instead then? */
77 com::Utf8Str strAdjustedDrivePath;
78 const char *pszDriveName = RTPathFilename(pszDrivePath);
79 if (pszDriveName && *pszDriveName != 'r')
80 {
81 strAdjustedDrivePath = drivePath.substr(0, (size_t)(pszDriveName - pszDrivePath));
82 strAdjustedDrivePath.append('r');
83 strAdjustedDrivePath.append(pszDriveName);
84 pszDrivePath = strAdjustedDrivePath.c_str();
85 }
86#endif
87
88 /*
89 * Try open the drive so we can extract futher details,
90 * like the size, sector size and partitions.
91 */
92 HRESULT hrc = E_FAIL;
93 RTFILE hRawFile = NIL_RTFILE;
94 int vrc = RTFileOpen(&hRawFile, pszDrivePath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
95 if (RT_SUCCESS(vrc))
96 {
97 vrc = RTFileQuerySize(hRawFile, &m.cbDisk);
98 int vrc2 = RTFileQuerySectorSize(hRawFile, &m.cbSector);
99 if (RT_FAILURE(vrc2))
100 vrc = vrc2;
101 if (RT_SUCCESS(vrc))
102 {
103 /*
104 * Hand it to DVM.
105 */
106 RTVFSFILE hVfsFile = NIL_RTVFSFILE;
107 vrc = RTVfsFileFromRTFile(hRawFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE /*fOpen*/,
108 true /*fLeaveOpen*/, &hVfsFile);
109 if (RT_SUCCESS(vrc))
110 {
111 RTDVM hVolMgr = NIL_RTDVM;
112 vrc = RTDvmCreate(&hVolMgr, hVfsFile, m.cbSector, 0 /*fFlags*/);
113 if (RT_SUCCESS(vrc))
114 {
115 vrc = RTDvmMapOpen(hVolMgr);
116 if (RT_SUCCESS(vrc))
117 {
118 hrc = S_OK;
119
120 /*
121 * Get details.
122 */
123 switch (RTDvmMapGetFormatType(hVolMgr))
124 {
125 case RTDVMFORMATTYPE_GPT:
126 m.partitioningType = PartitioningType_GPT;
127 break;
128 case RTDVMFORMATTYPE_MBR:
129 m.partitioningType = PartitioningType_MBR;
130 break;
131 case RTDVMFORMATTYPE_BSD_LABEL:
132 AssertMsgFailed(("TODO\n"));
133 break;
134 default:
135 AssertFailed();
136 }
137
138 RTUUID Uuid = RTUUID_INITIALIZE_NULL;
139 if (RT_SUCCESS(RTDvmMapQueryDiskUuid(hVolMgr, &Uuid)))
140 m.uuid = Uuid;
141
142 /*
143 * Enumerate volumes and tuck them into the partitions list..
144 */
145 uint32_t const cVolumes = RTDvmMapGetValidVolumes(hVolMgr);
146 RTDVMVOLUME hVol = NIL_RTDVMVOLUME;
147 for (uint32_t i = 0; i < cVolumes; i++)
148 {
149 /* Enumeration cruft: */
150 RTDVMVOLUME hVolNext = NIL_RTDVMVOLUME;
151 if (i == 0)
152 vrc = RTDvmMapQueryFirstVolume(hVolMgr, &hVolNext);
153 else
154 vrc = RTDvmMapQueryNextVolume(hVolMgr, hVol, &hVolNext);
155 AssertRCBreakStmt(vrc, hrc = Global::vboxStatusCodeToCOM(vrc));
156
157 uint32_t cRefs = RTDvmVolumeRelease(hVol);
158 Assert(cRefs != UINT32_MAX); RT_NOREF(cRefs);
159 hVol = hVolNext;
160
161 /* Instantiate a new partition object and add it to the list: */
162 ComObjPtr<HostDrivePartition> ptrHostPartition;
163 hrc = ptrHostPartition.createObject();
164 if (SUCCEEDED(hrc))
165 hrc = ptrHostPartition->initFromDvmVol(hVol);
166 if (SUCCEEDED(hrc))
167 try
168 {
169 m.partitions.push_back(ptrHostPartition);
170 }
171 catch (std::bad_alloc &)
172 {
173 AssertFailedBreakStmt(hrc = E_OUTOFMEMORY);
174 }
175 }
176 RTDvmVolumeRelease(hVol);
177 }
178 else
179 hrc = Global::vboxStatusCodeToCOM(vrc);
180 RTDvmRelease(hVolMgr);
181 }
182 else
183 hrc = Global::vboxStatusCodeToCOM(vrc);
184 RTVfsFileRelease(hVfsFile);
185 }
186 else
187 hrc = Global::vboxStatusCodeToCOM(vrc);
188 }
189 else /* VERR_IO_NOT_READ / STATUS_NO_MEDIA_IN_DEVICE is likely for card readers on windows. */
190 hrc = Global::vboxStatusCodeToCOM(vrc);
191 RTFileClose(hRawFile);
192 }
193 else
194 hrc = Global::vboxStatusCodeToCOM(vrc);
195
196 /* Confirm a successful initialization */
197 if (SUCCEEDED(hrc))
198 autoInitSpan.setSucceeded();
199 else
200 autoInitSpan.setLimited(hrc);
201 return S_OK;
202}
203
204/**
205 * Uninitializes the instance.
206 * Called either from FinalRelease() or by the parent when it gets destroyed.
207 */
208void HostDrive::uninit()
209{
210 LogFlowThisFunc(("\n"));
211
212 /* Enclose the state transition Ready->InUninit->NotReady */
213 AutoUninitSpan autoUninitSpan(this);
214 if (autoUninitSpan.uninitDone())
215 return;
216
217 m.drivePath.setNull();
218 m.partitions.clear();
219}
220
221
222/*********************************************************************************************************************************
223* IHostDrive properties *
224*********************************************************************************************************************************/
225
226HRESULT HostDrive::getPartitioningType(PartitioningType_T *aPartitioningType)
227{
228 *aPartitioningType = m.partitioningType;
229 return S_OK;
230}
231
232HRESULT HostDrive::getDrivePath(com::Utf8Str &aDrivePath)
233{
234 aDrivePath = m.drivePath;
235 return S_OK;
236}
237
238HRESULT HostDrive::getUuid(com::Guid &aUuid)
239{
240 aUuid = m.uuid;
241 return S_OK;
242}
243
244HRESULT HostDrive::getSectorSize(ULONG *aSectorSize)
245{
246 *aSectorSize = m.cbSector;
247 return S_OK;
248}
249
250HRESULT HostDrive::getSize(LONG64 *aSize)
251{
252 *aSize = (LONG64)m.cbDisk;
253 if (*aSize < 0)
254 *aSize = INT64_MAX;
255 return S_OK;
256}
257
258HRESULT HostDrive::getModel(com::Utf8Str &aModel)
259{
260 return aModel.assignEx(m.model);
261}
262
263HRESULT HostDrive::getPartitions(std::vector<ComPtr<IHostDrivePartition> > &aPartitions)
264{
265 aPartitions = m.partitions;
266 return S_OK;
267}
268
269
270
271/* 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