VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dvm/dvm.cpp@ 36868

Last change on this file since 36868 was 36868, checked in by vboxsync, 14 years ago

Runtime/common/dvm: export

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.1 KB
Line 
1/* $Id: dvm.cpp 36868 2011-04-28 07:33:27Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - generic code.
4 */
5
6/*
7 * Copyright (C) 2011 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27#include <iprt/types.h>
28#include <iprt/assert.h>
29#include <iprt/mem.h>
30#include <iprt/dvm.h>
31#include <iprt/err.h>
32#include <iprt/asm.h>
33#include <iprt/string.h>
34#include "internal/dvm.h"
35
36/*******************************************************************************
37* Structures and Typedefs *
38*******************************************************************************/
39
40/**
41 * The internal volume manager structure.
42 */
43typedef struct RTDVMINTERNAL
44{
45 /** The DVM magic (RTDVM_MAGIC). */
46 uint32_t u32Magic;
47 /** The disk descriptor. */
48 RTDVMDISK DvmDisk;
49 /** Pointer to the backend operations table after a successful probe. */
50 PCRTDVMFMTOPS pDvmFmtOps;
51 /** The format specific volume manager data. */
52 RTDVMFMT hVolMgrFmt;
53 /** Reference counter. */
54 uint32_t volatile cRefs;
55} RTDVMINTERNAL;
56/** Pointer to an internal volume manager. */
57typedef RTDVMINTERNAL *PRTDVMINTERNAL;
58
59/**
60 * The internal volume structure.
61 */
62typedef struct RTDVMVOLUMEINTERNAL
63{
64 /** The DVM volume magic (RTDVMVOLUME_MAGIC). */
65 uint32_t u32Magic;
66 /** Pointer to the owning volume manager. */
67 PRTDVMINTERNAL pVolMgr;
68 /** Format specific volume data. */
69 RTDVMVOLUMEFMT hVolFmt;
70 /** Reference counter. */
71 uint32_t volatile cRefs;
72} RTDVMVOLUMEINTERNAL;
73/** Pointer to an internal volume. */
74typedef RTDVMVOLUMEINTERNAL *PRTDVMVOLUMEINTERNAL;
75
76/*******************************************************************************
77* Global variables *
78*******************************************************************************/
79extern RTDVMFMTOPS g_DvmFmtMbr;
80extern RTDVMFMTOPS g_DvmFmtGpt;
81
82/**
83 * Supported volume formats.
84 */
85static PCRTDVMFMTOPS g_aDvmFmts[] =
86{
87 &g_DvmFmtMbr,
88 &g_DvmFmtGpt
89};
90
91/**
92 * Descriptions of the volume types.
93 */
94static const char * g_apcszDvmVolTypes[] =
95{
96 "Invalid",
97 "Unknown",
98 "NTFS",
99 "FAT16",
100 "FAT32",
101 "Linux swap",
102 "Linux native",
103 "Linux LVM",
104 "Linux SoftRaid",
105 "FreeBSD",
106 "NetBSD",
107 "OpenBSD",
108 "Mac OS X HFS or HFS+",
109 "Solaris"
110};
111
112RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead,
113 PFNDVMWRITE pfnWrite, uint64_t cbDisk,
114 uint64_t cbSector, void *pvUser)
115{
116 int rc = VINF_SUCCESS;
117 PRTDVMINTERNAL pThis;
118
119 pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));
120 if (VALID_PTR(pThis))
121 {
122 pThis->u32Magic = RTDVM_MAGIC;
123 pThis->DvmDisk.cbDisk = cbDisk;
124 pThis->DvmDisk.cbSector = cbSector;
125 pThis->DvmDisk.pvUser = pvUser;
126 pThis->DvmDisk.pfnRead = pfnRead;
127 pThis->DvmDisk.pfnWrite = pfnWrite;
128 pThis->pDvmFmtOps = NULL;
129 pThis->hVolMgrFmt = NIL_RTDVMFMT;
130 pThis->cRefs = 1;
131 *phVolMgr = pThis;
132 }
133 else
134 rc = VERR_NO_MEMORY;
135
136 return rc;
137}
138
139RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr)
140{
141 PRTDVMINTERNAL pThis = hVolMgr;
142 AssertPtrReturn(pThis, UINT32_MAX);
143 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
144
145 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
146 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
147 return cRefs;
148}
149
150/**
151 * Destroys a volume manager handle.
152 *
153 * @param pThis The volume manager to destroy.
154 */
155static void rtDvmDestroy(PRTDVMINTERNAL pThis)
156{
157 if (pThis->hVolMgrFmt != NIL_RTDVMFMT)
158 {
159 AssertPtr(pThis->pDvmFmtOps);
160
161 /* Let the backend do it's own cleanup first. */
162 pThis->pDvmFmtOps->pfnClose(pThis->hVolMgrFmt);
163 pThis->hVolMgrFmt = NIL_RTDVMFMT;
164 }
165
166 pThis->DvmDisk.cbDisk = 0;
167 pThis->DvmDisk.pvUser = NULL;
168 pThis->DvmDisk.pfnRead = NULL;
169 pThis->DvmDisk.pfnWrite = NULL;
170 pThis->u32Magic = RTDVM_MAGIC_DEAD;
171 RTMemFree(pThis);
172}
173
174RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr)
175{
176 PRTDVMINTERNAL pThis = hVolMgr;
177 if (pThis == NIL_RTDVM)
178 return 0;
179 AssertPtrReturn(pThis, UINT32_MAX);
180 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
181
182 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
183 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
184 if (cRefs == 0)
185 rtDvmDestroy(pThis);
186 return cRefs;
187}
188
189RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr)
190{
191 int rc = VINF_SUCCESS;
192 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED;
193 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL;
194 PRTDVMINTERNAL pThis = hVolMgr;
195 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
196 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
197 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);
198
199 Assert(!pThis->pDvmFmtOps);
200
201 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
202 {
203 uint32_t uScore;
204 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
205
206 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore);
207 if ( RT_SUCCESS(rc)
208 && uScore > uScoreMax)
209 {
210 pDvmFmtOpsMatch = pDvmFmtOps;
211 uScoreMax = uScore;
212 }
213 else if (RT_FAILURE(rc))
214 break;
215 }
216
217 if (RT_SUCCESS(rc))
218 {
219 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED)
220 {
221 AssertPtr(pDvmFmtOpsMatch);
222
223 /* Open the format. */
224 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt);
225 if (RT_SUCCESS(rc))
226 pThis->pDvmFmtOps = pDvmFmtOpsMatch;
227 }
228 else
229 rc = VERR_NOT_FOUND;
230 }
231
232 return rc;
233}
234
235RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt)
236{
237 int rc = VINF_SUCCESS;
238 PRTDVMINTERNAL pThis = hVolMgr;
239 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
240 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER);
241 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
242 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);
243
244 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
245 {
246 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
247
248 if (!RTStrCmp(pDvmFmtOps->pcszFmt, pszFmt))
249 {
250 rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
251 if (RT_SUCCESS(rc))
252 pThis->pDvmFmtOps = pDvmFmtOps;
253
254 break;
255 }
256 }
257
258 return rc;
259}
260
261RTDECL(const char *) RTDvmMapGetFormat(RTDVM hVolMgr)
262{
263 PRTDVMINTERNAL pThis = hVolMgr;
264 AssertPtrReturn(pThis, NULL);
265 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, NULL);
266 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
267
268 return pThis->pDvmFmtOps->pcszFmt;
269}
270
271RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr)
272{
273 PRTDVMINTERNAL pThis = hVolMgr;
274 AssertPtrReturn(pThis, UINT32_MAX);
275 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
276 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
277
278 return pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
279}
280
281RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr)
282{
283 PRTDVMINTERNAL pThis = hVolMgr;
284 AssertPtrReturn(pThis, UINT32_MAX);
285 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
286 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
287
288 return pThis->pDvmFmtOps->pfnGetMaxVolumes(pThis->hVolMgrFmt);
289}
290
291static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt,
292 PRTDVMVOLUME phVol)
293{
294 int rc = VINF_SUCCESS;
295 PRTDVMVOLUMEINTERNAL pVol = NULL;
296
297 pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL));
298 if (VALID_PTR(pVol))
299 {
300 pVol->u32Magic = RTDVMVOLUME_MAGIC;
301 pVol->cRefs = 1;
302 pVol->pVolMgr = pThis;
303 pVol->hVolFmt = hVolFmt;
304
305 /* Reference the volume manager. */
306 RTDvmRetain(pThis);
307 *phVol = pVol;
308 }
309 else
310 rc = VERR_NO_MEMORY;
311
312 return rc;
313}
314
315RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
316{
317 int rc = VINF_SUCCESS;
318 PRTDVMINTERNAL pThis = hVolMgr;
319 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
320 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
321 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
322 AssertPtrReturn(phVol, VERR_INVALID_POINTER);
323
324 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT;
325 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt);
326 if (RT_SUCCESS(rc))
327 {
328 rc = rtDvmVolumeCreate(pThis, hVolFmt, phVol);
329 if (RT_FAILURE(rc))
330 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt);
331 }
332
333 return rc;
334}
335
336RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext)
337{
338 int rc = VINF_SUCCESS;
339 PRTDVMINTERNAL pThis = hVolMgr;
340 PRTDVMVOLUMEINTERNAL pVol = hVol;
341 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
342 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
343 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
344 AssertPtrReturn(pVol, VERR_INVALID_HANDLE);
345 AssertReturn(pVol->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
346 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER);
347
348 RTDVMVOLUMEFMT hVolFmtNext = NIL_RTDVMVOLUMEFMT;
349 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmtNext);
350 if (RT_SUCCESS(rc))
351 {
352 rc = rtDvmVolumeCreate(pThis, hVolFmtNext, phVolNext);
353 if (RT_FAILURE(rc))
354 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmtNext);
355 }
356
357 return rc;
358}
359
360RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
361{
362 PRTDVMVOLUMEINTERNAL pThis = hVol;
363 AssertPtrReturn(pThis, UINT32_MAX);
364 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
365
366 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
367 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
368 return cRefs;
369}
370
371/**
372 * Destroys a volume handle.
373 *
374 * @param pThis The volume to destroy.
375 */
376static void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis)
377{
378 PRTDVMINTERNAL pVolMgr = pThis->pVolMgr;
379
380 AssertPtr(pVolMgr);
381
382 /* Close the volume. */
383 pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt);
384
385 pThis->u32Magic = RTDVMVOLUME_MAGIC_DEAD;
386 pThis->pVolMgr = NULL;
387 pThis->hVolFmt = NIL_RTDVMVOLUMEFMT;
388 RTMemFree(pThis);
389
390 /* Release the reference of the volume manager. */
391 RTDvmRelease(pVolMgr);
392}
393
394RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
395{
396 PRTDVMVOLUMEINTERNAL pThis = hVol;
397 if (pThis == NIL_RTDVMVOLUME)
398 return 0;
399 AssertPtrReturn(pThis, UINT32_MAX);
400 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
401
402 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
403 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
404 if (cRefs == 0)
405 rtDvmVolumeDestroy(pThis);
406 return cRefs;
407}
408
409RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
410{
411 PRTDVMVOLUMEINTERNAL pThis = hVol;
412 AssertPtrReturn(pThis, 0);
413 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
414
415 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
416}
417
418RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
419{
420 PRTDVMVOLUMEINTERNAL pThis = hVol;
421 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
422 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
423 AssertReturn(ppszVolName, VERR_INVALID_POINTER);
424
425 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
426}
427
428RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
429{
430 PRTDVMVOLUMEINTERNAL pThis = hVol;
431 AssertPtrReturn(pThis, RTDVMVOLTYPE_INVALID);
432 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
433
434 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
435}
436
437RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
438{
439 PRTDVMVOLUMEINTERNAL pThis = hVol;
440 AssertPtrReturn(pThis, UINT64_MAX);
441 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
442
443 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
444}
445
446RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
447{
448 PRTDVMVOLUMEINTERNAL pThis = hVol;
449 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
450 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
451 AssertReturn(pvBuf, VERR_INVALID_POINTER);
452 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);
453
454 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
455}
456
457RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
458{
459 PRTDVMVOLUMEINTERNAL pThis = hVol;
460 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
461 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
462 AssertReturn(pvBuf, VERR_INVALID_POINTER);
463 AssertReturn(cbWrite > 0, VERR_INVALID_PARAMETER);
464
465 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
466}
467
468RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)
469{
470 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_32BIT_HACK, NULL);
471
472 return g_apcszDvmVolTypes[enmVolType];
473}
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