VirtualBox

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

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

iprt/dvm: use static, changed prefix of internal functions.

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